1 extern crate crc32fast;
2 extern crate deflate;
3 
4 use std::borrow::Cow;
5 use std::error;
6 use std::fmt;
7 use std::io::{self, Read, Write};
8 use std::mem;
9 use std::result;
10 
11 use crc32fast::Hasher as Crc32;
12 
13 use crate::chunk;
14 use crate::common::{BitDepth, BytesPerPixel, ColorType, Compression, Info};
15 use crate::filter::{filter, FilterType};
16 use crate::traits::WriteBytesExt;
17 
18 pub type Result<T> = result::Result<T, EncodingError>;
19 
20 #[derive(Debug)]
21 pub enum EncodingError {
22     IoError(io::Error),
23     Format(Cow<'static, str>),
24 }
25 
26 impl error::Error for EncodingError {
cause(&self) -> Option<&(dyn error::Error + 'static)>27     fn cause(&self) -> Option<&(dyn error::Error + 'static)> {
28         match self {
29             EncodingError::IoError(err) => Some(err),
30             _ => None,
31         }
32     }
33 }
34 
35 impl fmt::Display for EncodingError {
fmt(&self, fmt: &mut fmt::Formatter) -> result::Result<(), fmt::Error>36     fn fmt(&self, fmt: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
37         use self::EncodingError::*;
38         match self {
39             IoError(err) => write!(fmt, "{}", err),
40             Format(desc) => write!(fmt, "{}", desc),
41         }
42     }
43 }
44 
45 impl From<io::Error> for EncodingError {
from(err: io::Error) -> EncodingError46     fn from(err: io::Error) -> EncodingError {
47         EncodingError::IoError(err)
48     }
49 }
50 impl From<EncodingError> for io::Error {
from(err: EncodingError) -> io::Error51     fn from(err: EncodingError) -> io::Error {
52         io::Error::new(io::ErrorKind::Other, err.to_string())
53     }
54 }
55 
56 /// PNG Encoder
57 pub struct Encoder<W: Write> {
58     w: W,
59     info: Info,
60 }
61 
62 impl<W: Write> Encoder<W> {
new(w: W, width: u32, height: u32) -> Encoder<W>63     pub fn new(w: W, width: u32, height: u32) -> Encoder<W> {
64         let mut info = Info::default();
65         info.width = width;
66         info.height = height;
67         Encoder { w, info }
68     }
69 
set_palette(&mut self, palette: Vec<u8>)70     pub fn set_palette(&mut self, palette: Vec<u8>) {
71         self.info.palette = Some(palette);
72     }
73 
set_trns(&mut self, trns: Vec<u8>)74     pub fn set_trns(&mut self, trns: Vec<u8>) {
75         self.info.trns = Some(trns);
76     }
77 
write_header(self) -> Result<Writer<W>>78     pub fn write_header(self) -> Result<Writer<W>> {
79         Writer::new(self.w, self.info).init()
80     }
81 
82     /// Set the color of the encoded image.
83     ///
84     /// These correspond to the color types in the png IHDR data that will be written. The length
85     /// of the image data that is later supplied must match the color type, otherwise an error will
86     /// be emitted.
set_color(&mut self, color: ColorType)87     pub fn set_color(&mut self, color: ColorType) {
88         self.info.color_type = color;
89     }
90 
91     /// Set the indicated depth of the image data.
set_depth(&mut self, depth: BitDepth)92     pub fn set_depth(&mut self, depth: BitDepth) {
93         self.info.bit_depth = depth;
94     }
95 
96     /// Set compression parameters.
97     ///
98     /// Accepts a `Compression` or any type that can transform into a `Compression`. Notably `deflate::Compression` and
99     /// `deflate::CompressionOptions` which "just work".
set_compression<C: Into<Compression>>(&mut self, compression: C)100     pub fn set_compression<C: Into<Compression>>(&mut self, compression: C) {
101         self.info.compression = compression.into();
102     }
103 
104     /// Set the used filter type.
105     ///
106     /// The default filter is [`FilterType::Sub`] which provides a basic prediction algorithm for
107     /// sample values based on the previous. For a potentially better compression ratio, at the
108     /// cost of more complex processing, try out [`FilterType::Paeth`].
109     ///
110     /// [`FilterType::Sub`]: enum.FilterType.html#variant.Sub
111     /// [`FilterType::Paeth`]: enum.FilterType.html#variant.Paeth
set_filter(&mut self, filter: FilterType)112     pub fn set_filter(&mut self, filter: FilterType) {
113         self.info.filter = filter;
114     }
115 }
116 
117 /// PNG writer
118 pub struct Writer<W: Write> {
119     w: W,
120     info: Info,
121 }
122 
123 const DEFAULT_BUFFER_LENGTH: usize = 4 * 1024;
124 
write_chunk<W: Write>(mut w: W, name: [u8; 4], data: &[u8]) -> Result<()>125 fn write_chunk<W: Write>(mut w: W, name: [u8; 4], data: &[u8]) -> Result<()> {
126     w.write_be(data.len() as u32)?;
127     w.write_all(&name)?;
128     w.write_all(data)?;
129     let mut crc = Crc32::new();
130     crc.update(&name);
131     crc.update(data);
132     w.write_be(crc.finalize())?;
133     Ok(())
134 }
135 
136 impl<W: Write> Writer<W> {
new(w: W, info: Info) -> Writer<W>137     fn new(w: W, info: Info) -> Writer<W> {
138         Writer { w, info }
139     }
140 
init(mut self) -> Result<Self>141     fn init(mut self) -> Result<Self> {
142         if self.info.width == 0 {
143             return Err(EncodingError::Format("Zero width not allowed".into()));
144         }
145 
146         if self.info.height == 0 {
147             return Err(EncodingError::Format("Zero height not allowed".into()));
148         }
149 
150         // TODO: this could yield the typified BytesPerPixel.
151         if self
152             .info
153             .color_type
154             .is_combination_invalid(self.info.bit_depth)
155         {
156             return Err(EncodingError::Format(
157                 format!(
158                     "Invalid combination of bit-depth '{:?}' and color-type '{:?}'",
159                     self.info.bit_depth, self.info.color_type
160                 )
161                 .into(),
162             ));
163         }
164 
165         self.w.write_all(&[137, 80, 78, 71, 13, 10, 26, 10])?;
166         let mut data = [0; 13];
167         (&mut data[..]).write_be(self.info.width)?;
168         (&mut data[4..]).write_be(self.info.height)?;
169         data[8] = self.info.bit_depth as u8;
170         data[9] = self.info.color_type as u8;
171         data[12] = if self.info.interlaced { 1 } else { 0 };
172         self.write_chunk(chunk::IHDR, &data)?;
173 
174         if let Some(p) = &self.info.palette {
175             write_chunk(&mut self.w, chunk::PLTE, p)?;
176         };
177 
178         if let Some(t) = &self.info.trns {
179             write_chunk(&mut self.w, chunk::tRNS, t)?;
180         }
181 
182         Ok(self)
183     }
184 
write_chunk(&mut self, name: [u8; 4], data: &[u8]) -> Result<()>185     pub fn write_chunk(&mut self, name: [u8; 4], data: &[u8]) -> Result<()> {
186         write_chunk(&mut self.w, name, data)
187     }
188 
189     /// Writes the image data.
write_image_data(&mut self, data: &[u8]) -> Result<()>190     pub fn write_image_data(&mut self, data: &[u8]) -> Result<()> {
191         const MAX_CHUNK_LEN: u32 = (1u32 << 31) - 1;
192 
193         if self.info.color_type == ColorType::Indexed && self.info.palette.is_none() {
194             return Err(EncodingError::Format(
195                 "can't write indexed image without palette".into(),
196             ));
197         }
198 
199         let bpp = self.info.bpp_in_prediction();
200         let in_len = self.info.raw_row_length() - 1;
201         let prev = vec![0; in_len];
202         let mut prev = prev.as_slice();
203         let mut current = vec![0; in_len];
204         let data_size = in_len * self.info.height as usize;
205         if data_size != data.len() {
206             let message = format!("wrong data size, expected {} got {}", data_size, data.len());
207             return Err(EncodingError::Format(message.into()));
208         }
209         let mut zlib = deflate::write::ZlibEncoder::new(Vec::new(), self.info.compression.clone());
210         let filter_method = self.info.filter;
211         for line in data.chunks(in_len) {
212             current.copy_from_slice(&line);
213             zlib.write_all(&[filter_method as u8])?;
214             filter(filter_method, bpp, &prev, &mut current);
215             zlib.write_all(&current)?;
216             prev = line;
217         }
218         let zlib_encoded = zlib.finish()?;
219         for chunk in zlib_encoded.chunks(MAX_CHUNK_LEN as usize) {
220             self.write_chunk(chunk::IDAT, &chunk)?;
221         }
222         Ok(())
223     }
224 
225     /// Create an stream writer.
226     ///
227     /// This allows you create images that do not fit in memory. The default
228     /// chunk size is 4K, use `stream_writer_with_size` to set another chuck
229     /// size.
230     ///
231     /// This borrows the writer. This preserves it which allows manually
232     /// appending additional chunks after the image data has been written
stream_writer(&mut self) -> StreamWriter<W>233     pub fn stream_writer(&mut self) -> StreamWriter<W> {
234         self.stream_writer_with_size(DEFAULT_BUFFER_LENGTH)
235     }
236 
237     /// Create a stream writer with custom buffer size.
238     ///
239     /// See [`stream_writer`].
240     ///
241     /// [`stream_writer`]: #fn.stream_writer
stream_writer_with_size(&mut self, size: usize) -> StreamWriter<W>242     pub fn stream_writer_with_size(&mut self, size: usize) -> StreamWriter<W> {
243         StreamWriter::new(ChunkOutput::Borrowed(self), size)
244     }
245 
246     /// Turn this into a stream writer for image data.
247     ///
248     /// This allows you create images that do not fit in memory. The default
249     /// chunk size is 4K, use `stream_writer_with_size` to set another chuck
250     /// size.
into_stream_writer(self) -> StreamWriter<'static, W>251     pub fn into_stream_writer(self) -> StreamWriter<'static, W> {
252         self.into_stream_writer_with_size(DEFAULT_BUFFER_LENGTH)
253     }
254 
255     /// Turn this into a stream writer with custom buffer size.
256     ///
257     /// See [`into_stream_writer`].
258     ///
259     /// [`into_stream_writer`]: #fn.into_stream_writer
into_stream_writer_with_size(self, size: usize) -> StreamWriter<'static, W>260     pub fn into_stream_writer_with_size(self, size: usize) -> StreamWriter<'static, W> {
261         StreamWriter::new(ChunkOutput::Owned(self), size)
262     }
263 }
264 
265 impl<W: Write> Drop for Writer<W> {
drop(&mut self)266     fn drop(&mut self) {
267         let _ = self.write_chunk(chunk::IEND, &[]);
268     }
269 }
270 
271 struct ChunkWriter<'a, W: Write> {
272     writer: ChunkOutput<'a, W>,
273     buffer: Vec<u8>,
274     index: usize,
275 }
276 
277 enum ChunkOutput<'a, W: Write> {
278     Borrowed(&'a mut Writer<W>),
279     Owned(Writer<W>),
280 }
281 
282 impl<'a, W: Write> ChunkWriter<'a, W> {
new(writer: ChunkOutput<'a, W>, buf_len: usize) -> ChunkWriter<'a, W>283     fn new(writer: ChunkOutput<'a, W>, buf_len: usize) -> ChunkWriter<'a, W> {
284         ChunkWriter {
285             writer,
286             buffer: vec![0; buf_len],
287             index: 0,
288         }
289     }
290 }
291 
292 impl<'a, W: Write> AsMut<Writer<W>> for ChunkOutput<'a, W> {
as_mut(&mut self) -> &mut Writer<W>293     fn as_mut(&mut self) -> &mut Writer<W> {
294         match self {
295             ChunkOutput::Borrowed(writer) => writer,
296             ChunkOutput::Owned(writer) => writer,
297         }
298     }
299 }
300 
301 impl<'a, W: Write> Write for ChunkWriter<'a, W> {
write(&mut self, mut buf: &[u8]) -> io::Result<usize>302     fn write(&mut self, mut buf: &[u8]) -> io::Result<usize> {
303         let written = buf.read(&mut self.buffer[self.index..])?;
304         self.index += written;
305 
306         if self.index + 1 >= self.buffer.len() {
307             self.writer
308                 .as_mut()
309                 .write_chunk(chunk::IDAT, &self.buffer)?;
310             self.index = 0;
311         }
312 
313         Ok(written)
314     }
315 
flush(&mut self) -> io::Result<()>316     fn flush(&mut self) -> io::Result<()> {
317         if self.index > 0 {
318             self.writer
319                 .as_mut()
320                 .write_chunk(chunk::IDAT, &self.buffer[..=self.index])?;
321         }
322         self.index = 0;
323         Ok(())
324     }
325 }
326 
327 impl<'a, W: Write> Drop for ChunkWriter<'a, W> {
drop(&mut self)328     fn drop(&mut self) {
329         let _ = self.flush();
330     }
331 }
332 
333 /// Streaming png writer
334 ///
335 /// This may silently fail in the destructor, so it is a good idea to call
336 /// [`finish`](#method.finish) or [`flush`](https://doc.rust-lang.org/stable/std/io/trait.Write.html#tymethod.flush) before dropping.
337 pub struct StreamWriter<'a, W: Write> {
338     writer: deflate::write::ZlibEncoder<ChunkWriter<'a, W>>,
339     prev_buf: Vec<u8>,
340     curr_buf: Vec<u8>,
341     index: usize,
342     bpp: BytesPerPixel,
343     filter: FilterType,
344 }
345 
346 impl<'a, W: Write> StreamWriter<'a, W> {
new(mut writer: ChunkOutput<'a, W>, buf_len: usize) -> StreamWriter<'a, W>347     fn new(mut writer: ChunkOutput<'a, W>, buf_len: usize) -> StreamWriter<'a, W> {
348         let bpp = writer.as_mut().info.bpp_in_prediction();
349         let in_len = writer.as_mut().info.raw_row_length() - 1;
350         let filter = writer.as_mut().info.filter;
351         let prev_buf = vec![0; in_len];
352         let curr_buf = vec![0; in_len];
353 
354         let compression = writer.as_mut().info.compression.clone();
355         let chunk_writer = ChunkWriter::new(writer, buf_len);
356         let zlib = deflate::write::ZlibEncoder::new(chunk_writer, compression);
357 
358         StreamWriter {
359             writer: zlib,
360             index: 0,
361             prev_buf,
362             curr_buf,
363             bpp,
364             filter,
365         }
366     }
367 
finish(mut self) -> Result<()>368     pub fn finish(mut self) -> Result<()> {
369         // TODO: call `writer.finish` somehow?
370         self.flush()?;
371         Ok(())
372     }
373 }
374 
375 impl<'a, W: Write> Write for StreamWriter<'a, W> {
write(&mut self, mut buf: &[u8]) -> io::Result<usize>376     fn write(&mut self, mut buf: &[u8]) -> io::Result<usize> {
377         let written = buf.read(&mut self.curr_buf[self.index..])?;
378         self.index += written;
379 
380         if self.index >= self.curr_buf.len() {
381             self.writer.write_all(&[self.filter as u8])?;
382             filter(self.filter, self.bpp, &self.prev_buf, &mut self.curr_buf);
383             self.writer.write_all(&self.curr_buf)?;
384             mem::swap(&mut self.prev_buf, &mut self.curr_buf);
385             self.index = 0;
386         }
387 
388         Ok(written)
389     }
390 
flush(&mut self) -> io::Result<()>391     fn flush(&mut self) -> io::Result<()> {
392         self.writer.flush()?;
393         if self.index > 0 {
394             let message = format!("wrong data size, got {} bytes too many", self.index);
395             return Err(EncodingError::Format(message.into()).into());
396         }
397         Ok(())
398     }
399 }
400 
401 impl<'a, W: Write> Drop for StreamWriter<'a, W> {
drop(&mut self)402     fn drop(&mut self) {
403         let _ = self.flush();
404     }
405 }
406 
407 #[cfg(test)]
408 mod tests {
409     use super::*;
410 
411     extern crate glob;
412 
413     use rand::{thread_rng, Rng};
414     use std::fs::File;
415     use std::io::Write;
416     use std::{cmp, io};
417 
418     #[test]
roundtrip()419     fn roundtrip() {
420         // More loops = more random testing, but also more test wait time
421         for _ in 0..10 {
422             for path in glob::glob("tests/pngsuite/*.png")
423                 .unwrap()
424                 .map(|r| r.unwrap())
425             {
426                 if path.file_name().unwrap().to_str().unwrap().starts_with("x") {
427                     // x* files are expected to fail to decode
428                     continue;
429                 }
430                 eprintln!("{}", path.display());
431                 // Decode image
432                 let decoder = crate::Decoder::new(File::open(path).unwrap());
433                 let (info, mut reader) = decoder.read_info().unwrap();
434                 if info.line_size != 32 {
435                     // TODO encoding only works with line size 32?
436                     continue;
437                 }
438                 let mut buf = vec![0; info.buffer_size()];
439                 eprintln!("{:?}", info);
440                 reader.next_frame(&mut buf).unwrap();
441                 // Encode decoded image
442                 let mut out = Vec::new();
443                 {
444                     let mut wrapper = RandomChunkWriter {
445                         rng: thread_rng(),
446                         w: &mut out,
447                     };
448 
449                     let mut encoder = Encoder::new(&mut wrapper, info.width, info.height)
450                         .write_header()
451                         .unwrap();
452                     encoder.write_image_data(&buf).unwrap();
453                 }
454                 // Decode encoded decoded image
455                 let decoder = crate::Decoder::new(&*out);
456                 let (info, mut reader) = decoder.read_info().unwrap();
457                 let mut buf2 = vec![0; info.buffer_size()];
458                 reader.next_frame(&mut buf2).unwrap();
459                 // check if the encoded image is ok:
460                 assert_eq!(buf, buf2);
461             }
462         }
463     }
464 
465     #[test]
roundtrip_stream()466     fn roundtrip_stream() {
467         // More loops = more random testing, but also more test wait time
468         for _ in 0..10 {
469             for path in glob::glob("tests/pngsuite/*.png")
470                 .unwrap()
471                 .map(|r| r.unwrap())
472             {
473                 if path.file_name().unwrap().to_str().unwrap().starts_with("x") {
474                     // x* files are expected to fail to decode
475                     continue;
476                 }
477                 // Decode image
478                 let decoder = crate::Decoder::new(File::open(path).unwrap());
479                 let (info, mut reader) = decoder.read_info().unwrap();
480                 if info.line_size != 32 {
481                     // TODO encoding only works with line size 32?
482                     continue;
483                 }
484                 let mut buf = vec![0; info.buffer_size()];
485                 reader.next_frame(&mut buf).unwrap();
486                 // Encode decoded image
487                 let mut out = Vec::new();
488                 {
489                     let mut wrapper = RandomChunkWriter {
490                         rng: thread_rng(),
491                         w: &mut out,
492                     };
493 
494                     let mut encoder = Encoder::new(&mut wrapper, info.width, info.height)
495                         .write_header()
496                         .unwrap();
497                     let mut stream_writer = encoder.stream_writer();
498 
499                     let mut outer_wrapper = RandomChunkWriter {
500                         rng: thread_rng(),
501                         w: &mut stream_writer,
502                     };
503 
504                     outer_wrapper.write_all(&buf).unwrap();
505                 }
506                 // Decode encoded decoded image
507                 let decoder = crate::Decoder::new(&*out);
508                 let (info, mut reader) = decoder.read_info().unwrap();
509                 let mut buf2 = vec![0; info.buffer_size()];
510                 reader.next_frame(&mut buf2).unwrap();
511                 // check if the encoded image is ok:
512                 assert_eq!(buf, buf2);
513             }
514         }
515     }
516 
517     #[test]
image_palette() -> Result<()>518     fn image_palette() -> Result<()> {
519         let samples = 3;
520         for bit_depth in vec![1u8, 2, 4, 8] {
521             // Do a reference decoding, choose a fitting palette image from pngsuite
522             let path = format!("tests/pngsuite/basn3p0{}.png", bit_depth);
523             let decoder = crate::Decoder::new(File::open(&path).unwrap());
524             let (info, mut reader) = decoder.read_info().unwrap();
525 
526             let palette: Vec<u8> = reader.info().palette.clone().unwrap();
527             let mut decoded_pixels = vec![0; info.buffer_size()];
528             assert_eq!(
529                 info.width as usize * info.height as usize * samples,
530                 decoded_pixels.len()
531             );
532             reader.next_frame(&mut decoded_pixels).unwrap();
533 
534             let pixels_per_byte = 8 / usize::from(bit_depth);
535             let mut indexed_data = vec![0; decoded_pixels.len() / samples];
536             {
537                 // Retransform the image into palette bits.
538                 let mut indexes = vec![];
539                 for color in decoded_pixels.chunks(samples) {
540                     let j = palette
541                         .chunks(samples)
542                         .position(|pcolor| color == pcolor)
543                         .unwrap();
544                     indexes.push(j as u8);
545                 }
546 
547                 let idx_per_byte = indexes.chunks(pixels_per_byte);
548                 indexed_data.truncate(idx_per_byte.len());
549                 for (pixels, byte) in idx_per_byte.zip(&mut indexed_data) {
550                     let mut shift = 8;
551                     for idx in pixels {
552                         shift -= bit_depth;
553                         *byte = *byte | idx << shift;
554                     }
555                 }
556             };
557 
558             let mut out = Vec::new();
559             {
560                 let mut encoder = Encoder::new(&mut out, info.width, info.height);
561                 encoder.set_depth(BitDepth::from_u8(bit_depth).unwrap());
562                 encoder.set_color(ColorType::Indexed);
563                 encoder.set_palette(palette.clone());
564 
565                 let mut writer = encoder.write_header().unwrap();
566                 writer.write_image_data(&indexed_data).unwrap();
567             }
568 
569             // Decode re-encoded image
570             let decoder = crate::Decoder::new(&*out);
571             let (info, mut reader) = decoder.read_info().unwrap();
572             let mut redecoded = vec![0; info.buffer_size()];
573             reader.next_frame(&mut redecoded).unwrap();
574             // check if the encoded image is ok:
575             assert_eq!(decoded_pixels, redecoded);
576         }
577         Ok(())
578     }
579 
580     #[test]
expect_error_on_wrong_image_len() -> Result<()>581     fn expect_error_on_wrong_image_len() -> Result<()> {
582         use std::io::Cursor;
583 
584         let width = 10;
585         let height = 10;
586 
587         let output = vec![0u8; 1024];
588         let writer = Cursor::new(output);
589         let mut encoder = Encoder::new(writer, width as u32, height as u32);
590         encoder.set_depth(BitDepth::Eight);
591         encoder.set_color(ColorType::RGB);
592         let mut png_writer = encoder.write_header()?;
593 
594         let correct_image_size = width * height * 3;
595         let image = vec![0u8; correct_image_size + 1];
596         let result = png_writer.write_image_data(image.as_ref());
597         assert!(result.is_err());
598 
599         Ok(())
600     }
601 
602     #[test]
expect_error_on_empty_image() -> Result<()>603     fn expect_error_on_empty_image() -> Result<()> {
604         use std::io::Cursor;
605 
606         let output = vec![0u8; 1024];
607         let mut writer = Cursor::new(output);
608 
609         let encoder = Encoder::new(&mut writer, 0, 0);
610         assert!(encoder.write_header().is_err());
611 
612         let encoder = Encoder::new(&mut writer, 100, 0);
613         assert!(encoder.write_header().is_err());
614 
615         let encoder = Encoder::new(&mut writer, 0, 100);
616         assert!(encoder.write_header().is_err());
617 
618         Ok(())
619     }
620 
621     #[test]
expect_error_on_invalid_bit_depth_color_type_combination() -> Result<()>622     fn expect_error_on_invalid_bit_depth_color_type_combination() -> Result<()> {
623         use std::io::Cursor;
624 
625         let output = vec![0u8; 1024];
626         let mut writer = Cursor::new(output);
627 
628         let mut encoder = Encoder::new(&mut writer, 1, 1);
629         encoder.set_depth(BitDepth::One);
630         encoder.set_color(ColorType::RGB);
631         assert!(encoder.write_header().is_err());
632 
633         let mut encoder = Encoder::new(&mut writer, 1, 1);
634         encoder.set_depth(BitDepth::One);
635         encoder.set_color(ColorType::GrayscaleAlpha);
636         assert!(encoder.write_header().is_err());
637 
638         let mut encoder = Encoder::new(&mut writer, 1, 1);
639         encoder.set_depth(BitDepth::One);
640         encoder.set_color(ColorType::RGBA);
641         assert!(encoder.write_header().is_err());
642 
643         let mut encoder = Encoder::new(&mut writer, 1, 1);
644         encoder.set_depth(BitDepth::Two);
645         encoder.set_color(ColorType::RGB);
646         assert!(encoder.write_header().is_err());
647 
648         let mut encoder = Encoder::new(&mut writer, 1, 1);
649         encoder.set_depth(BitDepth::Two);
650         encoder.set_color(ColorType::GrayscaleAlpha);
651         assert!(encoder.write_header().is_err());
652 
653         let mut encoder = Encoder::new(&mut writer, 1, 1);
654         encoder.set_depth(BitDepth::Two);
655         encoder.set_color(ColorType::RGBA);
656         assert!(encoder.write_header().is_err());
657 
658         let mut encoder = Encoder::new(&mut writer, 1, 1);
659         encoder.set_depth(BitDepth::Four);
660         encoder.set_color(ColorType::RGB);
661         assert!(encoder.write_header().is_err());
662 
663         let mut encoder = Encoder::new(&mut writer, 1, 1);
664         encoder.set_depth(BitDepth::Four);
665         encoder.set_color(ColorType::GrayscaleAlpha);
666         assert!(encoder.write_header().is_err());
667 
668         let mut encoder = Encoder::new(&mut writer, 1, 1);
669         encoder.set_depth(BitDepth::Four);
670         encoder.set_color(ColorType::RGBA);
671         assert!(encoder.write_header().is_err());
672 
673         let mut encoder = Encoder::new(&mut writer, 1, 1);
674         encoder.set_depth(BitDepth::Sixteen);
675         encoder.set_color(ColorType::Indexed);
676         assert!(encoder.write_header().is_err());
677 
678         Ok(())
679     }
680 
681     #[test]
can_write_header_with_valid_bit_depth_color_type_combination() -> Result<()>682     fn can_write_header_with_valid_bit_depth_color_type_combination() -> Result<()> {
683         use std::io::Cursor;
684 
685         let output = vec![0u8; 1024];
686         let mut writer = Cursor::new(output);
687 
688         let mut encoder = Encoder::new(&mut writer, 1, 1);
689         encoder.set_depth(BitDepth::One);
690         encoder.set_color(ColorType::Grayscale);
691         assert!(encoder.write_header().is_ok());
692 
693         let mut encoder = Encoder::new(&mut writer, 1, 1);
694         encoder.set_depth(BitDepth::One);
695         encoder.set_color(ColorType::Indexed);
696         assert!(encoder.write_header().is_ok());
697 
698         let mut encoder = Encoder::new(&mut writer, 1, 1);
699         encoder.set_depth(BitDepth::Two);
700         encoder.set_color(ColorType::Grayscale);
701         assert!(encoder.write_header().is_ok());
702 
703         let mut encoder = Encoder::new(&mut writer, 1, 1);
704         encoder.set_depth(BitDepth::Two);
705         encoder.set_color(ColorType::Indexed);
706         assert!(encoder.write_header().is_ok());
707 
708         let mut encoder = Encoder::new(&mut writer, 1, 1);
709         encoder.set_depth(BitDepth::Four);
710         encoder.set_color(ColorType::Grayscale);
711         assert!(encoder.write_header().is_ok());
712 
713         let mut encoder = Encoder::new(&mut writer, 1, 1);
714         encoder.set_depth(BitDepth::Four);
715         encoder.set_color(ColorType::Indexed);
716         assert!(encoder.write_header().is_ok());
717 
718         let mut encoder = Encoder::new(&mut writer, 1, 1);
719         encoder.set_depth(BitDepth::Eight);
720         encoder.set_color(ColorType::Grayscale);
721         assert!(encoder.write_header().is_ok());
722 
723         let mut encoder = Encoder::new(&mut writer, 1, 1);
724         encoder.set_depth(BitDepth::Eight);
725         encoder.set_color(ColorType::RGB);
726         assert!(encoder.write_header().is_ok());
727 
728         let mut encoder = Encoder::new(&mut writer, 1, 1);
729         encoder.set_depth(BitDepth::Eight);
730         encoder.set_color(ColorType::Indexed);
731         assert!(encoder.write_header().is_ok());
732 
733         let mut encoder = Encoder::new(&mut writer, 1, 1);
734         encoder.set_depth(BitDepth::Eight);
735         encoder.set_color(ColorType::GrayscaleAlpha);
736         assert!(encoder.write_header().is_ok());
737 
738         let mut encoder = Encoder::new(&mut writer, 1, 1);
739         encoder.set_depth(BitDepth::Eight);
740         encoder.set_color(ColorType::RGBA);
741         assert!(encoder.write_header().is_ok());
742 
743         let mut encoder = Encoder::new(&mut writer, 1, 1);
744         encoder.set_depth(BitDepth::Sixteen);
745         encoder.set_color(ColorType::Grayscale);
746         assert!(encoder.write_header().is_ok());
747 
748         let mut encoder = Encoder::new(&mut writer, 1, 1);
749         encoder.set_depth(BitDepth::Sixteen);
750         encoder.set_color(ColorType::RGB);
751         assert!(encoder.write_header().is_ok());
752 
753         let mut encoder = Encoder::new(&mut writer, 1, 1);
754         encoder.set_depth(BitDepth::Sixteen);
755         encoder.set_color(ColorType::GrayscaleAlpha);
756         assert!(encoder.write_header().is_ok());
757 
758         let mut encoder = Encoder::new(&mut writer, 1, 1);
759         encoder.set_depth(BitDepth::Sixteen);
760         encoder.set_color(ColorType::RGBA);
761         assert!(encoder.write_header().is_ok());
762 
763         Ok(())
764     }
765 
766     #[test]
all_filters_roundtrip() -> io::Result<()>767     fn all_filters_roundtrip() -> io::Result<()> {
768         let pixel: Vec<_> = (0..48).collect();
769 
770         let roundtrip = |filter: FilterType| -> io::Result<()> {
771             let mut buffer = vec![];
772             let mut encoder = Encoder::new(&mut buffer, 4, 4);
773             encoder.set_depth(BitDepth::Eight);
774             encoder.set_color(ColorType::RGB);
775             encoder.set_filter(filter);
776             encoder.write_header()?.write_image_data(&pixel)?;
777 
778             let decoder = crate::Decoder::new(io::Cursor::new(buffer));
779             let (info, mut reader) = decoder.read_info()?;
780             assert_eq!(info.width, 4);
781             assert_eq!(info.height, 4);
782             let mut dest = vec![0; pixel.len()];
783             reader.next_frame(&mut dest)?;
784             assert_eq!(dest, pixel, "Deviation with filter type {:?}", filter);
785 
786             Ok(())
787         };
788 
789         roundtrip(FilterType::NoFilter)?;
790         roundtrip(FilterType::Sub)?;
791         roundtrip(FilterType::Up)?;
792         roundtrip(FilterType::Avg)?;
793         roundtrip(FilterType::Paeth)?;
794 
795         Ok(())
796     }
797 
798     /// A Writer that only writes a few bytes at a time
799     struct RandomChunkWriter<'a, R: Rng, W: Write + 'a> {
800         rng: R,
801         w: &'a mut W,
802     }
803 
804     impl<'a, R: Rng, W: Write + 'a> Write for RandomChunkWriter<'a, R, W> {
write(&mut self, buf: &[u8]) -> io::Result<usize>805         fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
806             // choose a random length to write
807             let len = cmp::min(self.rng.gen_range(1, 50), buf.len());
808 
809             self.w.write(&buf[0..len])
810         }
811 
flush(&mut self) -> io::Result<()>812         fn flush(&mut self) -> io::Result<()> {
813             self.w.flush()
814         }
815     }
816 }
817