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
16impl<R: Read> Parameter<Decoder<R>> for Transformations {
34 fn set_param(self, this: &mut Decoder<R>) {
35 this.transform = self
36 }
37}
38
39
40pub 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 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 pub pixels: u64,
60}
61
62impl Default for Limits {
63 fn default() -> Limits {
64 Limits {
65 pixels: 1 << 26,
66 }
67 }
68}
69
70pub struct Decoder<R: Read> {
72 r: R,
74 transform: Transformations,
76 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 pub fn set_limits(&mut self, limits: Limits) {
110 self.limits = limits;
111 }
112
113 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 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 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
175pub struct Reader<R: Read> {
179 decoder: ReadDecoder<R>,
180 bpp: usize,
181 rowlen: usize,
182 adam7: Option<utils::Adam7Iterator>,
183 prev: Vec<u8>,
185 current: Vec<u8>,
187 transform: Transformations,
189 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 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 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 pub fn next_frame(&mut self, buf: &mut [u8]) -> Result<(), DecodingError> {
258 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 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 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 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 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 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 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 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 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 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 _ 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 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