1use super::header::{Header, ImageType, ALPHA_BIT_MASK, SCREEN_ORIGIN_BIT_MASK};
2use crate::{
3 color::{ColorType, ExtendedColorType},
4 error::{
5 ImageError, ImageResult, LimitError, LimitErrorKind, UnsupportedError, UnsupportedErrorKind,
6 },
7 image::{ImageDecoder, ImageFormat},
8};
9use byteorder_lite::ReadBytesExt;
10use std::io::{self, Read};
11
12struct ColorMap {
13 /// sizes in bytes
14 start_offset: usize,
15 entry_size: usize,
16 bytes: Vec<u8>,
17}
18
19impl ColorMap {
20 pub(crate) fn from_reader(
21 r: &mut dyn Read,
22 start_offset: u16,
23 num_entries: u16,
24 bits_per_entry: u8,
25 ) -> ImageResult<ColorMap> {
26 let bytes_per_entry = (bits_per_entry as usize + 7) / 8;
27
28 let mut bytes = vec![0; bytes_per_entry * num_entries as usize];
29 r.read_exact(&mut bytes)?;
30
31 Ok(ColorMap {
32 entry_size: bytes_per_entry,
33 start_offset: start_offset as usize,
34 bytes,
35 })
36 }
37
38 /// Get one entry from the color map
39 pub(crate) fn get(&self, index: usize) -> Option<&[u8]> {
40 let entry = self.start_offset + self.entry_size * index;
41 self.bytes.get(entry..entry + self.entry_size)
42 }
43}
44
45/// The representation of a TGA decoder
46pub struct TgaDecoder<R> {
47 r: R,
48
49 width: usize,
50 height: usize,
51 bytes_per_pixel: usize,
52 has_loaded_metadata: bool,
53
54 image_type: ImageType,
55 color_type: ColorType,
56 original_color_type: Option<ExtendedColorType>,
57
58 header: Header,
59 color_map: Option<ColorMap>,
60}
61
62impl<R: Read> TgaDecoder<R> {
63 /// Create a new decoder that decodes from the stream `r`
64 pub fn new(r: R) -> ImageResult<TgaDecoder<R>> {
65 let mut decoder = TgaDecoder {
66 r,
67
68 width: 0,
69 height: 0,
70 bytes_per_pixel: 0,
71 has_loaded_metadata: false,
72
73 image_type: ImageType::Unknown,
74 color_type: ColorType::L8,
75 original_color_type: None,
76
77 header: Header::default(),
78 color_map: None,
79 };
80 decoder.read_metadata()?;
81 Ok(decoder)
82 }
83
84 fn read_header(&mut self) -> ImageResult<()> {
85 self.header = Header::from_reader(&mut self.r)?;
86 self.image_type = ImageType::new(self.header.image_type);
87 self.width = self.header.image_width as usize;
88 self.height = self.header.image_height as usize;
89 self.bytes_per_pixel = (self.header.pixel_depth as usize + 7) / 8;
90 Ok(())
91 }
92
93 fn read_metadata(&mut self) -> ImageResult<()> {
94 if !self.has_loaded_metadata {
95 self.read_header()?;
96 self.read_image_id()?;
97 self.read_color_map()?;
98 self.read_color_information()?;
99 self.has_loaded_metadata = true;
100 }
101 Ok(())
102 }
103
104 /// Loads the color information for the decoder
105 ///
106 /// To keep things simple, we won't handle bit depths that aren't divisible
107 /// by 8 and are larger than 32.
108 fn read_color_information(&mut self) -> ImageResult<()> {
109 if self.header.pixel_depth % 8 != 0 || self.header.pixel_depth > 32 {
110 // Bit depth must be divisible by 8, and must be less than or equal
111 // to 32.
112 return Err(ImageError::Unsupported(
113 UnsupportedError::from_format_and_kind(
114 ImageFormat::Tga.into(),
115 UnsupportedErrorKind::Color(ExtendedColorType::Unknown(
116 self.header.pixel_depth,
117 )),
118 ),
119 ));
120 }
121
122 let num_alpha_bits = self.header.image_desc & ALPHA_BIT_MASK;
123
124 let other_channel_bits = if self.header.map_type != 0 {
125 self.header.map_entry_size
126 } else {
127 if num_alpha_bits > self.header.pixel_depth {
128 return Err(ImageError::Unsupported(
129 UnsupportedError::from_format_and_kind(
130 ImageFormat::Tga.into(),
131 UnsupportedErrorKind::Color(ExtendedColorType::Unknown(
132 self.header.pixel_depth,
133 )),
134 ),
135 ));
136 }
137
138 self.header.pixel_depth - num_alpha_bits
139 };
140 let color = self.image_type.is_color();
141
142 match (num_alpha_bits, other_channel_bits, color) {
143 // really, the encoding is BGR and BGRA, this is fixed
144 // up with `TgaDecoder::reverse_encoding`.
145 (0, 32, true) => self.color_type = ColorType::Rgba8,
146 (8, 24, true) => self.color_type = ColorType::Rgba8,
147 (0, 24, true) => self.color_type = ColorType::Rgb8,
148 (8, 8, false) => self.color_type = ColorType::La8,
149 (0, 8, false) => self.color_type = ColorType::L8,
150 (8, 0, false) => {
151 // alpha-only image is treated as L8
152 self.color_type = ColorType::L8;
153 self.original_color_type = Some(ExtendedColorType::A8);
154 }
155 _ => {
156 return Err(ImageError::Unsupported(
157 UnsupportedError::from_format_and_kind(
158 ImageFormat::Tga.into(),
159 UnsupportedErrorKind::Color(ExtendedColorType::Unknown(
160 self.header.pixel_depth,
161 )),
162 ),
163 ))
164 }
165 }
166 Ok(())
167 }
168
169 /// Read the image id field
170 ///
171 /// We're not interested in this field, so this function skips it if it
172 /// is present
173 fn read_image_id(&mut self) -> ImageResult<()> {
174 self.r
175 .read_exact(&mut vec![0; self.header.id_length as usize])?;
176 Ok(())
177 }
178
179 fn read_color_map(&mut self) -> ImageResult<()> {
180 if self.header.map_type == 1 {
181 // FIXME: we could reverse the map entries, which avoids having to reverse all pixels
182 // in the final output individually.
183 self.color_map = Some(ColorMap::from_reader(
184 &mut self.r,
185 self.header.map_origin,
186 self.header.map_length,
187 self.header.map_entry_size,
188 )?);
189 }
190 Ok(())
191 }
192
193 /// Expands indices into its mapped color
194 fn expand_color_map(&self, pixel_data: &[u8]) -> io::Result<Vec<u8>> {
195 #[inline]
196 fn bytes_to_index(bytes: &[u8]) -> usize {
197 let mut result = 0usize;
198 for byte in bytes {
199 result = (result << 8) | *byte as usize;
200 }
201 result
202 }
203
204 let bytes_per_entry = (self.header.map_entry_size as usize + 7) / 8;
205 let mut result = Vec::with_capacity(self.width * self.height * bytes_per_entry);
206
207 if self.bytes_per_pixel == 0 {
208 return Err(io::ErrorKind::Other.into());
209 }
210
211 let color_map = self
212 .color_map
213 .as_ref()
214 .ok_or_else(|| io::Error::from(io::ErrorKind::Other))?;
215
216 for chunk in pixel_data.chunks(self.bytes_per_pixel) {
217 let index = bytes_to_index(chunk);
218 if let Some(color) = color_map.get(index) {
219 result.extend_from_slice(color);
220 } else {
221 return Err(io::ErrorKind::Other.into());
222 }
223 }
224
225 Ok(result)
226 }
227
228 /// Reads a run length encoded data for given number of bytes
229 fn read_encoded_data(&mut self, num_bytes: usize) -> io::Result<Vec<u8>> {
230 let mut pixel_data = Vec::with_capacity(num_bytes);
231 let mut repeat_buf = Vec::with_capacity(self.bytes_per_pixel);
232
233 while pixel_data.len() < num_bytes {
234 let run_packet = self.r.read_u8()?;
235 // If the highest bit in `run_packet` is set, then we repeat pixels
236 //
237 // Note: the TGA format adds 1 to both counts because having a count
238 // of 0 would be pointless.
239 if (run_packet & 0x80) != 0 {
240 // high bit set, so we will repeat the data
241 let repeat_count = ((run_packet & !0x80) + 1) as usize;
242 self.r
243 .by_ref()
244 .take(self.bytes_per_pixel as u64)
245 .read_to_end(&mut repeat_buf)?;
246
247 // get the repeating pixels from the bytes of the pixel stored in `repeat_buf`
248 let data = repeat_buf
249 .iter()
250 .cycle()
251 .take(repeat_count * self.bytes_per_pixel);
252 pixel_data.extend(data);
253 repeat_buf.clear();
254 } else {
255 // not set, so `run_packet+1` is the number of non-encoded pixels
256 let num_raw_bytes = (run_packet + 1) as usize * self.bytes_per_pixel;
257 self.r
258 .by_ref()
259 .take(num_raw_bytes as u64)
260 .read_to_end(&mut pixel_data)?;
261 }
262 }
263
264 if pixel_data.len() > num_bytes {
265 // FIXME: the last packet contained more data than we asked for!
266 // This is at least a warning. We truncate the data since some methods rely on the
267 // length to be accurate in the success case.
268 pixel_data.truncate(num_bytes);
269 }
270
271 Ok(pixel_data)
272 }
273
274 /// Reads a run length encoded packet
275 fn read_all_encoded_data(&mut self) -> ImageResult<Vec<u8>> {
276 let num_bytes = self.width * self.height * self.bytes_per_pixel;
277
278 Ok(self.read_encoded_data(num_bytes)?)
279 }
280
281 /// Reverse from BGR encoding to RGB encoding
282 ///
283 /// TGA files are stored in the BGRA encoding. This function swaps
284 /// the blue and red bytes in the `pixels` array.
285 fn reverse_encoding_in_output(&mut self, pixels: &mut [u8]) {
286 // We only need to reverse the encoding of color images
287 match self.color_type {
288 ColorType::Rgb8 | ColorType::Rgba8 => {
289 for chunk in pixels.chunks_mut(self.color_type.bytes_per_pixel().into()) {
290 chunk.swap(0, 2);
291 }
292 }
293 _ => {}
294 }
295 }
296
297 /// Flip the image vertically depending on the screen origin bit
298 ///
299 /// The bit in position 5 of the image descriptor byte is the screen origin bit.
300 /// If it's 1, the origin is in the top left corner.
301 /// If it's 0, the origin is in the bottom left corner.
302 /// This function checks the bit, and if it's 0, flips the image vertically.
303 fn flip_vertically(&mut self, pixels: &mut [u8]) {
304 if self.is_flipped_vertically() {
305 if self.height == 0 {
306 return;
307 }
308
309 let num_bytes = pixels.len();
310
311 let width_bytes = num_bytes / self.height;
312
313 // Flip the image vertically.
314 for vertical_index in 0..(self.height / 2) {
315 let vertical_target = (self.height - vertical_index) * width_bytes - width_bytes;
316
317 for horizontal_index in 0..width_bytes {
318 let source = vertical_index * width_bytes + horizontal_index;
319 let target = vertical_target + horizontal_index;
320
321 pixels.swap(target, source);
322 }
323 }
324 }
325 }
326
327 /// Check whether the image is vertically flipped
328 ///
329 /// The bit in position 5 of the image descriptor byte is the screen origin bit.
330 /// If it's 1, the origin is in the top left corner.
331 /// If it's 0, the origin is in the bottom left corner.
332 /// This function checks the bit, and if it's 0, flips the image vertically.
333 fn is_flipped_vertically(&self) -> bool {
334 let screen_origin_bit = SCREEN_ORIGIN_BIT_MASK & self.header.image_desc != 0;
335 !screen_origin_bit
336 }
337}
338
339impl<R: Read> ImageDecoder for TgaDecoder<R> {
340 fn dimensions(&self) -> (u32, u32) {
341 (self.width as u32, self.height as u32)
342 }
343
344 fn color_type(&self) -> ColorType {
345 self.color_type
346 }
347
348 fn original_color_type(&self) -> ExtendedColorType {
349 self.original_color_type
350 .unwrap_or_else(|| self.color_type().into())
351 }
352
353 fn read_image(mut self, buf: &mut [u8]) -> ImageResult<()> {
354 assert_eq!(u64::try_from(buf.len()), Ok(self.total_bytes()));
355
356 // In indexed images, we might need more bytes than pixels to read them. That's nonsensical
357 // to encode but we'll not want to crash.
358 let mut fallback_buf = vec![];
359 // read the pixels from the data region
360 let rawbuf = if self.image_type.is_encoded() {
361 let pixel_data = self.read_all_encoded_data()?;
362 if self.bytes_per_pixel <= usize::from(self.color_type.bytes_per_pixel()) {
363 buf[..pixel_data.len()].copy_from_slice(&pixel_data);
364 &buf[..pixel_data.len()]
365 } else {
366 fallback_buf = pixel_data;
367 &fallback_buf[..]
368 }
369 } else {
370 let num_raw_bytes = self.width * self.height * self.bytes_per_pixel;
371 if self.bytes_per_pixel <= usize::from(self.color_type.bytes_per_pixel()) {
372 self.r.by_ref().read_exact(&mut buf[..num_raw_bytes])?;
373 &buf[..num_raw_bytes]
374 } else {
375 fallback_buf.resize(num_raw_bytes, 0u8);
376 self.r
377 .by_ref()
378 .read_exact(&mut fallback_buf[..num_raw_bytes])?;
379 &fallback_buf[..num_raw_bytes]
380 }
381 };
382
383 // expand the indices using the color map if necessary
384 if self.image_type.is_color_mapped() {
385 let pixel_data = self.expand_color_map(rawbuf)?;
386 // not enough data to fill the buffer, or would overflow the buffer
387 if pixel_data.len() != buf.len() {
388 return Err(ImageError::Limits(LimitError::from_kind(
389 LimitErrorKind::DimensionError,
390 )));
391 }
392 buf.copy_from_slice(&pixel_data);
393 }
394
395 self.reverse_encoding_in_output(buf);
396
397 self.flip_vertically(buf);
398
399 Ok(())
400 }
401
402 fn read_image_boxed(self: Box<Self>, buf: &mut [u8]) -> ImageResult<()> {
403 (*self).read_image(buf)
404 }
405}
406