refimage 0.13.1

Imaging library. Provides basic image processing and encoders/decoders for common image formats.
Documentation
//! Image interop
use image::ImageBuffer;

use crate::{
    ColorSpace, DynamicImage, DynamicImageRef, GenericImage, GenericImageOwned, GenericImageRef,
    ImageProps,
};

#[cfg_attr(docsrs, doc(cfg(feature = "image")))]
impl<'a> TryFrom<DynamicImageRef<'a>> for DynamicImage {
    type Error = &'static str;

    fn try_from(value: DynamicImageRef<'a>) -> Result<Self, Self::Error> {
        use DynamicImageRef::*;
        let width = value.width() as u32;
        let height = value.height() as u32;
        let cspace = value.color_space();
        let channels = value.channels();
        if channels > 4 {
            return Err("Too many channels");
        }
        match cspace {
            ColorSpace::Gray => match value {
                U8(data) => Ok(DynamicImage::ImageLuma8(
                    ImageBuffer::from_vec(width, height, data.into_vec())
                        .ok_or("Could not create Gray8 image")?,
                )),
                U16(data) => Ok(DynamicImage::ImageLuma16(
                    ImageBuffer::from_vec(width, height, data.into_vec())
                        .ok_or("Could not create Gray16 image")?,
                )),
                F32(_) => Err("Gray32F not supported"),
            },
            ColorSpace::Rgb => match value {
                U8(data) => Ok(DynamicImage::ImageRgb8(
                    ImageBuffer::from_vec(width, height, data.into_vec())
                        .ok_or("Could not create Rgb8 image")?,
                )),
                U16(data) => Ok(DynamicImage::ImageRgb16(
                    ImageBuffer::from_vec(width, height, data.into_vec())
                        .ok_or("Could not create Rgb16 image")?,
                )),
                F32(data) => Ok(DynamicImage::ImageRgb32F(
                    ImageBuffer::from_vec(width, height, data.into_vec())
                        .ok_or("Could not create Rgb32F image")?,
                )),
            },
            _ => Err("Unsupported color space"),
        }
    }
}

use crate::{DynamicImageOwned, ImageOwned};

#[cfg_attr(docsrs, doc(cfg(feature = "image")))]
impl TryFrom<DynamicImage> for DynamicImageOwned {
    type Error = &'static str;

    fn try_from(data: DynamicImage) -> Result<Self, Self::Error> {
        let wid = data.width() as u16;
        let hei = data.height() as u16;
        match data {
            DynamicImage::ImageLuma8(data) => Ok(DynamicImageOwned::U8(
                ImageOwned::new(data.into_raw(), wid.into(), hei.into(), ColorSpace::Gray)
                    .map_err(|_| "Could not create DynamicImageOwned from ImageLuma8")?,
            )),
            DynamicImage::ImageRgb8(data) => Ok(DynamicImageOwned::U8(
                ImageOwned::new(data.into_raw(), wid.into(), hei.into(), ColorSpace::Rgb)
                    .map_err(|_| "Could not create DynamicImageOwned from ImageRgb8")?,
            )),
            DynamicImage::ImageLuma16(data) => Ok(DynamicImageOwned::U16(
                ImageOwned::new(data.into_raw(), wid.into(), hei.into(), ColorSpace::Gray)
                    .map_err(|_| "Could not create DynamicImageOwned from ImageLuma16")?,
            )),
            DynamicImage::ImageRgb16(data) => Ok(DynamicImageOwned::U16(
                ImageOwned::new(data.into_raw(), wid.into(), hei.into(), ColorSpace::Rgb)
                    .map_err(|_| "Could not create DynamicImageOwned from ImageRgb16")?,
            )),
            DynamicImage::ImageRgb32F(data) => Ok(DynamicImageOwned::F32(
                ImageOwned::new(data.into_raw(), wid.into(), hei.into(), ColorSpace::Rgb)
                    .map_err(|_| "Could not create DynamicImageOwned from ImageRgb32F")?,
            )),
            _ => Err("Unknown image type"),
        }
    }
}

#[cfg_attr(docsrs, doc(cfg(feature = "image")))]
impl TryFrom<DynamicImageOwned> for DynamicImage {
    type Error = &'static str;

    fn try_from(value: DynamicImageOwned) -> Result<Self, Self::Error> {
        use DynamicImageOwned::*;
        let width = value.width() as u32;
        let height = value.height() as u32;
        let cspace = value.color_space();
        let channels = value.channels();
        if channels > 4 {
            return Err("Too many channels");
        }
        match cspace {
            ColorSpace::Gray => match value {
                U8(data) => Ok(DynamicImage::ImageLuma8(
                    ImageBuffer::from_vec(width, height, data.into_vec())
                        .ok_or("Could not create Gray8 image")?,
                )),
                U16(data) => Ok(DynamicImage::ImageLuma16(
                    ImageBuffer::from_vec(width, height, data.into_vec())
                        .ok_or("Could not create Gray16 image")?,
                )),
                F32(_) => Err("Gray32F not supported"),
            },
            ColorSpace::Rgb => match value {
                U8(data) => Ok(DynamicImage::ImageRgb8(
                    ImageBuffer::from_vec(width, height, data.into_vec())
                        .ok_or("Could not create Rgb8 image")?,
                )),
                U16(data) => Ok(DynamicImage::ImageRgb16(
                    ImageBuffer::from_vec(width, height, data.into_vec())
                        .ok_or("Could not create Rgb16 image")?,
                )),
                F32(data) => Ok(DynamicImage::ImageRgb32F(
                    ImageBuffer::from_vec(width, height, data.into_vec())
                        .ok_or("Could not create Rgb32F image")?,
                )),
            },
            _ => Err("Unsupported color space"),
        }
    }
}

impl TryFrom<GenericImageOwned> for DynamicImage {
    type Error = &'static str;

    fn try_from(value: GenericImageOwned) -> Result<Self, Self::Error> {
        value.image.try_into()
    }
}

impl TryFrom<GenericImageRef<'_>> for DynamicImage {
    type Error = &'static str;

    fn try_from(value: GenericImageRef<'_>) -> Result<Self, Self::Error> {
        value.image.try_into()
    }
}

impl TryFrom<GenericImage<'_>> for DynamicImage {
    type Error = &'static str;

    fn try_from(value: GenericImage<'_>) -> Result<Self, Self::Error> {
        match value {
            GenericImage::Own(data) => data.try_into(),
            GenericImage::Ref(data) => data.try_into(),
        }
    }
}

mod test {

    #[test]
    fn test_dynamicimagedata() {
        use super::DynamicImageRef;
        use crate::{ColorSpace, ImageRef};
        use image::DynamicImage;
        let mut data: Vec<u8> = vec![1, 2, 3, 4, 5, 6];
        let a =
            ImageRef::new(&mut data, 3, 2, ColorSpace::Gray).expect("Failed to create ImageRef");
        let b = DynamicImageRef::from(a);
        let c = DynamicImage::try_from(b).unwrap();
        assert_eq!(c.width(), 3);
    }

    #[test]
    fn test_dynamicimageowned() {
        use super::DynamicImageOwned;
        use crate::ImageProps;
        use crate::{ColorSpace, ImageOwned};
        use image::DynamicImage;
        let data: Vec<u8> = vec![1, 2, 3, 4, 5, 6];
        let a = ImageOwned::new(data, 3, 2, ColorSpace::Gray).expect("Failed to create ImageRef");
        let b = DynamicImageOwned::from(a.clone());
        let c = DynamicImage::try_from(b).unwrap();
        let c_ = c.resize(128, 128, image::imageops::FilterType::Nearest);
        let _d: DynamicImageOwned = c_
            .try_into()
            .expect("Failed to convert DynamicImage to DynamicImageOwned");
        assert_eq!(_d.width(), 128);
    }
}