feat: smooth skin effect
Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
This commit is contained in:
@@ -14,7 +14,8 @@ use ptp::{
|
|||||||
FujiColorChromeFXBlue, FujiCustomSetting, FujiCustomSettingName, FujiDynamicRange,
|
FujiColorChromeFXBlue, FujiCustomSetting, FujiCustomSettingName, FujiDynamicRange,
|
||||||
FujiDynamicRangePriority, FujiFilmSimulation, FujiGrainEffect, FujiHighISONR,
|
FujiDynamicRangePriority, FujiFilmSimulation, FujiGrainEffect, FujiHighISONR,
|
||||||
FujiHighlightTone, FujiImageQuality, FujiImageSize, FujiShadowTone, FujiSharpness,
|
FujiHighlightTone, FujiImageQuality, FujiImageSize, FujiShadowTone, FujiSharpness,
|
||||||
FujiWhiteBalance, FujiWhiteBalanceShift, FujiWhiteBalanceTemperature, UsbMode,
|
FujiSmoothSkinEffect, FujiWhiteBalance, FujiWhiteBalanceShift, FujiWhiteBalanceTemperature,
|
||||||
|
UsbMode,
|
||||||
},
|
},
|
||||||
structs::DeviceInfo,
|
structs::DeviceInfo,
|
||||||
};
|
};
|
||||||
@@ -257,6 +258,14 @@ impl Camera {
|
|||||||
pub fn set_color_chrome_fx_blue(&mut self, value: FujiColorChromeFXBlue) -> anyhow::Result<()> {
|
pub fn set_color_chrome_fx_blue(&mut self, value: FujiColorChromeFXBlue) -> anyhow::Result<()> {
|
||||||
self.r#impl.set_color_chrome_fx_blue(&mut self.ptp, value)
|
self.r#impl.set_color_chrome_fx_blue(&mut self.ptp, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_smooth_skin_effect(&mut self) -> anyhow::Result<FujiSmoothSkinEffect> {
|
||||||
|
self.r#impl.get_smooth_skin_effect(&mut self.ptp)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_smooth_skin_effect(&mut self, value: FujiSmoothSkinEffect) -> anyhow::Result<()> {
|
||||||
|
self.r#impl.set_smooth_skin_effect(&mut self.ptp, value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for Camera {
|
impl Drop for Camera {
|
||||||
@@ -789,4 +798,25 @@ pub trait CameraImpl<P: rusb::UsbContext> {
|
|||||||
)?;
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_smooth_skin_effect(&self, ptp: &mut Ptp) -> anyhow::Result<FujiSmoothSkinEffect> {
|
||||||
|
let bytes =
|
||||||
|
self.get_prop_value(ptp, DevicePropCode::FujiStillCustomSettingSmoothSkinEffect)?;
|
||||||
|
let result = FujiSmoothSkinEffect::try_from_ptp(&bytes)?;
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_smooth_skin_effect(
|
||||||
|
&self,
|
||||||
|
ptp: &mut Ptp,
|
||||||
|
value: FujiSmoothSkinEffect,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let bytes = value.try_into_ptp()?;
|
||||||
|
self.set_prop_value(
|
||||||
|
ptp,
|
||||||
|
DevicePropCode::FujiStillCustomSettingSmoothSkinEffect,
|
||||||
|
&bytes,
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -145,7 +145,7 @@ pub enum DevicePropCode {
|
|||||||
FujiStillCustomSettingGrainEffect = 0xD195,
|
FujiStillCustomSettingGrainEffect = 0xD195,
|
||||||
FujiStillCustomSettingColorChromeEffect = 0xD196,
|
FujiStillCustomSettingColorChromeEffect = 0xD196,
|
||||||
FujiStillCustomSettingColorChromeFXBlue = 0xD197,
|
FujiStillCustomSettingColorChromeFXBlue = 0xD197,
|
||||||
// TODO: 0xD198 All 1s
|
FujiStillCustomSettingSmoothSkinEffect = 0xD198,
|
||||||
FujiStillCustomSettingWhiteBalance = 0xD199,
|
FujiStillCustomSettingWhiteBalance = 0xD199,
|
||||||
FujiStillCustomSettingWhiteBalanceShiftRed = 0xD19A,
|
FujiStillCustomSettingWhiteBalanceShiftRed = 0xD19A,
|
||||||
FujiStillCustomSettingWhiteBalanceShiftBlue = 0xD19B,
|
FujiStillCustomSettingWhiteBalanceShiftBlue = 0xD19B,
|
||||||
@@ -875,6 +875,59 @@ impl FromStr for FujiColorChromeFXBlue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(u16)]
|
||||||
|
#[derive(
|
||||||
|
Debug,
|
||||||
|
Clone,
|
||||||
|
Copy,
|
||||||
|
PartialEq,
|
||||||
|
Eq,
|
||||||
|
Serialize,
|
||||||
|
IntoPrimitive,
|
||||||
|
TryFromPrimitive,
|
||||||
|
PtpSerialize,
|
||||||
|
PtpDeserialize,
|
||||||
|
EnumIter,
|
||||||
|
)]
|
||||||
|
pub enum FujiSmoothSkinEffect {
|
||||||
|
Strong = 0x3,
|
||||||
|
Weak = 0x2,
|
||||||
|
Off = 0x1,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for FujiSmoothSkinEffect {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::Strong => write!(f, "Strong"),
|
||||||
|
Self::Weak => write!(f, "Weak"),
|
||||||
|
Self::Off => write!(f, "Off"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for FujiSmoothSkinEffect {
|
||||||
|
type Err = anyhow::Error;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> anyhow::Result<Self> {
|
||||||
|
let input = s.trim().to_lowercase();
|
||||||
|
|
||||||
|
match input.as_str() {
|
||||||
|
"strong" => return Ok(Self::Strong),
|
||||||
|
"weak" => return Ok(Self::Weak),
|
||||||
|
"off" => return Ok(Self::Off),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
let choices: Vec<String> = Self::iter().map(|v| v.to_string()).collect();
|
||||||
|
if let Some(best) = suggest_closest(s, &choices) {
|
||||||
|
bail!("Unknown smooth skin effect '{s}'. Did you mean '{best}'?");
|
||||||
|
}
|
||||||
|
|
||||||
|
bail!("Unknown smooth skin effect '{s}'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[repr(u16)]
|
#[repr(u16)]
|
||||||
#[derive(
|
#[derive(
|
||||||
Debug,
|
Debug,
|
||||||
|
@@ -1,18 +1,14 @@
|
|||||||
use clap::Args;
|
use clap::Args;
|
||||||
|
|
||||||
use crate::camera::ptp::hex::{
|
use crate::camera::ptp::hex::{
|
||||||
FujiClarity, FujiColor, FujiColorChromeEffect, FujiColorChromeFXBlue, FujiCustomSettingName,
|
FujiClarity, FujiColor, FujiColorChromeEffect, FujiColorChromeFXBlue, FujiDynamicRange,
|
||||||
FujiDynamicRange, FujiDynamicRangePriority, FujiFilmSimulation, FujiGrainEffect, FujiHighISONR,
|
FujiDynamicRangePriority, FujiFilmSimulation, FujiGrainEffect, FujiHighISONR,
|
||||||
FujiHighlightTone, FujiImageQuality, FujiImageSize, FujiShadowTone, FujiSharpness,
|
FujiHighlightTone, FujiImageQuality, FujiImageSize, FujiShadowTone, FujiSharpness,
|
||||||
FujiWhiteBalance, FujiWhiteBalanceShift, FujiWhiteBalanceTemperature,
|
FujiSmoothSkinEffect, FujiWhiteBalance, FujiWhiteBalanceShift, FujiWhiteBalanceTemperature,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Args, Debug)]
|
#[derive(Args, Debug)]
|
||||||
pub struct FilmSimulationOptions {
|
pub struct FilmSimulationOptions {
|
||||||
/// The name of the slot
|
|
||||||
#[clap(long)]
|
|
||||||
pub name: Option<FujiCustomSettingName>,
|
|
||||||
|
|
||||||
/// The Fujifilm film simulation to use
|
/// The Fujifilm film simulation to use
|
||||||
#[clap(long)]
|
#[clap(long)]
|
||||||
pub simulation: Option<FujiFilmSimulation>,
|
pub simulation: Option<FujiFilmSimulation>,
|
||||||
@@ -84,4 +80,8 @@ pub struct FilmSimulationOptions {
|
|||||||
/// Color Chrome FX Blue
|
/// Color Chrome FX Blue
|
||||||
#[clap(long)]
|
#[clap(long)]
|
||||||
pub color_chrome_fx_blue: Option<FujiColorChromeFXBlue>,
|
pub color_chrome_fx_blue: Option<FujiColorChromeFXBlue>,
|
||||||
|
|
||||||
|
/// Smooth Skin Effect
|
||||||
|
#[clap(long)]
|
||||||
|
pub smooth_skin_effect: Option<FujiSmoothSkinEffect>,
|
||||||
}
|
}
|
||||||
|
@@ -5,8 +5,8 @@ use crate::{
|
|||||||
FujiClarity, FujiColor, FujiColorChromeEffect, FujiColorChromeFXBlue, FujiCustomSetting,
|
FujiClarity, FujiColor, FujiColorChromeEffect, FujiColorChromeFXBlue, FujiCustomSetting,
|
||||||
FujiCustomSettingName, FujiDynamicRange, FujiDynamicRangePriority, FujiFilmSimulation,
|
FujiCustomSettingName, FujiDynamicRange, FujiDynamicRangePriority, FujiFilmSimulation,
|
||||||
FujiGrainEffect, FujiHighISONR, FujiHighlightTone, FujiImageQuality, FujiImageSize,
|
FujiGrainEffect, FujiHighISONR, FujiHighlightTone, FujiImageQuality, FujiImageSize,
|
||||||
FujiShadowTone, FujiSharpness, FujiWhiteBalance, FujiWhiteBalanceShift,
|
FujiShadowTone, FujiSharpness, FujiSmoothSkinEffect, FujiWhiteBalance,
|
||||||
FujiWhiteBalanceTemperature,
|
FujiWhiteBalanceShift, FujiWhiteBalanceTemperature,
|
||||||
},
|
},
|
||||||
usb,
|
usb,
|
||||||
};
|
};
|
||||||
@@ -39,6 +39,10 @@ pub enum SimulationCmd {
|
|||||||
/// Simulation slot number
|
/// Simulation slot number
|
||||||
slot: FujiCustomSetting,
|
slot: FujiCustomSetting,
|
||||||
|
|
||||||
|
/// The name of the slot
|
||||||
|
#[clap(long)]
|
||||||
|
name: Option<FujiCustomSettingName>,
|
||||||
|
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
film_simulation_options: FilmSimulationOptions,
|
film_simulation_options: FilmSimulationOptions,
|
||||||
},
|
},
|
||||||
@@ -116,6 +120,7 @@ pub struct FilmSimulationRepr {
|
|||||||
pub grain: FujiGrainEffect,
|
pub grain: FujiGrainEffect,
|
||||||
pub color_chrome_effect: FujiColorChromeEffect,
|
pub color_chrome_effect: FujiColorChromeEffect,
|
||||||
pub color_chrome_fx_blue: FujiColorChromeFXBlue,
|
pub color_chrome_fx_blue: FujiColorChromeFXBlue,
|
||||||
|
pub smooth_skin_effect: FujiSmoothSkinEffect,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for FilmSimulationRepr {
|
impl fmt::Display for FilmSimulationRepr {
|
||||||
@@ -145,7 +150,8 @@ impl fmt::Display for FilmSimulationRepr {
|
|||||||
writeln!(f, "Noise Reduction: {}", self.noise_reduction)?;
|
writeln!(f, "Noise Reduction: {}", self.noise_reduction)?;
|
||||||
writeln!(f, "Grain: {}", self.grain)?;
|
writeln!(f, "Grain: {}", self.grain)?;
|
||||||
writeln!(f, "Color Chrome Effect: {}", self.color_chrome_effect)?;
|
writeln!(f, "Color Chrome Effect: {}", self.color_chrome_effect)?;
|
||||||
writeln!(f, "Color Chrome FX Blue: {}", self.color_chrome_fx_blue)
|
writeln!(f, "Color Chrome FX Blue: {}", self.color_chrome_fx_blue)?;
|
||||||
|
writeln!(f, "Smooth Skin Effect: {}", self.smooth_skin_effect)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,6 +179,7 @@ fn handle_get(json: bool, device_id: Option<&str>, slot: FujiCustomSetting) -> a
|
|||||||
grain: camera.get_grain_effect()?,
|
grain: camera.get_grain_effect()?,
|
||||||
color_chrome_effect: camera.get_color_chrome_effect()?,
|
color_chrome_effect: camera.get_color_chrome_effect()?,
|
||||||
color_chrome_fx_blue: camera.get_color_chrome_fx_blue()?,
|
color_chrome_fx_blue: camera.get_color_chrome_fx_blue()?,
|
||||||
|
smooth_skin_effect: camera.get_smooth_skin_effect()?,
|
||||||
};
|
};
|
||||||
|
|
||||||
if json {
|
if json {
|
||||||
@@ -187,13 +194,14 @@ fn handle_get(json: bool, device_id: Option<&str>, slot: FujiCustomSetting) -> a
|
|||||||
fn handle_set(
|
fn handle_set(
|
||||||
device_id: Option<&str>,
|
device_id: Option<&str>,
|
||||||
slot: FujiCustomSetting,
|
slot: FujiCustomSetting,
|
||||||
options: &FilmSimulationOptions,
|
name: Option<FujiCustomSettingName>,
|
||||||
|
options: FilmSimulationOptions,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let mut camera = usb::get_camera(device_id)?;
|
let mut camera = usb::get_camera(device_id)?;
|
||||||
camera.set_active_custom_setting(slot)?;
|
camera.set_active_custom_setting(slot)?;
|
||||||
|
|
||||||
// General
|
// General
|
||||||
if let Some(name) = &options.name {
|
if let Some(name) = &name {
|
||||||
camera.set_custom_setting_name(name)?;
|
camera.set_custom_setting_name(name)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,6 +246,10 @@ fn handle_set(
|
|||||||
camera.set_color_chrome_fx_blue(*color_chrome_fx_blue)?;
|
camera.set_color_chrome_fx_blue(*color_chrome_fx_blue)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(smooth_skin_effect) = &options.smooth_skin_effect {
|
||||||
|
camera.set_smooth_skin_effect(*smooth_skin_effect)?;
|
||||||
|
}
|
||||||
|
|
||||||
// White Balance
|
// White Balance
|
||||||
if let Some(white_balance) = &options.white_balance {
|
if let Some(white_balance) = &options.white_balance {
|
||||||
camera.set_white_balance(*white_balance)?;
|
camera.set_white_balance(*white_balance)?;
|
||||||
@@ -328,8 +340,9 @@ pub fn handle(cmd: SimulationCmd, json: bool, device_id: Option<&str>) -> anyhow
|
|||||||
SimulationCmd::Get { slot } => handle_get(json, device_id, slot),
|
SimulationCmd::Get { slot } => handle_get(json, device_id, slot),
|
||||||
SimulationCmd::Set {
|
SimulationCmd::Set {
|
||||||
slot,
|
slot,
|
||||||
|
name,
|
||||||
film_simulation_options,
|
film_simulation_options,
|
||||||
} => handle_set(device_id, slot, &film_simulation_options),
|
} => handle_set(device_id, slot, name, film_simulation_options),
|
||||||
SimulationCmd::Export { slot, output_file } => handle_export(device_id, slot, &output_file),
|
SimulationCmd::Export { slot, output_file } => handle_export(device_id, slot, &output_file),
|
||||||
SimulationCmd::Import { slot, input_file } => handle_import(device_id, slot, &input_file),
|
SimulationCmd::Import { slot, input_file } => handle_import(device_id, slot, &input_file),
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user