use crate::bit_writer::BitWriter;
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum ColorSpace {
Rgb = 0,
Gray = 1,
Xyb = 2,
Unknown = 3,
}
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum WhitePoint {
D65 = 1,
Custom = 2,
E = 10,
Dci = 11,
}
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Primaries {
Srgb = 1,
Custom = 2,
Bt2100 = 9,
P3 = 11,
}
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum TransferFunction {
Bt709 = 1,
Unknown = 2,
Linear = 8,
Srgb = 13,
Pq = 16,
Dci = 17,
Hlg = 18,
}
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Default)]
pub enum RenderingIntent {
Perceptual = 0,
#[default]
Relative = 1,
Saturation = 2,
Absolute = 3,
}
#[derive(Debug, Clone, Copy)]
pub struct ColorEncoding {
pub white_point: WhitePoint,
pub primaries: Primaries,
pub transfer: TransferFunction,
pub rendering_intent: RenderingIntent,
}
impl Default for ColorEncoding {
fn default() -> Self {
Self::srgb()
}
}
impl ColorEncoding {
pub const fn srgb_linear() -> Self {
Self {
white_point: WhitePoint::D65,
primaries: Primaries::Srgb,
transfer: TransferFunction::Linear,
rendering_intent: RenderingIntent::Relative,
}
}
pub const fn srgb() -> Self {
Self {
white_point: WhitePoint::D65,
primaries: Primaries::Srgb,
transfer: TransferFunction::Srgb,
rendering_intent: RenderingIntent::Relative,
}
}
pub const fn display_p3() -> Self {
Self {
white_point: WhitePoint::D65,
primaries: Primaries::P3,
transfer: TransferFunction::Srgb,
rendering_intent: RenderingIntent::Relative,
}
}
pub const fn bt2020_pq() -> Self {
Self {
white_point: WhitePoint::D65,
primaries: Primaries::Bt2100,
transfer: TransferFunction::Pq,
rendering_intent: RenderingIntent::Relative,
}
}
pub const fn bt2020_hlg() -> Self {
Self {
white_point: WhitePoint::D65,
primaries: Primaries::Bt2100,
transfer: TransferFunction::Hlg,
rendering_intent: RenderingIntent::Relative,
}
}
}
fn write_jxl_enum(value: u32, w: &mut BitWriter) {
if value == 0 {
w.write(2, 0);
} else if value == 1 {
w.write(2, 1);
} else if (2..18).contains(&value) {
w.write(2, 2);
w.write(4, (value - 2) as u64);
} else if (18..82).contains(&value) {
w.write(2, 3);
w.write(6, (value - 18) as u64);
} else {
unimplemented!("enum value {} out of JXL U32Coder range [0, 82)", value);
}
}
pub(crate) fn write_color_encoding_with_icc(
enc: &ColorEncoding,
want_icc: bool,
grayscale: bool,
w: &mut BitWriter,
) {
w.write(1, 0); w.write(1, if want_icc { 1 } else { 0 }); let color_space = if grayscale {
ColorSpace::Gray
} else {
ColorSpace::Rgb
};
w.write(2, color_space as u64); if want_icc {
let _ = enc;
return;
}
write_jxl_enum(enc.white_point as u32, w);
if !grayscale {
write_jxl_enum(enc.primaries as u32, w);
}
w.write(1, 0); write_jxl_enum(enc.transfer as u32, w);
write_jxl_enum(enc.rendering_intent as u32, w);
}