1extern 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 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 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#[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 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#[derive(Clone, Copy, Debug)]
67pub struct PixelDimensions {
68 pub xppu: u32,
70 pub yppu: u32,
72 pub unit: Unit,
74}
75
76#[derive(Debug, Clone, Copy, PartialEq, Eq)]
77#[repr(u8)]
78pub enum Unit {
80 Unspecified = 0,
81 Meter = 1,
82}
83
84impl Unit {
85 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#[derive(Clone, Debug)]
97pub struct FrameControl {
98 pub sequence_number: u32,
100 pub width: u32,
102 pub height: u32,
104 pub x_offset: u32,
106 pub y_offset: u32,
108 pub delay_num: u16,
110 pub delay_den: u16,
112 pub dispose_op: u8,
114 pub blend_op: u8,
116}
117
118#[derive(Clone, Copy, Debug)]
120pub struct AnimationControl {
121 pub num_frames: u32,
123 pub num_plays: u32,
125}
126
127#[derive(Debug, Clone)]
128pub enum Compression {
129 Default,
131 Fast,
133 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#[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 compression: deflate::Compression::Fast.into(),
198 filter: filter::FilterType::Sub,
199 }
200 }
201}
202
203impl Info {
204 pub fn size(&self) -> (u32, u32) {
206 (self.width, self.height)
207 }
208
209 pub fn is_animated(&self) -> bool {
211 self.frame_control.is_some() && self.animation_control.is_some()
212 }
213
214 pub fn animation_control(&self) -> Option<&AnimationControl> {
216 self.animation_control.as_ref()
217 }
218
219 pub fn frame_control(&self) -> Option<&FrameControl> {
221 self.frame_control.as_ref()
222 }
223
224 pub fn bits_per_pixel(&self) -> usize {
226 self.color_type.samples() * self.bit_depth as usize
227 }
228
229 pub fn bytes_per_pixel(&self) -> usize {
231 self.color_type.samples() * ((self.bit_depth as usize + 7) >> 3)
232 }
233
234 pub fn raw_bytes(&self) -> usize {
236 self.height as usize * self.raw_row_length()
237 }
238
239 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 }
247
248 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 }
256}
257
258
259bitflags! {
260 pub struct Transformations: u32 {
264 const IDENTITY = 0x0000; const STRIP_16 = 0x0001; const STRIP_ALPHA = 0x0002; const PACKING = 0x0004; const PACKSWAP = 0x0008; const EXPAND = 0x0010; const INVERT_MONO = 0x0020; const SHIFT = 0x0040; const BGR = 0x0080; const SWAP_ALPHA = 0x0100; const SWAP_ENDIAN = 0x0200; const INVERT_ALPHA = 0x0400; const STRIP_FILLER = 0x0800; const STRIP_FILLER_BEFORE = 0x0800; const STRIP_FILLER_AFTER = 0x1000; const GRAY_TO_RGB = 0x2000; const EXPAND_16 = 0x4000; const SCALE_16 = 0x8000; }
297}
298