1 | use super::header::{Header, ImageType, ALPHA_BIT_MASK, SCREEN_ORIGIN_BIT_MASK}; |
2 | use crate::{ |
3 | color::{ColorType, ExtendedColorType}, |
4 | error::{ |
5 | ImageError, ImageResult, LimitError, LimitErrorKind, UnsupportedError, UnsupportedErrorKind, |
6 | }, |
7 | image::{ImageDecoder, ImageFormat, ImageReadBuffer}, |
8 | }; |
9 | use byteorder::ReadBytesExt; |
10 | use std::{ |
11 | io::{self, Read, Seek}, |
12 | mem, |
13 | }; |
14 | |
15 | struct ColorMap { |
16 | /// sizes in bytes |
17 | start_offset: usize, |
18 | entry_size: usize, |
19 | bytes: Vec<u8>, |
20 | } |
21 | |
22 | impl 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 |
49 | pub 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 | |
69 | impl<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 | |
413 | impl<'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 | |
496 | pub struct TGAReader<R> { |
497 | buffer: ImageReadBuffer, |
498 | decoder: TgaDecoder<R>, |
499 | } |
500 | impl<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 | |