1 mod stream;
2 
3 pub use self::stream::{StreamingDecoder, Decoded, DecodingError};
4 use self::stream::{CHUNCK_BUFFER_SIZE, get_info};
5 
6 use std::mem;
7 use std::borrow;
8 use std::io::{Read, Write, BufReader, BufRead};
9 
10 use crate::common::{ColorType, BitDepth, Info, Transformations};
11 use crate::filter::{unfilter, FilterType};
12 use crate::chunk::IDAT;
13 use crate::utils;
14 
15 /*
16 pub enum InterlaceHandling {
17     /// Outputs the raw rows
18     RawRows,
19     /// Fill missing the pixels from the existing ones
20     Rectangle,
21     /// Only fill the needed pixels
22     Sparkle
23 }
24 */
25 
26 /// Output info
27 #[derive(Debug)]
28 pub struct OutputInfo {
29     pub width: u32,
30     pub height: u32,
31     pub color_type: ColorType,
32     pub bit_depth: BitDepth,
33     pub line_size: usize,
34 }
35 
36 impl OutputInfo {
37     /// Returns the size needed to hold a decoded frame
buffer_size(&self) -> usize38     pub fn buffer_size(&self) -> usize {
39         self.line_size * self.height as usize
40     }
41 }
42 
43 #[derive(Clone, Copy, Debug)]
44 /// Limits on the resources the `Decoder` is allowed too use
45 pub struct Limits {
46     /// maximum number of bytes the decoder is allowed to allocate, default is 64Mib
47     pub bytes: usize,
48 }
49 
50 impl Default for Limits {
default() -> Limits51     fn default() -> Limits {
52         Limits {
53             bytes: 1024*1024*64,
54         }
55     }
56 }
57 
58 /// PNG Decoder
59 pub struct Decoder<R: Read> {
60     /// Reader
61     r: R,
62     /// Output transformations
63     transform: Transformations,
64     /// Limits on resources the Decoder is allowed to use
65     limits: Limits,
66 }
67 
68 impl<R: Read> Decoder<R> {
new(r: R) -> Decoder<R>69     pub fn new(r: R) -> Decoder<R> {
70         Decoder::new_with_limits(r, Limits::default())
71     }
72 
new_with_limits(r: R, limits: Limits) -> Decoder<R>73     pub fn new_with_limits(r: R, limits: Limits) -> Decoder<R> {
74         Decoder {
75             r,
76             transform: crate::Transformations::EXPAND | crate::Transformations::SCALE_16 | crate::Transformations::STRIP_16,
77             limits,
78         }
79     }
80 
81     /// Limit resource usage
82     ///
83     /// ```
84     /// use std::fs::File;
85     /// use png::{Decoder, Limits};
86     /// // This image is 32x32 pixels, so the deocder will allocate more than four bytes
87     /// let mut limits = Limits::default();
88     /// limits.bytes = 4;
89     /// let mut decoder = Decoder::new_with_limits(File::open("tests/pngsuite/basi0g01.png").unwrap(), limits);
90     /// assert!(decoder.read_info().is_err());
91     /// // This image is 32x32 pixels, so the decoder will allocate less than 10Kib
92     /// let mut limits = Limits::default();
93     /// limits.bytes = 10*1024;
94     /// let mut decoder = Decoder::new_with_limits(File::open("tests/pngsuite/basi0g01.png").unwrap(), limits);
95     /// assert!(decoder.read_info().is_ok());
96     /// ```
set_limits(&mut self, limits: Limits)97     pub fn set_limits(&mut self, limits: Limits) {
98         self.limits = limits;
99     }
100 
101     /// Reads all meta data until the first IDAT chunk
read_info(self) -> Result<(OutputInfo, Reader<R>), DecodingError>102     pub fn read_info(self) -> Result<(OutputInfo, Reader<R>), DecodingError> {
103         let mut r = Reader::new(self.r, StreamingDecoder::new(), self.transform, self.limits);
104         r.init()?;
105         let (ct, bits) = r.output_color_type();
106         let info = {
107             let info = r.info();
108             OutputInfo {
109                 width: info.width,
110                 height: info.height,
111                 color_type: ct,
112                 bit_depth: bits,
113                 line_size: r.output_line_size(info.width),
114             }
115         };
116         Ok((info, r))
117     }
118 
119     /// Set the allowed and performed transformations.
120     ///
121     /// A transformation is a pre-processing on the raw image data modifying content or encoding.
122     /// Many options have an impact on memory or CPU usage during decoding.
set_transformations(&mut self, transform: Transformations)123     pub fn set_transformations(&mut self, transform: Transformations) {
124         self.transform = transform;
125     }
126 }
127 
128 struct ReadDecoder<R: Read> {
129     reader: BufReader<R>,
130     decoder: StreamingDecoder,
131     at_eof: bool
132 }
133 
134 impl<R: Read> ReadDecoder<R> {
135     /// Returns the next decoded chunk. If the chunk is an ImageData chunk, its contents are written
136     /// into image_data.
decode_next(&mut self, image_data: &mut Vec<u8>) -> Result<Option<Decoded>, DecodingError>137     fn decode_next(&mut self, image_data: &mut Vec<u8>) -> Result<Option<Decoded>, DecodingError> {
138         while !self.at_eof {
139             let (consumed, result) = {
140                 let buf = self.reader.fill_buf()?;
141                 if buf.is_empty() {
142                     return Err(DecodingError::Format(
143                         "unexpected EOF".into()
144                     ))
145                 }
146                 self.decoder.update(buf, image_data)?
147             };
148             self.reader.consume(consumed);
149             match result {
150                 Decoded::Nothing => (),
151                 Decoded::ImageEnd => self.at_eof = true,
152                 result => return Ok(Some(result))
153             }
154         }
155         Ok(None)
156     }
157 
info(&self) -> Option<&Info>158     fn info(&self) -> Option<&Info> {
159         get_info(&self.decoder)
160     }
161 }
162 
163 /// PNG reader (mostly high-level interface)
164 ///
165 /// Provides a high level that iterates over lines or whole images.
166 pub struct Reader<R: Read> {
167     decoder: ReadDecoder<R>,
168     bpp: usize,
169     rowlen: usize,
170     adam7: Option<utils::Adam7Iterator>,
171     /// Previous raw line
172     prev: Vec<u8>,
173     /// Current raw line
174     current: Vec<u8>,
175     /// Output transformations
176     transform: Transformations,
177     /// Processed line
178     processed: Vec<u8>,
179     limits: Limits,
180 }
181 
182 macro_rules! get_info(
183     ($this:expr) => {
184         $this.decoder.info().unwrap()
185     }
186 );
187 
188 impl<R: Read> Reader<R> {
189     /// Creates a new PNG reader
new(r: R, d: StreamingDecoder, t: Transformations, limits: Limits) -> Reader<R>190     fn new(r: R, d: StreamingDecoder, t: Transformations, limits: Limits) -> Reader<R> {
191         Reader {
192             decoder: ReadDecoder {
193                 reader: BufReader::with_capacity(CHUNCK_BUFFER_SIZE, r),
194                 decoder: d,
195                 at_eof: false
196             },
197             bpp: 0,
198             rowlen: 0,
199             adam7: None,
200             prev: Vec::new(),
201             current: Vec::new(),
202             transform: t,
203             processed: Vec::new(),
204             limits,
205         }
206     }
207 
208     /// Reads all meta data until the first IDAT chunk
init(&mut self) -> Result<(), DecodingError>209     fn init(&mut self) -> Result<(), DecodingError> {
210         use crate::Decoded::*;
211         if self.decoder.info().is_some() {
212             Ok(())
213         } else {
214             loop {
215                 match self.decoder.decode_next(&mut Vec::new())? {
216                     Some(ChunkBegin(_, IDAT)) => break,
217                     None => return Err(DecodingError::Format(
218                         "IDAT chunk missing".into()
219                     )),
220                     _ => (),
221                 }
222             }
223             {
224                 let info = match self.decoder.info() {
225                     Some(info) => info,
226                     None => return Err(DecodingError::Format(
227                       "IHDR chunk missing".into()
228                     ))
229                 };
230                 self.bpp = info.bytes_per_pixel();
231                 self.rowlen = info.raw_row_length();
232                 if info.interlaced {
233                     self.adam7 = Some(utils::Adam7Iterator::new(info.width, info.height))
234                 }
235             }
236             self.allocate_out_buf()?;
237             self.prev = vec![0; self.rowlen];
238             Ok(())
239         }
240     }
241 
info(&self) -> &Info242     pub fn info(&self) -> &Info {
243         get_info!(self)
244     }
245 
246     /// Decodes the next frame into `buf`
next_frame(&mut self, buf: &mut [u8]) -> Result<(), DecodingError>247     pub fn next_frame(&mut self, buf: &mut [u8]) -> Result<(), DecodingError> {
248         // TODO 16 bit
249         let (color_type, bit_depth) = self.output_color_type();
250         let width = get_info!(self).width;
251         if buf.len() < self.output_buffer_size() {
252             return Err(DecodingError::Other(
253                 "supplied buffer is too small to hold the image".into()
254             ))
255         }
256         if get_info!(self).interlaced {
257              while let Some((row, adam7)) = self.next_interlaced_row()? {
258                  let (pass, line, _) = adam7.unwrap();
259                  let samples = color_type.samples() as u8;
260                  utils::expand_pass(buf, width, row, pass, line, samples * (bit_depth as u8));
261              }
262         } else {
263             let mut len = 0;
264             while let Some(row) = self.next_row()? {
265                 len += (&mut buf[len..]).write(row)?;
266             }
267         }
268         Ok(())
269     }
270 
271     /// Returns the next processed row of the image
next_row(&mut self) -> Result<Option<&[u8]>, DecodingError>272     pub fn next_row(&mut self) -> Result<Option<&[u8]>, DecodingError> {
273         self.next_interlaced_row().map(|v| v.map(|v| v.0))
274     }
275 
276     /// Returns the next processed row of the image
next_interlaced_row(&mut self) -> Result<Option<(&[u8], Option<(u8, u32, u32)>)>, DecodingError>277     pub fn next_interlaced_row(&mut self) -> Result<Option<(&[u8], Option<(u8, u32, u32)>)>, DecodingError> {
278         use crate::common::ColorType::*;
279         let transform = self.transform;
280         if transform == crate::Transformations::IDENTITY {
281             self.next_raw_interlaced_row()
282         } else {
283             // swap buffer to circumvent borrow issues
284             let mut buffer = mem::replace(&mut self.processed, Vec::new());
285             let (got_next, adam7) = if let Some((row, adam7)) = self.next_raw_interlaced_row()? {
286                 (&mut buffer[..]).write_all(row)?;
287                 (true, adam7)
288             } else {
289                 (false, None)
290             };
291             // swap back
292             let _ = mem::replace(&mut self.processed, buffer);
293             if got_next {
294                 let (color_type, bit_depth, trns) = {
295                     let info = get_info!(self);
296                     (info.color_type, info.bit_depth as u8, info.trns.is_some())
297                 };
298                 let output_buffer = if let Some((_, _, width)) = adam7 {
299                     let width = self.line_size(width);
300                     &mut self.processed[..width]
301                 } else {
302                     &mut *self.processed
303                 };
304                 let mut len = output_buffer.len();
305                 if transform.contains(crate::Transformations::EXPAND) {
306                     match color_type {
307                         Indexed => {
308                             expand_paletted(output_buffer, get_info!(self))?
309                         }
310                         Grayscale | GrayscaleAlpha if bit_depth < 8 => expand_gray_u8(
311                             output_buffer, get_info!(self)
312                         ),
313                         Grayscale | RGB if trns => {
314                             let channels = color_type.samples();
315                             let trns = get_info!(self).trns.as_ref().unwrap();
316                             if bit_depth == 8 {
317                                 utils::expand_trns_line(output_buffer, &*trns, channels);
318                             } else {
319                                 utils::expand_trns_line16(output_buffer, &*trns, channels);
320                             }
321                         },
322                         _ => ()
323                     }
324                 }
325                 if bit_depth == 16 && transform.intersects(crate::Transformations::SCALE_16 | crate::Transformations::STRIP_16) {
326                     len /= 2;
327                     for i in 0..len {
328                         output_buffer[i] = output_buffer[2 * i];
329                     }
330                 }
331                 Ok(Some((
332                     &output_buffer[..len],
333                     adam7
334                 )))
335             } else {
336                 Ok(None)
337             }
338         }
339     }
340 
341     /// Returns the color type and the number of bits per sample
342     /// of the data returned by `Reader::next_row` and Reader::frames`.
output_color_type(&mut self) -> (ColorType, BitDepth)343     pub fn output_color_type(&mut self) -> (ColorType, BitDepth) {
344         use crate::common::ColorType::*;
345         let t = self.transform;
346         let info = get_info!(self);
347         if t == crate::Transformations::IDENTITY {
348             (info.color_type, info.bit_depth)
349         } else {
350             let bits = match info.bit_depth as u8 {
351                 16 if t.intersects(
352                     crate::Transformations::SCALE_16 | crate::Transformations::STRIP_16
353                 ) => 8,
354                 n if n < 8 && t.contains(crate::Transformations::EXPAND) => 8,
355                 n => n
356             };
357             let color_type = if t.contains(crate::Transformations::EXPAND) {
358                 let has_trns = info.trns.is_some();
359                 match info.color_type {
360                     Grayscale if has_trns => GrayscaleAlpha,
361                     RGB if has_trns => RGBA,
362                     Indexed if has_trns => RGBA,
363                     Indexed => RGB,
364                     ct => ct
365                 }
366             } else {
367                 info.color_type
368             };
369             (color_type, BitDepth::from_u8(bits).unwrap())
370         }
371     }
372 
373     /// Returns the number of bytes required to hold a deinterlaced image frame
374     /// that is decoded using the given input transformations.
output_buffer_size(&self) -> usize375     pub fn output_buffer_size(&self) -> usize {
376         let (width, height) = get_info!(self).size();
377         let size = self.output_line_size(width);
378         size * height as usize
379     }
380 
381     /// Returns the number of bytes required to hold a deinterlaced row.
output_line_size(&self, width: u32) -> usize382     pub fn output_line_size(&self, width: u32) -> usize {
383         let size = self.line_size(width);
384         if get_info!(self).bit_depth as u8 == 16 && self.transform.intersects(
385             crate::Transformations::SCALE_16 | crate::Transformations::STRIP_16
386         ) {
387             size / 2
388         } else {
389             size
390         }
391     }
392 
393     /// Returns the number of bytes required to decode a deinterlaced row.
line_size(&self, width: u32) -> usize394     fn line_size(&self, width: u32) -> usize {
395         use crate::common::ColorType::*;
396         let t = self.transform;
397         let info = get_info!(self);
398         let trns = info.trns.is_some();
399         // TODO 16 bit
400         let bits = match info.color_type {
401             Indexed if trns && t.contains(crate::Transformations::EXPAND) => 4 * 8,
402             Indexed if t.contains(crate::Transformations::EXPAND) => 3 * 8,
403             RGB if trns && t.contains(crate::Transformations::EXPAND) => 4 * 8,
404             Grayscale if trns && t.contains(crate::Transformations::EXPAND) => 2 * 8,
405             Grayscale if t.contains(crate::Transformations::EXPAND) => 1 * 8,
406             GrayscaleAlpha if t.contains(crate::Transformations::EXPAND) => 2 * 8,
407             // divide by 2 as it will get mutiplied by two later
408             _ if info.bit_depth as u8 == 16 => info.bits_per_pixel() / 2,
409             _ => info.bits_per_pixel()
410         }
411         * width as usize
412         * if info.bit_depth as u8 == 16 { 2 } else { 1 };
413         let len = bits / 8;
414         let extra = bits % 8;
415         len + match extra { 0 => 0, _ => 1 }
416     }
417 
allocate_out_buf(&mut self) -> Result<(), DecodingError>418     fn allocate_out_buf(&mut self) -> Result<(), DecodingError> {
419         let width = get_info!(self).width;
420         let bytes = self.limits.bytes;
421         if bytes < self.line_size(width) {
422             return Err(DecodingError::LimitsExceeded);
423         }
424         self.processed = vec![0; self.line_size(width)];
425         Ok(())
426     }
427 
428     /// Returns the next raw row of the image
next_raw_interlaced_row(&mut self) -> Result<Option<(&[u8], Option<(u8, u32, u32)>)>, DecodingError>429     fn next_raw_interlaced_row(&mut self) -> Result<Option<(&[u8], Option<(u8, u32, u32)>)>, DecodingError> {
430         let _ = get_info!(self);
431         let bpp = self.bpp;
432         let (rowlen, passdata) = if let Some(ref mut adam7) = self.adam7 {
433             let last_pass = adam7.current_pass();
434             if let Some((pass, line, len)) = adam7.next() {
435                 let rowlen = get_info!(self).raw_row_length_from_width(len);
436                 if last_pass != pass {
437                     self.prev.clear();
438                     for _ in 0..rowlen {
439                         self.prev.push(0);
440                     }
441                 }
442                 (rowlen, Some((pass, line, len)))
443             } else {
444                 return Ok(None)
445             }
446         } else {
447             (self.rowlen, None)
448         };
449         loop {
450             if self.current.len() >= rowlen {
451                 if let Some(filter) = FilterType::from_u8(self.current[0]) {
452                     if let Err(message) = unfilter(filter, bpp, &self.prev[1..rowlen], &mut self.current[1..rowlen]) {
453                         return Err(DecodingError::Format(
454                             borrow::Cow::Borrowed(message)
455                         ))
456                     }
457                     self.prev[..rowlen].copy_from_slice(&self.current[..rowlen]);
458                     self.current.drain(0..rowlen);
459                     return Ok(
460                         Some((
461                             &self.prev[1..rowlen],
462                             passdata
463                         ))
464                     )
465                 } else {
466                     return Err(DecodingError::Format(
467                         format!("invalid filter method ({})", self.current[0]).into()
468                     ))
469                 }
470             } else {
471                 let val = self.decoder.decode_next(&mut self.current)?;
472                 match val {
473                     Some(Decoded::ImageData) => {}
474                     None => {
475                         if !self.current.is_empty() {
476                             return Err(DecodingError::Format(
477                               "file truncated".into()
478                             ))
479                         } else {
480                             return Ok(None)
481                         }
482                     }
483                     _ => ()
484                 }
485             }
486         }
487     }
488 }
489 
expand_paletted(buffer: &mut [u8], info: &Info) -> Result<(), DecodingError>490 fn expand_paletted(buffer: &mut [u8], info: &Info) -> Result<(), DecodingError> {
491     if let Some(palette) = info.palette.as_ref() {
492         if let BitDepth::Sixteen = info.bit_depth {
493             Err(DecodingError::Format("Bit depth '16' is not valid for paletted images".into()))
494         } else {
495             let black = [0, 0, 0];
496             if let Some(ref trns) = info.trns {
497                 utils::unpack_bits(buffer, 4, info.bit_depth as u8, |i, chunk| {
498                     let (rgb, a) = (
499                         palette.get(3*i as usize..3*i as usize+3).unwrap_or(&black),
500                         *trns.get(i as usize).unwrap_or(&0xFF)
501                     );
502                     chunk[0] = rgb[0];
503                     chunk[1] = rgb[1];
504                     chunk[2] = rgb[2];
505                     chunk[3] = a;
506                 });
507             } else {
508                 utils::unpack_bits(buffer, 3, info.bit_depth as u8, |i, chunk| {
509                     let rgb = palette.get(3*i as usize..3*i as usize+3).unwrap_or(&black);
510                     chunk[0] = rgb[0];
511                     chunk[1] = rgb[1];
512                     chunk[2] = rgb[2];
513                 })
514             }
515             Ok(())
516         }
517     } else {
518         Err(DecodingError::Format("missing palette".into()))
519     }
520 }
521 
expand_gray_u8(buffer: &mut [u8], info: &Info)522 fn expand_gray_u8(buffer: &mut [u8], info: &Info) {
523     let rescale = true;
524     let scaling_factor = if rescale {
525         (255)/((1u16 << info.bit_depth as u8) - 1) as u8
526     } else {
527         1
528     };
529     if let Some(ref trns) = info.trns {
530         utils::unpack_bits(buffer, 2, info.bit_depth as u8, |pixel, chunk| {
531             if pixel == trns[0] {
532                 chunk[1] = 0
533             } else {
534                 chunk[1] = 0xFF
535             }
536             chunk[0] = pixel * scaling_factor
537         })
538     } else {
539         utils::unpack_bits(buffer, 1, info.bit_depth as u8, |val, chunk| {
540             chunk[0] = val * scaling_factor
541         })
542     }
543 }
544