1 | mod stream; |
2 | pub(crate) mod transform; |
3 | mod zlib; |
4 | |
5 | pub use self::stream::{DecodeOptions, Decoded, DecodingError, StreamingDecoder}; |
6 | use self::stream::{FormatErrorInner, CHUNCK_BUFFER_SIZE}; |
7 | use self::transform::{create_transform_fn, TransformFn}; |
8 | |
9 | use std::io::{BufRead, BufReader, Read}; |
10 | use std::mem; |
11 | use std::ops::Range; |
12 | |
13 | use crate::adam7; |
14 | use crate::chunk; |
15 | use crate::common::{ |
16 | BitDepth, BytesPerPixel, ColorType, Info, ParameterErrorKind, Transformations, |
17 | }; |
18 | use crate::filter::{unfilter, FilterType}; |
19 | |
20 | /* |
21 | pub enum InterlaceHandling { |
22 | /// Outputs the raw rows |
23 | RawRows, |
24 | /// Fill missing the pixels from the existing ones |
25 | Rectangle, |
26 | /// Only fill the needed pixels |
27 | Sparkle |
28 | } |
29 | */ |
30 | |
31 | /// Output info. |
32 | /// |
33 | /// This describes one particular frame of the image that was written into the output buffer. |
34 | #[derive (Debug, PartialEq, Eq)] |
35 | pub struct OutputInfo { |
36 | /// The pixel width of this frame. |
37 | pub width: u32, |
38 | /// The pixel height of this frame. |
39 | pub height: u32, |
40 | /// The chosen output color type. |
41 | pub color_type: ColorType, |
42 | /// The chosen output bit depth. |
43 | pub bit_depth: BitDepth, |
44 | /// The byte count of each scan line in the image. |
45 | pub line_size: usize, |
46 | } |
47 | |
48 | impl OutputInfo { |
49 | /// Returns the size needed to hold a decoded frame |
50 | /// If the output buffer was larger then bytes after this count should be ignored. They may |
51 | /// still have been changed. |
52 | pub fn buffer_size(&self) -> usize { |
53 | self.line_size * self.height as usize |
54 | } |
55 | } |
56 | |
57 | #[derive (Clone, Copy, Debug)] |
58 | /// Limits on the resources the `Decoder` is allowed too use |
59 | pub struct Limits { |
60 | /// maximum number of bytes the decoder is allowed to allocate, default is 64Mib |
61 | pub bytes: usize, |
62 | } |
63 | |
64 | impl Limits { |
65 | pub(crate) fn reserve_bytes(&mut self, bytes: usize) -> Result<(), DecodingError> { |
66 | if self.bytes >= bytes { |
67 | self.bytes -= bytes; |
68 | Ok(()) |
69 | } else { |
70 | Err(DecodingError::LimitsExceeded) |
71 | } |
72 | } |
73 | } |
74 | |
75 | impl Default for Limits { |
76 | fn default() -> Limits { |
77 | Limits { |
78 | bytes: 1024 * 1024 * 64, |
79 | } |
80 | } |
81 | } |
82 | |
83 | /// PNG Decoder |
84 | pub struct Decoder<R: Read> { |
85 | read_decoder: ReadDecoder<R>, |
86 | /// Output transformations |
87 | transform: Transformations, |
88 | } |
89 | |
90 | /// A row of data with interlace information attached. |
91 | #[derive (Clone, Copy, Debug)] |
92 | pub struct InterlacedRow<'data> { |
93 | data: &'data [u8], |
94 | interlace: InterlaceInfo, |
95 | } |
96 | |
97 | impl<'data> InterlacedRow<'data> { |
98 | pub fn data(&self) -> &'data [u8] { |
99 | self.data |
100 | } |
101 | |
102 | pub fn interlace(&self) -> InterlaceInfo { |
103 | self.interlace |
104 | } |
105 | } |
106 | |
107 | /// PNG (2003) specifies two interlace modes, but reserves future extensions. |
108 | #[derive (Clone, Copy, Debug)] |
109 | pub enum InterlaceInfo { |
110 | /// the null method means no interlacing |
111 | Null, |
112 | /// Adam7 derives its name from doing 7 passes over the image, only decoding a subset of all pixels in each pass. |
113 | /// The following table shows pictorially what parts of each 8x8 area of the image is found in each pass: |
114 | /// |
115 | /// 1 6 4 6 2 6 4 6 |
116 | /// 7 7 7 7 7 7 7 7 |
117 | /// 5 6 5 6 5 6 5 6 |
118 | /// 7 7 7 7 7 7 7 7 |
119 | /// 3 6 4 6 3 6 4 6 |
120 | /// 7 7 7 7 7 7 7 7 |
121 | /// 5 6 5 6 5 6 5 6 |
122 | /// 7 7 7 7 7 7 7 7 |
123 | Adam7 { pass: u8, line: u32, width: u32 }, |
124 | } |
125 | |
126 | /// A row of data without interlace information. |
127 | #[derive (Clone, Copy, Debug)] |
128 | pub struct Row<'data> { |
129 | data: &'data [u8], |
130 | } |
131 | |
132 | impl<'data> Row<'data> { |
133 | pub fn data(&self) -> &'data [u8] { |
134 | self.data |
135 | } |
136 | } |
137 | |
138 | impl<R: Read> Decoder<R> { |
139 | /// Create a new decoder configuration with default limits. |
140 | pub fn new(r: R) -> Decoder<R> { |
141 | Decoder::new_with_limits(r, Limits::default()) |
142 | } |
143 | |
144 | /// Create a new decoder configuration with custom limits. |
145 | pub fn new_with_limits(r: R, limits: Limits) -> Decoder<R> { |
146 | let mut decoder = StreamingDecoder::new(); |
147 | decoder.limits = limits; |
148 | |
149 | Decoder { |
150 | read_decoder: ReadDecoder { |
151 | reader: BufReader::with_capacity(CHUNCK_BUFFER_SIZE, r), |
152 | decoder, |
153 | at_eof: false, |
154 | }, |
155 | transform: Transformations::IDENTITY, |
156 | } |
157 | } |
158 | |
159 | /// Create a new decoder configuration with custom `DecodeOptions`. |
160 | pub fn new_with_options(r: R, decode_options: DecodeOptions) -> Decoder<R> { |
161 | let mut decoder = StreamingDecoder::new_with_options(decode_options); |
162 | decoder.limits = Limits::default(); |
163 | |
164 | Decoder { |
165 | read_decoder: ReadDecoder { |
166 | reader: BufReader::with_capacity(CHUNCK_BUFFER_SIZE, r), |
167 | decoder, |
168 | at_eof: false, |
169 | }, |
170 | transform: Transformations::IDENTITY, |
171 | } |
172 | } |
173 | |
174 | /// Limit resource usage. |
175 | /// |
176 | /// Note that your allocations, e.g. when reading into a pre-allocated buffer, are __NOT__ |
177 | /// considered part of the limits. Nevertheless, required intermediate buffers such as for |
178 | /// singular lines is checked against the limit. |
179 | /// |
180 | /// Note that this is a best-effort basis. |
181 | /// |
182 | /// ``` |
183 | /// use std::fs::File; |
184 | /// use png::{Decoder, Limits}; |
185 | /// // This image is 32×32, 1bit per pixel. The reader buffers one row which requires 4 bytes. |
186 | /// let mut limits = Limits::default(); |
187 | /// limits.bytes = 3; |
188 | /// let mut decoder = Decoder::new_with_limits(File::open("tests/pngsuite/basi0g01.png" ).unwrap(), limits); |
189 | /// assert!(decoder.read_info().is_err()); |
190 | /// |
191 | /// // This image is 32x32 pixels, so the decoder will allocate less than 10Kib |
192 | /// let mut limits = Limits::default(); |
193 | /// limits.bytes = 10*1024; |
194 | /// let mut decoder = Decoder::new_with_limits(File::open("tests/pngsuite/basi0g01.png" ).unwrap(), limits); |
195 | /// assert!(decoder.read_info().is_ok()); |
196 | /// ``` |
197 | pub fn set_limits(&mut self, limits: Limits) { |
198 | self.read_decoder.decoder.limits = limits; |
199 | } |
200 | |
201 | /// Read the PNG header and return the information contained within. |
202 | /// |
203 | /// Most image metadata will not be read until `read_info` is called, so those fields will be |
204 | /// None or empty. |
205 | pub fn read_header_info(&mut self) -> Result<&Info<'static>, DecodingError> { |
206 | let mut buf = Vec::new(); |
207 | while self.read_decoder.info().is_none() { |
208 | buf.clear(); |
209 | if self.read_decoder.decode_next(&mut buf)?.is_none() { |
210 | return Err(DecodingError::Format( |
211 | FormatErrorInner::UnexpectedEof.into(), |
212 | )); |
213 | } |
214 | } |
215 | Ok(self.read_decoder.info().unwrap()) |
216 | } |
217 | |
218 | /// Reads all meta data until the first IDAT chunk |
219 | pub fn read_info(mut self) -> Result<Reader<R>, DecodingError> { |
220 | self.read_header_info()?; |
221 | |
222 | let mut reader = Reader { |
223 | decoder: self.read_decoder, |
224 | bpp: BytesPerPixel::One, |
225 | subframe: SubframeInfo::not_yet_init(), |
226 | fctl_read: 0, |
227 | next_frame: SubframeIdx::Initial, |
228 | data_stream: Vec::new(), |
229 | prev_start: 0, |
230 | current_start: 0, |
231 | transform: self.transform, |
232 | transform_fn: None, |
233 | scratch_buffer: Vec::new(), |
234 | }; |
235 | |
236 | // Check if the decoding buffer of a single raw line has a valid size. |
237 | if reader.info().checked_raw_row_length().is_none() { |
238 | return Err(DecodingError::LimitsExceeded); |
239 | } |
240 | |
241 | // Check if the output buffer has a valid size. |
242 | let (width, height) = reader.info().size(); |
243 | let (color, depth) = reader.output_color_type(); |
244 | let rowlen = color |
245 | .checked_raw_row_length(depth, width) |
246 | .ok_or(DecodingError::LimitsExceeded)? |
247 | - 1; |
248 | let height: usize = |
249 | std::convert::TryFrom::try_from(height).map_err(|_| DecodingError::LimitsExceeded)?; |
250 | if rowlen.checked_mul(height).is_none() { |
251 | return Err(DecodingError::LimitsExceeded); |
252 | } |
253 | |
254 | reader.read_until_image_data()?; |
255 | Ok(reader) |
256 | } |
257 | |
258 | /// Set the allowed and performed transformations. |
259 | /// |
260 | /// A transformation is a pre-processing on the raw image data modifying content or encoding. |
261 | /// Many options have an impact on memory or CPU usage during decoding. |
262 | pub fn set_transformations(&mut self, transform: Transformations) { |
263 | self.transform = transform; |
264 | } |
265 | |
266 | /// Set the decoder to ignore all text chunks while parsing. |
267 | /// |
268 | /// eg. |
269 | /// ``` |
270 | /// use std::fs::File; |
271 | /// use png::Decoder; |
272 | /// let mut decoder = Decoder::new(File::open("tests/pngsuite/basi0g01.png" ).unwrap()); |
273 | /// decoder.set_ignore_text_chunk(true); |
274 | /// assert!(decoder.read_info().is_ok()); |
275 | /// ``` |
276 | pub fn set_ignore_text_chunk(&mut self, ignore_text_chunk: bool) { |
277 | self.read_decoder |
278 | .decoder |
279 | .set_ignore_text_chunk(ignore_text_chunk); |
280 | } |
281 | |
282 | /// Set the decoder to ignore and not verify the Adler-32 checksum |
283 | /// and CRC code. |
284 | pub fn ignore_checksums(&mut self, ignore_checksums: bool) { |
285 | self.read_decoder |
286 | .decoder |
287 | .set_ignore_adler32(ignore_checksums); |
288 | self.read_decoder.decoder.set_ignore_crc(ignore_checksums); |
289 | } |
290 | } |
291 | |
292 | struct ReadDecoder<R: Read> { |
293 | reader: BufReader<R>, |
294 | decoder: StreamingDecoder, |
295 | at_eof: bool, |
296 | } |
297 | |
298 | impl<R: Read> ReadDecoder<R> { |
299 | /// Returns the next decoded chunk. If the chunk is an ImageData chunk, its contents are written |
300 | /// into image_data. |
301 | fn decode_next(&mut self, image_data: &mut Vec<u8>) -> Result<Option<Decoded>, DecodingError> { |
302 | while !self.at_eof { |
303 | let (consumed, result) = { |
304 | let buf = self.reader.fill_buf()?; |
305 | if buf.is_empty() { |
306 | return Err(DecodingError::Format( |
307 | FormatErrorInner::UnexpectedEof.into(), |
308 | )); |
309 | } |
310 | self.decoder.update(buf, image_data)? |
311 | }; |
312 | self.reader.consume(consumed); |
313 | match result { |
314 | Decoded::Nothing => (), |
315 | Decoded::ImageEnd => self.at_eof = true, |
316 | result => return Ok(Some(result)), |
317 | } |
318 | } |
319 | Ok(None) |
320 | } |
321 | |
322 | fn finish_decoding(&mut self) -> Result<(), DecodingError> { |
323 | while !self.at_eof { |
324 | let buf = self.reader.fill_buf()?; |
325 | if buf.is_empty() { |
326 | return Err(DecodingError::Format( |
327 | FormatErrorInner::UnexpectedEof.into(), |
328 | )); |
329 | } |
330 | let (consumed, event) = self.decoder.update(buf, &mut vec![])?; |
331 | self.reader.consume(consumed); |
332 | match event { |
333 | Decoded::Nothing => (), |
334 | Decoded::ImageEnd => self.at_eof = true, |
335 | // ignore more data |
336 | Decoded::ChunkComplete(_, _) | Decoded::ChunkBegin(_, _) | Decoded::ImageData => {} |
337 | Decoded::ImageDataFlushed => return Ok(()), |
338 | Decoded::PartialChunk(_) => {} |
339 | new => unreachable!(" {:?}" , new), |
340 | } |
341 | } |
342 | |
343 | Err(DecodingError::Format( |
344 | FormatErrorInner::UnexpectedEof.into(), |
345 | )) |
346 | } |
347 | |
348 | fn info(&self) -> Option<&Info<'static>> { |
349 | self.decoder.info.as_ref() |
350 | } |
351 | } |
352 | |
353 | /// PNG reader (mostly high-level interface) |
354 | /// |
355 | /// Provides a high level that iterates over lines or whole images. |
356 | pub struct Reader<R: Read> { |
357 | decoder: ReadDecoder<R>, |
358 | bpp: BytesPerPixel, |
359 | subframe: SubframeInfo, |
360 | /// Number of frame control chunks read. |
361 | /// By the APNG specification the total number must equal the count specified in the animation |
362 | /// control chunk. The IDAT image _may_ have such a chunk applying to it. |
363 | fctl_read: u32, |
364 | next_frame: SubframeIdx, |
365 | /// Vec containing the uncompressed image data currently being processed. |
366 | data_stream: Vec<u8>, |
367 | /// Index in `data_stream` where the previous row starts. |
368 | prev_start: usize, |
369 | /// Index in `data_stream` where the current row starts. |
370 | current_start: usize, |
371 | /// Output transformations |
372 | transform: Transformations, |
373 | /// Function that can transform decompressed, unfiltered rows into final output. |
374 | /// See the `transform.rs` module for more details. |
375 | transform_fn: Option<TransformFn>, |
376 | /// This buffer is only used so that `next_row` and `next_interlaced_row` can return reference |
377 | /// to a byte slice. In a future version of this library, this buffer will be removed and |
378 | /// `next_row` and `next_interlaced_row` will write directly into a user provided output buffer. |
379 | scratch_buffer: Vec<u8>, |
380 | } |
381 | |
382 | /// The subframe specific information. |
383 | /// |
384 | /// In APNG the frames are constructed by combining previous frame and a new subframe (through a |
385 | /// combination of `dispose_op` and `overlay_op`). These sub frames specify individual dimension |
386 | /// information and reuse the global interlace options. This struct encapsulates the state of where |
387 | /// in a particular IDAT-frame or subframe we are. |
388 | struct SubframeInfo { |
389 | width: u32, |
390 | height: u32, |
391 | rowlen: usize, |
392 | interlace: InterlaceIter, |
393 | consumed_and_flushed: bool, |
394 | } |
395 | |
396 | #[derive (Clone)] |
397 | enum InterlaceIter { |
398 | None(Range<u32>), |
399 | Adam7(adam7::Adam7Iterator), |
400 | } |
401 | |
402 | /// Denote a frame as given by sequence numbers. |
403 | #[derive (Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] |
404 | enum SubframeIdx { |
405 | /// The initial frame in an IDAT chunk without fcTL chunk applying to it. |
406 | /// Note that this variant precedes `Some` as IDAT frames precede fdAT frames and all fdAT |
407 | /// frames must have a fcTL applying to it. |
408 | Initial, |
409 | /// An IDAT frame with fcTL or an fdAT frame. |
410 | Some(u32), |
411 | /// The past-the-end index. |
412 | End, |
413 | } |
414 | |
415 | impl<R: Read> Reader<R> { |
416 | /// Reads all meta data until the next frame data starts. |
417 | /// Requires IHDR before the IDAT and fcTL before fdAT. |
418 | fn read_until_image_data(&mut self) -> Result<(), DecodingError> { |
419 | loop { |
420 | // This is somewhat ugly. The API requires us to pass a buffer to decode_next but we |
421 | // know that we will stop before reading any image data from the stream. Thus pass an |
422 | // empty buffer and assert that remains empty. |
423 | let mut buf = Vec::new(); |
424 | let state = self.decoder.decode_next(&mut buf)?; |
425 | assert!(buf.is_empty()); |
426 | |
427 | match state { |
428 | Some(Decoded::ChunkBegin(_, chunk::IDAT)) |
429 | | Some(Decoded::ChunkBegin(_, chunk::fdAT)) => break, |
430 | Some(Decoded::FrameControl(_)) => { |
431 | self.subframe = SubframeInfo::new(self.info()); |
432 | // The next frame is the one to which this chunk applies. |
433 | self.next_frame = SubframeIdx::Some(self.fctl_read); |
434 | // TODO: what about overflow here? That would imply there are more fctl chunks |
435 | // than can be specified in the animation control but also that we have read |
436 | // several gigabytes of data. |
437 | self.fctl_read += 1; |
438 | } |
439 | None => { |
440 | return Err(DecodingError::Format( |
441 | FormatErrorInner::MissingImageData.into(), |
442 | )) |
443 | } |
444 | // Ignore all other chunk events. Any other chunk may be between IDAT chunks, fdAT |
445 | // chunks and their control chunks. |
446 | _ => {} |
447 | } |
448 | } |
449 | |
450 | let info = self |
451 | .decoder |
452 | .info() |
453 | .ok_or(DecodingError::Format(FormatErrorInner::MissingIhdr.into()))?; |
454 | self.bpp = info.bpp_in_prediction(); |
455 | self.subframe = SubframeInfo::new(info); |
456 | |
457 | // Allocate output buffer. |
458 | let buflen = self.output_line_size(self.subframe.width); |
459 | self.decoder.decoder.limits.reserve_bytes(buflen)?; |
460 | |
461 | self.prev_start = self.current_start; |
462 | |
463 | Ok(()) |
464 | } |
465 | |
466 | /// Get information on the image. |
467 | /// |
468 | /// The structure will change as new frames of an animated image are decoded. |
469 | pub fn info(&self) -> &Info<'static> { |
470 | self.decoder.info().unwrap() |
471 | } |
472 | |
473 | /// Decodes the next frame into `buf`. |
474 | /// |
475 | /// Note that this decodes raw subframes that need to be mixed according to blend-op and |
476 | /// dispose-op by the caller. |
477 | /// |
478 | /// The caller must always provide a buffer large enough to hold a complete frame (the APNG |
479 | /// specification restricts subframes to the dimensions given in the image header). The region |
480 | /// that has been written be checked afterwards by calling `info` after a successful call and |
481 | /// inspecting the `frame_control` data. This requirement may be lifted in a later version of |
482 | /// `png`. |
483 | /// |
484 | /// Output lines will be written in row-major, packed matrix with width and height of the read |
485 | /// frame (or subframe), all samples are in big endian byte order where this matters. |
486 | pub fn next_frame(&mut self, buf: &mut [u8]) -> Result<OutputInfo, DecodingError> { |
487 | let subframe_idx = match self.decoder.info().unwrap().frame_control() { |
488 | None => SubframeIdx::Initial, |
489 | Some(_) => SubframeIdx::Some(self.fctl_read - 1), |
490 | }; |
491 | |
492 | if self.next_frame == SubframeIdx::End { |
493 | return Err(DecodingError::Parameter( |
494 | ParameterErrorKind::PolledAfterEndOfImage.into(), |
495 | )); |
496 | } else if self.next_frame != subframe_idx { |
497 | // Advance until we've read the info / fcTL for this frame. |
498 | self.read_until_image_data()?; |
499 | } |
500 | |
501 | if buf.len() < self.output_buffer_size() { |
502 | return Err(DecodingError::Parameter( |
503 | ParameterErrorKind::ImageBufferSize { |
504 | expected: buf.len(), |
505 | actual: self.output_buffer_size(), |
506 | } |
507 | .into(), |
508 | )); |
509 | } |
510 | |
511 | let (color_type, bit_depth) = self.output_color_type(); |
512 | let output_info = OutputInfo { |
513 | width: self.subframe.width, |
514 | height: self.subframe.height, |
515 | color_type, |
516 | bit_depth, |
517 | line_size: self.output_line_size(self.subframe.width), |
518 | }; |
519 | |
520 | self.data_stream.clear(); |
521 | self.current_start = 0; |
522 | self.prev_start = 0; |
523 | let width = self.info().width; |
524 | if self.info().interlaced { |
525 | while let Some(InterlacedRow { |
526 | data: row, |
527 | interlace, |
528 | .. |
529 | }) = self.next_interlaced_row()? |
530 | { |
531 | let (line, pass) = match interlace { |
532 | InterlaceInfo::Adam7 { line, pass, .. } => (line, pass), |
533 | InterlaceInfo::Null => unreachable!("expected interlace information" ), |
534 | }; |
535 | let samples = color_type.samples() as u8; |
536 | adam7::expand_pass(buf, width, row, pass, line, samples * (bit_depth as u8)); |
537 | } |
538 | } else { |
539 | for row in buf |
540 | .chunks_exact_mut(output_info.line_size) |
541 | .take(self.subframe.height as usize) |
542 | { |
543 | self.next_interlaced_row_impl(self.subframe.rowlen, row)?; |
544 | } |
545 | } |
546 | |
547 | // Advance over the rest of data for this (sub-)frame. |
548 | if !self.subframe.consumed_and_flushed { |
549 | self.decoder.finish_decoding()?; |
550 | } |
551 | |
552 | // Advance our state to expect the next frame. |
553 | let past_end_subframe = self |
554 | .info() |
555 | .animation_control() |
556 | .map(|ac| ac.num_frames) |
557 | .unwrap_or(0); |
558 | self.next_frame = match self.next_frame { |
559 | SubframeIdx::End => unreachable!("Next frame called when already at image end" ), |
560 | // Reached the end of non-animated image. |
561 | SubframeIdx::Initial if past_end_subframe == 0 => SubframeIdx::End, |
562 | // An animated image, expecting first subframe. |
563 | SubframeIdx::Initial => SubframeIdx::Some(0), |
564 | // This was the last subframe, slightly fuzzy condition in case of programmer error. |
565 | SubframeIdx::Some(idx) if past_end_subframe <= idx + 1 => SubframeIdx::End, |
566 | // Expecting next subframe. |
567 | SubframeIdx::Some(idx) => SubframeIdx::Some(idx + 1), |
568 | }; |
569 | |
570 | Ok(output_info) |
571 | } |
572 | |
573 | /// Returns the next processed row of the image |
574 | pub fn next_row(&mut self) -> Result<Option<Row>, DecodingError> { |
575 | self.next_interlaced_row() |
576 | .map(|v| v.map(|v| Row { data: v.data })) |
577 | } |
578 | |
579 | /// Returns the next processed row of the image |
580 | pub fn next_interlaced_row(&mut self) -> Result<Option<InterlacedRow>, DecodingError> { |
581 | let (rowlen, interlace) = match self.next_pass() { |
582 | Some((rowlen, interlace)) => (rowlen, interlace), |
583 | None => return Ok(None), |
584 | }; |
585 | |
586 | let width = if let InterlaceInfo::Adam7 { width, .. } = interlace { |
587 | width |
588 | } else { |
589 | self.subframe.width |
590 | }; |
591 | let output_line_size = self.output_line_size(width); |
592 | |
593 | // TODO: change the interface of `next_interlaced_row` to take an output buffer instead of |
594 | // making us return a reference to a buffer that we own. |
595 | let mut output_buffer = mem::take(&mut self.scratch_buffer); |
596 | output_buffer.resize(output_line_size, 0u8); |
597 | let ret = self.next_interlaced_row_impl(rowlen, &mut output_buffer); |
598 | self.scratch_buffer = output_buffer; |
599 | ret?; |
600 | |
601 | Ok(Some(InterlacedRow { |
602 | data: &self.scratch_buffer[..output_line_size], |
603 | interlace, |
604 | })) |
605 | } |
606 | |
607 | /// Read the rest of the image and chunks and finish up, including text chunks or others |
608 | /// This will discard the rest of the image if the image is not read already with [`Reader::next_frame`], [`Reader::next_row`] or [`Reader::next_interlaced_row`] |
609 | pub fn finish(&mut self) -> Result<(), DecodingError> { |
610 | self.next_frame = SubframeIdx::End; |
611 | self.data_stream.clear(); |
612 | self.current_start = 0; |
613 | self.prev_start = 0; |
614 | loop { |
615 | let mut buf = Vec::new(); |
616 | let state = self.decoder.decode_next(&mut buf)?; |
617 | |
618 | if state.is_none() { |
619 | break; |
620 | } |
621 | } |
622 | |
623 | Ok(()) |
624 | } |
625 | |
626 | /// Fetch the next interlaced row and filter it according to our own transformations. |
627 | fn next_interlaced_row_impl( |
628 | &mut self, |
629 | rowlen: usize, |
630 | output_buffer: &mut [u8], |
631 | ) -> Result<(), DecodingError> { |
632 | self.next_raw_interlaced_row(rowlen)?; |
633 | assert_eq!(self.current_start - self.prev_start, rowlen - 1); |
634 | let row = &self.data_stream[self.prev_start..self.current_start]; |
635 | |
636 | // Apply transformations and write resulting data to buffer. |
637 | let transform_fn = { |
638 | if self.transform_fn.is_none() { |
639 | self.transform_fn = Some(create_transform_fn(self.info(), self.transform)?); |
640 | } |
641 | self.transform_fn.as_deref().unwrap() |
642 | }; |
643 | transform_fn(row, output_buffer, self.info()); |
644 | |
645 | Ok(()) |
646 | } |
647 | |
648 | /// Returns the color type and the number of bits per sample |
649 | /// of the data returned by `Reader::next_row` and Reader::frames`. |
650 | pub fn output_color_type(&self) -> (ColorType, BitDepth) { |
651 | use crate::common::ColorType::*; |
652 | let t = self.transform; |
653 | let info = self.info(); |
654 | if t == Transformations::IDENTITY { |
655 | (info.color_type, info.bit_depth) |
656 | } else { |
657 | let bits = match info.bit_depth as u8 { |
658 | 16 if t.intersects(Transformations::STRIP_16) => 8, |
659 | n if n < 8 |
660 | && (t.contains(Transformations::EXPAND) |
661 | || t.contains(Transformations::ALPHA)) => |
662 | { |
663 | 8 |
664 | } |
665 | n => n, |
666 | }; |
667 | let color_type = |
668 | if t.contains(Transformations::EXPAND) || t.contains(Transformations::ALPHA) { |
669 | let has_trns = info.trns.is_some() || t.contains(Transformations::ALPHA); |
670 | match info.color_type { |
671 | Grayscale if has_trns => GrayscaleAlpha, |
672 | Rgb if has_trns => Rgba, |
673 | Indexed if has_trns => Rgba, |
674 | Indexed => Rgb, |
675 | ct => ct, |
676 | } |
677 | } else { |
678 | info.color_type |
679 | }; |
680 | (color_type, BitDepth::from_u8(bits).unwrap()) |
681 | } |
682 | } |
683 | |
684 | /// Returns the number of bytes required to hold a deinterlaced image frame |
685 | /// that is decoded using the given input transformations. |
686 | pub fn output_buffer_size(&self) -> usize { |
687 | let (width, height) = self.info().size(); |
688 | let size = self.output_line_size(width); |
689 | size * height as usize |
690 | } |
691 | |
692 | /// Returns the number of bytes required to hold a deinterlaced row. |
693 | pub fn output_line_size(&self, width: u32) -> usize { |
694 | let (color, depth) = self.output_color_type(); |
695 | color.raw_row_length_from_width(depth, width) - 1 |
696 | } |
697 | |
698 | fn next_pass(&mut self) -> Option<(usize, InterlaceInfo)> { |
699 | match self.subframe.interlace { |
700 | InterlaceIter::Adam7(ref mut adam7) => { |
701 | let last_pass = adam7.current_pass(); |
702 | let (pass, line, width) = adam7.next()?; |
703 | let rowlen = self.info().raw_row_length_from_width(width); |
704 | if last_pass != pass { |
705 | self.prev_start = self.current_start; |
706 | } |
707 | Some((rowlen, InterlaceInfo::Adam7 { pass, line, width })) |
708 | } |
709 | InterlaceIter::None(ref mut height) => { |
710 | let _ = height.next()?; |
711 | Some((self.subframe.rowlen, InterlaceInfo::Null)) |
712 | } |
713 | } |
714 | } |
715 | |
716 | /// Write the next raw interlaced row into `self.prev`. |
717 | /// |
718 | /// The scanline is filtered against the previous scanline according to the specification. |
719 | fn next_raw_interlaced_row(&mut self, rowlen: usize) -> Result<(), DecodingError> { |
720 | // Read image data until we have at least one full row (but possibly more than one). |
721 | while self.data_stream.len() - self.current_start < rowlen { |
722 | if self.subframe.consumed_and_flushed { |
723 | return Err(DecodingError::Format( |
724 | FormatErrorInner::NoMoreImageData.into(), |
725 | )); |
726 | } |
727 | |
728 | // Clear the current buffer before appending more data. |
729 | if self.prev_start > 0 { |
730 | self.data_stream.copy_within(self.prev_start.., 0); |
731 | self.data_stream |
732 | .truncate(self.data_stream.len() - self.prev_start); |
733 | self.current_start -= self.prev_start; |
734 | self.prev_start = 0; |
735 | } |
736 | |
737 | match self.decoder.decode_next(&mut self.data_stream)? { |
738 | Some(Decoded::ImageData) => {} |
739 | Some(Decoded::ImageDataFlushed) => { |
740 | self.subframe.consumed_and_flushed = true; |
741 | } |
742 | None => { |
743 | return Err(DecodingError::Format( |
744 | if self.data_stream.is_empty() { |
745 | FormatErrorInner::NoMoreImageData |
746 | } else { |
747 | FormatErrorInner::UnexpectedEndOfChunk |
748 | } |
749 | .into(), |
750 | )); |
751 | } |
752 | _ => (), |
753 | } |
754 | } |
755 | |
756 | // Get a reference to the current row and point scan_start to the next one. |
757 | let (prev, row) = self.data_stream.split_at_mut(self.current_start); |
758 | |
759 | // Unfilter the row. |
760 | let filter = FilterType::from_u8(row[0]).ok_or(DecodingError::Format( |
761 | FormatErrorInner::UnknownFilterMethod(row[0]).into(), |
762 | ))?; |
763 | unfilter( |
764 | filter, |
765 | self.bpp, |
766 | &prev[self.prev_start..], |
767 | &mut row[1..rowlen], |
768 | ); |
769 | |
770 | self.prev_start = self.current_start + 1; |
771 | self.current_start += rowlen; |
772 | |
773 | Ok(()) |
774 | } |
775 | } |
776 | |
777 | impl SubframeInfo { |
778 | fn not_yet_init() -> Self { |
779 | SubframeInfo { |
780 | width: 0, |
781 | height: 0, |
782 | rowlen: 0, |
783 | interlace: InterlaceIter::None(0..0), |
784 | consumed_and_flushed: false, |
785 | } |
786 | } |
787 | |
788 | fn new(info: &Info) -> Self { |
789 | // The apng fctnl overrides width and height. |
790 | // All other data is set by the main info struct. |
791 | let (width, height) = if let Some(fc) = info.frame_control { |
792 | (fc.width, fc.height) |
793 | } else { |
794 | (info.width, info.height) |
795 | }; |
796 | |
797 | let interlace = if info.interlaced { |
798 | InterlaceIter::Adam7(adam7::Adam7Iterator::new(width, height)) |
799 | } else { |
800 | InterlaceIter::None(0..height) |
801 | }; |
802 | |
803 | SubframeInfo { |
804 | width, |
805 | height, |
806 | rowlen: info.raw_row_length_from_width(width), |
807 | interlace, |
808 | consumed_and_flushed: false, |
809 | } |
810 | } |
811 | } |
812 | |