1use alloc::borrow::Cow;
2use alloc::vec::Vec;
3use core::convert::{TryFrom, TryInto};
4use core::iter::FusedIterator;
5use core::mem;
6use core::num::NonZeroU64;
7use std::io;
8use std::io::prelude::*;
9
10use crate::common::{Block, Frame};
11use crate::{AnyExtension, Extension, Repeat};
12
13mod converter;
14mod decoder;
15
16pub use self::decoder::{
17 Decoded, DecodingError, DecodingFormatError, FrameDataType, FrameDecoder, OutputBuffer,
18 StreamingDecoder, Version, PLTE_CHANNELS,
19};
20
21pub use self::converter::ColorOutput;
22use self::converter::PixelConverter;
23
24#[derive(Clone, Debug)]
25pub enum MemoryLimit {
27 Unlimited,
37 Bytes(NonZeroU64),
47}
48
49impl MemoryLimit {
50 fn check_size(&self, size: usize) -> Result<(), DecodingError> {
51 match self {
52 Self::Unlimited => Ok(()),
53 Self::Bytes(limit) => {
54 if size as u64 <= limit.get() {
55 Ok(())
56 } else {
57 Err(DecodingError::MemoryLimit)
58 }
59 }
60 }
61 }
62
63 fn buffer_size(&self, color: ColorOutput, width: u16, height: u16) -> Option<usize> {
64 let pixels = u64::from(width) * u64::from(height);
65
66 let bytes_per_pixel = match color {
67 ColorOutput::Indexed => 1,
68 ColorOutput::RGBA => 4,
69 };
70
71 let total_bytes = pixels * bytes_per_pixel;
73
74 let usize_bytes = usize::try_from(total_bytes).ok()?;
76
77 match self {
78 Self::Unlimited => Some(usize_bytes),
79 Self::Bytes(limit) => {
80 if total_bytes > limit.get() {
81 None
82 } else {
83 Some(usize_bytes)
84 }
85 }
86 }
87 }
88
89 #[inline]
90 fn try_reserve(&self, vec: &mut Vec<u8>, additional: usize) -> Result<(), DecodingError> {
91 let len = vec
92 .len()
93 .checked_add(additional)
94 .ok_or(DecodingError::MemoryLimit)?;
95 self.check_size(len)?;
96 vec.try_reserve(additional)
97 .map_err(|_| DecodingError::OutOfMemory)?;
98 Ok(())
99 }
100}
101
102#[derive(Clone, Debug)]
104pub struct DecodeOptions {
105 memory_limit: MemoryLimit,
106 color_output: ColorOutput,
107 check_frame_consistency: bool,
108 skip_frame_decoding: bool,
109 check_for_end_code: bool,
110 allow_unknown_blocks: bool,
111}
112
113impl Default for DecodeOptions {
114 fn default() -> Self {
115 Self::new()
116 }
117}
118
119impl DecodeOptions {
120 #[must_use]
122 #[inline]
123 pub fn new() -> Self {
124 Self {
125 memory_limit: MemoryLimit::Bytes(50_000_000.try_into().unwrap()), color_output: ColorOutput::Indexed,
127 check_frame_consistency: false,
128 skip_frame_decoding: false,
129 check_for_end_code: false,
130 allow_unknown_blocks: false,
131 }
132 }
133
134 #[inline]
136 pub fn set_color_output(&mut self, color: ColorOutput) {
137 self.color_output = color;
138 }
139
140 pub fn set_memory_limit(&mut self, limit: MemoryLimit) {
142 self.memory_limit = limit;
143 }
144
145 pub fn check_frame_consistency(&mut self, check: bool) {
156 self.check_frame_consistency = check;
157 }
158
159 pub fn skip_frame_decoding(&mut self, skip: bool) {
168 self.skip_frame_decoding = skip;
169 }
170
171 pub fn check_lzw_end_code(&mut self, check: bool) {
183 self.check_for_end_code = check;
184 }
185
186 pub fn allow_unknown_blocks(&mut self, check: bool) {
202 self.allow_unknown_blocks = check;
203 }
204
205 pub fn read_info<R: Read>(self, r: R) -> Result<Decoder<R>, DecodingError> {
209 Decoder::with_no_init(r, StreamingDecoder::with_options(&self), self).init()
210 }
211}
212
213struct ReadDecoder<R: Read> {
214 reader: io::BufReader<R>,
215 decoder: StreamingDecoder,
216 at_eof: bool,
217}
218
219impl<R: Read> ReadDecoder<R> {
220 #[inline(never)]
221 fn decode_next(
222 &mut self,
223 write_into: &mut OutputBuffer<'_>,
224 ) -> Result<Option<Decoded>, DecodingError> {
225 while !self.at_eof {
226 let (consumed, result) = {
227 let buf = self.reader.fill_buf()?;
228 if buf.is_empty() {
229 return Err(DecodingError::UnexpectedEof);
230 }
231
232 self.decoder.update(buf, write_into)?
233 };
234 self.reader.consume(consumed);
235 match result {
236 Decoded::Nothing => (),
237 Decoded::BlockStart(Block::Trailer) => {
238 self.at_eof = true;
239 }
240 result => return Ok(Some(result)),
241 }
242 }
243 Ok(None)
244 }
245
246 fn into_inner(self) -> io::BufReader<R> {
247 self.reader
248 }
249
250 fn decode_next_bytes(&mut self, out: &mut OutputBuffer<'_>) -> Result<usize, DecodingError> {
251 match self.decode_next(out)? {
252 Some(Decoded::BytesDecoded(len)) => Ok(len.get()),
253 Some(Decoded::DataEnd) => Ok(0),
254 _ => Err(DecodingError::format("unexpected data")),
255 }
256 }
257}
258const EXT_NAME_NETSCAPE: &[u8] = b"NETSCAPE2.0";
260const EXT_NAME_XMP: &[u8] = b"XMP DataXMP";
261const EXT_NAME_ICC: &[u8] = b"ICCRGBG1012";
262
263enum AppExtensionState {
265 None,
267 Netscape,
268 Xmp,
269 Icc,
270 Skip,
271}
272
273#[allow(dead_code)]
274pub struct Decoder<R: Read> {
276 decoder: ReadDecoder<R>,
277 pixel_converter: PixelConverter,
278 memory_limit: MemoryLimit,
279 bg_color: Option<u8>,
280 repeat: Repeat,
281 current_frame: Frame<'static>,
282 current_frame_data_type: FrameDataType,
283 app_extension_state: AppExtensionState,
284 xmp_metadata: Option<Vec<u8>>,
286 icc_profile: Option<Vec<u8>>,
288}
289
290impl<R> Decoder<R>
291where
292 R: Read,
293{
294 #[inline]
296 pub fn new(reader: R) -> Result<Self, DecodingError> {
297 DecodeOptions::new().read_info(reader)
298 }
299
300 #[must_use]
302 #[inline]
303 pub fn build() -> DecodeOptions {
304 DecodeOptions::new()
305 }
306
307 fn with_no_init(reader: R, decoder: StreamingDecoder, options: DecodeOptions) -> Self {
308 Self {
309 decoder: ReadDecoder {
310 reader: io::BufReader::new(reader),
311 decoder,
312 at_eof: false,
313 },
314 bg_color: None,
315 pixel_converter: PixelConverter::new(options.color_output),
316 memory_limit: options.memory_limit.clone(),
317 repeat: Repeat::default(),
318 current_frame: Frame::default(),
319 current_frame_data_type: FrameDataType::Pixels,
320 app_extension_state: AppExtensionState::None,
321 xmp_metadata: None,
322 icc_profile: None,
323 }
324 }
325
326 fn init(mut self) -> Result<Self, DecodingError> {
327 const APP_EXTENSION: AnyExtension = AnyExtension(Extension::Application as u8);
328 loop {
329 match self.decoder.decode_next(&mut OutputBuffer::None)? {
330 Some(Decoded::BackgroundColor(bg_color)) => {
331 self.bg_color = Some(bg_color);
332 }
333 Some(Decoded::GlobalPalette(palette)) => {
334 self.pixel_converter.set_global_palette(palette.into());
335 }
336 Some(Decoded::SubBlock {
337 ext: APP_EXTENSION,
338 is_last,
339 }) => {
340 self.read_application_extension(is_last)?;
341 }
342 Some(Decoded::HeaderEnd) => break,
343 Some(_) => {
344 continue;
346 }
347 None => {
348 return Err(DecodingError::format(
349 "file does not contain any image data",
350 ))
351 }
352 }
353 }
354 if let Some(palette) = self.pixel_converter.global_palette() {
356 if self.bg_color.unwrap_or(0) as usize >= (palette.len() / PLTE_CHANNELS) {
357 self.bg_color = None;
358 }
359 }
360 Ok(self)
361 }
362
363 fn read_application_extension(&mut self, is_last: bool) -> Result<(), DecodingError> {
364 let data = self.decoder.decoder.last_ext_sub_block();
365 match self.app_extension_state {
366 AppExtensionState::None => {
367 self.app_extension_state = match data {
369 EXT_NAME_NETSCAPE => AppExtensionState::Netscape,
370 EXT_NAME_XMP => {
371 self.xmp_metadata = Some(Vec::new());
372 AppExtensionState::Xmp
373 }
374 EXT_NAME_ICC => {
375 self.icc_profile = Some(Vec::new());
376 AppExtensionState::Icc
377 }
378 _ => AppExtensionState::Skip,
379 }
380 }
381 AppExtensionState::Netscape => {
382 if let [1, rest @ ..] = data {
383 if let Ok(repeat) = rest.try_into().map(u16::from_le_bytes) {
384 self.repeat = if repeat == 0 {
385 Repeat::Infinite
386 } else {
387 Repeat::Finite(repeat)
388 };
389 }
390 }
391 self.app_extension_state = AppExtensionState::Skip;
392 }
393 AppExtensionState::Xmp => {
394 if let Some(xmp_metadata) = &mut self.xmp_metadata {
395 self.memory_limit
398 .try_reserve(xmp_metadata, 1 + data.len())?;
399 xmp_metadata.push(data.len() as u8);
400 xmp_metadata.extend_from_slice(data);
401 if is_last {
402 const RAMP_SIZE: usize = 257;
407 if xmp_metadata.len() >= RAMP_SIZE
408 && xmp_metadata.ends_with(&[0x03, 0x02, 0x01, 0x00])
409 && xmp_metadata[xmp_metadata.len() - RAMP_SIZE..]
410 .starts_with(&[0x01, 0x0ff])
411 {
412 xmp_metadata.truncate(xmp_metadata.len() - RAMP_SIZE);
413 }
414 }
415 }
416 }
417 AppExtensionState::Icc => {
418 if let Some(icc) = &mut self.icc_profile {
419 self.memory_limit.try_reserve(icc, data.len())?;
420 icc.extend_from_slice(data);
421 }
422 }
423 AppExtensionState::Skip => {}
424 };
425 if is_last {
426 self.app_extension_state = AppExtensionState::None;
427 }
428 Ok(())
429 }
430
431 pub fn next_frame_info(&mut self) -> Result<Option<&Frame<'static>>, DecodingError> {
433 loop {
434 match self.decoder.decode_next(&mut OutputBuffer::None)? {
435 Some(Decoded::FrameMetadata(frame_data_type)) => {
436 self.current_frame = self.decoder.decoder.current_frame_mut().take();
437 self.current_frame_data_type = frame_data_type;
438 if self.current_frame.palette.is_none() && self.global_palette().is_none() {
439 return Err(DecodingError::format(
440 "no color table available for current frame",
441 ));
442 }
443 break;
444 }
445 Some(_) => (),
446 None => return Ok(None),
447 }
448 }
449 Ok(Some(&self.current_frame))
450 }
451
452 pub fn read_next_frame(&mut self) -> Result<Option<&Frame<'static>>, DecodingError> {
459 if self.next_frame_info()?.is_some() {
460 match self.current_frame_data_type {
461 FrameDataType::Pixels => {
462 self.pixel_converter.read_frame(
463 &mut self.current_frame,
464 &mut |out| self.decoder.decode_next_bytes(out),
465 &self.memory_limit,
466 )?;
467 }
468 FrameDataType::Lzw { min_code_size } => {
469 let mut vec = if matches!(self.current_frame.buffer, Cow::Owned(_)) {
470 let mut vec =
471 mem::replace(&mut self.current_frame.buffer, Cow::Borrowed(&[]))
472 .into_owned();
473 vec.clear();
474 vec
475 } else {
476 Vec::new()
477 };
478 vec.try_reserve(
480 usize::from(self.current_frame.width)
481 * usize::from(self.current_frame.height)
482 / 4,
483 )
484 .map_err(|_| DecodingError::OutOfMemory)?;
485 self.copy_lzw_into_buffer(min_code_size, &mut vec)?;
486 self.current_frame.buffer = Cow::Owned(vec);
487 }
488 }
489 Ok(Some(&self.current_frame))
490 } else {
491 Ok(None)
492 }
493 }
494
495 fn take_current_frame(&mut self) -> Option<Frame<'static>> {
497 if self.current_frame.buffer.is_empty() {
498 return None;
499 }
500 Some(self.current_frame.take())
501 }
502
503 pub fn read_into_buffer(&mut self, buf: &mut [u8]) -> Result<(), DecodingError> {
509 self.pixel_converter
510 .read_into_buffer(&self.current_frame, buf, &mut |out| {
511 self.decoder.decode_next_bytes(out)
512 })
513 }
514
515 fn copy_lzw_into_buffer(
516 &mut self,
517 min_code_size: u8,
518 buf: &mut Vec<u8>,
519 ) -> Result<(), DecodingError> {
520 buf.push(min_code_size);
522 loop {
523 match self.decoder.decode_next(&mut OutputBuffer::Vec(buf))? {
524 Some(Decoded::LzwDataCopied(_len)) => {}
525 Some(Decoded::DataEnd) => return Ok(()),
526 _ => return Err(DecodingError::format("unexpected data")),
527 }
528 }
529 }
530
531 pub fn fill_buffer(&mut self, buf: &mut [u8]) -> Result<bool, DecodingError> {
539 self.pixel_converter
540 .fill_buffer(&self.current_frame, buf, &mut |out| {
541 self.decoder.decode_next_bytes(out)
542 })
543 }
544
545 pub fn buffer_size(&self) -> usize {
547 self.pixel_converter
548 .buffer_size(&self.current_frame)
549 .unwrap()
550 }
551
552 pub fn line_length(&self) -> usize {
554 self.pixel_converter.line_length(&self.current_frame)
555 }
556
557 #[inline]
559 pub fn palette(&self) -> Result<&[u8], DecodingError> {
560 Ok(match self.current_frame.palette {
561 Some(ref table) => table,
562 None => self.global_palette().ok_or_else(|| {
563 DecodingError::format("no color table available for current frame")
564 })?,
565 })
566 }
567
568 pub fn global_palette(&self) -> Option<&[u8]> {
570 self.pixel_converter.global_palette()
571 }
572
573 #[inline]
575 pub fn width(&self) -> u16 {
576 self.decoder.decoder.width()
577 }
578
579 #[inline]
581 pub fn height(&self) -> u16 {
582 self.decoder.decoder.height()
583 }
584
585 #[inline]
587 #[must_use]
588 pub fn xmp_metadata(&self) -> Option<&[u8]> {
589 self.xmp_metadata.as_deref()
590 }
591
592 #[inline]
594 #[must_use]
595 pub fn icc_profile(&self) -> Option<&[u8]> {
596 self.icc_profile.as_deref()
597 }
598
599 pub fn into_inner(self) -> io::BufReader<R> {
601 self.decoder.into_inner()
602 }
603
604 pub fn bg_color(&self) -> Option<usize> {
609 self.bg_color.map(|v| v as usize)
610 }
611
612 #[inline]
614 pub fn repeat(&self) -> Repeat {
615 self.repeat
616 }
617}
618
619impl<R: Read> IntoIterator for Decoder<R> {
620 type Item = Result<Frame<'static>, DecodingError>;
621 type IntoIter = DecoderIter<R>;
622
623 #[inline]
624 fn into_iter(self) -> Self::IntoIter {
625 DecoderIter {
626 inner: self,
627 ended: false,
628 }
629 }
630}
631
632pub struct DecoderIter<R: Read> {
634 inner: Decoder<R>,
635 ended: bool,
636}
637
638impl<R: Read> DecoderIter<R> {
639 pub fn into_inner(self) -> io::BufReader<R> {
643 self.inner.into_inner()
644 }
645}
646
647impl<R: Read> FusedIterator for DecoderIter<R> {}
648
649impl<R: Read> Iterator for DecoderIter<R> {
650 type Item = Result<Frame<'static>, DecodingError>;
651
652 fn next(&mut self) -> Option<Self::Item> {
653 if !self.ended {
654 match self.inner.read_next_frame() {
655 Ok(Some(_)) => self.inner.take_current_frame().map(Ok),
656 Ok(None) => {
657 self.ended = true;
658 None
659 }
660 Err(err) => {
661 self.ended = true;
662 Some(Err(err))
663 }
664 }
665 } else {
666 None
667 }
668 }
669}