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