fn main() {
use fovea::image::{Image, ImageView};
use fovea::pixel::{Mono8, Mono16, Rgb8, RgbF32, Srgb8};
use fovea::transform::{ConvertPixel, FullRange, Luminance, SrgbGamma, convert_image};
let img8 = Image::from_vec(
2,
2,
vec![
Mono8::new(0),
Mono8::new(128), Mono8::new(255),
Mono8::new(64), ],
)
.expect("pixel count matches 2×2");
let img16: Image<Mono16> = convert_image(&img8, FullRange);
println!("── FullRange: Mono8 → Mono16 ──");
println!(" Mono8(0) → Mono16({})", img16.pixel_at(0, 0).value()); println!(" Mono8(128) → Mono16({})", img16.pixel_at(1, 0).value()); println!(" Mono8(255) → Mono16({})", img16.pixel_at(0, 1).value()); println!(" Mono8(64) → Mono16({})", img16.pixel_at(1, 1).value());
let rgb_img = Image::from_vec(
2,
1,
vec![
Rgb8::new(255, 0, 0), Rgb8::new(0, 255, 0), ],
)
.expect("pixel count matches 2×1");
let gray: Image<Mono8> = convert_image(&rgb_img, Luminance);
println!("\n── Luminance: Rgb8 → Mono8 ──");
println!(" Red(255,0,0) → Mono8({})", gray.pixel_at(0, 0).value());
println!(" Green(0,255,0) → Mono8({})", gray.pixel_at(1, 0).value());
println!(" (Green is brighter because of the 0.587 coefficient)");
assert!(
gray.pixel_at(1, 0).value() > gray.pixel_at(0, 0).value(),
"green should be perceptually brighter than red"
);
let srgb_img = Image::from_vec(
1,
1,
vec![
Srgb8::new(128, 128, 128),
],
)
.expect("pixel count matches 1×1");
let linear: Image<RgbF32> = convert_image(&srgb_img, SrgbGamma);
let p = linear.pixel_at(0, 0);
println!("\n── SrgbGamma: Srgb8 → RgbF32 ──");
println!(
" Srgb8(128,128,128) → RgbF32({:.4}, {:.4}, {:.4})",
p.r, p.g, p.b
);
println!(" (Mid-gray sRGB ≈ 0.216 in linear light, NOT 0.502)");
println!(" (The transfer function is non-linear — that's the whole point)");
assert!(
p.r < 0.25,
"linear value of sRGB 128 should be well below 0.25"
);
assert!(p.r > 0.15, "linear value of sRGB 128 should be above 0.15");
println!("\n── Direct ConvertPixel::convert calls ──");
let mono_val = Mono8::new(200);
let wide: Mono16 = FullRange.convert(&mono_val);
println!(
" FullRange.convert(&Mono8(200)) = Mono16({})",
wide.value()
);
let red = Rgb8::new(128, 64, 32);
let luma: Mono8 = Luminance.convert(&red);
println!(
" Luminance.convert(&Rgb8(128,64,32)) = Mono8({})",
luma.value()
);
println!("\nDone! Strategy types make conversion intent explicit and type-safe.");
println!("Trying an unsupported pair (e.g. FullRange for Rgb8 → Mono8)");
println!("would be a compile-time error, not a runtime surprise.");
}