load_image 3.5.0-beta.1

Load PNG or JPEG with color profile support
Documentation
use rgb::{Gray, GrayAlpha, Rgb, Rgba};

use rgb::bytemuck::Pod;
use rgb::bytemuck::Zeroable;

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub(crate) enum PixelFormat {
    RGB8,
    RGBA8,
    GRAY8,
    GRAYA8,
    RGB16,
    RGBA16,
    GRAY16,
    GRAYA16,
    #[cfg(any(feature = "jpeg", feature = "mozjpeg"))]
    CMYK8,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub(crate) enum ColorSpace {
    Rgb,
    Gray,
    Cmyk,
    Other,
}

#[repr(C)]
#[derive(Copy, Clone, Debug)]
#[cfg_attr(not(any(feature = "jpeg", feature = "mozjpeg")), allow(dead_code))]
pub struct CMYK {
    pub c: u8,
    pub m: u8,
    pub y: u8,
    pub k: u8,
}

unsafe impl Pod for CMYK {}
unsafe impl Zeroable for CMYK {}

pub(crate) trait HasPixelFormat where Self: Copy + Pod {
    fn pixel_format() -> (PixelFormat, ColorSpace);
}

pub(crate) trait PixelConversion where Self: Copy {
    type Converted: Copy + Pod;
    type ConvertedOpaque: Copy + Pod;
}

macro_rules! pixel_conversion {
    ( $in_type:ty => $out_type:ty, $out_type_opaque:ty ) => {
        impl PixelConversion for $in_type {
            type Converted = $out_type;
            type ConvertedOpaque = $out_type_opaque;
        }
    };
}

macro_rules! pixel_format {
    ( $in_type:ty, $format:expr, $colorspace:expr ) => {
        impl HasPixelFormat for $in_type {
            fn pixel_format() -> (PixelFormat, ColorSpace) {
                ($format, $colorspace)
            }
        }
    };
}

#[cfg(any(feature = "jpeg", feature = "mozjpeg"))]
pixel_format! {CMYK, PixelFormat::CMYK8, ColorSpace::Cmyk }
#[cfg(any(feature = "jpeg", feature = "mozjpeg"))]
pixel_conversion! {CMYK => Rgb<u16>, Rgb<u16>}

pixel_format! {Rgb<u8>, PixelFormat::RGB8, ColorSpace::Rgb }
pixel_format! {Rgba<u8>, PixelFormat::RGBA8, ColorSpace::Rgb }
pixel_format! {Gray<u8>, PixelFormat::GRAY8, ColorSpace::Gray }
pixel_format! {GrayAlpha<u8>, PixelFormat::GRAYA8, ColorSpace::Gray }
pixel_format! {Rgb<u16>, PixelFormat::RGB16, ColorSpace::Rgb }
pixel_format! {Rgba<u16>, PixelFormat::RGBA16, ColorSpace::Rgb }
pixel_format! {Gray<u16>, PixelFormat::GRAY16, ColorSpace::Gray }
pixel_format! {GrayAlpha<u16>, PixelFormat::GRAYA16, ColorSpace::Gray }

pixel_conversion! {Rgb<u8> => Rgb<u16>, Rgb<u16>}
pixel_conversion! {Rgba<u8> => Rgba<u16>, Rgb<u16>}
pixel_conversion! {Gray<u8> => Gray<u16>, Gray<u16>}
pixel_conversion! {GrayAlpha<u8> => GrayAlpha<u16>, Gray<u16>}
pixel_conversion! {Rgb<u16> => Rgb<u16>, Rgb<u16>}
pixel_conversion! {Rgba<u16> => Rgba<u16>, Rgb<u16>}
pixel_conversion! {Gray<u16> => Gray<u16>, Gray<u16>}
pixel_conversion! {GrayAlpha<u16> => GrayAlpha<u16>, Gray<u16>}