| 1 | use std::borrow::Cow; |
| 2 | use std::io; |
| 3 | use std::iter::FusedIterator; |
| 4 | use std::mem; |
| 5 | |
| 6 | use std::io::prelude::*; |
| 7 | use std::num::NonZeroU64; |
| 8 | use std::convert::{TryFrom, TryInto}; |
| 9 | |
| 10 | use crate::Repeat; |
| 11 | use crate::common::{Block, Frame}; |
| 12 | |
| 13 | mod decoder; |
| 14 | mod converter; |
| 15 | |
| 16 | pub use self::decoder::{ |
| 17 | PLTE_CHANNELS, StreamingDecoder, Decoded, DecodingError, DecodingFormatError, |
| 18 | Version, FrameDataType, OutputBuffer, FrameDecoder |
| 19 | }; |
| 20 | |
| 21 | use self::converter::PixelConverter; |
| 22 | pub use self::converter::ColorOutput; |
| 23 | |
| 24 | #[derive (Clone, Debug)] |
| 25 | /// The maximum amount of memory the decoder is allowed to use for each frame |
| 26 | pub enum MemoryLimit { |
| 27 | /// Enforce no memory limit. |
| 28 | /// |
| 29 | /// If you intend to process images from unknown origins this is a potentially dangerous |
| 30 | /// constant to use, as your program could be vulnerable to decompression bombs. That is, |
| 31 | /// malicious images crafted specifically to require an enormous amount of memory to process |
| 32 | /// while having a disproportionately small file size. |
| 33 | /// |
| 34 | /// The risks for modern machines are a bit smaller as the size of each frame cannot |
| 35 | /// exceed 16GiB, but this is still a significant amount of memory. |
| 36 | Unlimited, |
| 37 | /// Limit the amount of memory that can be used for a single frame to this many bytes. |
| 38 | /// |
| 39 | /// It may not be enforced precisely due to allocator overhead |
| 40 | /// and the decoder potentially allocating small auxiliary buffers, |
| 41 | /// but it will precisely limit the size of the output buffer for each frame. |
| 42 | // |
| 43 | // The `NonZero` type is used to make FFI simpler. |
| 44 | // Due to the guaranteed niche optimization, `Unlimited` will be represented as `0`, |
| 45 | // and the whole enum as a simple `u64`. |
| 46 | Bytes(NonZeroU64), |
| 47 | } |
| 48 | |
| 49 | impl 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 | // This cannot overflow because the maximum possible value is 16GiB, well within u64 range |
| 72 | let total_bytes = pixels * bytes_per_pixel; |
| 73 | |
| 74 | // On 32-bit platforms the size of the output buffer may not be representable |
| 75 | 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 | /// Options for opening a GIF decoder. [`DecodeOptions::read_info`] will start the decoder. |
| 91 | #[derive (Clone, Debug)] |
| 92 | pub 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 | |
| 101 | impl Default for DecodeOptions { |
| 102 | fn default() -> Self { |
| 103 | Self::new() |
| 104 | } |
| 105 | } |
| 106 | |
| 107 | impl DecodeOptions { |
| 108 | /// Creates a new decoder builder |
| 109 | #[must_use ] |
| 110 | #[inline ] |
| 111 | pub fn new() -> DecodeOptions { |
| 112 | DecodeOptions { |
| 113 | memory_limit: MemoryLimit::Bytes(50_000_000.try_into().unwrap()), // 50 MB |
| 114 | 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 | /// Configure how color data is decoded. |
| 123 | #[inline ] |
| 124 | pub fn set_color_output(&mut self, color: ColorOutput) { |
| 125 | self.color_output = color; |
| 126 | } |
| 127 | |
| 128 | /// Configure a memory limit for decoding. |
| 129 | pub fn set_memory_limit(&mut self, limit: MemoryLimit) { |
| 130 | self.memory_limit = limit; |
| 131 | } |
| 132 | |
| 133 | /// Configure if frames must be within the screen descriptor. |
| 134 | /// |
| 135 | /// The default is `false`. |
| 136 | /// |
| 137 | /// When turned on, all frame descriptors being read must fit within the screen descriptor or |
| 138 | /// otherwise an error is returned and the stream left in an unspecified state. |
| 139 | /// |
| 140 | /// When turned off, frames may be arbitrarily larger or offset in relation to the screen. Many |
| 141 | /// other decoder libraries handle this in highly divergent ways. This moves all checks to the |
| 142 | /// caller, for example to emulate a specific style. |
| 143 | pub fn check_frame_consistency(&mut self, check: bool) { |
| 144 | self.check_frame_consistency = check; |
| 145 | } |
| 146 | |
| 147 | /// Configure whether to skip decoding frames. |
| 148 | /// |
| 149 | /// The default is false. |
| 150 | /// |
| 151 | /// When turned on, LZW decoding is skipped. [`Decoder::read_next_frame`] will return |
| 152 | /// compressed LZW bytes in frame's data. |
| 153 | /// [`Decoder::next_frame_info`] will return the metadata of the next frame as usual. |
| 154 | /// This is useful to count frames without incurring the overhead of decoding. |
| 155 | pub fn skip_frame_decoding(&mut self, skip: bool) { |
| 156 | self.skip_frame_decoding = skip; |
| 157 | } |
| 158 | |
| 159 | /// Configure if LZW encoded blocks must end with a marker end code. |
| 160 | /// |
| 161 | /// The default is `false`. |
| 162 | /// |
| 163 | /// When turned on, all image data blocks—which are LZW encoded—must contain a special bit |
| 164 | /// sequence signalling the end of the data. LZW processing terminates when this code is |
| 165 | /// encountered. The specification states that it must be the last code output by the encoder |
| 166 | /// for an image. |
| 167 | /// |
| 168 | /// When turned off then image data blocks can simply end. Note that this might silently ignore |
| 169 | /// some bits of the last or second to last byte. |
| 170 | pub fn check_lzw_end_code(&mut self, check: bool) { |
| 171 | self.check_for_end_code = check; |
| 172 | } |
| 173 | |
| 174 | /// Configure if unknown blocks are allowed to be decoded. |
| 175 | /// |
| 176 | /// The default is `false`. |
| 177 | /// |
| 178 | /// When turned on, the decoder will allow unknown blocks to be in the |
| 179 | /// `BlockStart` position. |
| 180 | /// |
| 181 | /// When turned off, decoded block starts must mark an `Image`, `Extension`, |
| 182 | /// or `Trailer` block. Otherwise, the decoded image will return an error. |
| 183 | /// If an unknown block error is returned from decoding, enabling this |
| 184 | /// setting may allow for a further state of decoding on the next attempt. |
| 185 | pub fn allow_unknown_blocks(&mut self, check: bool) { |
| 186 | self.allow_unknown_blocks = check; |
| 187 | } |
| 188 | |
| 189 | /// Reads the logical screen descriptor including the global color palette |
| 190 | /// |
| 191 | /// Returns a [`Decoder`]. All decoder configuration has to be done beforehand. |
| 192 | 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 | |
| 197 | struct ReadDecoder<R: Read> { |
| 198 | reader: io::BufReader<R>, |
| 199 | decoder: StreamingDecoder, |
| 200 | at_eof: bool, |
| 201 | } |
| 202 | |
| 203 | impl<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)] |
| 241 | /// GIF decoder. Create [`DecodeOptions`] to get started, and call [`DecodeOptions::read_info`]. |
| 242 | pub 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 | |
| 251 | impl<R> Decoder<R> where R: Read { |
| 252 | /// Create a new decoder with default options. |
| 253 | #[inline ] |
| 254 | pub fn new(reader: R) -> Result<Self, DecodingError> { |
| 255 | DecodeOptions::new().read_info(reader) |
| 256 | } |
| 257 | |
| 258 | /// Return a builder that allows configuring limits etc. |
| 259 | #[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 | // There will be extra events when parsing application extension |
| 297 | continue |
| 298 | }, |
| 299 | None => return Err(DecodingError::format( |
| 300 | "file does not contain any image data" |
| 301 | )) |
| 302 | } |
| 303 | } |
| 304 | // If the background color is invalid, ignore it |
| 305 | 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 | /// Returns the next frame info |
| 314 | 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 | /// Reads the next frame from the image. |
| 335 | /// |
| 336 | /// Do not call `Self::next_frame_info` beforehand. |
| 337 | /// Deinterlaces the result. |
| 338 | /// |
| 339 | /// You can also call `.into_iter()` on the decoder to use it as a regular iterator. |
| 340 | 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 | // Guesstimate 2bpp |
| 355 | 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 | /// This is private for iterator's use |
| 368 | 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 | /// Reads the data of the current frame into a pre-allocated buffer. |
| 376 | /// |
| 377 | /// `Self::next_frame_info` needs to be called beforehand. |
| 378 | /// The length of `buf` must be at least `Self::buffer_size`. |
| 379 | /// Deinterlaces the result. |
| 380 | 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 | // `write_lzw_pre_encoded_frame` smuggles `min_code_size` in the first byte. |
| 386 | 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 | /// Reads data of the current frame into a pre-allocated buffer until the buffer has been |
| 397 | /// filled completely. |
| 398 | /// |
| 399 | /// The buffer length must be an even number of pixels (multiple of 4 if decoding RGBA). |
| 400 | /// |
| 401 | /// `Self::next_frame_info` needs to be called beforehand. Returns `true` if the supplied |
| 402 | /// buffer could be filled completely. Should not be called after `false` had been returned. |
| 403 | 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 | /// Output buffer size |
| 408 | pub fn buffer_size(&self) -> usize { |
| 409 | self.pixel_converter.buffer_size(&self.current_frame).unwrap() |
| 410 | } |
| 411 | |
| 412 | /// Line length of the current frame |
| 413 | pub fn line_length(&self) -> usize { |
| 414 | self.pixel_converter.line_length(&self.current_frame) |
| 415 | } |
| 416 | |
| 417 | /// Returns the color palette relevant for the frame that has been decoded |
| 418 | #[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 | /// The global color palette |
| 429 | pub fn global_palette(&self) -> Option<&[u8]> { |
| 430 | self.pixel_converter.global_palette() |
| 431 | } |
| 432 | |
| 433 | /// Width of the image |
| 434 | #[inline ] |
| 435 | pub fn width(&self) -> u16 { |
| 436 | self.decoder.decoder.width() |
| 437 | } |
| 438 | |
| 439 | /// Height of the image |
| 440 | #[inline ] |
| 441 | pub fn height(&self) -> u16 { |
| 442 | self.decoder.decoder.height() |
| 443 | } |
| 444 | |
| 445 | /// Abort decoding and recover the `io::Read` instance |
| 446 | pub fn into_inner(self) -> io::BufReader<R> { |
| 447 | self.decoder.into_inner() |
| 448 | } |
| 449 | |
| 450 | /// Index of the background color in the global palette |
| 451 | /// |
| 452 | /// In practice this is not used, and the background is |
| 453 | /// always transparent |
| 454 | pub fn bg_color(&self) -> Option<usize> { |
| 455 | self.bg_color.map(|v| v as usize) |
| 456 | } |
| 457 | |
| 458 | /// Number of loop repetitions |
| 459 | #[inline ] |
| 460 | pub fn repeat(&self) -> Repeat { |
| 461 | self.repeat |
| 462 | } |
| 463 | } |
| 464 | |
| 465 | impl<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 | |
| 478 | /// Use `decoder.into_iter()` to iterate over the frames |
| 479 | pub struct DecoderIter<R: Read> { |
| 480 | inner: Decoder<R>, |
| 481 | ended: bool, |
| 482 | } |
| 483 | |
| 484 | impl<R: Read> DecoderIter<R> { |
| 485 | /// Abort decoding and recover the `io::Read` instance |
| 486 | /// |
| 487 | /// Use `for frame in iter.by_ref()` to be able to call this afterwards. |
| 488 | pub fn into_inner(self) -> io::BufReader<R> { |
| 489 | self.inner.into_inner() |
| 490 | } |
| 491 | } |
| 492 | |
| 493 | impl<R: Read> FusedIterator for DecoderIter<R> {} |
| 494 | |
| 495 | impl<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: DecodingError) => { |
| 507 | self.ended = true; |
| 508 | Some(Err(err)) |
| 509 | }, |
| 510 | } |
| 511 | } else { |
| 512 | None |
| 513 | } |
| 514 | } |
| 515 | } |
| 516 | |