1 use std::borrow::Cow;
2 use std::default::Default;
3 use std::error;
4 use std::fmt;
5 use std::mem;
6 use std::io;
7 use std::cmp::min;
8 use std::convert::From;
9
10 extern crate inflate;
11
12 use self::inflate::InflateStream;
13 use crc::Crc32;
14 use traits::ReadBytesExt;
15 use common::{ColorType, BitDepth, Info, Unit, PixelDimensions, AnimationControl, FrameControl};
16 use chunk::{self, ChunkType, IHDR, IDAT, IEND};
17
18 /// TODO check if these size are reasonable
19 pub const CHUNCK_BUFFER_SIZE: usize = 32*1024;
20
21 #[derive(Debug)]
22 enum U32Value {
23 // CHUNKS
24 Length,
25 Type(u32),
26 Crc(ChunkType)
27 }
28
29 #[derive(Debug)]
30 enum State {
31 Signature(u8, [u8; 7]),
32 U32Byte3(U32Value, u32),
33 U32Byte2(U32Value, u32),
34 U32Byte1(U32Value, u32),
35 U32(U32Value),
36 ReadChunk(ChunkType, bool),
37 PartialChunk(ChunkType),
38 DecodeData(ChunkType, usize),
39 }
40
41 #[derive(Debug)]
42 /// Result of the decoding process
43 pub enum Decoded<'a> {
44 /// Nothing decoded yet
45 Nothing,
46 Header(u32, u32, BitDepth, ColorType, bool),
47 ChunkBegin(u32, ChunkType),
48 ChunkComplete(u32, ChunkType),
49 PixelDimensions(PixelDimensions),
50 AnimationControl(AnimationControl),
51 FrameControl(&'a FrameControl),
52 /// Decoded raw image data.
53 ImageData(&'a [u8]),
54 PartialChunk(ChunkType, &'a [u8]),
55 ImageEnd,
56 }
57
58 #[derive(Debug)]
59 pub enum DecodingError {
60 IoError(io::Error),
61 Format(Cow<'static, str>),
62 InvalidSignature,
63 CrcMismatch {
64 /// bytes to skip to try to recover from this error
65 recover: usize,
66 /// Stored CRC32 value
67 crc_val: u32,
68 /// Calculated CRC32 sum
69 crc_sum: u32,
70 chunk: ChunkType
71 },
72 Other(Cow<'static, str>),
73 CorruptFlateStream
74 }
75
76 impl error::Error for DecodingError {
description(&self) -> &str77 fn description(&self) -> &str {
78 use self::DecodingError::*;
79 match *self {
80 IoError(ref err) => err.description(),
81 Format(ref desc) | Other(ref desc) => &desc,
82 InvalidSignature => "invalid signature",
83 CrcMismatch { .. } => "CRC error",
84 CorruptFlateStream => "compressed data stream corrupted"
85 }
86 }
87 }
88
89 impl fmt::Display for DecodingError {
fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error>90 fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
91 write!(fmt, "{}", (self as &error::Error).description())
92 }
93 }
94
95 impl From<io::Error> for DecodingError {
from(err: io::Error) -> DecodingError96 fn from(err: io::Error) -> DecodingError {
97 DecodingError::IoError(err)
98 }
99 }
100
101 impl From<String> for DecodingError {
from(err: String) -> DecodingError102 fn from(err: String) -> DecodingError {
103 DecodingError::Other(err.into())
104 }
105 }
106
107 impl From<DecodingError> for io::Error {
from(err: DecodingError) -> io::Error108 fn from(err: DecodingError) -> io::Error {
109 use std::error::Error;
110 match err {
111 DecodingError::IoError(err) => err,
112 err => io::Error::new(
113 io::ErrorKind::Other,
114 err.description()
115 )
116 }
117 }
118 }
119
120 /// PNG StreamingDecoder (low-level interface)
121 pub struct StreamingDecoder {
122 state: Option<State>,
123 current_chunk: (Crc32, u32, Vec<u8>),
124 inflater: InflateStream,
125 info: Option<Info>,
126 current_seq_no: Option<u32>,
127 have_idat: bool,
128 }
129
130 impl StreamingDecoder {
131 /// Creates a new StreamingDecoder
132 ///
133 /// Allocates the internal buffers.
new() -> StreamingDecoder134 pub fn new() -> StreamingDecoder {
135 StreamingDecoder {
136 state: Some(State::Signature(0, [0; 7])),
137 current_chunk: (Crc32::new(), 0, Vec::with_capacity(CHUNCK_BUFFER_SIZE)),
138 inflater: InflateStream::from_zlib(),
139 info: None,
140 current_seq_no: None,
141 have_idat: false
142 }
143 }
144
145 /// Resets the StreamingDecoder
reset(&mut self)146 pub fn reset(&mut self) {
147 self.state = Some(State::Signature(0, [0; 7]));
148 self.current_chunk.0 = Crc32::new();
149 self.current_chunk.1 = 0;
150 self.current_chunk.2.clear();
151 self.inflater = InflateStream::from_zlib();
152 self.info = None;
153 self.current_seq_no = None;
154 self.have_idat = false;
155 }
156
157 /// Low level StreamingDecoder interface.
158 ///
159 /// Allows to stream partial data to the encoder. Returns a tuple containing the
160 /// bytes that have been consumed from the input buffer and the current decoding
161 /// result.
update<'a>(&'a mut self, mut buf: &[u8]) -> Result<(usize, Decoded<'a>), DecodingError>162 pub fn update<'a>(&'a mut self, mut buf: &[u8])
163 -> Result<(usize, Decoded<'a>), DecodingError> {
164 // NOTE: Do not change the function signature without double-checking the
165 // unsafe block!
166 let len = buf.len();
167 while buf.len() > 0 && self.state.is_some() {
168 match self.next_state(buf) {
169 Ok((bytes, Decoded::Nothing)) => {
170 buf = &buf[bytes..]
171 }
172 Ok((bytes, result)) => {
173 buf = &buf[bytes..];
174 return Ok(
175 (len-buf.len(),
176 // This transmute just casts the lifetime away. Since Rust only
177 // has SESE regions, this early return cannot be worked out and
178 // such that the borrow region of self includes the whole block.
179 // The explixit lifetimes in the function signature ensure that
180 // this is safe.
181 // ### NOTE
182 // To check that everything is sound, return the result without
183 // the match (e.g. `return Ok(try!(self.next_state(buf)))`). If
184 // it compiles the returned lifetime is correct.
185 unsafe {
186 mem::transmute::<Decoded, Decoded>(result)
187 }
188 ))
189 }
190 Err(err) => return Err(err)
191 }
192 }
193 Ok((len-buf.len(), Decoded::Nothing))
194 }
195
next_state<'a>(&'a mut self, buf: &[u8]) -> Result<(usize, Decoded<'a>), DecodingError>196 fn next_state<'a>(&'a mut self, buf: &[u8])
197 -> Result<(usize, Decoded<'a>), DecodingError> {
198 use self::State::*;
199
200 macro_rules! goto (
201 ($n:expr, $state:expr) => ({
202 self.state = Some($state);
203 Ok(($n, Decoded::Nothing))
204 });
205 ($state:expr) => ({
206 self.state = Some($state);
207 Ok((1, Decoded::Nothing))
208 });
209 ($n:expr, $state:expr, emit $res:expr) => ({
210 self.state = Some($state);
211 Ok(($n, $res))
212 });
213 ($state:expr, emit $res:expr) => ({
214 self.state = Some($state);
215 Ok((1, $res))
216 })
217 );
218
219 let current_byte = buf[0];
220
221 // Driver should ensure that state is never None
222 let state = self.state.take().unwrap();
223 //println!("state: {:?}", state);
224
225 match state {
226 Signature(i, mut signature) => if i < 7 {
227 signature[i as usize] = current_byte;
228 goto!(Signature(i+1, signature))
229 } else {
230 if signature == [137, 80, 78, 71, 13, 10, 26] && current_byte == 10 {
231 goto!(U32(U32Value::Length))
232 } else {
233 Err(DecodingError::InvalidSignature)
234 }
235 },
236 U32Byte3(type_, mut val) => {
237 use self::U32Value::*;
238 val |= current_byte as u32;
239 match type_ {
240 Length => goto!(U32(Type(val))),
241 Type(length) => {
242 let type_str = [
243 (val >> 24) as u8,
244 (val >> 16) as u8,
245 (val >> 8) as u8,
246 val as u8
247 ];
248 self.current_chunk.0.reset();
249 self.current_chunk.0.update(&type_str);
250 self.current_chunk.1 = length;
251 goto!(
252 ReadChunk(type_str, true),
253 emit Decoded::ChunkBegin(length, type_str)
254 )
255 },
256 Crc(type_str) => {
257 if val == self.current_chunk.0.checksum() {
258 goto!(
259 State::U32(U32Value::Length),
260 emit if type_str == IEND {
261 Decoded::ImageEnd
262 } else {
263 Decoded::ChunkComplete(val, type_str)
264 }
265 )
266 } else {
267 Err(DecodingError::CrcMismatch {
268 recover: 1,
269 crc_val: val,
270 crc_sum: self.current_chunk.0.checksum(),
271 chunk: type_str
272 })
273 }
274 },
275 }
276 },
277 U32Byte2(type_, val) => {
278 goto!(U32Byte3(type_, val | (current_byte as u32) << 8))
279 },
280 U32Byte1(type_, val) => {
281 goto!(U32Byte2(type_, val | (current_byte as u32) << 16))
282 },
283 U32(type_) => {
284 goto!(U32Byte1(type_, (current_byte as u32) << 24))
285 },
286 PartialChunk(type_str) => {
287 match type_str {
288 IDAT => {
289 self.have_idat = true;
290 goto!(
291 0,
292 DecodeData(type_str, 0),
293 emit Decoded::PartialChunk(type_str, &self.current_chunk.2)
294 )
295 },
296 chunk::fdAT => {
297 if let Some(seq_no) = self.current_seq_no {
298 let mut buf = &self.current_chunk.2[..];
299 let next_seq_no = try!(buf.read_be());
300 if next_seq_no != seq_no + 1 {
301 return Err(DecodingError::Format(format!(
302 "Sequence is not in order, expected #{} got #{}.",
303 seq_no + 1,
304 next_seq_no
305 ).into()))
306 }
307 self.current_seq_no = Some(next_seq_no);
308 } else {
309 return Err(DecodingError::Format("fcTL chunk missing before fdAT chunk.".into()))
310 }
311 goto!(
312 0,
313 DecodeData(type_str, 4),
314 emit Decoded::PartialChunk(type_str, &self.current_chunk.2)
315 )
316 },
317 // Handle other chunks
318 _ => {
319 if self.current_chunk.1 == 0 { // complete chunk
320 Ok((0, try!(self.parse_chunk(type_str))))
321 } else {
322 goto!(
323 0, ReadChunk(type_str, true),
324 emit Decoded::PartialChunk(type_str, &self.current_chunk.2)
325 )
326 }
327 }
328 }
329
330 },
331 ReadChunk(type_str, clear) => {
332 if clear {
333 self.current_chunk.2.clear();
334 }
335 if self.current_chunk.1 > 0 {
336 let (ref mut crc, ref mut remaining, ref mut c_buf) = self.current_chunk;
337 let buf_avail = c_buf.capacity() - c_buf.len();
338 let bytes_avail = min(buf.len(), buf_avail);
339 let n = min(*remaining, bytes_avail as u32);
340 if buf_avail == 0 {
341 goto!(0, PartialChunk(type_str))
342 } else {
343 let buf = &buf[..n as usize];
344 crc.update(buf);
345 c_buf.extend(buf.iter().map(|&v| v));
346 *remaining -= n;
347 if *remaining == 0 {
348 goto!(n as usize, PartialChunk(type_str
349 ))
350 } else {
351 goto!(n as usize, ReadChunk(type_str, false))
352 }
353
354 }
355 } else {
356 goto!(0, U32(U32Value::Crc(type_str)))
357 }
358 }
359 DecodeData(type_str, mut n) => {
360 let chunk_len = self.current_chunk.2.len();
361 let (c, data) = try!(self.inflater.update(&self.current_chunk.2[n..]));
362 n += c;
363 if n == chunk_len && data.len() == 0 && c == 0 {
364 goto!(
365 0,
366 ReadChunk(type_str, true),
367 emit Decoded::ImageData(data)
368 )
369 } else {
370 goto!(
371 0,
372 DecodeData(type_str, n),
373 emit Decoded::ImageData(data)
374 )
375 }
376 }
377 }
378 }
379
parse_chunk(&mut self, type_str: [u8; 4]) -> Result<Decoded, DecodingError>380 fn parse_chunk(&mut self, type_str: [u8; 4])
381 -> Result<Decoded, DecodingError> {
382 self.state = Some(State::U32(U32Value::Crc(type_str)));
383 let state_ptr: *mut _ = &mut self.state;
384 if self.info.is_none() && type_str != IHDR {
385 return Err(DecodingError::Format(format!(
386 "{} chunk appeared before IHDR chunk", String::from_utf8_lossy(&type_str)
387 ).into()))
388 }
389 match match type_str {
390 IHDR => {
391 self.parse_ihdr()
392 }
393 chunk::PLTE => {
394 self.parse_plte()
395 }
396 chunk::tRNS => {
397 self.parse_trns()
398 }
399 chunk::pHYs => {
400 self.parse_phys()
401 }
402 chunk::acTL => {
403 self.parse_actl()
404 }
405 chunk::fcTL => {
406 self.parse_fctl()
407 }
408 _ => Ok(Decoded::PartialChunk(type_str, &self.current_chunk.2))
409 } {
410 Err(err) =>{
411 // Borrow of self ends here, because Decoding error does not borrow self.
412 *unsafe { &mut *state_ptr } = None;
413 Err(err)
414 },
415 ok => ok
416 }
417 }
418
get_info_or_err(&self) -> Result<&Info, DecodingError>419 fn get_info_or_err(&self) -> Result<&Info, DecodingError> {
420 self.info.as_ref().ok_or(DecodingError::Format(
421 "IHDR chunk missing".into()
422 ))
423 }
424
parse_fctl(&mut self) -> Result<Decoded, DecodingError>425 fn parse_fctl(&mut self)
426 -> Result<Decoded, DecodingError> {
427 let mut buf = &self.current_chunk.2[..];
428 let next_seq_no = try!(buf.read_be());
429
430 // Asuming that fcTL is required before *every* fdAT-sequence
431 self.current_seq_no = Some(if let Some(seq_no) = self.current_seq_no {
432 if next_seq_no != seq_no + 1 {
433 return Err(DecodingError::Format(format!(
434 "Sequence is not in order, expected #{} got #{}.",
435 seq_no + 1,
436 next_seq_no
437 ).into()))
438 }
439 next_seq_no
440 } else {
441 if next_seq_no != 0 {
442 return Err(DecodingError::Format(format!(
443 "Sequence is not in order, expected #{} got #{}.",
444 0,
445 next_seq_no
446 ).into()))
447 }
448 0
449 });
450 self.inflater = InflateStream::from_zlib();
451 self.info.as_mut().unwrap().frame_control = Some(FrameControl {
452 sequence_number: next_seq_no,
453 width: try!(buf.read_be()),
454 height: try!(buf.read_be()),
455 x_offset: try!(buf.read_be()),
456 y_offset: try!(buf.read_be()),
457 delay_num: try!(buf.read_be()),
458 delay_den: try!(buf.read_be()),
459 dispose_op: try!(buf.read_be()),
460 blend_op : try!(buf.read_be()),
461 });
462 Ok(Decoded::FrameControl(self.info.as_ref().unwrap().frame_control.as_ref().unwrap()))
463 }
464
parse_actl(&mut self) -> Result<Decoded, DecodingError>465 fn parse_actl(&mut self)
466 -> Result<Decoded, DecodingError> {
467 if self.have_idat {
468 Err(DecodingError::Format(
469 "acTL chunk appeared after first IDAT chunk".into()
470 ))
471 } else {
472 let mut buf = &self.current_chunk.2[..];
473 let actl = AnimationControl {
474 num_frames: try!(buf.read_be()),
475 num_plays: try!(buf.read_be())
476 };
477 self.info.as_mut().unwrap().animation_control = Some(actl);
478 Ok(Decoded::AnimationControl(actl))
479 }
480 }
481
parse_plte(&mut self) -> Result<Decoded, DecodingError>482 fn parse_plte(&mut self)
483 -> Result<Decoded, DecodingError> {
484 let mut vec = Vec::new();
485 vec.extend(self.current_chunk.2.iter().map(|&v| v));
486 self.info.as_mut().map(
487 |info| info.palette = Some(vec)
488 );
489 Ok(Decoded::Nothing)
490 }
491
parse_trns(&mut self) -> Result<Decoded, DecodingError>492 fn parse_trns(&mut self)
493 -> Result<Decoded, DecodingError> {
494 use common::ColorType::*;
495 let (color_type, bit_depth) = {
496 let info = try!(self.get_info_or_err());
497 (info.color_type, info.bit_depth as u8)
498 };
499 let mut vec = Vec::new();
500 vec.extend(self.current_chunk.2.iter().map(|&v| v));
501 let len = vec.len();
502 let info = match self.info {
503 Some(ref mut info) => info,
504 None => return Err(DecodingError::Format(
505 "tRNS chunk occured before IHDR chunk".into()
506 ))
507 };
508 info.trns = Some(vec);
509 let vec = info.trns.as_mut().unwrap();
510 match color_type {
511 Grayscale => {
512 if len < 2 {
513 return Err(DecodingError::Format(
514 "not enough palette entries".into()
515 ))
516 }
517 if bit_depth < 16 {
518 vec[0] = vec[1];
519 vec.truncate(1);
520 }
521 Ok(Decoded::Nothing)
522 },
523 RGB => {
524 if len < 6 {
525 return Err(DecodingError::Format(
526 "not enough palette entries".into()
527 ))
528 }
529 if bit_depth < 16 {
530 vec[0] = vec[1];
531 vec[1] = vec[3];
532 vec[2] = vec[5];
533 vec.truncate(3);
534 }
535 Ok(Decoded::Nothing)
536 },
537 Indexed => {
538 let _ = info.palette.as_ref().ok_or(DecodingError::Format(
539 "tRNS chunk occured before PLTE chunk".into()
540 ));
541 Ok(Decoded::Nothing)
542 },
543 c => Err(DecodingError::Format(
544 format!("tRNS chunk found for color type ({})", c as u8).into()
545 ))
546 }
547
548 }
549
parse_phys(&mut self) -> Result<Decoded, DecodingError>550 fn parse_phys(&mut self)
551 -> Result<Decoded, DecodingError> {
552 if self.have_idat {
553 Err(DecodingError::Format(
554 "pHYs chunk appeared after first IDAT chunk".into()
555 ))
556 } else {
557 let mut buf = &self.current_chunk.2[..];
558 let xppu = try!(buf.read_be());
559 let yppu = try!(buf.read_be());
560 let unit = try!(buf.read_be());
561 let unit = match Unit::from_u8(unit) {
562 Some(unit) => unit,
563 None => return Err(DecodingError::Format(
564 format!("invalid unit ({})", unit).into()
565 ))
566 };
567 let pixel_dims = PixelDimensions {
568 xppu: xppu,
569 yppu: yppu,
570 unit: unit,
571 };
572 self.info.as_mut().unwrap().pixel_dims = Some(pixel_dims);
573 Ok(Decoded::PixelDimensions(pixel_dims))
574 }
575 }
576
parse_ihdr(&mut self) -> Result<Decoded, DecodingError>577 fn parse_ihdr(&mut self)
578 -> Result<Decoded, DecodingError> {
579 // TODO: check if color/bit depths combination is valid
580 let mut buf = &self.current_chunk.2[..];
581 let width = try!(buf.read_be());
582 let height = try!(buf.read_be());
583 let bit_depth = try!(buf.read_be());
584 let bit_depth = match BitDepth::from_u8(bit_depth) {
585 Some(bits) => bits,
586 None => return Err(DecodingError::Format(
587 format!("invalid bit depth ({})", bit_depth).into()
588 ))
589 };
590 let color_type = try!(buf.read_be());
591 let color_type = match ColorType::from_u8(color_type) {
592 Some(color_type) => color_type,
593 None => return Err(DecodingError::Format(
594 format!("invalid color type ({})", color_type).into()
595 ))
596 };
597 match try!(buf.read_be()) { // compression method
598 0u8 => (),
599 n => return Err(DecodingError::Format(
600 format!("unknown compression method ({})", n).into()
601 ))
602 }
603 match try!(buf.read_be()) { // filter method
604 0u8 => (),
605 n => return Err(DecodingError::Format(
606 format!("unknown filter method ({})", n).into()
607 ))
608 }
609 let interlaced = match try!(buf.read_be()) {
610 0u8 => false,
611 1 => {
612 true
613 },
614 n => return Err(DecodingError::Format(
615 format!("unknown interlace method ({})", n).into()
616 ))
617 };
618 let mut info = Info::default();
619
620 info.width = width;
621 info.height = height;
622 info.bit_depth = bit_depth;
623 info.color_type = color_type;
624 info.interlaced = interlaced;
625 self.info = Some(info);
626 Ok(Decoded::Header(
627 width,
628 height,
629 bit_depth,
630 color_type,
631 interlaced
632 ))
633 }
634 }
635
636 #[inline(always)]
get_info(d: &StreamingDecoder) -> Option<&Info>637 pub fn get_info(d: &StreamingDecoder) -> Option<&Info> {
638 d.info.as_ref()
639 }
640