1 //! Common types shared between the encoder and decoder
2 use crate::filter;
3 
4 use std::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         use self::ColorType::*;
21         match *self {
22             Grayscale | Indexed => 1,
23             RGB => 3,
24             GrayscaleAlpha => 2,
25             RGBA => 4,
26         }
27     }
28 
29     /// u8 -> Self. Temporary solution until Rust provides a canonical one.
from_u8(n: u8) -> Option<ColorType>30     pub fn from_u8(n: u8) -> Option<ColorType> {
31         match n {
32             0 => Some(ColorType::Grayscale),
33             2 => Some(ColorType::RGB),
34             3 => Some(ColorType::Indexed),
35             4 => Some(ColorType::GrayscaleAlpha),
36             6 => Some(ColorType::RGBA),
37             _ => None,
38         }
39     }
40 }
41 
42 /// Bit depth of the png file
43 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
44 #[repr(u8)]
45 pub enum BitDepth {
46     One = 1,
47     Two = 2,
48     Four = 4,
49     Eight = 8,
50     Sixteen = 16,
51 }
52 
53 impl BitDepth {
54     /// u8 -> Self. Temporary solution until Rust provides a canonical one.
from_u8(n: u8) -> Option<BitDepth>55     pub fn from_u8(n: u8) -> Option<BitDepth> {
56         match n {
57             1 => Some(BitDepth::One),
58             2 => Some(BitDepth::Two),
59             4 => Some(BitDepth::Four),
60             8 => Some(BitDepth::Eight),
61             16 => Some(BitDepth::Sixteen),
62             _ => None,
63         }
64     }
65 }
66 
67 /// Pixel dimensions information
68 #[derive(Clone, Copy, Debug)]
69 pub struct PixelDimensions {
70     /// Pixels per unit, X axis
71     pub xppu: u32,
72     /// Pixels per unit, Y axis
73     pub yppu: u32,
74     /// Either *Meter* or *Unspecified*
75     pub unit: Unit,
76 }
77 
78 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
79 #[repr(u8)]
80 /// Physical unit of the pixel dimensions
81 pub enum Unit {
82     Unspecified = 0,
83     Meter = 1,
84 }
85 
86 impl Unit {
87     /// u8 -> Self. Temporary solution until Rust provides a canonical one.
from_u8(n: u8) -> Option<Unit>88     pub fn from_u8(n: u8) -> Option<Unit> {
89         match n {
90             0 => Some(Unit::Unspecified),
91             1 => Some(Unit::Meter),
92             _ => None,
93         }
94     }
95 }
96 
97 /// How to reset buffer of an animated png (APNG) at the end of a frame.
98 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
99 #[repr(u8)]
100 pub enum DisposeOp {
101     /// Leave the buffer unchanged.
102     None = 0,
103     /// Clear buffer with the background color.
104     Background = 1,
105     /// Reset the buffer to the state before the current frame.
106     Previous = 2,
107 }
108 
109 impl DisposeOp {
110     /// u8 -> Self. Using enum_primitive or transmute is probably the right thing but this will do for now.
from_u8(n: u8) -> Option<DisposeOp>111     pub fn from_u8(n: u8) -> Option<DisposeOp> {
112         match n {
113             0 => Some(DisposeOp::None),
114             1 => Some(DisposeOp::Background),
115             2 => Some(DisposeOp::Previous),
116             _ => None,
117         }
118     }
119 }
120 
121 impl fmt::Display for DisposeOp {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result122     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
123         let name = match *self {
124             DisposeOp::None => "DISPOSE_OP_NONE",
125             DisposeOp::Background => "DISPOSE_OP_BACKGROUND",
126             DisposeOp::Previous => "DISPOSE_OP_PREVIOUS",
127         };
128         write!(f, "{}", name)
129     }
130 }
131 
132 /// How pixels are written into the buffer.
133 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
134 #[repr(u8)]
135 pub enum BlendOp {
136     /// Pixels overwrite the value at their position.
137     Source = 0,
138     /// The new pixels are blended into the current state based on alpha.
139     Over = 1,
140 }
141 
142 impl BlendOp {
143     /// u8 -> Self. Using enum_primitive or transmute is probably the right thing but this will do for now.
from_u8(n: u8) -> Option<BlendOp>144     pub fn from_u8(n: u8) -> Option<BlendOp> {
145         match n {
146             0 => Some(BlendOp::Source),
147             1 => Some(BlendOp::Over),
148             _ => None,
149         }
150     }
151 }
152 
153 impl fmt::Display for BlendOp {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result154     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
155         let name = match *self {
156             BlendOp::Source => "BLEND_OP_SOURCE",
157             BlendOp::Over => "BLEND_OP_OVER",
158         };
159         write!(f, "{}", name)
160     }
161 }
162 
163 /// Frame control information
164 #[derive(Clone, Copy, Debug)]
165 pub struct FrameControl {
166     /// Sequence number of the animation chunk, starting from 0
167     pub sequence_number: u32,
168     /// Width of the following frame
169     pub width: u32,
170     /// Height of the following frame
171     pub height: u32,
172     /// X position at which to render the following frame
173     pub x_offset: u32,
174     /// Y position at which to render the following frame
175     pub y_offset: u32,
176     /// Frame delay fraction numerator
177     pub delay_num: u16,
178     /// Frame delay fraction denominator
179     pub delay_den: u16,
180     /// Type of frame area disposal to be done after rendering this frame
181     pub dispose_op: DisposeOp,
182     /// Type of frame area rendering for this frame
183     pub blend_op: BlendOp,
184 }
185 
186 impl Default for FrameControl {
default() -> FrameControl187     fn default() -> FrameControl {
188         FrameControl {
189             sequence_number: 0,
190             width: 0,
191             height: 0,
192             x_offset: 0,
193             y_offset: 0,
194             delay_num: 1,
195             delay_den: 30,
196             dispose_op: DisposeOp::None,
197             blend_op: BlendOp::Source,
198         }
199     }
200 }
201 
202 impl FrameControl {
set_seq_num(&mut self, s: u32)203     pub fn set_seq_num(&mut self, s: u32) {
204         self.sequence_number = s;
205     }
206 
inc_seq_num(&mut self, i: u32)207     pub fn inc_seq_num(&mut self, i: u32) {
208         self.sequence_number += i;
209     }
210 }
211 
212 /// Animation control information
213 #[derive(Clone, Copy, Debug)]
214 pub struct AnimationControl {
215     /// Number of frames
216     pub num_frames: u32,
217     /// Number of times to loop this APNG.  0 indicates infinite looping.
218     pub num_plays: u32,
219 }
220 
221 /// The type and strength of applied compression.
222 #[derive(Debug, Clone)]
223 pub enum Compression {
224     /// Default level
225     Default,
226     /// Fast minimal compression
227     Fast,
228     /// Higher compression level
229     ///
230     /// Best in this context isn't actually the highest possible level
231     /// the encoder can do, but is meant to emulate the `Best` setting in the `Flate2`
232     /// library.
233     Best,
234     Huffman,
235     Rle,
236 }
237 
238 /// PNG info struct
239 #[derive(Debug)]
240 pub struct Info {
241     pub width: u32,
242     pub height: u32,
243     pub bit_depth: BitDepth,
244     pub color_type: ColorType,
245     pub interlaced: bool,
246     pub trns: Option<Vec<u8>>,
247     pub pixel_dims: Option<PixelDimensions>,
248     pub palette: Option<Vec<u8>>,
249     pub frame_control: Option<FrameControl>,
250     pub animation_control: Option<AnimationControl>,
251     pub compression: Compression,
252     pub filter: filter::FilterType,
253 }
254 
255 impl Default for Info {
default() -> Info256     fn default() -> Info {
257         Info {
258             width: 0,
259             height: 0,
260             bit_depth: BitDepth::Eight,
261             color_type: ColorType::Grayscale,
262             interlaced: false,
263             palette: None,
264             trns: None,
265             pixel_dims: None,
266             frame_control: None,
267             animation_control: None,
268             // Default to `deflate::Compresion::Fast` and `filter::FilterType::Sub`
269             // to maintain backward compatible output.
270             compression: Compression::Fast,
271             filter: filter::FilterType::Sub,
272         }
273     }
274 }
275 
276 impl Info {
277     /// Size of the image
size(&self) -> (u32, u32)278     pub fn size(&self) -> (u32, u32) {
279         (self.width, self.height)
280     }
281 
282     /// Returns true if the image is an APNG image.
is_animated(&self) -> bool283     pub fn is_animated(&self) -> bool {
284         self.frame_control.is_some() && self.animation_control.is_some()
285     }
286 
287     /// Returns the frame control information of the image
animation_control(&self) -> Option<&AnimationControl>288     pub fn animation_control(&self) -> Option<&AnimationControl> {
289         self.animation_control.as_ref()
290     }
291 
292     /// Returns the frame control information of the current frame
frame_control(&self) -> Option<&FrameControl>293     pub fn frame_control(&self) -> Option<&FrameControl> {
294         self.frame_control.as_ref()
295     }
296 
297     /// Returns the bits per pixel
bits_per_pixel(&self) -> usize298     pub fn bits_per_pixel(&self) -> usize {
299         self.color_type.samples() * self.bit_depth as usize
300     }
301 
302     /// Returns the bytes per pixel
bytes_per_pixel(&self) -> usize303     pub fn bytes_per_pixel(&self) -> usize {
304         self.color_type.samples() * ((self.bit_depth as usize + 7) >> 3)
305     }
306 
307     /// Returns the number of bytes needed for one deinterlaced image
raw_bytes(&self) -> usize308     pub fn raw_bytes(&self) -> usize {
309         self.height as usize * self.raw_row_length()
310     }
311 
312     /// Returns the number of bytes needed for one deinterlaced row
raw_row_length(&self) -> usize313     pub fn raw_row_length(&self) -> usize {
314         let bits = self.width as usize * self.color_type.samples() * self.bit_depth as usize;
315         let extra = bits % 8;
316         bits / 8
317             + match extra {
318                 0 => 0,
319                 _ => 1,
320             }
321             + 1 // filter method
322     }
323 
324     /// Returns the number of bytes needed for one deinterlaced row of width `width`
raw_row_length_from_width(&self, width: u32) -> usize325     pub fn raw_row_length_from_width(&self, width: u32) -> usize {
326         let bits = width as usize * self.color_type.samples() * self.bit_depth as usize;
327         let extra = bits % 8;
328         bits / 8
329             + match extra {
330                 0 => 0,
331                 _ => 1,
332             }
333             + 1 // filter method
334     }
335 }
336 
337 bitflags! {
338     /// # Output transformations
339     ///
340     /// Only `IDENTITY` and `TRANSFORM_EXPAND | TRANSFORM_STRIP_ALPHA` can be used at the moment.
341     pub struct Transformations: u32 {
342         /// No transformation
343         const IDENTITY            = 0x0000; // read and write */
344         /// Strip 16-bit samples to 8 bits
345         const STRIP_16            = 0x0001; // read only */
346         /// Discard the alpha channel
347         const STRIP_ALPHA         = 0x0002; // read only */
348         /// Expand 1; 2 and 4-bit samples to bytes
349         const PACKING             = 0x0004; // read and write */
350         /// Change order of packed pixels to LSB first
351         const PACKSWAP            = 0x0008; // read and write */
352         /// Expand paletted images to RGB; expand grayscale images of
353         /// less than 8-bit depth to 8-bit depth; and expand tRNS chunks
354         /// to alpha channels.
355         const EXPAND              = 0x0010; // read only */
356         /// Invert monochrome images
357         const INVERT_MONO         = 0x0020; // read and write */
358         /// Normalize pixels to the sBIT depth
359         const SHIFT               = 0x0040; // read and write */
360         /// Flip RGB to BGR; RGBA to BGRA
361         const BGR                 = 0x0080; // read and write */
362         /// Flip RGBA to ARGB or GA to AG
363         const SWAP_ALPHA          = 0x0100; // read and write */
364         /// Byte-swap 16-bit samples
365         const SWAP_ENDIAN         = 0x0200; // read and write */
366         /// Change alpha from opacity to transparency
367         const INVERT_ALPHA        = 0x0400; // read and write */
368         const STRIP_FILLER        = 0x0800; // write only */
369         const STRIP_FILLER_BEFORE = 0x0800; // write only
370         const STRIP_FILLER_AFTER  = 0x1000; // write only */
371         const GRAY_TO_RGB         = 0x2000; // read only */
372         const EXPAND_16           = 0x4000; // read only */
373         const SCALE_16            = 0x8000; // read only */
374     }
375 }
376 
377 /// Mod to encapsulate the converters depending on the `deflate` crate.
378 ///
379 /// Since this only contains trait impls, there is no need to make this public, they are simply
380 /// available when the mod is compiled as well.
381 #[cfg(feature = "png-encoding")]
382 mod deflate_convert {
383     extern crate deflate;
384     use super::Compression;
385 
386     impl From<deflate::Compression> for Compression {
from(c: deflate::Compression) -> Self387         fn from(c: deflate::Compression) -> Self {
388             match c {
389                 deflate::Compression::Default => Compression::Default,
390                 deflate::Compression::Fast => Compression::Fast,
391                 deflate::Compression::Best => Compression::Best,
392             }
393         }
394     }
395 
396     impl From<Compression> for deflate::CompressionOptions {
from(c: Compression) -> Self397         fn from(c: Compression) -> Self {
398             match c {
399                 Compression::Default => deflate::CompressionOptions::default(),
400                 Compression::Fast => deflate::CompressionOptions::fast(),
401                 Compression::Best => deflate::CompressionOptions::high(),
402                 Compression::Huffman => deflate::CompressionOptions::huffman_only(),
403                 Compression::Rle => deflate::CompressionOptions::rle(),
404             }
405         }
406     }
407 }
408