1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
use crate::ImageData;
use crate::ImageInfo;
use crate::PixelFormat;

impl ImageData for image::DynamicImage {
	fn data(self) -> Box<[u8]> {
		match self {
			image::DynamicImage::ImageLuma8(x)   => into_bytes(x),
			image::DynamicImage::ImageLumaA8(x)  => into_bytes(x),
			image::DynamicImage::ImageLuma16(_)  => panic!("unsupported pixel format: Luma16"),
			image::DynamicImage::ImageLumaA16(_) => panic!("unsupported pixel format: LumaA16"),
			image::DynamicImage::ImageRgb8(x)    => into_bytes(x),
			image::DynamicImage::ImageRgba8(x)   => into_bytes(x),
			image::DynamicImage::ImageRgb16(_)   => panic!("unsupported pixel format: Rgb16"),
			image::DynamicImage::ImageRgba16(_)  => panic!("unsupported pixel format: Rgba16"),
			image::DynamicImage::ImageBgr8(x)    => into_bytes(x),
			image::DynamicImage::ImageBgra8(x)   => into_bytes(x),
		}
	}

	fn info(&self) -> Result<ImageInfo, String> {
		match self {
			image::DynamicImage::ImageLuma8(x)   => info(x),
			image::DynamicImage::ImageLumaA8(x)  => info(x),
			image::DynamicImage::ImageLuma16(_)  => Err(String::from("unsupported pixel format: Luma16")),
			image::DynamicImage::ImageLumaA16(_) => Err(String::from("unsupported pixel format: LumaA16")),
			image::DynamicImage::ImageRgb8(x)    => info(x),
			image::DynamicImage::ImageRgba8(x)   => info(x),
			image::DynamicImage::ImageRgb16(_)   => Err(String::from("unsupported pixel format: Rgb16")),
			image::DynamicImage::ImageRgba16(_)  => Err(String::from("unsupported pixel format: Rgba16")),
			image::DynamicImage::ImageBgr8(x)    => info(x),
			image::DynamicImage::ImageBgra8(x)   => info(x),
		}
	}
}

impl ImageData for &'_ image::DynamicImage {
	fn data(self) -> Box<[u8]> {
		match self {
			image::DynamicImage::ImageLuma8(x)   => Box::from(as_bytes(x)),
			image::DynamicImage::ImageLumaA8(x)  => Box::from(as_bytes(x)),
			image::DynamicImage::ImageLuma16(_)  => panic!("unsupported pixel format: Luma16"),
			image::DynamicImage::ImageLumaA16(_) => panic!("unsupported pixel format: LumaA16"),
			image::DynamicImage::ImageRgb8(x)    => Box::from(as_bytes(x)),
			image::DynamicImage::ImageRgba8(x)   => Box::from(as_bytes(x)),
			image::DynamicImage::ImageRgb16(_)   => panic!("unsupported pixel format: Rgb16"),
			image::DynamicImage::ImageRgba16(_)  => panic!("unsupported pixel format: Rgba16"),
			image::DynamicImage::ImageBgr8(x)    => Box::from(as_bytes(x)),
			image::DynamicImage::ImageBgra8(x)   => Box::from(as_bytes(x)),
		}
	}

	fn info(&self) -> Result<ImageInfo, String> {
		(*self).info()
	}
}

impl<P> ImageData for image::ImageBuffer<P, Vec<u8>>
where
	P: image::Pixel<Subpixel = u8> + 'static,
{
	fn data(self) -> Box<[u8]> {
		self.into_raw().into_boxed_slice()
	}

	fn info(&self) -> Result<ImageInfo, String> {
		info(self)
	}
}

impl<P> ImageData for &'_ image::ImageBuffer<P, Vec<u8>>
where
	P: image::Pixel<Subpixel = u8> + 'static,
{
	fn data(self) -> Box<[u8]> {
		Box::from(as_bytes(self))
	}

	fn info(&self) -> Result<ImageInfo, String> {
		(*self).info()
	}
}

/// Consume an [`image::ImageBuffer`] and return the pixel data as boxed slice.
fn into_bytes<P: 'static + image::Pixel<Subpixel = u8>>(buffer: image::ImageBuffer<P, Vec<u8>>) -> Box<[u8]> {
	buffer.into_raw().into_boxed_slice()
}

/// Copy the pixel data of an [`image::ImageBuffer`] to a boxed slice.
fn as_bytes<P: 'static + image::Pixel<Subpixel = u8>>(buffer: &image::ImageBuffer<P, Vec<u8>>) -> &[u8] {
	&*buffer
}

/// Extract the [`ImageInfo`] from an [`image::ImageBuffer`].
fn info<P, C>(image: &image::ImageBuffer<P, C>) -> Result<ImageInfo, String>
where
	P: image::Pixel<Subpixel = u8> + 'static,
	C: std::ops::Deref<Target = [u8]>,
{
	Ok(ImageInfo {
		pixel_format: pixel_format::<P>()?,
		width: image.width() as usize,
		height: image.height() as usize,
		row_stride: image.sample_layout().height_stride,
	})
}

/// Extract the PixelFormat from an [`image::Pixel`].
fn pixel_format<P: image::Pixel>() -> Result<PixelFormat, String> {
	match P::COLOR_TYPE {
		image::ColorType::Bgr8  => Ok(PixelFormat::Bgr8),
		image::ColorType::Bgra8 => Ok(PixelFormat::Bgra8),
		image::ColorType::Rgb8  => Ok(PixelFormat::Rgb8),
		image::ColorType::Rgba8 => Ok(PixelFormat::Rgba8),
		image::ColorType::L8    => Ok(PixelFormat::Mono8),
		x  => Err(format!("unsupported color type: {:?}", x)),
	}
}