From 1b6a04ca5504955c571d1c97504fb45ea0befee4 Mon Sep 17 00:00:00 2001
From: Valentin Popov <valentin@popov.link>
Date: Mon, 8 Jan 2024 01:21:28 +0400
Subject: Initial vendor packages

Signed-off-by: Valentin Popov <valentin@popov.link>
---
 vendor/image/src/codecs/tga/header.rs | 150 ++++++++++++++++++++++++++++++++++
 1 file changed, 150 insertions(+)
 create mode 100644 vendor/image/src/codecs/tga/header.rs

(limited to 'vendor/image/src/codecs/tga/header.rs')

diff --git a/vendor/image/src/codecs/tga/header.rs b/vendor/image/src/codecs/tga/header.rs
new file mode 100644
index 0000000..83ba7a3
--- /dev/null
+++ b/vendor/image/src/codecs/tga/header.rs
@@ -0,0 +1,150 @@
+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(())
+    }
+}
-- 
cgit v1.2.3