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