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