png/decoder/
mod.rs

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