open_vector_tile/open/
image_layer.rs

1use alloc::{fmt, str::FromStr, string::String, vec::Vec};
2use pbf::{BitCast, ProtoRead, ProtoWrite, Protobuf};
3
4// TODO: This could be faster if we don't read in the grid data on parsing but only if the user needs it
5
6/// Track the image type
7#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord)]
8pub enum ImageType {
9    /// PNG
10    #[default]
11    PNG = 0,
12    /// JPEG
13    JPG = 1,
14    /// WebP
15    WEBP = 2,
16    /// GIF
17    GIF = 3,
18    /// AVIF
19    AVIF = 4,
20    /// SVG
21    SVG = 5,
22    /// BMP
23    BMP = 6,
24    /// RAW
25    RAW = 7,
26    /// Unknown
27    UNKNOWN = 8,
28}
29impl BitCast for ImageType {
30    fn to_u64(&self) -> u64 {
31        (*self) as u64
32    }
33    fn from_u64(value: u64) -> Self {
34        match value {
35            0 => ImageType::PNG,
36            1 => ImageType::JPG,
37            2 => ImageType::WEBP,
38            3 => ImageType::GIF,
39            4 => ImageType::AVIF,
40            5 => ImageType::SVG,
41            6 => ImageType::BMP,
42            7 => ImageType::RAW,
43            8 => ImageType::UNKNOWN,
44            _ => panic!("unknown value: {}", value),
45        }
46    }
47}
48impl FromStr for ImageType {
49    type Err = &'static str;
50
51    fn from_str(s: &str) -> Result<Self, Self::Err> {
52        match s.to_uppercase().as_str() {
53            "PNG" => Ok(ImageType::PNG),
54            "JPG" | "JPEG" => Ok(ImageType::JPG),
55            "WEBP" => Ok(ImageType::WEBP),
56            "GIF" => Ok(ImageType::GIF),
57            "AVIF" => Ok(ImageType::AVIF),
58            "SVG" => Ok(ImageType::SVG),
59            "BMP" => Ok(ImageType::BMP),
60            "RAW" => Ok(ImageType::RAW),
61            "UNKNOWN" => Ok(ImageType::UNKNOWN),
62            #[tarpaulin::skip]
63            _ => Err("Unknown image type"),
64        }
65    }
66}
67impl From<&str> for ImageType {
68    fn from(s: &str) -> Self {
69        ImageType::from_str(s.to_uppercase().as_str()).unwrap_or(ImageType::PNG)
70    }
71}
72impl fmt::Display for ImageType {
73    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74        let name = match self {
75            ImageType::PNG => "PNG",
76            ImageType::JPG => "JPG",
77            ImageType::WEBP => "WEBP",
78            ImageType::GIF => "GIF",
79            ImageType::AVIF => "AVIF",
80            ImageType::SVG => "SVG",
81            ImageType::BMP => "BMP",
82            ImageType::RAW => "RAW",
83            ImageType::UNKNOWN => "UNKNOWN",
84        };
85        write!(f, "{}", name)
86    }
87}
88
89/// Elevation object to read from
90#[derive(Debug, Default, Clone, PartialEq)]
91pub struct ImageData {
92    /// The name of the image
93    pub name: String,
94    /// The image type
95    pub image_type: ImageType,
96    /// The image width
97    pub width: u32,
98    /// The image height
99    pub height: u32,
100    /// The image data
101    pub image: Vec<u8>,
102}
103impl ImageData {
104    /// Create a new ImageData
105    pub fn new(
106        name: String,
107        image_type: ImageType,
108        width: u32,
109        height: u32,
110        image: Vec<u8>,
111    ) -> Self {
112        Self { name, image_type, width, height, image }
113    }
114}
115impl ProtoRead for ImageData {
116    fn read(&mut self, tag: u64, pb: &mut Protobuf) {
117        match tag {
118            1 => self.image_type = pb.read_varint::<ImageType>(),
119            2 => self.width = pb.read_varint(),
120            3 => self.height = pb.read_varint(),
121            4 => self.image = pb.read_bytes(),
122            5 => self.name = pb.read_string(),
123            #[tarpaulin::skip]
124            _ => panic!("unknown tag: {}", tag),
125        }
126    }
127}
128impl ProtoWrite for ImageData {
129    fn write(&self, pb: &mut Protobuf) {
130        pb.write_varint_field(1, self.image_type);
131        pb.write_varint_field(2, self.width);
132        pb.write_varint_field(3, self.height);
133        pb.write_bytes_field(4, &self.image);
134        pb.write_string_field(5, &self.name);
135    }
136}