use crate::pixel_format::{ColorSpace, PixelFormat};
use bytemuck::Pod;
use lcms2::{InfoType, Intent, Locale, Transform as LcmsTransform};
pub use lcms2::Error as CmsError;
pub(crate) struct Profile(lcms2::Profile);
impl Profile {
pub(crate) fn new_icc(data: &[u8]) -> Result<Profile, CmsError> {
lcms2::Profile::new_icc(data).map(Profile)
}
pub(crate) fn new_srgb() -> Profile {
Profile(lcms2::Profile::new_srgb())
}
pub(crate) fn color_space(&self) -> ColorSpace {
match self.0.color_space() {
lcms2::ColorSpaceSignature::RgbData => ColorSpace::Rgb,
lcms2::ColorSpaceSignature::GrayData => ColorSpace::Gray,
lcms2::ColorSpaceSignature::CmykData => ColorSpace::Cmyk,
_ => ColorSpace::Other,
}
}
pub(crate) fn description(&self) -> Option<String> {
self.0.info(InfoType::Description, Locale::new("en_US"))
}
}
pub(crate) struct Transform<In: Pod, Out: Pod> {
inner: LcmsTransform<In, Out>,
}
fn to_lcms_format(format: PixelFormat) -> lcms2::PixelFormat {
use lcms2::PixelFormat as P;
match format {
PixelFormat::RGB8 => P::RGB_8,
PixelFormat::RGBA8 => P::RGBA_8,
PixelFormat::GRAY8 => P::GRAY_8,
PixelFormat::GRAYA8 => P::GRAYA_8,
PixelFormat::RGB16 => P::RGB_16,
PixelFormat::RGBA16 => P::RGBA_16,
PixelFormat::GRAY16 => P::GRAY_16,
PixelFormat::GRAYA16 => P::GRAYA_16,
#[cfg(any(feature = "jpeg", feature = "mozjpeg"))]
PixelFormat::CMYK8 => P::CMYK_8,
}
}
impl<In: Pod, Out: Pod> Transform<In, Out> {
pub(crate) fn new(src: &Profile, src_format: PixelFormat, dst: &Profile, dst_format: PixelFormat) -> Result<Self, CmsError> {
let inner = LcmsTransform::new(
&src.0,
to_lcms_format(src_format),
&dst.0,
to_lcms_format(dst_format),
Intent::RelativeColorimetric,
)?;
Ok(Self { inner })
}
pub(crate) fn transform_pixels(&self, src: &[In], dst: &mut [Out]) -> Result<(), CmsError> {
self.inner.transform_pixels(src, dst);
Ok(())
}
}