diff options
Diffstat (limited to 'vendor/image/src/codecs/tga/encoder.rs')
-rw-r--r-- | vendor/image/src/codecs/tga/encoder.rs | 215 |
1 files changed, 0 insertions, 215 deletions
diff --git a/vendor/image/src/codecs/tga/encoder.rs b/vendor/image/src/codecs/tga/encoder.rs deleted file mode 100644 index cf34984..0000000 --- a/vendor/image/src/codecs/tga/encoder.rs +++ /dev/null @@ -1,215 +0,0 @@ -use super::header::Header; -use crate::{error::EncodingError, ColorType, ImageEncoder, ImageError, ImageFormat, ImageResult}; -use std::{convert::TryFrom, error, fmt, io::Write}; - -/// Errors that can occur during encoding and saving of a TGA image. -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] -enum EncoderError { - /// Invalid TGA width. - WidthInvalid(u32), - - /// Invalid TGA height. - HeightInvalid(u32), -} - -impl fmt::Display for EncoderError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - EncoderError::WidthInvalid(s) => f.write_fmt(format_args!("Invalid TGA width: {}", s)), - EncoderError::HeightInvalid(s) => { - f.write_fmt(format_args!("Invalid TGA height: {}", s)) - } - } - } -} - -impl From<EncoderError> for ImageError { - fn from(e: EncoderError) -> ImageError { - ImageError::Encoding(EncodingError::new(ImageFormat::Tga.into(), e)) - } -} - -impl error::Error for EncoderError {} - -/// TGA encoder. -pub struct TgaEncoder<W: Write> { - writer: W, -} - -impl<W: Write> TgaEncoder<W> { - /// Create a new encoder that writes its output to ```w```. - pub fn new(w: W) -> TgaEncoder<W> { - TgaEncoder { writer: w } - } - - /// Encodes the image ```buf``` that has dimensions ```width``` - /// and ```height``` and ```ColorType``` ```color_type```. - /// - /// The dimensions of the image must be between 0 and 65535 (inclusive) or - /// an error will be returned. - pub fn encode( - mut self, - buf: &[u8], - width: u32, - height: u32, - color_type: ColorType, - ) -> ImageResult<()> { - // Validate dimensions. - let width = u16::try_from(width) - .map_err(|_| ImageError::from(EncoderError::WidthInvalid(width)))?; - - let height = u16::try_from(height) - .map_err(|_| ImageError::from(EncoderError::HeightInvalid(height)))?; - - // Write out TGA header. - let header = Header::from_pixel_info(color_type, width, height)?; - header.write_to(&mut self.writer)?; - - // Write out Bgr(a)8 or L(a)8 image data. - match color_type { - ColorType::Rgb8 | ColorType::Rgba8 => { - let mut image = Vec::from(buf); - - for chunk in image.chunks_mut(usize::from(color_type.bytes_per_pixel())) { - chunk.swap(0, 2); - } - - self.writer.write_all(&image)?; - } - _ => { - self.writer.write_all(buf)?; - } - } - - Ok(()) - } -} - -impl<W: Write> ImageEncoder for TgaEncoder<W> { - fn write_image( - self, - buf: &[u8], - width: u32, - height: u32, - color_type: ColorType, - ) -> ImageResult<()> { - self.encode(buf, width, height, color_type) - } -} - -#[cfg(test)] -mod tests { - use super::{EncoderError, TgaEncoder}; - use crate::{codecs::tga::TgaDecoder, ColorType, ImageDecoder, ImageError}; - use std::{error::Error, io::Cursor}; - - fn round_trip_image(image: &[u8], width: u32, height: u32, c: ColorType) -> Vec<u8> { - let mut encoded_data = Vec::new(); - { - let encoder = TgaEncoder::new(&mut encoded_data); - encoder - .encode(&image, width, height, c) - .expect("could not encode image"); - } - - let decoder = TgaDecoder::new(Cursor::new(&encoded_data)).expect("failed to decode"); - - let mut buf = vec![0; decoder.total_bytes() as usize]; - decoder.read_image(&mut buf).expect("failed to decode"); - buf - } - - #[test] - fn test_image_width_too_large() { - // TGA cannot encode images larger than 65,535×65,535 - // create a 65,536×1 8-bit black image buffer - let size = usize::from(u16::MAX) + 1; - let dimension = size as u32; - let img = vec![0u8; size]; - // Try to encode an image that is too large - let mut encoded = Vec::new(); - let encoder = TgaEncoder::new(&mut encoded); - let result = encoder.encode(&img, dimension, 1, ColorType::L8); - match result { - Err(ImageError::Encoding(err)) => { - let err = err - .source() - .unwrap() - .downcast_ref::<EncoderError>() - .unwrap(); - assert_eq!(*err, EncoderError::WidthInvalid(dimension)); - } - other => panic!( - "Encoding an image that is too wide should return a InvalidWidth \ - it returned {:?} instead", - other - ), - } - } - - #[test] - fn test_image_height_too_large() { - // TGA cannot encode images larger than 65,535×65,535 - // create a 65,536×1 8-bit black image buffer - let size = usize::from(u16::MAX) + 1; - let dimension = size as u32; - let img = vec![0u8; size]; - // Try to encode an image that is too large - let mut encoded = Vec::new(); - let encoder = TgaEncoder::new(&mut encoded); - let result = encoder.encode(&img, 1, dimension, ColorType::L8); - match result { - Err(ImageError::Encoding(err)) => { - let err = err - .source() - .unwrap() - .downcast_ref::<EncoderError>() - .unwrap(); - assert_eq!(*err, EncoderError::HeightInvalid(dimension)); - } - other => panic!( - "Encoding an image that is too tall should return a InvalidHeight \ - it returned {:?} instead", - other - ), - } - } - - #[test] - fn round_trip_single_pixel_rgb() { - let image = [0, 1, 2]; - let decoded = round_trip_image(&image, 1, 1, ColorType::Rgb8); - assert_eq!(decoded.len(), image.len()); - assert_eq!(decoded.as_slice(), image); - } - - #[test] - fn round_trip_single_pixel_rgba() { - let image = [0, 1, 2, 3]; - let decoded = round_trip_image(&image, 1, 1, ColorType::Rgba8); - assert_eq!(decoded.len(), image.len()); - assert_eq!(decoded.as_slice(), image); - } - - #[test] - fn round_trip_gray() { - let image = [0, 1, 2]; - let decoded = round_trip_image(&image, 3, 1, ColorType::L8); - assert_eq!(decoded.len(), image.len()); - assert_eq!(decoded.as_slice(), image); - } - - #[test] - fn round_trip_graya() { - let image = [0, 1, 2, 3, 4, 5]; - let decoded = round_trip_image(&image, 1, 3, ColorType::La8); - assert_eq!(decoded.len(), image.len()); - assert_eq!(decoded.as_slice(), image); - } - - #[test] - fn round_trip_3px_rgb() { - let image = [0; 3 * 3 * 3]; // 3x3 pixels, 3 bytes per pixel - let _decoded = round_trip_image(&image, 3, 3, ColorType::Rgb8); - } -} |