feat: 支持将色彩校准的值写入本地配置文件。

This commit is contained in:
Ivan Li 2023-04-16 18:17:49 +08:00
parent fc8b3164d8
commit 6e6160fc0a
10 changed files with 145 additions and 19 deletions

View File

@ -2,7 +2,8 @@
"files.autoSave": "onWindowChange",
"cSpell.words": [
"Itertools",
"Leds"
"Leds",
"unlisten"
],
"idf.customExtraVars": {
"OPENOCD_SCRIPTS": "/Users/ivan/.espressif/tools/openocd-esp32/v0.11.0-esp32-20211220/openocd-esp32/share/openocd/scripts"

7
.vscode/tasks.json vendored
View File

@ -14,7 +14,12 @@
],
"problemMatcher": [
"$eslint-stylish"
]
],
"options": {
"env": {
"RUST_LOG": "info"
}
}
},
{
"label": "ui:dev",

View File

@ -5,7 +5,7 @@ use paris::{error, info};
use serde::{Deserialize, Serialize};
use tauri::api::path::config_dir;
use crate::screenshot::{self, LedSamplePoints};
use crate::screenshot::LedSamplePoints;
const CONFIG_FILE_NAME: &str = "cc.ivanli.ambient_light/led_strip_config.toml";
@ -26,10 +26,18 @@ pub struct LedStripConfig {
pub len: usize,
}
#[derive(Clone, Copy, Serialize, Deserialize, Debug)]
pub struct ColorCalibration {
r: f32,
g: f32,
b: f32,
}
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct LedStripConfigGroup {
pub strips: Vec<LedStripConfig>,
pub mappers: Vec<SamplePointMapper>,
pub color_calibration: ColorCalibration,
}
impl LedStripConfigGroup {
@ -115,7 +123,17 @@ impl LedStripConfigGroup {
})
}
}
Ok(Self { strips, mappers })
let color_calibration = ColorCalibration {
r: 1.0,
g: 1.0,
b: 1.0,
};
Ok(Self {
strips,
mappers,
color_calibration,
})
}
}

View File

@ -5,7 +5,7 @@ use tokio::sync::OnceCell;
use crate::ambient_light::{config, LedStripConfigGroup};
use super::{Border, SamplePointMapper};
use super::{Border, SamplePointMapper, ColorCalibration};
pub struct ConfigManager {
config: Arc<RwLock<LedStripConfigGroup>>,
@ -223,4 +223,15 @@ impl ConfigManager {
) -> tokio::sync::watch::Receiver<LedStripConfigGroup> {
self.config_update_receiver.clone()
}
pub async fn set_color_calibration(&self, color_calibration: ColorCalibration) -> anyhow::Result<()> {
let config = self.config.write().await;
let mut cloned_config = config.clone();
cloned_config.color_calibration = color_calibration;
drop(config);
self.update(&cloned_config).await
}
}

View File

@ -192,7 +192,7 @@ impl LedColorsPublisher {
warn!("Failed to send sorted colors: {}", err);
}
};
log::info!("tick: {}ms", start.elapsed().as_millis());
log::debug!("tick: {}ms", start.elapsed().as_millis());
start = tokio::time::Instant::now();
}
}

View File

@ -8,7 +8,9 @@ mod rpc;
pub mod screenshot;
mod screenshot_manager;
use ambient_light::{Border, LedColorsPublisher, LedStripConfig, LedStripConfigGroup};
use ambient_light::{
Border, ColorCalibration, LedColorsPublisher, LedStripConfig, LedStripConfigGroup,
};
use core_graphics::display::{
kCGNullWindowID, kCGWindowImageDefault, kCGWindowListOptionOnScreenOnly, CGDisplay,
};
@ -145,14 +147,14 @@ async fn send_colors(buffer: Vec<u8>) -> Result<(), String> {
}
#[tauri::command]
async fn move_strip_part(display_id: u32, border: Border, target_start: usize) -> Result<(), String> {
async fn move_strip_part(
display_id: u32,
border: Border,
target_start: usize,
) -> Result<(), String> {
let config_manager = ambient_light::ConfigManager::global().await;
config_manager
.move_strip_part(
display_id,
border,
target_start,
)
.move_strip_part(display_id, border, target_start)
.await
.map_err(|e| {
error!("can not move strip part: {}", e);
@ -172,6 +174,18 @@ async fn reverse_led_strip_part(display_id: u32, border: Border) -> Result<(), S
})
}
#[tauri::command]
async fn set_color_calibration(calibration: ColorCalibration) -> Result<(), String> {
let config_manager = ambient_light::ConfigManager::global().await;
config_manager
.set_color_calibration(calibration)
.await
.map_err(|e| {
error!("can not set color calibration: {}", e);
e.to_string()
})
}
#[tokio::main]
async fn main() {
env_logger::init();
@ -194,6 +208,7 @@ async fn main() {
send_colors,
move_strip_part,
reverse_led_strip_part,
set_color_calibration,
])
.register_uri_scheme_protocol("ambient-light", move |_app, request| {
let response = ResponseBuilder::new().header("Access-Control-Allow-Origin", "*");
@ -359,6 +374,7 @@ async fn main() {
.unwrap();
}
});
let app_handle = app.handle().clone();
tokio::spawn(async move {
let publisher = ambient_light::LedColorsPublisher::global().await;

View File

@ -1,13 +1,18 @@
import { Component, JSX } from 'solid-js';
type Props = {} & JSX.HTMLAttributes<HTMLInputElement>;
type Props = {
value?: number;
} & JSX.HTMLAttributes<HTMLInputElement>;
export const ColorSlider: Component<Props> = (props) => {
return (
<input
type="range"
value="50"
{...props}
max={1}
min={0}
step={0.01}
value={props.value}
class={
'w-full h-2 bg-gradient-to-r rounded-lg appearance-none cursor-pointer dark:bg-gray-700 drop-shadow ' +
props.class

View File

@ -1,7 +1,38 @@
import { listen } from '@tauri-apps/api/event';
import { createEffect, onCleanup } from 'solid-js';
import { ColorCalibration, LedStripConfigContainer } from '../../models/led-strip-config';
import { ledStripStore, setLedStripStore } from '../../stores/led-strip.store';
import { ColorSlider } from './color-slider';
import { TestColorsBg } from './test-colors-bg';
import { invoke } from '@tauri-apps/api';
export const WhiteBalance = () => {
// listen to config_changed event
createEffect(() => {
const unlisten = listen('config_changed', (event) => {
const { strips, mappers, color_calibration } =
event.payload as LedStripConfigContainer;
console.log(event.payload);
setLedStripStore({
strips,
mappers,
colorCalibration: color_calibration,
});
});
onCleanup(() => {
unlisten.then((unlisten) => unlisten());
});
});
const updateColorCalibration = (field: keyof ColorCalibration, value: number) => {
const calibration = { ...ledStripStore.colorCalibration, [field]: value };
console.log(field, calibration);
invoke('set_color_calibration', {
calibration,
}).catch((error) => console.log(error));
};
const exit = () => {
window.history.back();
};
@ -14,15 +45,42 @@ export const WhiteBalance = () => {
<div class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-10/12 max-w-lg bg-stone-200 p-5 rounded-xl drop-shadow">
<label class="flex items-center gap-2">
<span class="w-3 block">R:</span>
<ColorSlider class="from-cyan-500 to-red-500" />
<ColorSlider
class="from-cyan-500 to-red-500"
value={ledStripStore.colorCalibration.r}
onInput={(ev) =>
updateColorCalibration(
'r',
(ev.target as HTMLInputElement).valueAsNumber ?? 1,
)
}
/>
</label>
<label class="flex items-center gap-2">
<span class="w-3 block">G:</span>
<ColorSlider class="from-pink-500 to-green-500" />
<ColorSlider
class="from-pink-500 to-green-500"
value={ledStripStore.colorCalibration.g}
onInput={(ev) =>
updateColorCalibration(
'g',
(ev.target as HTMLInputElement).valueAsNumber ?? 1,
)
}
/>
</label>
<label class="flex items-center gap-2">
<span class="w-3 block">B:</span>
<ColorSlider class="from-yellow-500 to-blue-500" />
<ColorSlider
class="from-yellow-500 to-blue-500"
value={ledStripStore.colorCalibration.b}
onInput={(ev) =>
updateColorCalibration(
'b',
(ev.target as HTMLInputElement).valueAsNumber ?? 1,
)
}
/>
</label>
<label class="flex items-center gap-2">
<span class="w-3 block">W:</span>

View File

@ -6,9 +6,16 @@ export type LedStripPixelMapper = {
pos: number;
};
export class ColorCalibration {
r: number = 1;
g: number = 1;
b: number = 1;
}
export type LedStripConfigContainer = {
strips: LedStripConfig[];
mappers: LedStripPixelMapper[];
color_calibration: ColorCalibration;
};
export class LedStripConfig {

View File

@ -1,9 +1,14 @@
import { createStore } from 'solid-js/store';
import { LedStripConfig, LedStripPixelMapper } from '../models/led-strip-config';
import {
ColorCalibration,
LedStripConfig,
LedStripPixelMapper,
} from '../models/led-strip-config';
export const [ledStripStore, setLedStripStore] = createStore({
strips: new Array<LedStripConfig>(),
mappers: new Array<LedStripPixelMapper>(),
colorCalibration: new ColorCalibration(),
colors: new Uint8ClampedArray(),
sortedColors: new Uint8ClampedArray(),
get totalLedCount() {