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 TgaDecoder = &mut self.decoder;
503 self.buffer.read(buf, |buf: &mut [u8]| decoder.read_scanline(buf))
504 }
505}
506