diff options
Diffstat (limited to 'vendor/image/src/codecs/tga')
-rw-r--r-- | vendor/image/src/codecs/tga/decoder.rs | 502 | ||||
-rw-r--r-- | vendor/image/src/codecs/tga/encoder.rs | 215 | ||||
-rw-r--r-- | vendor/image/src/codecs/tga/header.rs | 150 | ||||
-rw-r--r-- | vendor/image/src/codecs/tga/mod.rs | 17 |
4 files changed, 0 insertions, 884 deletions
diff --git a/vendor/image/src/codecs/tga/decoder.rs b/vendor/image/src/codecs/tga/decoder.rs deleted file mode 100644 index 16243ce..0000000 --- a/vendor/image/src/codecs/tga/decoder.rs +++ /dev/null @@ -1,502 +0,0 @@ -use super::header::{Header, ImageType, ALPHA_BIT_MASK, SCREEN_ORIGIN_BIT_MASK}; -use crate::{ - color::{ColorType, ExtendedColorType}, - error::{ - ImageError, ImageResult, LimitError, LimitErrorKind, UnsupportedError, UnsupportedErrorKind, - }, - image::{ImageDecoder, ImageFormat, ImageReadBuffer}, -}; -use byteorder::ReadBytesExt; -use std::{ - convert::TryFrom, - io::{self, Read, Seek}, - mem, -}; - -struct ColorMap { - /// sizes in bytes - start_offset: usize, - entry_size: usize, - bytes: Vec<u8>, -} - -impl ColorMap { - pub(crate) fn from_reader( - r: &mut dyn Read, - start_offset: u16, - num_entries: u16, - bits_per_entry: u8, - ) -> ImageResult<ColorMap> { - let bytes_per_entry = (bits_per_entry as usize + 7) / 8; - - let mut bytes = vec![0; bytes_per_entry * num_entries as usize]; - r.read_exact(&mut bytes)?; - - Ok(ColorMap { - entry_size: bytes_per_entry, - start_offset: start_offset as usize, - bytes, - }) - } - - /// Get one entry from the color map - pub(crate) fn get(&self, index: usize) -> Option<&[u8]> { - let entry = self.start_offset + self.entry_size * index; - self.bytes.get(entry..entry + self.entry_size) - } -} - -/// The representation of a TGA decoder -pub struct TgaDecoder<R> { - r: R, - - width: usize, - height: usize, - bytes_per_pixel: usize, - has_loaded_metadata: bool, - - image_type: ImageType, - color_type: ColorType, - original_color_type: Option<ExtendedColorType>, - - header: Header, - color_map: Option<ColorMap>, - - // Used in read_scanline - line_read: Option<usize>, - line_remain_buff: Vec<u8>, -} - -impl<R: Read + Seek> TgaDecoder<R> { - /// Create a new decoder that decodes from the stream `r` - pub fn new(r: R) -> ImageResult<TgaDecoder<R>> { - let mut decoder = TgaDecoder { - r, - - width: 0, - height: 0, - bytes_per_pixel: 0, - has_loaded_metadata: false, - - image_type: ImageType::Unknown, - color_type: ColorType::L8, - original_color_type: None, - - header: Header::default(), - color_map: None, - - line_read: None, - line_remain_buff: Vec::new(), - }; - decoder.read_metadata()?; - Ok(decoder) - } - - fn read_header(&mut self) -> ImageResult<()> { - self.header = Header::from_reader(&mut self.r)?; - self.image_type = ImageType::new(self.header.image_type); - self.width = self.header.image_width as usize; - self.height = self.header.image_height as usize; - self.bytes_per_pixel = (self.header.pixel_depth as usize + 7) / 8; - Ok(()) - } - - fn read_metadata(&mut self) -> ImageResult<()> { - if !self.has_loaded_metadata { - self.read_header()?; - self.read_image_id()?; - self.read_color_map()?; - self.read_color_information()?; - self.has_loaded_metadata = true; - } - Ok(()) - } - - /// Loads the color information for the decoder - /// - /// To keep things simple, we won't handle bit depths that aren't divisible - /// by 8 and are larger than 32. - fn read_color_information(&mut self) -> ImageResult<()> { - if self.header.pixel_depth % 8 != 0 || self.header.pixel_depth > 32 { - // Bit depth must be divisible by 8, and must be less than or equal - // to 32. - return Err(ImageError::Unsupported( - UnsupportedError::from_format_and_kind( - ImageFormat::Tga.into(), - UnsupportedErrorKind::Color(ExtendedColorType::Unknown( - self.header.pixel_depth, - )), - ), - )); - } - - let num_alpha_bits = self.header.image_desc & ALPHA_BIT_MASK; - - let other_channel_bits = if self.header.map_type != 0 { - self.header.map_entry_size - } else { - if num_alpha_bits > self.header.pixel_depth { - return Err(ImageError::Unsupported( - UnsupportedError::from_format_and_kind( - ImageFormat::Tga.into(), - UnsupportedErrorKind::Color(ExtendedColorType::Unknown( - self.header.pixel_depth, - )), - ), - )); - } - - self.header.pixel_depth - num_alpha_bits - }; - let color = self.image_type.is_color(); - - match (num_alpha_bits, other_channel_bits, color) { - // really, the encoding is BGR and BGRA, this is fixed - // up with `TgaDecoder::reverse_encoding`. - (0, 32, true) => self.color_type = ColorType::Rgba8, - (8, 24, true) => self.color_type = ColorType::Rgba8, - (0, 24, true) => self.color_type = ColorType::Rgb8, - (8, 8, false) => self.color_type = ColorType::La8, - (0, 8, false) => self.color_type = ColorType::L8, - (8, 0, false) => { - // alpha-only image is treated as L8 - self.color_type = ColorType::L8; - self.original_color_type = Some(ExtendedColorType::A8); - } - _ => { - return Err(ImageError::Unsupported( - UnsupportedError::from_format_and_kind( - ImageFormat::Tga.into(), - UnsupportedErrorKind::Color(ExtendedColorType::Unknown( - self.header.pixel_depth, - )), - ), - )) - } - } - Ok(()) - } - - /// Read the image id field - /// - /// We're not interested in this field, so this function skips it if it - /// is present - fn read_image_id(&mut self) -> ImageResult<()> { - self.r - .seek(io::SeekFrom::Current(i64::from(self.header.id_length)))?; - Ok(()) - } - - fn read_color_map(&mut self) -> ImageResult<()> { - if self.header.map_type == 1 { - // FIXME: we could reverse the map entries, which avoids having to reverse all pixels - // in the final output individually. - self.color_map = Some(ColorMap::from_reader( - &mut self.r, - self.header.map_origin, - self.header.map_length, - self.header.map_entry_size, - )?); - } - Ok(()) - } - - /// Expands indices into its mapped color - fn expand_color_map(&self, pixel_data: &[u8]) -> io::Result<Vec<u8>> { - #[inline] - fn bytes_to_index(bytes: &[u8]) -> usize { - let mut result = 0usize; - for byte in bytes.iter() { - result = result << 8 | *byte as usize; - } - result - } - - let bytes_per_entry = (self.header.map_entry_size as usize + 7) / 8; - let mut result = Vec::with_capacity(self.width * self.height * bytes_per_entry); - - if self.bytes_per_pixel == 0 { - return Err(io::ErrorKind::Other.into()); - } - - let color_map = self - .color_map - .as_ref() - .ok_or_else(|| io::Error::from(io::ErrorKind::Other))?; - - for chunk in pixel_data.chunks(self.bytes_per_pixel) { - let index = bytes_to_index(chunk); - if let Some(color) = color_map.get(index) { - result.extend_from_slice(color); - } else { - return Err(io::ErrorKind::Other.into()); - } - } - - Ok(result) - } - - /// Reads a run length encoded data for given number of bytes - fn read_encoded_data(&mut self, num_bytes: usize) -> io::Result<Vec<u8>> { - let mut pixel_data = Vec::with_capacity(num_bytes); - let mut repeat_buf = Vec::with_capacity(self.bytes_per_pixel); - - while pixel_data.len() < num_bytes { - let run_packet = self.r.read_u8()?; - // If the highest bit in `run_packet` is set, then we repeat pixels - // - // Note: the TGA format adds 1 to both counts because having a count - // of 0 would be pointless. - if (run_packet & 0x80) != 0 { - // high bit set, so we will repeat the data - let repeat_count = ((run_packet & !0x80) + 1) as usize; - self.r - .by_ref() - .take(self.bytes_per_pixel as u64) - .read_to_end(&mut repeat_buf)?; - - // get the repeating pixels from the bytes of the pixel stored in `repeat_buf` - let data = repeat_buf - .iter() - .cycle() - .take(repeat_count * self.bytes_per_pixel); - pixel_data.extend(data); - repeat_buf.clear(); - } else { - // not set, so `run_packet+1` is the number of non-encoded pixels - let num_raw_bytes = (run_packet + 1) as usize * self.bytes_per_pixel; - self.r - .by_ref() - .take(num_raw_bytes as u64) - .read_to_end(&mut pixel_data)?; - } - } - - if pixel_data.len() > num_bytes { - // FIXME: the last packet contained more data than we asked for! - // This is at least a warning. We truncate the data since some methods rely on the - // length to be accurate in the success case. - pixel_data.truncate(num_bytes); - } - - Ok(pixel_data) - } - - /// Reads a run length encoded packet - fn read_all_encoded_data(&mut self) -> ImageResult<Vec<u8>> { - let num_bytes = self.width * self.height * self.bytes_per_pixel; - - Ok(self.read_encoded_data(num_bytes)?) - } - - /// Reads a run length encoded line - fn read_encoded_line(&mut self) -> io::Result<Vec<u8>> { - let line_num_bytes = self.width * self.bytes_per_pixel; - let remain_len = self.line_remain_buff.len(); - - if remain_len >= line_num_bytes { - // `Vec::split_to` if std had it - let bytes = { - let bytes_after = self.line_remain_buff.split_off(line_num_bytes); - mem::replace(&mut self.line_remain_buff, bytes_after) - }; - - return Ok(bytes); - } - - let num_bytes = line_num_bytes - remain_len; - - let line_data = self.read_encoded_data(num_bytes)?; - - let mut pixel_data = Vec::with_capacity(line_num_bytes); - pixel_data.append(&mut self.line_remain_buff); - pixel_data.extend_from_slice(&line_data[..num_bytes]); - - // put the remain data to line_remain_buff. - // expects `self.line_remain_buff` to be empty from - // the above `pixel_data.append` call - debug_assert!(self.line_remain_buff.is_empty()); - self.line_remain_buff - .extend_from_slice(&line_data[num_bytes..]); - - Ok(pixel_data) - } - - /// Reverse from BGR encoding to RGB encoding - /// - /// TGA files are stored in the BGRA encoding. This function swaps - /// the blue and red bytes in the `pixels` array. - fn reverse_encoding_in_output(&mut self, pixels: &mut [u8]) { - // We only need to reverse the encoding of color images - match self.color_type { - ColorType::Rgb8 | ColorType::Rgba8 => { - for chunk in pixels.chunks_mut(self.color_type.bytes_per_pixel().into()) { - chunk.swap(0, 2); - } - } - _ => {} - } - } - - /// Flip the image vertically depending on the screen origin bit - /// - /// The bit in position 5 of the image descriptor byte is the screen origin bit. - /// If it's 1, the origin is in the top left corner. - /// If it's 0, the origin is in the bottom left corner. - /// This function checks the bit, and if it's 0, flips the image vertically. - fn flip_vertically(&mut self, pixels: &mut [u8]) { - if self.is_flipped_vertically() { - if self.height == 0 { - return; - } - - let num_bytes = pixels.len(); - - let width_bytes = num_bytes / self.height; - - // Flip the image vertically. - for vertical_index in 0..(self.height / 2) { - let vertical_target = (self.height - vertical_index) * width_bytes - width_bytes; - - for horizontal_index in 0..width_bytes { - let source = vertical_index * width_bytes + horizontal_index; - let target = vertical_target + horizontal_index; - - pixels.swap(target, source); - } - } - } - } - - /// Check whether the image is vertically flipped - /// - /// The bit in position 5 of the image descriptor byte is the screen origin bit. - /// If it's 1, the origin is in the top left corner. - /// If it's 0, the origin is in the bottom left corner. - /// This function checks the bit, and if it's 0, flips the image vertically. - fn is_flipped_vertically(&self) -> bool { - let screen_origin_bit = SCREEN_ORIGIN_BIT_MASK & self.header.image_desc != 0; - !screen_origin_bit - } - - fn read_scanline(&mut self, buf: &mut [u8]) -> io::Result<usize> { - if let Some(line_read) = self.line_read { - if line_read == self.height { - return Ok(0); - } - } - - // read the pixels from the data region - let mut pixel_data = if self.image_type.is_encoded() { - self.read_encoded_line()? - } else { - let num_raw_bytes = self.width * self.bytes_per_pixel; - let mut buf = vec![0; num_raw_bytes]; - self.r.by_ref().read_exact(&mut buf)?; - buf - }; - - // expand the indices using the color map if necessary - if self.image_type.is_color_mapped() { - pixel_data = self.expand_color_map(&pixel_data)?; - } - self.reverse_encoding_in_output(&mut pixel_data); - - // copy to the output buffer - buf[..pixel_data.len()].copy_from_slice(&pixel_data); - - self.line_read = Some(self.line_read.unwrap_or(0) + 1); - - Ok(pixel_data.len()) - } -} - -impl<'a, R: 'a + Read + Seek> ImageDecoder<'a> for TgaDecoder<R> { - type Reader = TGAReader<R>; - - fn dimensions(&self) -> (u32, u32) { - (self.width as u32, self.height as u32) - } - - fn color_type(&self) -> ColorType { - self.color_type - } - - fn original_color_type(&self) -> ExtendedColorType { - self.original_color_type - .unwrap_or_else(|| self.color_type().into()) - } - - fn scanline_bytes(&self) -> u64 { - // This cannot overflow because TGA has a maximum width of u16::MAX_VALUE and - // `bytes_per_pixel` is a u8. - u64::from(self.color_type.bytes_per_pixel()) * self.width as u64 - } - - fn into_reader(self) -> ImageResult<Self::Reader> { - Ok(TGAReader { - buffer: ImageReadBuffer::new(self.scanline_bytes(), self.total_bytes()), - decoder: self, - }) - } - - fn read_image(mut self, buf: &mut [u8]) -> ImageResult<()> { - assert_eq!(u64::try_from(buf.len()), Ok(self.total_bytes())); - - // In indexed images, we might need more bytes than pixels to read them. That's nonsensical - // to encode but we'll not want to crash. - let mut fallback_buf = vec![]; - // read the pixels from the data region - let rawbuf = if self.image_type.is_encoded() { - let pixel_data = self.read_all_encoded_data()?; - if self.bytes_per_pixel <= usize::from(self.color_type.bytes_per_pixel()) { - buf[..pixel_data.len()].copy_from_slice(&pixel_data); - &buf[..pixel_data.len()] - } else { - fallback_buf = pixel_data; - &fallback_buf[..] - } - } else { - let num_raw_bytes = self.width * self.height * self.bytes_per_pixel; - if self.bytes_per_pixel <= usize::from(self.color_type.bytes_per_pixel()) { - self.r.by_ref().read_exact(&mut buf[..num_raw_bytes])?; - &buf[..num_raw_bytes] - } else { - fallback_buf.resize(num_raw_bytes, 0u8); - self.r - .by_ref() - .read_exact(&mut fallback_buf[..num_raw_bytes])?; - &fallback_buf[..num_raw_bytes] - } - }; - - // expand the indices using the color map if necessary - if self.image_type.is_color_mapped() { - let pixel_data = self.expand_color_map(rawbuf)?; - // not enough data to fill the buffer, or would overflow the buffer - if pixel_data.len() != buf.len() { - return Err(ImageError::Limits(LimitError::from_kind( - LimitErrorKind::DimensionError, - ))); - } - buf.copy_from_slice(&pixel_data); - } - - self.reverse_encoding_in_output(buf); - - self.flip_vertically(buf); - - Ok(()) - } -} - -pub struct TGAReader<R> { - buffer: ImageReadBuffer, - decoder: TgaDecoder<R>, -} -impl<R: Read + Seek> Read for TGAReader<R> { - fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { - let decoder = &mut self.decoder; - self.buffer.read(buf, |buf| decoder.read_scanline(buf)) - } -} 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); - } -} diff --git a/vendor/image/src/codecs/tga/header.rs b/vendor/image/src/codecs/tga/header.rs deleted file mode 100644 index 83ba7a3..0000000 --- a/vendor/image/src/codecs/tga/header.rs +++ /dev/null @@ -1,150 +0,0 @@ -use crate::{ - error::{UnsupportedError, UnsupportedErrorKind}, - ColorType, ImageError, ImageFormat, ImageResult, -}; -use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; -use std::io::{Read, Write}; - -pub(crate) const ALPHA_BIT_MASK: u8 = 0b1111; -pub(crate) const SCREEN_ORIGIN_BIT_MASK: u8 = 0b10_0000; - -pub(crate) enum ImageType { - NoImageData = 0, - /// Uncompressed images. - RawColorMap = 1, - RawTrueColor = 2, - RawGrayScale = 3, - /// Run length encoded images. - RunColorMap = 9, - RunTrueColor = 10, - RunGrayScale = 11, - Unknown, -} - -impl ImageType { - /// Create a new image type from a u8. - pub(crate) fn new(img_type: u8) -> ImageType { - match img_type { - 0 => ImageType::NoImageData, - - 1 => ImageType::RawColorMap, - 2 => ImageType::RawTrueColor, - 3 => ImageType::RawGrayScale, - - 9 => ImageType::RunColorMap, - 10 => ImageType::RunTrueColor, - 11 => ImageType::RunGrayScale, - - _ => ImageType::Unknown, - } - } - - /// Check if the image format uses colors as opposed to gray scale. - pub(crate) fn is_color(&self) -> bool { - matches! { *self, - ImageType::RawColorMap - | ImageType::RawTrueColor - | ImageType::RunTrueColor - | ImageType::RunColorMap - } - } - - /// Does the image use a color map. - pub(crate) fn is_color_mapped(&self) -> bool { - matches! { *self, ImageType::RawColorMap | ImageType::RunColorMap } - } - - /// Is the image run length encoded. - pub(crate) fn is_encoded(&self) -> bool { - matches! {*self, ImageType::RunColorMap | ImageType::RunTrueColor | ImageType::RunGrayScale } - } -} - -/// Header used by TGA image files. -#[derive(Debug, Default)] -pub(crate) struct Header { - pub(crate) id_length: u8, // length of ID string - pub(crate) map_type: u8, // color map type - pub(crate) image_type: u8, // image type code - pub(crate) map_origin: u16, // starting index of map - pub(crate) map_length: u16, // length of map - pub(crate) map_entry_size: u8, // size of map entries in bits - pub(crate) x_origin: u16, // x-origin of image - pub(crate) y_origin: u16, // y-origin of image - pub(crate) image_width: u16, // width of image - pub(crate) image_height: u16, // height of image - pub(crate) pixel_depth: u8, // bits per pixel - pub(crate) image_desc: u8, // image descriptor -} - -impl Header { - /// Load the header with values from pixel information. - pub(crate) fn from_pixel_info( - color_type: ColorType, - width: u16, - height: u16, - ) -> ImageResult<Self> { - let mut header = Self::default(); - - if width > 0 && height > 0 { - let (num_alpha_bits, other_channel_bits, image_type) = match color_type { - ColorType::Rgba8 => (8, 24, ImageType::RawTrueColor), - ColorType::Rgb8 => (0, 24, ImageType::RawTrueColor), - ColorType::La8 => (8, 8, ImageType::RawGrayScale), - ColorType::L8 => (0, 8, ImageType::RawGrayScale), - _ => { - return Err(ImageError::Unsupported( - UnsupportedError::from_format_and_kind( - ImageFormat::Tga.into(), - UnsupportedErrorKind::Color(color_type.into()), - ), - )) - } - }; - - header.image_type = image_type as u8; - header.image_width = width; - header.image_height = height; - header.pixel_depth = num_alpha_bits + other_channel_bits; - header.image_desc = num_alpha_bits & ALPHA_BIT_MASK; - header.image_desc |= SCREEN_ORIGIN_BIT_MASK; // Upper left origin. - } - - Ok(header) - } - - /// Load the header with values from the reader. - pub(crate) fn from_reader(r: &mut dyn Read) -> ImageResult<Self> { - Ok(Self { - id_length: r.read_u8()?, - map_type: r.read_u8()?, - image_type: r.read_u8()?, - map_origin: r.read_u16::<LittleEndian>()?, - map_length: r.read_u16::<LittleEndian>()?, - map_entry_size: r.read_u8()?, - x_origin: r.read_u16::<LittleEndian>()?, - y_origin: r.read_u16::<LittleEndian>()?, - image_width: r.read_u16::<LittleEndian>()?, - image_height: r.read_u16::<LittleEndian>()?, - pixel_depth: r.read_u8()?, - image_desc: r.read_u8()?, - }) - } - - /// Write out the header values. - pub(crate) fn write_to(&self, w: &mut dyn Write) -> ImageResult<()> { - w.write_u8(self.id_length)?; - w.write_u8(self.map_type)?; - w.write_u8(self.image_type)?; - w.write_u16::<LittleEndian>(self.map_origin)?; - w.write_u16::<LittleEndian>(self.map_length)?; - w.write_u8(self.map_entry_size)?; - w.write_u16::<LittleEndian>(self.x_origin)?; - w.write_u16::<LittleEndian>(self.y_origin)?; - w.write_u16::<LittleEndian>(self.image_width)?; - w.write_u16::<LittleEndian>(self.image_height)?; - w.write_u8(self.pixel_depth)?; - w.write_u8(self.image_desc)?; - Ok(()) - } -} diff --git a/vendor/image/src/codecs/tga/mod.rs b/vendor/image/src/codecs/tga/mod.rs deleted file mode 100644 index fdc2f0c..0000000 --- a/vendor/image/src/codecs/tga/mod.rs +++ /dev/null @@ -1,17 +0,0 @@ -//! Decoding of TGA Images -//! -//! # Related Links -//! <http://googlesites.inequation.org/tgautilities> - -/// A decoder for TGA images -/// -/// Currently this decoder does not support 8, 15 and 16 bit color images. -pub use self::decoder::TgaDecoder; - -//TODO add 8, 15, 16 bit color support - -pub use self::encoder::TgaEncoder; - -mod decoder; -mod encoder; -mod header; |