png/
common.rs

1//! Common types shared between the encoder and decoder
2extern crate deflate;
3use filter;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6#[repr(u8)]
7pub enum ColorType {
8    Grayscale = 0,
9    RGB = 2,
10    Indexed = 3,
11    GrayscaleAlpha = 4,
12    RGBA = 6
13}
14
15impl ColorType {
16    /// Returns the number of samples used per pixel of `ColorType`
17    pub fn samples(&self) -> usize {
18        use self::ColorType::*;
19        match *self {
20            Grayscale | Indexed => 1,
21            RGB => 3,
22            GrayscaleAlpha => 2,
23            RGBA => 4
24        }
25    }
26    
27    /// u8 -> Self. Temporary solution until Rust provides a canonical one.
28    pub fn from_u8(n: u8) -> Option<ColorType> {
29        match n {
30            0 => Some(ColorType::Grayscale),
31            2 => Some(ColorType::RGB),
32            3 => Some(ColorType::Indexed),
33            4 => Some(ColorType::GrayscaleAlpha),
34            6 => Some(ColorType::RGBA),
35            _ => None
36        }
37    }
38}
39
40/// Bit depth of the png file
41#[derive(Debug, Clone, Copy, PartialEq, Eq)]
42#[repr(u8)]
43pub enum BitDepth {
44    One     = 1,
45    Two     = 2,
46    Four    = 4,
47    Eight   = 8,
48    Sixteen = 16,
49}
50
51impl BitDepth {
52    /// u8 -> Self. Temporary solution until Rust provides a canonical one.
53    pub fn from_u8(n: u8) -> Option<BitDepth> {
54        match n {
55            1 => Some(BitDepth::One),
56            2 => Some(BitDepth::Two),
57            4 => Some(BitDepth::Four),
58            8 => Some(BitDepth::Eight),
59            16 => Some(BitDepth::Sixteen),
60            _ => None
61        }
62    }
63}
64
65/// Pixel dimensions information
66#[derive(Clone, Copy, Debug)]
67pub struct PixelDimensions {
68    /// Pixels per unit, X axis
69    pub xppu: u32,
70    /// Pixels per unit, Y axis
71    pub yppu: u32,
72    /// Either *Meter* or *Unspecified*
73    pub unit: Unit,
74}
75
76#[derive(Debug, Clone, Copy, PartialEq, Eq)]
77#[repr(u8)]
78/// Physical unit of the pixel dimensions
79pub enum Unit {
80    Unspecified = 0,
81    Meter = 1,
82}
83
84impl Unit {
85    /// u8 -> Self. Temporary solution until Rust provides a canonical one.
86    pub fn from_u8(n: u8) -> Option<Unit> {
87        match n {
88            0 => Some(Unit::Unspecified),
89            1 => Some(Unit::Meter),
90            _ => None
91        }
92    }
93}
94
95/// Frame control information
96#[derive(Clone, Debug)]
97pub struct FrameControl {
98    /// Sequence number of the animation chunk, starting from 0
99    pub sequence_number: u32,
100    /// Width of the following frame
101    pub width: u32,
102    /// Height of the following frame
103    pub height: u32,
104    /// X position at which to render the following frame
105    pub x_offset: u32,
106    /// Y position at which to render the following frame
107    pub y_offset: u32,
108    /// Frame delay fraction numerator
109    pub delay_num: u16,
110    /// Frame delay fraction denominator
111    pub delay_den: u16,
112    /// Type of frame area disposal to be done after rendering this frame
113    pub dispose_op: u8,
114    /// Type of frame area rendering for this frame
115    pub blend_op: u8,
116}
117
118/// Animation control information
119#[derive(Clone, Copy, Debug)]
120pub struct AnimationControl {
121    /// Number of frames
122    pub num_frames: u32,
123    /// Number of times to loop this APNG.  0 indicates infinite looping.
124    pub num_plays: u32,
125}
126
127#[derive(Debug, Clone)]
128pub enum Compression {
129    /// Default level  
130    Default,
131    /// Fast minimal compression
132    Fast,
133    /// Higher compression level  
134    ///
135    /// Best in this context isn't actually the highest possible level
136    /// the encoder can do, but is meant to emulate the `Best` setting in the `Flate2`
137    /// library.
138    Best,
139    Huffman,
140    Rle,
141}
142
143impl From<deflate::Compression> for Compression {
144    fn from(c: deflate::Compression) -> Self {
145        match c {
146            deflate::Compression::Default => Compression::Default,
147            deflate::Compression::Fast => Compression::Fast,
148            deflate::Compression::Best => Compression::Best,
149        }
150    }
151}
152
153impl From<Compression> for deflate::CompressionOptions {
154    fn from(c: Compression) -> Self {
155        match c {
156            Compression::Default => deflate::CompressionOptions::default(),
157            Compression::Fast => deflate::CompressionOptions::fast(),
158            Compression::Best => deflate::CompressionOptions::high(),
159            Compression::Huffman => deflate::CompressionOptions::huffman_only(),
160            Compression::Rle => deflate::CompressionOptions::rle(),
161        }
162    }
163}
164
165/// PNG info struct
166#[derive(Debug)]
167pub struct Info {
168    pub width: u32,
169    pub height: u32,
170    pub bit_depth: BitDepth,
171    pub color_type: ColorType,
172    pub interlaced: bool,
173    pub trns: Option<Vec<u8>>,
174    pub pixel_dims: Option<PixelDimensions>,
175    pub palette: Option<Vec<u8>>,
176    pub frame_control: Option<FrameControl>,
177    pub animation_control: Option<AnimationControl>,
178    pub compression: Compression,
179    pub filter: filter::FilterType,
180}
181
182impl Default for Info {
183    fn default() -> Info {
184        Info {
185            width: 0,
186            height: 0,
187            bit_depth: BitDepth::Eight,
188            color_type: ColorType::Grayscale,
189            interlaced: false,
190            palette: None,
191            trns: None,
192            pixel_dims: None,
193            frame_control: None,
194            animation_control: None,
195            // Default to `deflate::Compresion::Fast` and `filter::FilterType::Sub` 
196            // to maintain backward compatible output. 
197            compression: deflate::Compression::Fast.into(),
198            filter: filter::FilterType::Sub,
199        }
200    }
201}
202
203impl Info {
204    /// Size of the image
205    pub fn size(&self) -> (u32, u32) {
206        (self.width, self.height)
207    }
208    
209    /// Returns true if the image is an APNG image.
210    pub fn is_animated(&self) -> bool {
211        self.frame_control.is_some() && self.animation_control.is_some()
212    }
213    
214    /// Returns the frame control information of the image
215    pub fn animation_control(&self) -> Option<&AnimationControl> {
216        self.animation_control.as_ref()
217    }
218    
219    /// Returns the frame control information of the current frame
220    pub fn frame_control(&self) -> Option<&FrameControl> {
221        self.frame_control.as_ref()
222    }
223    
224    /// Returns the bits per pixel
225    pub fn bits_per_pixel(&self) -> usize {
226        self.color_type.samples() * self.bit_depth as usize
227    }
228    
229    /// Returns the bytes per pixel
230    pub fn bytes_per_pixel(&self) -> usize {
231        self.color_type.samples() * ((self.bit_depth as usize + 7) >> 3)
232    }
233    
234    /// Returns the number of bytes needed for one deinterlaced image
235    pub fn raw_bytes(&self) -> usize {
236        self.height as usize * self.raw_row_length()
237    }
238    
239    /// Returns the number of bytes needed for one deinterlaced row 
240    pub fn raw_row_length(&self) -> usize {
241        let bits = self.width as usize * self.color_type.samples() * self.bit_depth as usize;
242        let extra = bits % 8;
243        bits/8
244        + match extra { 0 => 0, _ => 1 }
245        + 1 // filter method
246    }
247    
248    /// Returns the number of bytes needed for one deinterlaced row of width `width`
249    pub fn raw_row_length_from_width(&self, width: u32) -> usize {
250        let bits = width as usize * self.color_type.samples() * self.bit_depth as usize;
251        let extra = bits % 8;
252        bits/8
253        + match extra { 0 => 0, _ => 1 }
254        + 1 // filter method
255    }
256}
257
258
259bitflags! {
260    /// # Output transformations
261    ///
262    /// Only `IDENTITY` and `TRANSFORM_EXPAND | TRANSFORM_STRIP_ALPHA` can be used at the moment.
263    pub struct Transformations: u32 {
264        /// No transformation
265        const IDENTITY            = 0x0000; // read and write */
266        /// Strip 16-bit samples to 8 bits
267        const STRIP_16            = 0x0001; // read only */
268        /// Discard the alpha channel
269        const STRIP_ALPHA         = 0x0002; // read only */
270        /// Expand 1; 2 and 4-bit samples to bytes
271        const PACKING             = 0x0004; // read and write */
272        /// Change order of packed pixels to LSB first
273        const PACKSWAP            = 0x0008; // read and write */
274        /// Expand paletted images to RGB; expand grayscale images of
275        /// less than 8-bit depth to 8-bit depth; and expand tRNS chunks
276        /// to alpha channels.
277        const EXPAND              = 0x0010; // read only */
278        /// Invert monochrome images
279        const INVERT_MONO         = 0x0020; // read and write */
280        /// Normalize pixels to the sBIT depth
281        const SHIFT               = 0x0040; // read and write */
282        /// Flip RGB to BGR; RGBA to BGRA
283        const BGR                 = 0x0080; // read and write */
284        /// Flip RGBA to ARGB or GA to AG
285        const SWAP_ALPHA          = 0x0100; // read and write */
286        /// Byte-swap 16-bit samples
287        const SWAP_ENDIAN         = 0x0200; // read and write */
288        /// Change alpha from opacity to transparency
289        const INVERT_ALPHA        = 0x0400; // read and write */
290        const STRIP_FILLER        = 0x0800; // write only */
291        const STRIP_FILLER_BEFORE = 0x0800; // write only
292        const STRIP_FILLER_AFTER  = 0x1000; // write only */
293        const GRAY_TO_RGB         = 0x2000; // read only */
294        const EXPAND_16           = 0x4000; // read only */
295        const SCALE_16            = 0x8000; // read only */
296    }
297}
298