image/codecs/tga/
decoder.rs

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