1use std::borrow::Cow;
2use std::io;
3use std::iter::FusedIterator;
4use std::mem;
5
6use std::io::prelude::*;
7use std::num::NonZeroU64;
8use std::convert::{TryFrom, TryInto};
9
10use crate::Repeat;
11use crate::common::{Block, Frame};
12
13mod decoder;
14mod converter;
15
16pub use self::decoder::{
17 PLTE_CHANNELS, StreamingDecoder, Decoded, DecodingError, DecodingFormatError,
18 Version, FrameDataType, OutputBuffer, FrameDecoder
19};
20
21use self::converter::PixelConverter;
22pub use self::converter::ColorOutput;
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 MemoryLimit::Unlimited => Ok(()),
53 MemoryLimit::Bytes(limit) => {
54 if size as u64 <= limit.get() {
55 Ok(())
56 } else {
57 Err(DecodingError::format("memory limit reached"))
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 MemoryLimit::Unlimited => Some(usize_bytes),
79 MemoryLimit::Bytes(limit) => {
80 if total_bytes > limit.get() {
81 None
82 } else {
83 Some(usize_bytes)
84 }
85 },
86 }
87 }
88}
89
90#[derive(Clone, Debug)]
92pub struct DecodeOptions {
93 memory_limit: MemoryLimit,
94 color_output: ColorOutput,
95 check_frame_consistency: bool,
96 skip_frame_decoding: bool,
97 check_for_end_code: bool,
98 allow_unknown_blocks: bool,
99}
100
101impl Default for DecodeOptions {
102 fn default() -> Self {
103 Self::new()
104 }
105}
106
107impl DecodeOptions {
108 #[must_use]
110 #[inline]
111 pub fn new() -> DecodeOptions {
112 DecodeOptions {
113 memory_limit: MemoryLimit::Bytes(50_000_000.try_into().unwrap()), color_output: ColorOutput::Indexed,
115 check_frame_consistency: false,
116 skip_frame_decoding: false,
117 check_for_end_code: false,
118 allow_unknown_blocks: false,
119 }
120 }
121
122 #[inline]
124 pub fn set_color_output(&mut self, color: ColorOutput) {
125 self.color_output = color;
126 }
127
128 pub fn set_memory_limit(&mut self, limit: MemoryLimit) {
130 self.memory_limit = limit;
131 }
132
133 pub fn check_frame_consistency(&mut self, check: bool) {
144 self.check_frame_consistency = check;
145 }
146
147 pub fn skip_frame_decoding(&mut self, skip: bool) {
156 self.skip_frame_decoding = skip;
157 }
158
159 pub fn check_lzw_end_code(&mut self, check: bool) {
171 self.check_for_end_code = check;
172 }
173
174 pub fn allow_unknown_blocks(&mut self, check: bool) {
186 self.allow_unknown_blocks = check;
187 }
188
189 pub fn read_info<R: Read>(self, r: R) -> Result<Decoder<R>, DecodingError> {
193 Decoder::with_no_init(r, StreamingDecoder::with_options(&self), self).init()
194 }
195}
196
197struct ReadDecoder<R: Read> {
198 reader: io::BufReader<R>,
199 decoder: StreamingDecoder,
200 at_eof: bool,
201}
202
203impl<R: Read> ReadDecoder<R> {
204 #[inline(never)]
205 fn decode_next(&mut self, write_into: &mut OutputBuffer<'_>) -> Result<Option<Decoded>, DecodingError> {
206 while !self.at_eof {
207 let (consumed, result) = {
208 let buf = self.reader.fill_buf()?;
209 if buf.is_empty() {
210 return Err(io::ErrorKind::UnexpectedEof.into());
211 }
212
213 self.decoder.update(buf, write_into)?
214 };
215 self.reader.consume(consumed);
216 match result {
217 Decoded::Nothing => (),
218 Decoded::BlockStart(Block::Trailer) => {
219 self.at_eof = true;
220 },
221 result => return Ok(Some(result))
222 }
223 }
224 Ok(None)
225 }
226
227 fn into_inner(self) -> io::BufReader<R> {
228 self.reader
229 }
230
231 fn decode_next_bytes(&mut self, out: &mut OutputBuffer<'_>) -> Result<usize, DecodingError> {
232 match self.decode_next(out)? {
233 Some(Decoded::BytesDecoded(len)) => Ok(len.get()),
234 Some(Decoded::DataEnd) => Ok(0),
235 _ => Err(DecodingError::format("unexpected data")),
236 }
237 }
238}
239
240#[allow(dead_code)]
241pub struct Decoder<R: Read> {
243 decoder: ReadDecoder<R>,
244 pixel_converter: PixelConverter,
245 bg_color: Option<u8>,
246 repeat: Repeat,
247 current_frame: Frame<'static>,
248 current_frame_data_type: FrameDataType,
249}
250
251impl<R> Decoder<R> where R: Read {
252 #[inline]
254 pub fn new(reader: R) -> Result<Self, DecodingError> {
255 DecodeOptions::new().read_info(reader)
256 }
257
258 #[must_use]
260 #[inline]
261 pub fn build() -> DecodeOptions {
262 DecodeOptions::new()
263 }
264
265 fn with_no_init(reader: R, decoder: StreamingDecoder, options: DecodeOptions) -> Decoder<R> {
266 Decoder {
267 decoder: ReadDecoder {
268 reader: io::BufReader::new(reader),
269 decoder,
270 at_eof: false,
271 },
272 bg_color: None,
273 pixel_converter: PixelConverter::new(options.color_output, options.memory_limit),
274 repeat: Repeat::default(),
275 current_frame: Frame::default(),
276 current_frame_data_type: FrameDataType::Pixels,
277 }
278 }
279
280 fn init(mut self) -> Result<Self, DecodingError> {
281 loop {
282 match self.decoder.decode_next(&mut OutputBuffer::None)? {
283 Some(Decoded::BackgroundColor(bg_color)) => {
284 self.bg_color = Some(bg_color);
285 }
286 Some(Decoded::GlobalPalette(palette)) => {
287 self.pixel_converter.set_global_palette(palette.into());
288 },
289 Some(Decoded::Repetitions(repeat)) => {
290 self.repeat = repeat;
291 },
292 Some(Decoded::HeaderEnd) => {
293 break
294 },
295 Some(_) => {
296 continue
298 },
299 None => return Err(DecodingError::format(
300 "file does not contain any image data"
301 ))
302 }
303 }
304 if let Some(palette) = self.pixel_converter.global_palette() {
306 if self.bg_color.unwrap_or(0) as usize >= (palette.len() / PLTE_CHANNELS) {
307 self.bg_color = None;
308 }
309 }
310 Ok(self)
311 }
312
313 pub fn next_frame_info(&mut self) -> Result<Option<&Frame<'static>>, DecodingError> {
315 loop {
316 match self.decoder.decode_next(&mut OutputBuffer::None)? {
317 Some(Decoded::FrameMetadata(frame_data_type)) => {
318 self.current_frame = self.decoder.decoder.current_frame_mut().take();
319 self.current_frame_data_type = frame_data_type;
320 if self.current_frame.palette.is_none() && self.global_palette().is_none() {
321 return Err(DecodingError::format(
322 "no color table available for current frame",
323 ));
324 }
325 break;
326 }
327 Some(_) => (),
328 None => return Ok(None),
329 }
330 }
331 Ok(Some(&self.current_frame))
332 }
333
334 pub fn read_next_frame(&mut self) -> Result<Option<&Frame<'static>>, DecodingError> {
341 if let Some(_) = self.next_frame_info()? {
342 match self.current_frame_data_type {
343 FrameDataType::Pixels => {
344 self.pixel_converter.read_frame(&mut self.current_frame, &mut |out| self.decoder.decode_next_bytes(out))?;
345 },
346 FrameDataType::Lzw { min_code_size } => {
347 let mut vec = if matches!(self.current_frame.buffer, Cow::Owned(_)) {
348 let mut vec = mem::replace(&mut self.current_frame.buffer, Cow::Borrowed(&[])).into_owned();
349 vec.clear();
350 vec
351 } else {
352 Vec::new()
353 };
354 vec.try_reserve(usize::from(self.current_frame.width) * usize::from(self.current_frame.height) / 4)
356 .map_err(|_| io::Error::from(io::ErrorKind::OutOfMemory))?;
357 self.copy_lzw_into_buffer(min_code_size, &mut vec)?;
358 self.current_frame.buffer = Cow::Owned(vec);
359 },
360 }
361 Ok(Some(&self.current_frame))
362 } else {
363 Ok(None)
364 }
365 }
366
367 fn take_current_frame(&mut self) -> Option<Frame<'static>> {
369 if self.current_frame.buffer.is_empty() {
370 return None;
371 }
372 Some(self.current_frame.take())
373 }
374
375 pub fn read_into_buffer(&mut self, buf: &mut [u8]) -> Result<(), DecodingError> {
381 self.pixel_converter.read_into_buffer(&mut self.current_frame, buf, &mut |out| self.decoder.decode_next_bytes(out))
382 }
383
384 fn copy_lzw_into_buffer(&mut self, min_code_size: u8, buf: &mut Vec<u8>) -> Result<(), DecodingError> {
385 buf.push(min_code_size);
387 loop {
388 match self.decoder.decode_next(&mut OutputBuffer::Vec(buf))? {
389 Some(Decoded::LzwDataCopied(_len)) => {},
390 Some(Decoded::DataEnd) => return Ok(()),
391 _ => return Err(DecodingError::format("unexpected data")),
392 }
393 }
394 }
395
396 pub fn fill_buffer(&mut self, buf: &mut [u8]) -> Result<bool, DecodingError> {
404 self.pixel_converter.fill_buffer(&mut self.current_frame, buf, &mut |out| self.decoder.decode_next_bytes(out))
405 }
406
407 pub fn buffer_size(&self) -> usize {
409 self.pixel_converter.buffer_size(&self.current_frame).unwrap()
410 }
411
412 pub fn line_length(&self) -> usize {
414 self.pixel_converter.line_length(&self.current_frame)
415 }
416
417 #[inline]
419 pub fn palette(&self) -> Result<&[u8], DecodingError> {
420 Ok(match self.current_frame.palette {
421 Some(ref table) => table,
422 None => self.global_palette().ok_or(DecodingError::format(
423 "no color table available for current frame",
424 ))?,
425 })
426 }
427
428 pub fn global_palette(&self) -> Option<&[u8]> {
430 self.pixel_converter.global_palette()
431 }
432
433 #[inline]
435 pub fn width(&self) -> u16 {
436 self.decoder.decoder.width()
437 }
438
439 #[inline]
441 pub fn height(&self) -> u16 {
442 self.decoder.decoder.height()
443 }
444
445 pub fn into_inner(self) -> io::BufReader<R> {
447 self.decoder.into_inner()
448 }
449
450 pub fn bg_color(&self) -> Option<usize> {
455 self.bg_color.map(|v| v as usize)
456 }
457
458 #[inline]
460 pub fn repeat(&self) -> Repeat {
461 self.repeat
462 }
463}
464
465impl<R: Read> IntoIterator for Decoder<R> {
466 type Item = Result<Frame<'static>, DecodingError>;
467 type IntoIter = DecoderIter<R>;
468
469 #[inline]
470 fn into_iter(self) -> Self::IntoIter {
471 DecoderIter {
472 inner: self,
473 ended: false,
474 }
475 }
476}
477
478pub struct DecoderIter<R: Read> {
480 inner: Decoder<R>,
481 ended: bool,
482}
483
484impl<R: Read> DecoderIter<R> {
485 pub fn into_inner(self) -> io::BufReader<R> {
489 self.inner.into_inner()
490 }
491}
492
493impl<R: Read> FusedIterator for DecoderIter<R> {}
494
495impl<R: Read> Iterator for DecoderIter<R> {
496 type Item = Result<Frame<'static>, DecodingError>;
497
498 fn next(&mut self) -> Option<Self::Item> {
499 if !self.ended {
500 match self.inner.read_next_frame() {
501 Ok(Some(_)) => self.inner.take_current_frame().map(Ok),
502 Ok(None) => {
503 self.ended = true;
504 None
505 },
506 Err(err) => {
507 self.ended = true;
508 Some(Err(err))
509 },
510 }
511 } else {
512 None
513 }
514 }
515}