### Implement a CMS backend Source: https://docs.rs/zenpixels-convert/latest/src/zenpixels_convert/cms.rs.html?search= Example implementation of the ColorManagement trait for a custom CMS backend. ```rust struct MyLcms2; impl ColorManagement for MyLcms2 { type Error = lcms2::Error; fn build_transform( &self, src_icc: &[u8], dst_icc: &[u8], ) -> Result, Self::Error> { let src = lcms2::Profile::new_icc(src_icc)?; let dst = lcms2::Profile::new_icc(dst_icc)?; let xform = lcms2::Transform::new(&src, &dst, ...)?; Ok(Box::new(Lcms2RowTransform(xform))) } fn identify_profile(&self, icc: &[u8]) -> Option { // Fast: check MD5 hash against known profiles // Slow: parse TRC+matrix, compare within tolerance None } } ``` -------------------------------- ### Define at macro crate info Source: https://docs.rs/zenpixels-convert/latest/zenpixels_convert/macro.at.html Required setup in lib.rs to enable repository links for error tracing. ```rust whereat::define_at_crate_info!(); ``` -------------------------------- ### HDR Quantization Setup Source: https://docs.rs/zenpixels-convert/latest/src/zenpixels_convert/hdr.rs.html?search= Internal utility to validate pixel formats and transfer functions before PQ quantization. ```rust fn quantize_setup( px: &PixelSlice<'_>, target: PixelDescriptor, ) -> Result<(PixelDescriptor, DiffuseWhite, u32, u32), At> { let diffuse_white = px .color_context() .and_then(|c| c.diffuse_white) .unwrap_or(DiffuseWhite::BT2408); let desc = px.descriptor(); let src = match desc.pixel_format() { PixelFormat::RgbF32 => PixelDescriptor::RGBF32_LINEAR, PixelFormat::RgbaF32 => PixelDescriptor::RGBAF32_LINEAR, _ => return Err(whereat::at!(ConvertError::NoMatch { source: desc })), } .with_primaries(target.primaries); if desc.transfer != TransferFunction::Linear { return Err(whereat::at!(ConvertError::UnsupportedTransfer { from: desc.transfer, to: TransferFunction::Linear, })); } // The pipeline anchors PQ at 1.0 = 10000 cd/m²; only PQ targets are handled. if target.transfer != TransferFunction::Pq { return Err(whereat::at!(ConvertError::NoPath { from: desc, to: target, })); } let w = px.width(); let h = px.rows(); if w == 0 || h == 0 { return Err(whereat::at!(ConvertError::InvalidWidth(w))); } Ok((src, diffuse_white, w, h)) } ``` -------------------------------- ### HDR HLG U16 to Linear F32 Setup Source: https://docs.rs/zenpixels-convert/latest/src/zenpixels_convert/converter.rs.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Initializes descriptors for HLG U16 to linear F32 conversion. ```rust #[test] fn hlg_u16_to_linear_f32_roundtrip() { let hlg_u16 = PixelDescriptor::new( ChannelType::U16, ChannelLayout::Rgb, None, TransferFunction::Hlg, ); let lin_f32 = PixelDescriptor::new( ChannelType::F32, ChannelLayout::Rgb, None, TransferFunction::Linear, ); let src16: [u16; 3] = [0, 32768, 65535]; ``` -------------------------------- ### Alpha Premultiplication Test Source: https://docs.rs/zenpixels-convert/latest/src/zenpixels_convert/converter.rs.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Initial setup for testing straight to premultiplied alpha conversion. ```rust #[test] fn straight_to_premul_u8() { let straight = PixelDescriptor::RGBA8_SRGB; ``` -------------------------------- ### Using ResultAtExt for Location Tracking Source: https://docs.rs/zenpixels-convert/latest/zenpixels_convert/trait.ResultAtExt.html Example demonstrating how to use the at() method to propagate errors with location information. ```rust use whereat::{at, At, ResultAtExt}; #[derive(Debug)] enum MyError { Oops } fn inner() -> Result<(), At> { Err(at(MyError::Oops)) } fn outer() -> Result<(), At> { inner().at()?; Ok(()) } ``` -------------------------------- ### at!(err) Source: https://docs.rs/zenpixels-convert/latest/zenpixels_convert/macro.at.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Traces an error with crate metadata. Requires prior setup via define_at_crate_info!() or a custom at_crate_info() function. ```APIDOC ## at!(err) ### Description Traces an error with crate metadata for repository links. This macro requires the crate to be configured with `define_at_crate_info!()`. ### Usage ```rust use whereat::{at, At}; fn find_user(id: u64) -> Result> { if id == 0 { return Err(at!(MyError::NotFound)); } Ok(format!("User {}", id)) } ``` ``` -------------------------------- ### Reduce Pixel Formats to Load-Bearing Source: https://docs.rs/zenpixels-convert/latest/src/zenpixels_convert/load_bearing.rs.html?search= Examples demonstrating the reduction of various pixel formats (RGBA, GrayA, RGB) to their minimal load-bearing representation while preserving metadata like color primaries. ```rust #[test] fn linear_f32_wide_primaries_reduce_keeps_tag_and_values() { // P3-tagged linear f32 gray+opaque: reduces structurally // (alpha drop + chroma collapse) with values untouched and the // P3 tag carried over -- no primaries re-tag, no matrix. let pixels: [f32; 16] = [ 0.5, 0.5, 0.5, 1.0, 0.25, 0.25, 0.25, 1.0, 0.75, 0.75, 0.75, 1.0, 0.1, 0.1, 0.1, 1.0, ]; let bytes: &[u8] = bytemuck::cast_slice(&pixels); let descriptor = PixelDescriptor::from_pixel_format(PixelFormat::RgbaF32) .with_transfer(TransferFunction::Linear) .with_primaries(ColorPrimaries::DisplayP3); let slice = PixelSlice::new(bytes, 4, 1, 4 * 16, descriptor).unwrap(); let out = slice .try_reduce_to_load_bearing_format() .expect("should reduce"); assert_eq!(out.descriptor().format, PixelFormat::GrayF32); assert_eq!(out.descriptor().primaries, ColorPrimaries::DisplayP3); let view = out.as_slice(); let gray: &[f32] = bytemuck::cast_slice(view.row(0)); assert_eq!(gray, &[0.5_f32, 0.25, 0.75, 0.1], "values bit-exact"); } ``` ```rust #[test] fn ga_f32_opaque_reduces_to_gray_f32() { let pixels: [f32; 6] = [0.1, 1.0, 0.5, 1.0, 0.9, 1.0]; let bytes: &[u8] = bytemuck::cast_slice(&pixels); let slice = make_f32_slice(bytes, 3, 1, PixelFormat::GrayAF32, TransferFunction::Linear); assert_eq!(reduced(&slice).format, PixelFormat::GrayF32); } ``` ```rust #[test] fn rgb_f32_grayscale_reduces_to_gray_f32() { let pixels: [f32; 9] = [0.1, 0.1, 0.1, 0.5, 0.5, 0.5, 0.9, 0.9, 0.9]; let bytes: &[u8] = bytemuck::cast_slice(&pixels); let slice = make_f32_slice(bytes, 3, 1, PixelFormat::RgbF32, TransferFunction::Linear); assert_eq!(reduced(&slice).format, PixelFormat::GrayF32); } ``` -------------------------------- ### Measure Content Light Levels Source: https://docs.rs/zenpixels/latest/src/zenpixels/hdr.rs.html?search=std%3A%3Avec Examples demonstrating how to calculate MaxCLL and MaxFALL from various pixel buffer configurations, including handling of padding, stride, and non-linear data. ```rust fn rgbf32(pixels: &[[f32; 3]], w: u32, h: u32) -> PixelBuffer { let mut data = Vec::with_capacity(pixels.len() * 12); for p in pixels { for c in p { data.extend_from_slice(&c.to_ne_bytes()); } } PixelBuffer::from_vec(data, w, h, PixelDescriptor::RGBF32_LINEAR).unwrap() } ``` ```rust #[test] fn diffuse_white_defaults_to_bt2408() { assert_eq!(DiffuseWhite::default(), DiffuseWhite::BT2408); assert_eq!(DiffuseWhite::BT2408.nits(), 203.0); assert_eq!(DiffuseWhite::new(100.0).nits(), 100.0); } ``` ```rust #[test] fn measure_two_grays_cta_stills_semantics() { // [1.0, 2.0] @ 203: MaxCLL = 2·203 = 406; MaxFALL = avg(203, 406) = 304.5 → 305. let buf = rgbf32(&[[1.0; 3], [2.0; 3]], 2, 1); let cll = ContentLightLevel::measure(buf.as_slice(), DiffuseWhite::BT2408).unwrap(); assert_eq!(cll.max_content_light_level, 406); assert_eq!(cll.max_frame_average_light_level, 305); } ``` ```rust #[test] fn measure_handles_stride_and_ignores_padding() { use crate::PixelSlice; // 2×2 RGB f32: 6 real f32/row, padded to 9 f32/row (36-byte stride, a // multiple of the 12-byte pixel). The padding holds a 1e9 sentinel — if // a row cast ever ran past `width*bpp`, MaxCLL would explode to ~2e11. let (w, h, row_floats) = (2u32, 2u32, 9usize); let mut data = alloc::vec![1.0e9f32; row_floats * h as usize]; let pixels = [[0.5f32; 3], [1.0; 3], [2.0; 3], [0.25; 3]]; for (i, p) in pixels.iter().enumerate() { let base = (i / w as usize) * row_floats + (i % w as usize) * 3; data[base..base + 3].copy_from_slice(p); } // `Vec` is f32-aligned, so the byte view satisfies the slice's // alignment contract; stride 40 is a multiple of the f32 size. let bytes: &[u8] = bytemuck::cast_slice(&data); let px = PixelSlice::new(bytes, w, h, row_floats * 4, PixelDescriptor::RGBF32_LINEAR).unwrap(); let cll = ContentLightLevel::measure(px, DiffuseWhite::BT2408).unwrap(); // Peak max(R,G,B) = 2.0 → 406; FALL = avg(0.5,1,2,0.25)·203 = 190.3 → 190. assert_eq!(cll.max_content_light_level, 406); assert_eq!(cll.max_frame_average_light_level, 190); } ``` ```rust #[test] fn measure_clamps_nan_and_negative() { let buf = rgbf32(&[[-1.0, f32::NAN, 0.5]], 1, 1); let cll = ContentLightLevel::measure(buf.as_slice(), DiffuseWhite::BT2408).unwrap(); // max(R,G,B) folds from 0.0 → 0.5 · 203 = 101.5 → 102. assert_eq!(cll.max_content_light_level, 102); assert_eq!(cll.max_frame_average_light_level, 102); } ``` ```rust #[test] fn measure_ignores_alpha_and_custom_white() { let mut data = Vec::new(); for c in [0.5f32, 0.5, 0.5, 7.0] { data.extend_from_slice(&c.to_ne_bytes()); } let buf = PixelBuffer::from_vec(data, 1, 1, PixelDescriptor::RGBAF32_LINEAR).unwrap(); // alpha 7.0 ignored; custom 100-nit white: 0.5 · 100 = 50. let cll = ContentLightLevel::measure(buf.as_slice(), DiffuseWhite::new(100.0)).unwrap(); assert_eq!(cll.max_content_light_level, 50); } ``` ```rust #[test] fn measure_rejects_non_linear_and_non_f32() { let u8buf = PixelBuffer::from_vec(alloc::vec![0u8; 3], 1, 1, PixelDescriptor::RGB8_SRGB).unwrap(); assert!(ContentLightLevel::measure(u8buf.as_slice(), DiffuseWhite::BT2408).is_none()); let nonlinear = PixelDescriptor::RGBF32_LINEAR.with_transfer(TransferFunction::Srgb); let mut data = Vec::new(); for c in [0.5f32; 3] { data.extend_from_slice(&c.to_ne_bytes()); } ``` -------------------------------- ### Convert PixelBuffer Formats Source: https://docs.rs/zenpixels-convert/latest/src/zenpixels_convert/ext.rs.html?search= Examples of converting between various pixel formats like RGB8, RGBA8, Gray8, and BGRA8. ```rust #[test] #[cfg(feature = "rgb")] fn to_rgb8() { // Start with RGBA8 buffer, convert to typed RGB8 let data = vec![100u8, 150, 200, 255, 50, 100, 150, 255]; let buf = PixelBuffer::from_vec(data, 2, 1, PixelDescriptor::RGBA8_SRGB).unwrap(); let typed: PixelBuffer> = buf.to_rgb8(); assert_eq!(typed.width(), 2); assert_eq!(typed.height(), 1); let slice = typed.as_slice(); let row = slice.row(0); // Alpha should be dropped: 3 bytes per pixel assert_eq!(row[0], 100); assert_eq!(row[1], 150); assert_eq!(row[2], 200); assert_eq!(row[3], 50); assert_eq!(row[4], 100); assert_eq!(row[5], 150); } ``` ```rust #[test] #[cfg(feature = "rgb")] fn to_rgba8() { let data = vec![100u8, 150, 200, 50, 100, 150]; let buf = PixelBuffer::from_vec(data, 2, 1, PixelDescriptor::RGB8_SRGB).unwrap(); let typed: PixelBuffer> = buf.to_rgba8(); assert_eq!(typed.width(), 2); assert_eq!(typed.height(), 1); let slice = typed.as_slice(); let row = slice.row(0); // RGB -> RGBA with alpha=255 assert_eq!(row[0], 100); assert_eq!(row[1], 150); assert_eq!(row[2], 200); assert_eq!(row[3], 255); assert_eq!(row[4], 50); assert_eq!(row[5], 100); assert_eq!(row[6], 150); assert_eq!(row[7], 255); } ``` ```rust #[test] #[cfg(feature = "rgb")] fn to_gray8() { let data = vec![100u8, 150, 200, 50, 100, 150]; let buf = PixelBuffer::from_vec(data, 2, 1, PixelDescriptor::RGB8_SRGB).unwrap(); let typed: PixelBuffer> = buf.to_gray8(); assert_eq!(typed.width(), 2); assert_eq!(typed.height(), 1); let slice = typed.as_slice(); let row = slice.row(0); // Gray values should be luminance-weighted, not zero assert!(row[0] > 0, "gray pixel 0 should be non-zero"); assert!(row[1] > 0, "gray pixel 1 should be non-zero"); } ``` ```rust #[test] #[cfg(feature = "rgb")] fn to_bgra8() { let data = vec![100u8, 150, 200, 50, 100, 150]; let buf = PixelBuffer::from_vec(data, 2, 1, PixelDescriptor::RGB8_SRGB).unwrap(); let typed: PixelBuffer> = buf.to_bgra8(); assert_eq!(typed.width(), 2); assert_eq!(typed.height(), 1); let slice = typed.as_slice(); let row = slice.row(0); // BGRA layout: B, G, R, A // Pixel 0: R=100, G=150, B=200 -> BGRA = 200, 150, 100, 255 assert_eq!(row[0], 200); ``` -------------------------------- ### Get pixel descriptor Source: https://docs.rs/zenpixels/latest/src/zenpixels/descriptor.rs.html?search= Retrieves the base pixel descriptor for the format. ```rust /// Base descriptor with `Unknown` transfer and BT.709 primaries. #[allow(unreachable_patterns)] #[inline] pub const fn descriptor(self) -> PixelDescriptor { match self { Self::Rgb8 => PixelDescriptor::RGB8, Self::Rgba8 => PixelDescriptor::RGBA8, ``` -------------------------------- ### Initialize MasteringDisplay Source: https://docs.rs/zenpixels/latest/src/zenpixels/hdr.rs.html?search= Shows how to create a MasteringDisplay instance with specific color primaries and luminance values. ```rust #[test] fn mastering_display_new() { let md = MasteringDisplay::new( [[0.68, 0.32], [0.265, 0.69], [0.15, 0.06]], [0.3127, 0.329], 1000.0, 0.001, ); assert_eq!(md.max_luminance, 1000.0); assert_eq!(md.min_luminance, 0.001); } ``` -------------------------------- ### Test ColorContext Initialization and Profile Source Source: https://docs.rs/zenpixels/latest/src/zenpixels/color.rs.html Demonstrates creating ColorContext from various sources and extracting the profile source. ```rust #[test] fn color_context_from_icc() { let ctx = ColorContext::from_icc(vec![10, 20, 30]); assert!(ctx.icc.is_some()); assert_eq!(ctx.icc.as_deref(), Some(&[10u8, 20, 30][..])); assert!(ctx.cicp.is_none()); } #[test] #[allow(deprecated)] fn color_context_from_icc_and_cicp() { let ctx = ColorContext::from_icc_and_cicp(vec![1, 2], Cicp::BT2100_PQ); assert!(ctx.icc.is_some()); assert_eq!(ctx.cicp, Some(Cicp::BT2100_PQ)); } #[test] fn color_context_profile_source_icc_only() { let ctx = ColorContext::from_icc(vec![42]); let src = ctx.as_profile_source().unwrap(); assert_eq!(src, ColorProfileSource::Icc(&[42])); } #[test] fn color_context_profile_source_none() { let ctx = ColorContext { icc: None, cicp: None, diffuse_white: None, }; assert!(ctx.as_profile_source().is_none()); } ``` -------------------------------- ### Get Pixel Descriptor Source: https://docs.rs/zenpixels/latest/src/zenpixels/descriptor.rs.html Retrieves the base pixel descriptor for the format. ```rust /// Base descriptor with `Unknown` transfer and BT.709 primaries. #[allow(unreachable_patterns)] #[inline] pub const fn descriptor(self) -> PixelDescriptor { match self { Self::Rgb8 => PixelDescriptor::RGB8, ``` -------------------------------- ### Get human-readable name Source: https://docs.rs/zenpixels/latest/src/zenpixels/descriptor.rs.html?search= Returns a short string representation of the pixel format. ```rust /// Short human-readable name. #[allow(unreachable_patterns)] #[inline] pub const fn name(self) -> &'static str { match self { Self::Rgb8 => "RGB8", Self::Rgba8 => "RGBA8", Self::Rgb16 => "RGB16", Self::Rgba16 => "RGBA16", Self::RgbF32 => "RgbF32", Self::RgbaF32 => "RgbaF32", Self::Gray8 => "Gray8", Self::Gray16 => "Gray16", Self::GrayF32 => "GrayF32", Self::GrayA8 => "GrayA8", Self::GrayA16 => "GrayA16", Self::GrayAF32 => "GrayAF32", Self::Bgra8 => "BGRA8", Self::Rgbx8 => "RGBX8", Self::Bgrx8 => "BGRX8", Self::OklabF32 => "OklabF32", Self::OklabaF32 => "OklabaF32", Self::Cmyk8 => "CMYK8", Self::RgbF16 => "RgbF16", Self::RgbaF16 => "RgbaF16", Self::GrayF16 => "GrayF16", Self::GrayAF16 => "GrayAF16", _ => "Unknown", } } ``` -------------------------------- ### Construct a Conversion Plan Source: https://docs.rs/zenpixels-convert/latest/src/zenpixels_convert/convert.rs.html Initializes a conversion plan with default PQ scaling parameters. ```rust fn build(from: PixelDescriptor, to: PixelDescriptor, steps: Vec) -> Self { Self { from, to, steps, pq_anchor_scale: 1.0, } } ``` -------------------------------- ### Instantiate and Verify MasteringDisplay Source: https://docs.rs/zenpixels/latest/src/zenpixels/hdr.rs.html?search=std%3A%3Avec Shows how to create a MasteringDisplay instance with specific color primaries and luminance values, and how to access reference constants. ```rust #[test] fn mastering_display_new() { let md = MasteringDisplay::new( [[0.68, 0.32], [0.265, 0.69], [0.15, 0.06]], [0.3127, 0.329], 1000.0, 0.001, ); assert_eq!(md.max_luminance, 1000.0); assert_eq!(md.min_luminance, 0.001); } ``` ```rust #[test] fn mastering_display_constants() { assert_eq!(MasteringDisplay::HDR10_REFERENCE.max_luminance, 10000.0); assert_eq!(MasteringDisplay::DISPLAY_P3_1000.max_luminance, 1000.0); } ``` -------------------------------- ### Create a traced error Source: https://docs.rs/zenpixels-convert/latest/zenpixels_convert/struct.At.html Example of creating a traced error using the at() function. ```rust use whereat::{at, At}; #[derive(Debug)] enum MyError { Oops } // Create a traced error using at() function let err: At = at(MyError::Oops); assert_eq!(err.frame_count(), 1); ``` -------------------------------- ### Implement Pixel for Rgbx Source: https://docs.rs/zenpixels-convert/latest/zenpixels_convert/buffer/trait.Pixel.html Example implementation of the Pixel trait for the Rgbx type. ```rust impl Pixel for Rgbx { const DESCRIPTOR: PixelDescriptor = PixelDescriptor::RGBX8 } ``` -------------------------------- ### Construct ConvertOptions instances Source: https://docs.rs/zenpixels-convert/latest/zenpixels_convert/policy/struct.ConvertOptions.html?search= Demonstrates creating ConvertOptions using strict, permissive, or custom builder patterns. ```rust use zenpixels::{ConvertOptions, AlphaPolicy, DepthPolicy}; // Forbid all lossy operations (safe default) let strict = ConvertOptions::forbid_lossy(); // Allow common lossy operations with sensible defaults let permissive = ConvertOptions::permissive(); // Customize from a preset let custom = ConvertOptions::permissive() .with_alpha_policy(AlphaPolicy::CompositeOnto { r: 255, g: 255, b: 255 }) .with_depth_policy(DepthPolicy::Truncate); ``` -------------------------------- ### Implement Pixel for Bgrx Source: https://docs.rs/zenpixels-convert/latest/zenpixels_convert/buffer/trait.Pixel.html Example implementation of the Pixel trait for the Bgrx type. ```rust impl Pixel for Bgrx { const DESCRIPTOR: PixelDescriptor = PixelDescriptor::BGRX8 } ``` -------------------------------- ### Conversion Plan Construction Source: https://docs.rs/zenpixels-convert/latest/src/zenpixels_convert/convert.rs.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Initializes a conversion plan with default PQ scaling parameters. ```rust fn build(from: PixelDescriptor, to: PixelDescriptor, steps: Vec) -> Self { Self { from, to, steps, pq_anchor_scale: 1.0, } } ``` -------------------------------- ### Verify Gamut Clamping with ZenCmsLite Source: https://docs.rs/zenpixels-convert/latest/src/zenpixels_convert/cms_lite.rs.html?search= Demonstrates setting up a source-to-destination color transform and verifying that output values remain non-negative. ```rust let cms = ZenCmsLite; let src = ColorProfileSource::Named(NamedProfile::DisplayP3); let dst = ColorProfileSource::Named(NamedProfile::Srgb); let transform = cms .build_source_transform(src, dst, PixelFormat::RgbF32, PixelFormat::RgbF32) .unwrap() .unwrap(); let src_px: [f32; 3] = [0.0, 1.0, 0.0]; let mut dst_px = [0.0f32; 3]; transform.transform_row( bytemuck::cast_slice(&src_px), bytemuck::cast_slice_mut(&mut dst_px), 1, ); assert!( dst_px[0] >= 0.0, "clamped path should not produce negatives: {}", dst_px[0] ); ``` -------------------------------- ### Manage Load-Bearing Report State Source: https://docs.rs/zenpixels-convert/latest/src/zenpixels_convert/load_bearing.rs.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Examples for checking the analysis state of a LoadBearingReport. ```rust #[test] fn default_report_is_fully_unanalyzed() { // With per-field Option semantics, the default report is // "nothing was checked" — every field is None. apply_to on a // None-only report is identity (no Some(false) signals). let r = LoadBearingReport::default(); assert_eq!(r.uses_alpha, None); assert_eq!(r.uses_chroma, None); assert_eq!(r.uses_low_bits, None); assert!(!r.any_analyzed()); } ``` ```rust #[test] fn any_analyzed_fires_when_at_least_one_field_set() { let mut r = LoadBearingReport::default(); assert!(!r.any_analyzed()); r.uses_alpha = Some(true); assert!(r.any_analyzed(), "any_analyzed fires for any Some"); r.uses_alpha = None; r.uses_low_bits = Some(false); assert!(r.any_analyzed(), "any_analyzed fires on low-bits too"); } ``` -------------------------------- ### Get channel selection map Source: https://docs.rs/zenpixels-convert/latest/src/zenpixels_convert/load_bearing.rs.html?search=u32+-%3E+bool Retrieves the channel selection map for layout transitions. ```rust fn selection_map(src_layout: ChannelLayout, dst_layout: ChannelLayout) -> Option<&'static [usize]> { static IDENTITY: [usize; 4] = [0, 1, 2, 3]; Some(match (src_layout, dst_layout) { ``` -------------------------------- ### MasteringDisplay Instantiation and Constants Source: https://docs.rs/zenpixels/latest/src/zenpixels/hdr.rs.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Shows how to create a MasteringDisplay and access predefined HDR constants. ```rust let md = MasteringDisplay::new( [[0.68, 0.32], [0.265, 0.69], [0.15, 0.06]], [0.3127, 0.329], 1000.0, 0.001, ); assert_eq!(md.max_luminance, 1000.0); assert_eq!(md.min_luminance, 0.001); ``` ```rust assert_eq!(MasteringDisplay::HDR10_REFERENCE.max_luminance, 10000.0); assert_eq!(MasteringDisplay::DISPLAY_P3_1000.max_luminance, 1000.0); ``` -------------------------------- ### Handle Dimension Mismatch in from_pixels_erased Source: https://docs.rs/zenpixels/latest/src/zenpixels/buffer.rs.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Example of a test case for dimension mismatch in from_pixels_erased. ```rust let pixels: Vec> = vec![Rgb { r: 1, g: 2, b: 3 }]; ``` -------------------------------- ### Instantiate and Verify ContentLightLevel Source: https://docs.rs/zenpixels/latest/src/zenpixels/hdr.rs.html?search=std%3A%3Avec Demonstrates creating a new ContentLightLevel instance and verifying its default state. ```rust #[test] fn content_light_level_new() { let cll = ContentLightLevel::new(1000, 500); assert_eq!(cll.max_content_light_level, 1000); assert_eq!(cll.max_frame_average_light_level, 500); } ``` ```rust #[test] fn content_light_level_default() { let cll = ContentLightLevel::default(); assert_eq!(cll.max_content_light_level, 0); assert_eq!(cll.max_frame_average_light_level, 0); } ``` -------------------------------- ### Implement ConvertOptions Methods Source: https://docs.rs/zenpixels/latest/src/zenpixels/policy.rs.html?search= Methods for creating default configurations and modifying conversion policies. ```rust impl ConvertOptions { /// Forbid all lossy operations. /// /// - Alpha removal: forbidden (returns error) /// - Depth reduction: forbidden (returns error) /// - RGB→Gray: forbidden (returns error) /// - Gray→RGB: broadcast (lossless) /// /// Use this as a starting point when you want to ensure no data loss, /// then selectively relax with `with_*` methods. pub const fn forbid_lossy() -> Self { Self { gray_expand: GrayExpand::Broadcast, alpha_policy: AlphaPolicy::Forbid, depth_policy: DepthPolicy::Forbid, luma: None, clip_out_of_gamut: true, } } /// Allow common lossy operations with sensible defaults. /// /// - Alpha removal: discard only if all pixels are opaque /// - Depth reduction: round to nearest /// - RGB→Gray: BT.709 luma coefficients /// - Gray→RGB: broadcast (lossless) pub const fn permissive() -> Self { Self { gray_expand: GrayExpand::Broadcast, alpha_policy: AlphaPolicy::DiscardIfOpaque, depth_policy: DepthPolicy::Round, luma: Some(LumaCoefficients::Bt709), clip_out_of_gamut: true, } } /// Set the alpha removal policy. pub const fn with_alpha_policy(mut self, policy: AlphaPolicy) -> Self { self.alpha_policy = policy; self } /// Set the depth reduction policy. pub const fn with_depth_policy(mut self, policy: DepthPolicy) -> Self { self.depth_policy = policy; self } /// Set the grayscale expansion method. pub const fn with_gray_expand(mut self, expand: GrayExpand) -> Self { self.gray_expand = expand; self } /// Set whether f32 transfer conversions clamp to [0, 1] (`true`, default) /// or preserve extended-range values via sign-preserving transfers /// (`false`). u8/u16 outputs always clip. pub const fn with_clip_out_of_gamut(mut self, clip: bool) -> Self { self.clip_out_of_gamut = clip; self } /// Set the luma coefficients for RGB→Gray conversion. /// /// Pass `None` to forbid RGB→Gray conversion. pub const fn with_luma(mut self, luma: Option) -> Self { self.luma = luma; self } } ``` -------------------------------- ### ConvertPlan Creation Methods Source: https://docs.rs/zenpixels-convert/latest/zenpixels_convert/struct.ConvertPlan.html?search= Methods to initialize a conversion plan, optionally with explicit policy enforcement. ```rust pub fn new( from: PixelDescriptor, to: PixelDescriptor, ) -> Result> ``` ```rust pub fn new_explicit( from: PixelDescriptor, to: PixelDescriptor, options: &ConvertOptions, ) -> Result> ``` -------------------------------- ### Get nominal channel bits Source: https://docs.rs/zenpixels-convert/latest/src/zenpixels_convert/negotiate.rs.html?search=std%3A%3Avec Returns the nominal precision bits for a given channel type. ```rust /// Nominal precision bits for a channel type (for ordering, not bit-exact). /// /// F16 has 10 mantissa bits (~3.3 decimal digits) — between U8 (8 bits) and /// U16 (16 bits). #[allow(unreachable_patterns)] // non_exhaustive: future variants pub(crate) fn channel_bits(ct: ChannelType) -> u16 { match ct { ChannelType::U8 => 8, ChannelType::F16 => 11, // 10 mantissa + 1 implicit ChannelType::U16 => 16, ChannelType::F32 => 32, _ => 0, } } ``` -------------------------------- ### Matte Composite Entry Point Source: https://docs.rs/zenpixels-convert/latest/src/zenpixels_convert/convert_kernels.rs.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E High-level function to composite RGBA onto a solid matte color. ```rust fn matte_composite( src: &[u8], dst: &mut [u8], width: usize, from: PixelDescriptor, mr: u8, mg: u8, mb: u8, ) { let ch_type = from.channel_type(); let tf = from.transfer(); ``` -------------------------------- ### Public API Entry Point Source: https://docs.rs/zenpixels-convert/latest/src/zenpixels_convert/fast_gamut.rs.html?search= Public wrapper for the SIMD matrix-lookup table conversion process. ```rust pub(crate) fn convert_u16_rgb_simd_matlut( m: &[[f32; 3]; 3], src: &[u16], dst: &mut [u16], lin_lut: &[f32; 65536], enc_lut: &[u16; 65536], ) { debug_assert_eq!(src.len() % 3, 0); debug_assert_eq!(src.len(), dst.len()); ``` -------------------------------- ### Check PixelBuffer properties Source: https://docs.rs/zenpixels/latest/src/zenpixels/buffer.rs.html?search=std%3A%3Avec Examples for checking alpha channel presence and grayscale status of a PixelBuffer. ```rust #[test] fn pixel_buffer_has_alpha_rgba8() { let buf = PixelBuffer::new(2, 2, PixelDescriptor::RGBA8_SRGB); assert!(buf.has_alpha()); } #[test] fn pixel_buffer_has_alpha_rgb8_false() { let buf = PixelBuffer::new(2, 2, PixelDescriptor::RGB8_SRGB); assert!(!buf.has_alpha()); } #[test] fn pixel_buffer_is_grayscale_gray8() { let buf = PixelBuffer::new(2, 2, PixelDescriptor::GRAY8_SRGB); assert!(buf.is_grayscale()); } #[test] fn pixel_buffer_is_grayscale_rgb8_false() { let buf = PixelBuffer::new(2, 2, PixelDescriptor::RGB8_SRGB); assert!(!buf.is_grayscale()); } ``` -------------------------------- ### Reduce Pixel Formats Source: https://docs.rs/zenpixels-convert/latest/src/zenpixels_convert/load_bearing.rs.html Examples of reducing high-precision formats to lower-precision ones when data allows. ```rust #[test] fn rgba16_bit_replicated_reduces_to_rgba8() { let bytes: Vec = (0..4) .flat_map(|i| { let r = (i * 60) as u8; let g = (i * 30 + 10) as u8; let b = (i * 80 + 5) as u8; let a = 0xFF; [r, r, g, g, b, b, a, a] }) .collect(); let slice = make_slice(&bytes, 4, 1, PixelFormat::Rgba16); let r = slice.determine_load_bearing(); // analyzed bool removed assert_eq!(r.uses_low_bits, Some(false)); assert_eq!(r.uses_alpha, Some(false)); let target = r.apply_to(&slice.descriptor()); assert_eq!(target.format, PixelFormat::Rgb8); } ``` ```rust #[test] fn rgba16_actual_high_precision_keeps_u16() { let bytes: Vec = (0..4) .flat_map(|i| { let r_lo = (i * 17 + 1) as u8; let r_hi = (i * 60) as u8; [r_hi, r_lo, 0, 0, 0, 0, 0xFF, 0xFF] }) .collect(); let slice = make_slice(&bytes, 4, 1, PixelFormat::Rgba16); let r = slice.determine_load_bearing(); assert_eq!(r.uses_low_bits, Some(true)); } ``` -------------------------------- ### Negotiate Pixel Format Source: https://docs.rs/zenpixels-convert/latest/src/zenpixels_convert/negotiate.rs.html?search=u32+-%3E+bool Use this entry point to negotiate a target pixel format given source descriptors, provenance, and consumer cost overrides. ```rust let provenance = Provenance::with_origin_depth(ChannelType::U8); let target = negotiate( current_f32_desc, provenance, encoder_options.iter().copied(), ConvertIntent::Fastest, ); ``` ```rust pub fn negotiate( source: PixelDescriptor, provenance: Provenance, options: impl Iterator, intent: ConvertIntent, ) -> Option { best_of( source, provenance, options.map(|o| (o.descriptor, o.consumer_cost)), intent, ) } ``` -------------------------------- ### Demonstrate incorrect metadata handling Source: https://docs.rs/zenpixels-convert/latest/src/zenpixels_convert/output.rs.html An example of a common bug where pixel data and metadata diverge. ```rust // BUG: pixels and metadata can diverge let pixels = convert_to_p3(&buffer); let metadata = OutputMetadata { icc: Some(srgb_icc), .. }; // ^^^ pixels are Display P3 but metadata says sRGB — wrong! ``` -------------------------------- ### sub_rows_mut Source: https://docs.rs/zenpixels/latest/src/zenpixels/buffer.rs.html?search= Borrows a mutable sub-range of rows starting at `y` with a specified `count`. Panics if the range is out of bounds. ```APIDOC pub fn sub_rows_mut(&mut self, y: u32, count: u32) -> PixelSliceMut<'_, P> ``` -------------------------------- ### PixelDescriptor constructors Source: https://docs.rs/zenpixels/latest/src/zenpixels/descriptor.rs.html Examples of creating PixelDescriptor instances using full parameters or from existing pixel formats. ```rust #[test] fn new_full_constructor() { let desc = PixelDescriptor::new_full( ChannelType::U8, ChannelLayout::Rgb, None, TransferFunction::Srgb, ColorPrimaries::DisplayP3, ); assert_eq!(desc.primaries, ColorPrimaries::DisplayP3); assert_eq!(desc.transfer(), TransferFunction::Srgb); } #[test] fn from_pixel_format_constructor() { let desc = PixelDescriptor::from_pixel_format(PixelFormat::Rgba8); assert_eq!(desc.layout(), ChannelLayout::Rgba); assert_eq!(desc.transfer(), TransferFunction::Unknown); assert_eq!(desc.primaries, ColorPrimaries::Bt709); } ``` -------------------------------- ### Create a new ConvertPlan Source: https://docs.rs/zenpixels-convert/latest/zenpixels_convert/struct.ConvertPlan.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Initializes a conversion plan between two pixel descriptors. Panics if CMYK color models are used. ```rust pub fn new( from: PixelDescriptor, to: PixelDescriptor, ) -> Result> ``` -------------------------------- ### Testing ColorProfileSource Source: https://docs.rs/zenpixels/latest/src/zenpixels/color.rs.html?search=u32+-%3E+bool Examples for creating and verifying ColorProfileSource variants including Named, CICP, and ICC profiles. ```rust #[test] fn color_profile_source_named() { let src = ColorProfileSource::Named(NamedProfile::DisplayP3); assert_eq!(src, ColorProfileSource::Named(NamedProfile::DisplayP3)); assert_ne!(src, ColorProfileSource::Named(NamedProfile::Srgb)); } ``` ```rust #[test] fn color_profile_source_cicp() { let src = ColorProfileSource::Cicp(Cicp::BT2100_PQ); assert_eq!(src, ColorProfileSource::Cicp(Cicp::BT2100_PQ)); } ``` ```rust #[test] fn color_profile_source_icc() { let data: &[u8] = &[1, 2, 3]; let src = ColorProfileSource::Icc(data); assert_eq!(src, ColorProfileSource::Icc(&[1, 2, 3])); } ``` ```rust #[test] fn color_profile_source_debug_clone() { let src = ColorProfileSource::Named(NamedProfile::Srgb); let s = alloc::format!("{src:?}"); assert!(s.contains("Named")); let src2 = src.clone(); assert_eq!(src, src2); } ``` -------------------------------- ### Convert Buffer with Anchor Source: https://docs.rs/zenpixels-convert/latest/src/zenpixels_convert/adapt.rs.html?search= Demonstrates converting linear pixel data to PQ-encoded format using an anchor point for brightness scaling. ```rust // already PQ-absolute (the prior behavior). 1.0 linear → PQ code 65535. let (lin, target) = pq16_target(); let out = convert_buffer_with_anchor( &gray_rgb_f32(&[1.0]), 1, 1, packed_stride(1, lin), lin, target, DiffuseWhite::new(10_000.0), ) .unwrap(); let ob = out.as_slice().as_strided_bytes(); assert_eq!(u16::from_ne_bytes([ob[0], ob[1]]), 65535); } ``` -------------------------------- ### Decode and Metadata Extraction Source: https://docs.rs/zenpixels-convert/latest/src/zenpixels_convert/lib.rs.html?search=Option%3CT%3E%2C+%28T+-%3E+U%29+-%3E+Option%3CU%3E Example of decoding raw pixels into a PixelBuffer and constructing color context metadata. ```rust // Decode raw pixels let pixels: Vec = my_codec_decode(&file_bytes)?; let desc = PixelDescriptor::RGB8_SRGB; let buffer = PixelBuffer::from_vec(pixels, width, height, desc)?; // Extract color metadata for CMS integration let color_ctx = match (icc_chunk, cicp_chunk) { (Some(icc), Some(cicp)) => Some(Arc::new(ColorContext::from_icc_and_cicp(icc, cicp))), (Some(icc), None) => Some(Arc::new(ColorContext::from_icc(icc))), (None, Some(cicp)) => Some(Arc::new(ColorContext::from_cicp(cicp))), (None, None) => None, }; // Track provenance for re-encoding decisions let origin = ColorOrigin::from_icc_and_cicp(icc, cicp); // or: ColorOrigin::from_icc(icc) // or: ColorOrigin::from_cicp(cicp) // or: ColorOrigin::from_gama_chrm() // PNG gAMA+cHRM ``` -------------------------------- ### Perform Color Transformation with ZenCmsLite Source: https://docs.rs/zenpixels-convert/latest/src/zenpixels_convert/cms_lite.rs.html?search=std%3A%3Avec Demonstrates building a source-to-destination color transform and applying it to a pixel buffer. ```rust let cms = ZenCmsLite; let src = ColorProfileSource::Named(NamedProfile::DisplayP3); let dst = ColorProfileSource::Named(NamedProfile::Srgb); let transform = cms .build_source_transform(src, dst, PixelFormat::RgbF32, PixelFormat::RgbF32) .unwrap() .unwrap(); let src_px: [f32; 3] = [0.0, 1.0, 0.0]; let mut dst_px = [0.0f32; 3]; transform.transform_row( bytemuck::cast_slice(&src_px), bytemuck::cast_slice_mut(&mut dst_px), 1, ); ``` -------------------------------- ### macro_rules! at Source: https://docs.rs/zenpixels/latest/zenpixels/macro.at.html The at macro is used to wrap an error with crate metadata, requiring prior setup of crate information. ```APIDOC ## macro_rules! at ### Description Wraps an error with crate metadata for repository links. Requires `define_at_crate_info!()` or a custom `at_crate_info()` function to be defined in the crate. ### Usage ```rust use whereat::{at, At}; fn find_user(id: u64) -> Result> { if id == 0 { return Err(at!(MyError::NotFound)); } Ok(format!("User {}", id)) } ``` ``` -------------------------------- ### MasteringDisplay Constants and Constructor Source: https://docs.rs/zenpixels-convert/latest/zenpixels_convert/hdr/struct.MasteringDisplay.html?search= Predefined reference displays and a constructor for creating new MasteringDisplay instances. ```rust pub const HDR10_REFERENCE: MasteringDisplay ``` ```rust pub const DISPLAY_P3_1000: MasteringDisplay ``` ```rust pub const fn new( primaries_xy: [[f32; 2]; 3], white_point_xy: [f32; 2], max_luminance: f32, min_luminance: f32, ) -> MasteringDisplay ``` -------------------------------- ### Test ColorContext Initialization Source: https://docs.rs/zenpixels/latest/src/zenpixels/color.rs.html?search=std%3A%3Avec Demonstrates creating ColorContext from ICC data and combined ICC/CICP sources. ```rust #[test] fn color_context_from_icc() { let ctx = ColorContext::from_icc(vec![10, 20, 30]); assert!(ctx.icc.is_some()); assert_eq!(ctx.icc.as_deref(), Some(&[10u8, 20, 30][..])); assert!(ctx.cicp.is_none()); } ``` ```rust #[test] #[allow(deprecated)] fn color_context_from_icc_and_cicp() { let ctx = ColorContext::from_icc_and_cicp(vec![1, 2], Cicp::BT2100_PQ); assert!(ctx.icc.is_some()); assert_eq!(ctx.cicp, Some(Cicp::BT2100_PQ)); } ``` -------------------------------- ### Pixel Trait Implementations Source: https://docs.rs/zenpixels/latest/zenpixels/buffer/trait.Pixel.html?search=std%3A%3Avec Examples of implementing the Pixel trait for specific pixel formats like Bgrx and Rgbx. ```rust impl Pixel for Bgrx { const DESCRIPTOR: PixelDescriptor = PixelDescriptor::BGRX8 } ``` ```rust impl Pixel for Rgbx { const DESCRIPTOR: PixelDescriptor = PixelDescriptor::RGBX8 } ```