1 //! Common types shared between the encoder and decoder
2 use crate::filter;
3 
4 use std::{convert::TryFrom, fmt};
5 
6 /// Describes the layout of samples in a pixel
7 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
8 #[repr(u8)]
9 pub enum ColorType {
10     Grayscale = 0,
11     RGB = 2,
12     Indexed = 3,
13     GrayscaleAlpha = 4,
14     RGBA = 6,
15 }
16 
17 impl ColorType {
18     /// Returns the number of samples used per pixel of `ColorType`
samples(&self) -> usize19     pub fn samples(&self) -> usize {
20         self.samples_u8().into()
21     }
22 
samples_u8(self) -> u823     pub(crate) fn samples_u8(self) -> u8 {
24         use self::ColorType::*;
25         match self {
26             Grayscale | Indexed => 1,
27             RGB => 3,
28             GrayscaleAlpha => 2,
29             RGBA => 4,
30         }
31     }
32 
33     /// u8 -> Self. Temporary solution until Rust provides a canonical one.
from_u8(n: u8) -> Option<ColorType>34     pub fn from_u8(n: u8) -> Option<ColorType> {
35         match n {
36             0 => Some(ColorType::Grayscale),
37             2 => Some(ColorType::RGB),
38             3 => Some(ColorType::Indexed),
39             4 => Some(ColorType::GrayscaleAlpha),
40             6 => Some(ColorType::RGBA),
41             _ => None,
42         }
43     }
44 
checked_raw_row_length(&self, depth: BitDepth, width: u32) -> Option<usize>45     pub(crate) fn checked_raw_row_length(&self, depth: BitDepth, width: u32) -> Option<usize> {
46         // No overflow can occur in 64 bits, we multiply 32-bit with 5 more bits.
47         let bits = u64::from(width) * u64::from(self.samples_u8()) * u64::from(depth.into_u8());
48         TryFrom::try_from(1 + (bits + 7) / 8).ok()
49     }
50 
raw_row_length_from_width(&self, depth: BitDepth, width: u32) -> usize51     pub(crate) fn raw_row_length_from_width(&self, depth: BitDepth, width: u32) -> usize {
52         let samples = width as usize * self.samples();
53         1 + match depth {
54             BitDepth::Sixteen => samples * 2,
55             BitDepth::Eight => samples,
56             subbyte => {
57                 let samples_per_byte = 8 / subbyte as usize;
58                 let whole = samples / samples_per_byte;
59                 let fract = usize::from(samples % samples_per_byte > 0);
60                 whole + fract
61             }
62         }
63     }
64 
is_combination_invalid(self, bit_depth: BitDepth) -> bool65     pub(crate) fn is_combination_invalid(self, bit_depth: BitDepth) -> bool {
66         // Section 11.2.2 of the PNG standard disallows several combinations
67         // of bit depth and color type
68         ((bit_depth == BitDepth::One || bit_depth == BitDepth::Two || bit_depth == BitDepth::Four)
69             && (self == ColorType::RGB
70                 || self == ColorType::GrayscaleAlpha
71                 || self == ColorType::RGBA))
72             || (bit_depth == BitDepth::Sixteen && self == ColorType::Indexed)
73     }
74 }
75 
76 /// Bit depth of the png file
77 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
78 #[repr(u8)]
79 pub enum BitDepth {
80     One = 1,
81     Two = 2,
82     Four = 4,
83     Eight = 8,
84     Sixteen = 16,
85 }
86 
87 /// Internal count of bytes per pixel.
88 /// This is used for filtering which never uses sub-byte units. This essentially reduces the number
89 /// of possible byte chunk lengths to a very small set of values appropriate to be defined as an
90 /// enum.
91 #[derive(Debug, Clone, Copy)]
92 #[repr(u8)]
93 pub(crate) enum BytesPerPixel {
94     One = 1,
95     Two = 2,
96     Three = 3,
97     Four = 4,
98     Six = 6,
99     Eight = 8,
100 }
101 
102 impl BitDepth {
103     /// u8 -> Self. Temporary solution until Rust provides a canonical one.
from_u8(n: u8) -> Option<BitDepth>104     pub fn from_u8(n: u8) -> Option<BitDepth> {
105         match n {
106             1 => Some(BitDepth::One),
107             2 => Some(BitDepth::Two),
108             4 => Some(BitDepth::Four),
109             8 => Some(BitDepth::Eight),
110             16 => Some(BitDepth::Sixteen),
111             _ => None,
112         }
113     }
114 
into_u8(self) -> u8115     pub(crate) fn into_u8(self) -> u8 {
116         self as u8
117     }
118 }
119 
120 /// Pixel dimensions information
121 #[derive(Clone, Copy, Debug)]
122 pub struct PixelDimensions {
123     /// Pixels per unit, X axis
124     pub xppu: u32,
125     /// Pixels per unit, Y axis
126     pub yppu: u32,
127     /// Either *Meter* or *Unspecified*
128     pub unit: Unit,
129 }
130 
131 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
132 #[repr(u8)]
133 /// Physical unit of the pixel dimensions
134 pub enum Unit {
135     Unspecified = 0,
136     Meter = 1,
137 }
138 
139 impl Unit {
140     /// u8 -> Self. Temporary solution until Rust provides a canonical one.
from_u8(n: u8) -> Option<Unit>141     pub fn from_u8(n: u8) -> Option<Unit> {
142         match n {
143             0 => Some(Unit::Unspecified),
144             1 => Some(Unit::Meter),
145             _ => None,
146         }
147     }
148 }
149 
150 /// How to reset buffer of an animated png (APNG) at the end of a frame.
151 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
152 #[repr(u8)]
153 pub enum DisposeOp {
154     /// Leave the buffer unchanged.
155     None = 0,
156     /// Clear buffer with the background color.
157     Background = 1,
158     /// Reset the buffer to the state before the current frame.
159     Previous = 2,
160 }
161 
162 impl DisposeOp {
163     /// u8 -> Self. Using enum_primitive or transmute is probably the right thing but this will do for now.
from_u8(n: u8) -> Option<DisposeOp>164     pub fn from_u8(n: u8) -> Option<DisposeOp> {
165         match n {
166             0 => Some(DisposeOp::None),
167             1 => Some(DisposeOp::Background),
168             2 => Some(DisposeOp::Previous),
169             _ => None,
170         }
171     }
172 }
173 
174 impl fmt::Display for DisposeOp {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result175     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
176         let name = match *self {
177             DisposeOp::None => "DISPOSE_OP_NONE",
178             DisposeOp::Background => "DISPOSE_OP_BACKGROUND",
179             DisposeOp::Previous => "DISPOSE_OP_PREVIOUS",
180         };
181         write!(f, "{}", name)
182     }
183 }
184 
185 /// How pixels are written into the buffer.
186 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
187 #[repr(u8)]
188 pub enum BlendOp {
189     /// Pixels overwrite the value at their position.
190     Source = 0,
191     /// The new pixels are blended into the current state based on alpha.
192     Over = 1,
193 }
194 
195 impl BlendOp {
196     /// u8 -> Self. Using enum_primitive or transmute is probably the right thing but this will do for now.
from_u8(n: u8) -> Option<BlendOp>197     pub fn from_u8(n: u8) -> Option<BlendOp> {
198         match n {
199             0 => Some(BlendOp::Source),
200             1 => Some(BlendOp::Over),
201             _ => None,
202         }
203     }
204 }
205 
206 impl fmt::Display for BlendOp {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result207     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
208         let name = match *self {
209             BlendOp::Source => "BLEND_OP_SOURCE",
210             BlendOp::Over => "BLEND_OP_OVER",
211         };
212         write!(f, "{}", name)
213     }
214 }
215 
216 /// Frame control information
217 #[derive(Clone, Copy, Debug)]
218 pub struct FrameControl {
219     /// Sequence number of the animation chunk, starting from 0
220     pub sequence_number: u32,
221     /// Width of the following frame
222     pub width: u32,
223     /// Height of the following frame
224     pub height: u32,
225     /// X position at which to render the following frame
226     pub x_offset: u32,
227     /// Y position at which to render the following frame
228     pub y_offset: u32,
229     /// Frame delay fraction numerator
230     pub delay_num: u16,
231     /// Frame delay fraction denominator
232     pub delay_den: u16,
233     /// Type of frame area disposal to be done after rendering this frame
234     pub dispose_op: DisposeOp,
235     /// Type of frame area rendering for this frame
236     pub blend_op: BlendOp,
237 }
238 
239 impl Default for FrameControl {
default() -> FrameControl240     fn default() -> FrameControl {
241         FrameControl {
242             sequence_number: 0,
243             width: 0,
244             height: 0,
245             x_offset: 0,
246             y_offset: 0,
247             delay_num: 1,
248             delay_den: 30,
249             dispose_op: DisposeOp::None,
250             blend_op: BlendOp::Source,
251         }
252     }
253 }
254 
255 impl FrameControl {
set_seq_num(&mut self, s: u32)256     pub fn set_seq_num(&mut self, s: u32) {
257         self.sequence_number = s;
258     }
259 
inc_seq_num(&mut self, i: u32)260     pub fn inc_seq_num(&mut self, i: u32) {
261         self.sequence_number += i;
262     }
263 }
264 
265 /// Animation control information
266 #[derive(Clone, Copy, Debug)]
267 pub struct AnimationControl {
268     /// Number of frames
269     pub num_frames: u32,
270     /// Number of times to loop this APNG.  0 indicates infinite looping.
271     pub num_plays: u32,
272 }
273 
274 /// The type and strength of applied compression.
275 #[derive(Debug, Clone)]
276 pub enum Compression {
277     /// Default level
278     Default,
279     /// Fast minimal compression
280     Fast,
281     /// Higher compression level
282     ///
283     /// Best in this context isn't actually the highest possible level
284     /// the encoder can do, but is meant to emulate the `Best` setting in the `Flate2`
285     /// library.
286     Best,
287     Huffman,
288     Rle,
289 }
290 
291 /// PNG info struct
292 #[derive(Clone, Debug)]
293 pub struct Info {
294     pub width: u32,
295     pub height: u32,
296     pub bit_depth: BitDepth,
297     pub color_type: ColorType,
298     pub interlaced: bool,
299     pub trns: Option<Vec<u8>>,
300     pub pixel_dims: Option<PixelDimensions>,
301     pub palette: Option<Vec<u8>>,
302     pub frame_control: Option<FrameControl>,
303     pub animation_control: Option<AnimationControl>,
304     pub compression: Compression,
305     pub filter: filter::FilterType,
306 }
307 
308 impl Default for Info {
default() -> Info309     fn default() -> Info {
310         Info {
311             width: 0,
312             height: 0,
313             bit_depth: BitDepth::Eight,
314             color_type: ColorType::Grayscale,
315             interlaced: false,
316             palette: None,
317             trns: None,
318             pixel_dims: None,
319             frame_control: None,
320             animation_control: None,
321             // Default to `deflate::Compresion::Fast` and `filter::FilterType::Sub`
322             // to maintain backward compatible output.
323             compression: Compression::Fast,
324             filter: filter::FilterType::Sub,
325         }
326     }
327 }
328 
329 impl Info {
330     /// Size of the image
size(&self) -> (u32, u32)331     pub fn size(&self) -> (u32, u32) {
332         (self.width, self.height)
333     }
334 
335     /// Returns true if the image is an APNG image.
is_animated(&self) -> bool336     pub fn is_animated(&self) -> bool {
337         self.frame_control.is_some() && self.animation_control.is_some()
338     }
339 
340     /// Returns the frame control information of the image
animation_control(&self) -> Option<&AnimationControl>341     pub fn animation_control(&self) -> Option<&AnimationControl> {
342         self.animation_control.as_ref()
343     }
344 
345     /// Returns the frame control information of the current frame
frame_control(&self) -> Option<&FrameControl>346     pub fn frame_control(&self) -> Option<&FrameControl> {
347         self.frame_control.as_ref()
348     }
349 
350     /// Returns the bits per pixel
bits_per_pixel(&self) -> usize351     pub fn bits_per_pixel(&self) -> usize {
352         self.color_type.samples() * self.bit_depth as usize
353     }
354 
355     /// Returns the bytes per pixel
bytes_per_pixel(&self) -> usize356     pub fn bytes_per_pixel(&self) -> usize {
357         // If adjusting this for expansion or other transformation passes, remember to keep the old
358         // implementation for bpp_in_prediction, which is internal to the png specification.
359         self.color_type.samples() * ((self.bit_depth as usize + 7) >> 3)
360     }
361 
362     /// Return the number of bytes for this pixel used in prediction.
363     ///
364     /// Some filters use prediction, over the raw bytes of a scanline. Where a previous pixel is
365     /// require for such forms the specification instead references previous bytes. That is, for
366     /// a gray pixel of bit depth 2, the pixel used in prediction is actually 4 pixels prior. This
367     /// has the consequence that the number of possible values is rather small. To make this fact
368     /// more obvious in the type system and the optimizer we use an explicit enum here.
bpp_in_prediction(&self) -> BytesPerPixel369     pub(crate) fn bpp_in_prediction(&self) -> BytesPerPixel {
370         match self.bytes_per_pixel() {
371             1 => BytesPerPixel::One,
372             2 => BytesPerPixel::Two,
373             3 => BytesPerPixel::Three,
374             4 => BytesPerPixel::Four,
375             6 => BytesPerPixel::Six,   // Only rgb×16bit
376             8 => BytesPerPixel::Eight, // Only rgba×16bit
377             _ => unreachable!("Not a possible byte rounded pixel width"),
378         }
379     }
380 
381     /// Returns the number of bytes needed for one deinterlaced image
raw_bytes(&self) -> usize382     pub fn raw_bytes(&self) -> usize {
383         self.height as usize * self.raw_row_length()
384     }
385 
386     /// Returns the number of bytes needed for one deinterlaced row
raw_row_length(&self) -> usize387     pub fn raw_row_length(&self) -> usize {
388         self.raw_row_length_from_width(self.width)
389     }
390 
checked_raw_row_length(&self) -> Option<usize>391     pub(crate) fn checked_raw_row_length(&self) -> Option<usize> {
392         self.color_type
393             .checked_raw_row_length(self.bit_depth, self.width)
394     }
395 
396     /// Returns the number of bytes needed for one deinterlaced row of width `width`
raw_row_length_from_width(&self, width: u32) -> usize397     pub fn raw_row_length_from_width(&self, width: u32) -> usize {
398         self.color_type
399             .raw_row_length_from_width(self.bit_depth, width)
400     }
401 }
402 
403 impl BytesPerPixel {
into_usize(self) -> usize404     pub(crate) fn into_usize(self) -> usize {
405         self as usize
406     }
407 }
408 
409 bitflags! {
410     /// # Output transformations
411     ///
412     /// Only `IDENTITY` and `TRANSFORM_EXPAND | TRANSFORM_STRIP_ALPHA` can be used at the moment.
413     pub struct Transformations: u32 {
414         /// No transformation
415         const IDENTITY            = 0x0000; // read and write */
416         /// Strip 16-bit samples to 8 bits
417         const STRIP_16            = 0x0001; // read only */
418         /// Discard the alpha channel
419         const STRIP_ALPHA         = 0x0002; // read only */
420         /// Expand 1; 2 and 4-bit samples to bytes
421         const PACKING             = 0x0004; // read and write */
422         /// Change order of packed pixels to LSB first
423         const PACKSWAP            = 0x0008; // read and write */
424         /// Expand paletted images to RGB; expand grayscale images of
425         /// less than 8-bit depth to 8-bit depth; and expand tRNS chunks
426         /// to alpha channels.
427         const EXPAND              = 0x0010; // read only */
428         /// Invert monochrome images
429         const INVERT_MONO         = 0x0020; // read and write */
430         /// Normalize pixels to the sBIT depth
431         const SHIFT               = 0x0040; // read and write */
432         /// Flip RGB to BGR; RGBA to BGRA
433         const BGR                 = 0x0080; // read and write */
434         /// Flip RGBA to ARGB or GA to AG
435         const SWAP_ALPHA          = 0x0100; // read and write */
436         /// Byte-swap 16-bit samples
437         const SWAP_ENDIAN         = 0x0200; // read and write */
438         /// Change alpha from opacity to transparency
439         const INVERT_ALPHA        = 0x0400; // read and write */
440         const STRIP_FILLER        = 0x0800; // write only */
441         const STRIP_FILLER_BEFORE = 0x0800; // write only
442         const STRIP_FILLER_AFTER  = 0x1000; // write only */
443         const GRAY_TO_RGB         = 0x2000; // read only */
444         const EXPAND_16           = 0x4000; // read only */
445         const SCALE_16            = 0x8000; // read only */
446     }
447 }
448 
449 /// Mod to encapsulate the converters depending on the `deflate` crate.
450 ///
451 /// Since this only contains trait impls, there is no need to make this public, they are simply
452 /// available when the mod is compiled as well.
453 #[cfg(feature = "png-encoding")]
454 mod deflate_convert {
455     extern crate deflate;
456     use super::Compression;
457 
458     impl From<deflate::Compression> for Compression {
from(c: deflate::Compression) -> Self459         fn from(c: deflate::Compression) -> Self {
460             match c {
461                 deflate::Compression::Default => Compression::Default,
462                 deflate::Compression::Fast => Compression::Fast,
463                 deflate::Compression::Best => Compression::Best,
464             }
465         }
466     }
467 
468     impl From<Compression> for deflate::CompressionOptions {
from(c: Compression) -> Self469         fn from(c: Compression) -> Self {
470             match c {
471                 Compression::Default => deflate::CompressionOptions::default(),
472                 Compression::Fast => deflate::CompressionOptions::fast(),
473                 Compression::Best => deflate::CompressionOptions::high(),
474                 Compression::Huffman => deflate::CompressionOptions::huffman_only(),
475                 Compression::Rle => deflate::CompressionOptions::rle(),
476             }
477         }
478     }
479 }
480