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