type Result = core::result::Result; fn shape_error() -> ndarray::ShapeError { ndarray::ShapeError::from_kind(ndarray::ErrorKind::IncompatibleShape) } mod rgb8 { use super::Result; pub(super) fn image_as_ndarray(image: &image::RgbImage) -> Result> { let (width, height) = image.dimensions(); let data = image.as_raw(); ndarray::ArrayView3::from_shape((height as usize, width as usize, 3), data) } pub(super) fn image_into_ndarray(image: image::RgbImage) -> Result> { let (width, height) = image.dimensions(); let data = image.into_raw(); ndarray::Array3::from_shape_vec((height as usize, width as usize, 3), data) } pub(super) fn ndarray_to_image(array: &ndarray::ArrayView3) -> Result { let (height, width, channels) = array.dim(); let data = array.as_slice().ok_or_else(super::shape_error)?; if channels != 3 { return Err(super::shape_error()); } Ok( image::RgbImage::from_raw(width as u32, height as u32, data.to_vec()).ok_or( ndarray::ShapeError::from_kind(ndarray::ErrorKind::IncompatibleShape), )?, ) } } mod rgba8 { use super::Result; pub(super) fn image_as_ndarray( image: &image::RgbaImage, ) -> Result> { let (width, height) = image.dimensions(); let data = image.as_raw(); ndarray::ArrayView3::from_shape((height as usize, width as usize, 4), data) } pub(super) fn image_into_ndarray(image: image::RgbaImage) -> Result> { let (width, height) = image.dimensions(); let data = image.into_raw(); ndarray::Array3::from_shape_vec((height as usize, width as usize, 4), data) } pub(super) fn ndarray_to_image(array: &ndarray::ArrayView3) -> Result { let (height, width, channels) = array.dim(); let data = array.as_slice().ok_or_else(super::shape_error)?; if channels != 4 { return Err(super::shape_error()); } Ok( image::RgbaImage::from_raw(width as u32, height as u32, data.to_vec()).ok_or( ndarray::ShapeError::from_kind(ndarray::ErrorKind::IncompatibleShape), )?, ) } } mod gray8 { use super::Result; pub(super) fn image_as_ndarray( image: &image::GrayImage, ) -> Result> { let (width, height) = image.dimensions(); let data = image.as_raw(); ndarray::ArrayView2::from_shape((height as usize, width as usize), data) } pub(super) fn image_into_ndarray(image: image::GrayImage) -> Result> { let (width, height) = image.dimensions(); let data = image.into_raw(); ndarray::Array2::from_shape_vec((height as usize, width as usize), data) } pub(super) fn ndarray_to_image(array: &ndarray::ArrayView2) -> Result { let (height, width) = array.dim(); let data = array.as_slice().ok_or_else(super::shape_error)?; Ok( image::GrayImage::from_raw(width as u32, height as u32, data.to_vec()).ok_or( ndarray::ShapeError::from_kind(ndarray::ErrorKind::IncompatibleShape), )?, ) } } mod gray_alpha8 { use super::Result; pub(super) fn image_as_ndarray( image: &image::GrayAlphaImage, ) -> Result> { let (width, height) = image.dimensions(); let data = image.as_raw(); ndarray::ArrayView3::from_shape((height as usize, width as usize, 2), data) } pub(super) fn image_into_ndarray(image: image::GrayAlphaImage) -> Result> { let (width, height) = image.dimensions(); let data = image.into_raw(); ndarray::Array3::from_shape_vec((height as usize, width as usize, 2), data) } pub(super) fn ndarray_to_image( array: &ndarray::ArrayView3, ) -> Result { let (height, width, channels) = array.dim(); let data = array.as_slice().ok_or_else(super::shape_error)?; if channels != 2 { return Err(super::shape_error()); } Ok( image::GrayAlphaImage::from_raw(width as u32, height as u32, data.to_vec()).ok_or( ndarray::ShapeError::from_kind(ndarray::ErrorKind::IncompatibleShape), )?, ) } } mod dynamic_image { use super::*; pub fn image_as_ndarray(image: &image::DynamicImage) -> Result> { Ok(match image { image::DynamicImage::ImageRgb8(img) => rgb8::image_as_ndarray(img)?.into_dyn(), image::DynamicImage::ImageRgba8(img) => rgba8::image_as_ndarray(img)?.into_dyn(), image::DynamicImage::ImageLuma8(img) => gray8::image_as_ndarray(img)?.into_dyn(), image::DynamicImage::ImageLumaA8(img) => gray_alpha8::image_as_ndarray(img)?.into_dyn(), _ => { unimplemented!("Unsupported image format: {:?}", image); } }) } pub fn image_into_ndarray(image: image::DynamicImage) -> Result> { Ok(match image { image::DynamicImage::ImageRgb8(img) => rgb8::image_into_ndarray(img)?.into_dyn(), image::DynamicImage::ImageRgba8(img) => rgba8::image_into_ndarray(img)?.into_dyn(), image::DynamicImage::ImageLuma8(img) => gray8::image_into_ndarray(img)?.into_dyn(), image::DynamicImage::ImageLumaA8(img) => { gray_alpha8::image_into_ndarray(img)?.into_dyn() } _ => { unimplemented!("Unsupported image format: {:?}", image); } }) } } pub trait ImageToNdarray { type OwnedOutput; type RefOutput<'a> where Self: 'a; fn as_ndarray<'a>(&'a self) -> Result>; fn to_ndarray(&self) -> Result; fn into_ndarray(self) -> Result; } pub trait NdarrayToImage { fn to_image(&self) -> Result; } impl NdarrayToImage for ndarray::ArrayView3<'_, u8> { fn to_image(&self) -> Result { rgb8::ndarray_to_image(self) } } impl NdarrayToImage for ndarray::ArrayView3<'_, u8> { fn to_image(&self) -> Result { rgba8::ndarray_to_image(self) } } impl NdarrayToImage for ndarray::ArrayView2<'_, u8> { fn to_image(&self) -> Result { gray8::ndarray_to_image(self) } } impl NdarrayToImage for ndarray::ArrayView3<'_, u8> { fn to_image(&self) -> Result { gray_alpha8::ndarray_to_image(self) } } impl ImageToNdarray for image::RgbImage { type OwnedOutput = ndarray::Array3; type RefOutput<'a> = ndarray::ArrayView3<'a, u8>; fn as_ndarray<'a>(&'a self) -> Result> { rgb8::image_as_ndarray(self) } fn to_ndarray(&self) -> Result { Ok(self.as_ndarray()?.to_owned()) } fn into_ndarray(self) -> Result { rgb8::image_into_ndarray(self) } } impl ImageToNdarray for image::RgbaImage { type OwnedOutput = ndarray::Array3; type RefOutput<'a> = ndarray::ArrayView3<'a, u8>; fn as_ndarray<'a>(&'a self) -> Result> { rgba8::image_as_ndarray(self) } fn to_ndarray(&self) -> Result { Ok(self.as_ndarray()?.to_owned()) } fn into_ndarray(self) -> Result { rgba8::image_into_ndarray(self) } } impl ImageToNdarray for image::GrayImage { type OwnedOutput = ndarray::Array2; type RefOutput<'a> = ndarray::ArrayView2<'a, u8>; fn as_ndarray<'a>(&'a self) -> Result> { gray8::image_as_ndarray(self) } fn to_ndarray(&self) -> Result { Ok(self.as_ndarray()?.to_owned()) } fn into_ndarray(self) -> Result { gray8::image_into_ndarray(self) } } impl ImageToNdarray for image::GrayAlphaImage { type OwnedOutput = ndarray::Array3; type RefOutput<'a> = ndarray::ArrayView3<'a, u8>; fn as_ndarray<'a>(&'a self) -> Result> { gray_alpha8::image_as_ndarray(self) } fn to_ndarray(&self) -> Result { Ok(self.as_ndarray()?.to_owned()) } fn into_ndarray(self) -> Result { gray_alpha8::image_into_ndarray(self) } } impl ImageToNdarray for image::DynamicImage { type OwnedOutput = ndarray::ArrayD; type RefOutput<'a> = ndarray::ArrayViewD<'a, u8>; fn as_ndarray<'a>(&'a self) -> Result> { dynamic_image::image_as_ndarray(self) } fn to_ndarray(&self) -> Result { Ok(self.as_ndarray()?.to_owned()) } fn into_ndarray(self) -> Result { dynamic_image::image_into_ndarray(self) } }