summaryrefslogtreecommitdiffstats
path: root/third_party/rust/png/src/common.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/png/src/common.rs')
-rw-r--r--third_party/rust/png/src/common.rs404
1 files changed, 404 insertions, 0 deletions
diff --git a/third_party/rust/png/src/common.rs b/third_party/rust/png/src/common.rs
new file mode 100644
index 0000000000..014efb751e
--- /dev/null
+++ b/third_party/rust/png/src/common.rs
@@ -0,0 +1,404 @@
+//! Common types shared between the encoder and decoder
+use crate::filter;
+
+use std::fmt;
+
+/// Describes the layout of samples in a pixel
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[repr(u8)]
+pub enum ColorType {
+ Grayscale = 0,
+ RGB = 2,
+ Indexed = 3,
+ GrayscaleAlpha = 4,
+ RGBA = 6
+}
+
+impl ColorType {
+ /// Returns the number of samples used per pixel of `ColorType`
+ pub fn samples(&self) -> usize {
+ use self::ColorType::*;
+ match *self {
+ Grayscale | Indexed => 1,
+ RGB => 3,
+ GrayscaleAlpha => 2,
+ RGBA => 4
+ }
+ }
+
+ /// u8 -> Self. Temporary solution until Rust provides a canonical one.
+ pub fn from_u8(n: u8) -> Option<ColorType> {
+ match n {
+ 0 => Some(ColorType::Grayscale),
+ 2 => Some(ColorType::RGB),
+ 3 => Some(ColorType::Indexed),
+ 4 => Some(ColorType::GrayscaleAlpha),
+ 6 => Some(ColorType::RGBA),
+ _ => None
+ }
+ }
+}
+
+/// Bit depth of the png file
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[repr(u8)]
+pub enum BitDepth {
+ One = 1,
+ Two = 2,
+ Four = 4,
+ Eight = 8,
+ Sixteen = 16,
+}
+
+impl BitDepth {
+ /// u8 -> Self. Temporary solution until Rust provides a canonical one.
+ pub fn from_u8(n: u8) -> Option<BitDepth> {
+ match n {
+ 1 => Some(BitDepth::One),
+ 2 => Some(BitDepth::Two),
+ 4 => Some(BitDepth::Four),
+ 8 => Some(BitDepth::Eight),
+ 16 => Some(BitDepth::Sixteen),
+ _ => None
+ }
+ }
+}
+
+/// Pixel dimensions information
+#[derive(Clone, Copy, Debug)]
+pub struct PixelDimensions {
+ /// Pixels per unit, X axis
+ pub xppu: u32,
+ /// Pixels per unit, Y axis
+ pub yppu: u32,
+ /// Either *Meter* or *Unspecified*
+ pub unit: Unit,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[repr(u8)]
+/// Physical unit of the pixel dimensions
+pub enum Unit {
+ Unspecified = 0,
+ Meter = 1,
+}
+
+impl Unit {
+ /// u8 -> Self. Temporary solution until Rust provides a canonical one.
+ pub fn from_u8(n: u8) -> Option<Unit> {
+ match n {
+ 0 => Some(Unit::Unspecified),
+ 1 => Some(Unit::Meter),
+ _ => None
+ }
+ }
+}
+
+/// How to reset buffer of an animated png (APNG) at the end of a frame.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[repr(u8)]
+pub enum DisposeOp {
+ /// Leave the buffer unchanged.
+ None = 0,
+ /// Clear buffer with the background color.
+ Background = 1,
+ /// Reset the buffer to the state before the current frame.
+ Previous = 2,
+}
+
+impl DisposeOp {
+ /// u8 -> Self. Using enum_primitive or transmute is probably the right thing but this will do for now.
+ pub fn from_u8(n: u8) -> Option<DisposeOp> {
+ match n {
+ 0 => Some(DisposeOp::None),
+ 1 => Some(DisposeOp::Background),
+ 2 => Some(DisposeOp::Previous),
+ _ => None
+ }
+ }
+}
+
+impl fmt::Display for DisposeOp {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let name = match *self {
+ DisposeOp::None => "DISPOSE_OP_NONE",
+ DisposeOp::Background => "DISPOSE_OP_BACKGROUND",
+ DisposeOp::Previous => "DISPOSE_OP_PREVIOUS",
+ };
+ write!(f, "{}", name)
+ }
+}
+
+/// How pixels are written into the buffer.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[repr(u8)]
+pub enum BlendOp {
+ /// Pixels overwrite the value at their position.
+ Source = 0,
+ /// The new pixels are blended into the current state based on alpha.
+ Over = 1,
+}
+
+impl BlendOp {
+ /// u8 -> Self. Using enum_primitive or transmute is probably the right thing but this will do for now.
+ pub fn from_u8(n: u8) -> Option<BlendOp> {
+ match n {
+ 0 => Some(BlendOp::Source),
+ 1 => Some(BlendOp::Over),
+ _ => None
+ }
+ }
+}
+
+impl fmt::Display for BlendOp {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let name = match *self {
+ BlendOp::Source => "BLEND_OP_SOURCE",
+ BlendOp::Over => "BLEND_OP_OVER",
+ };
+ write!(f, "{}", name)
+ }
+}
+
+/// Frame control information
+#[derive(Clone, Copy, Debug)]
+pub struct FrameControl {
+ /// Sequence number of the animation chunk, starting from 0
+ pub sequence_number: u32,
+ /// Width of the following frame
+ pub width: u32,
+ /// Height of the following frame
+ pub height: u32,
+ /// X position at which to render the following frame
+ pub x_offset: u32,
+ /// Y position at which to render the following frame
+ pub y_offset: u32,
+ /// Frame delay fraction numerator
+ pub delay_num: u16,
+ /// Frame delay fraction denominator
+ pub delay_den: u16,
+ /// Type of frame area disposal to be done after rendering this frame
+ pub dispose_op: DisposeOp,
+ /// Type of frame area rendering for this frame
+ pub blend_op: BlendOp,
+}
+
+impl Default for FrameControl {
+ fn default() -> FrameControl {
+ FrameControl {
+ sequence_number: 0,
+ width: 0,
+ height: 0,
+ x_offset: 0,
+ y_offset: 0,
+ delay_num: 1,
+ delay_den: 30,
+ dispose_op: DisposeOp::None,
+ blend_op: BlendOp::Source,
+ }
+ }
+}
+
+impl FrameControl {
+ pub fn set_seq_num(&mut self, s: u32) {
+ self.sequence_number = s;
+ }
+
+ pub fn inc_seq_num(&mut self, i: u32) {
+ self.sequence_number += i;
+ }
+
+}
+
+/// Animation control information
+#[derive(Clone, Copy, Debug)]
+pub struct AnimationControl {
+ /// Number of frames
+ pub num_frames: u32,
+ /// Number of times to loop this APNG. 0 indicates infinite looping.
+ pub num_plays: u32,
+}
+
+/// The type and strength of applied compression.
+#[derive(Debug, Clone)]
+pub enum Compression {
+ /// Default level
+ Default,
+ /// Fast minimal compression
+ Fast,
+ /// Higher compression level
+ ///
+ /// Best in this context isn't actually the highest possible level
+ /// the encoder can do, but is meant to emulate the `Best` setting in the `Flate2`
+ /// library.
+ Best,
+ Huffman,
+ Rle,
+}
+
+/// PNG info struct
+#[derive(Debug)]
+pub struct Info {
+ pub width: u32,
+ pub height: u32,
+ pub bit_depth: BitDepth,
+ pub color_type: ColorType,
+ pub interlaced: bool,
+ pub trns: Option<Vec<u8>>,
+ pub pixel_dims: Option<PixelDimensions>,
+ pub palette: Option<Vec<u8>>,
+ pub frame_control: Option<FrameControl>,
+ pub animation_control: Option<AnimationControl>,
+ pub compression: Compression,
+ pub filter: filter::FilterType,
+}
+
+impl Default for Info {
+ fn default() -> Info {
+ Info {
+ width: 0,
+ height: 0,
+ bit_depth: BitDepth::Eight,
+ color_type: ColorType::Grayscale,
+ interlaced: false,
+ palette: None,
+ trns: None,
+ pixel_dims: None,
+ frame_control: None,
+ animation_control: None,
+ // Default to `deflate::Compresion::Fast` and `filter::FilterType::Sub`
+ // to maintain backward compatible output.
+ compression: Compression::Fast,
+ filter: filter::FilterType::Sub,
+ }
+ }
+}
+
+impl Info {
+ /// Size of the image
+ pub fn size(&self) -> (u32, u32) {
+ (self.width, self.height)
+ }
+
+ /// Returns true if the image is an APNG image.
+ pub fn is_animated(&self) -> bool {
+ self.frame_control.is_some() && self.animation_control.is_some()
+ }
+
+ /// Returns the frame control information of the image
+ pub fn animation_control(&self) -> Option<&AnimationControl> {
+ self.animation_control.as_ref()
+ }
+
+ /// Returns the frame control information of the current frame
+ pub fn frame_control(&self) -> Option<&FrameControl> {
+ self.frame_control.as_ref()
+ }
+
+ /// Returns the bits per pixel
+ pub fn bits_per_pixel(&self) -> usize {
+ self.color_type.samples() * self.bit_depth as usize
+ }
+
+ /// Returns the bytes per pixel
+ pub fn bytes_per_pixel(&self) -> usize {
+ self.color_type.samples() * ((self.bit_depth as usize + 7) >> 3)
+ }
+
+ /// Returns the number of bytes needed for one deinterlaced image
+ pub fn raw_bytes(&self) -> usize {
+ self.height as usize * self.raw_row_length()
+ }
+
+ /// Returns the number of bytes needed for one deinterlaced row
+ pub fn raw_row_length(&self) -> usize {
+ let bits = self.width as usize * self.color_type.samples() * self.bit_depth as usize;
+ let extra = bits % 8;
+ bits/8
+ + match extra { 0 => 0, _ => 1 }
+ + 1 // filter method
+ }
+
+ /// Returns the number of bytes needed for one deinterlaced row of width `width`
+ pub fn raw_row_length_from_width(&self, width: u32) -> usize {
+ let bits = width as usize * self.color_type.samples() * self.bit_depth as usize;
+ let extra = bits % 8;
+ bits/8
+ + match extra { 0 => 0, _ => 1 }
+ + 1 // filter method
+ }
+}
+
+
+bitflags! {
+ /// # Output transformations
+ ///
+ /// Only `IDENTITY` and `TRANSFORM_EXPAND | TRANSFORM_STRIP_ALPHA` can be used at the moment.
+ pub struct Transformations: u32 {
+ /// No transformation
+ const IDENTITY = 0x0000; // read and write */
+ /// Strip 16-bit samples to 8 bits
+ const STRIP_16 = 0x0001; // read only */
+ /// Discard the alpha channel
+ const STRIP_ALPHA = 0x0002; // read only */
+ /// Expand 1; 2 and 4-bit samples to bytes
+ const PACKING = 0x0004; // read and write */
+ /// Change order of packed pixels to LSB first
+ const PACKSWAP = 0x0008; // read and write */
+ /// Expand paletted images to RGB; expand grayscale images of
+ /// less than 8-bit depth to 8-bit depth; and expand tRNS chunks
+ /// to alpha channels.
+ const EXPAND = 0x0010; // read only */
+ /// Invert monochrome images
+ const INVERT_MONO = 0x0020; // read and write */
+ /// Normalize pixels to the sBIT depth
+ const SHIFT = 0x0040; // read and write */
+ /// Flip RGB to BGR; RGBA to BGRA
+ const BGR = 0x0080; // read and write */
+ /// Flip RGBA to ARGB or GA to AG
+ const SWAP_ALPHA = 0x0100; // read and write */
+ /// Byte-swap 16-bit samples
+ const SWAP_ENDIAN = 0x0200; // read and write */
+ /// Change alpha from opacity to transparency
+ const INVERT_ALPHA = 0x0400; // read and write */
+ const STRIP_FILLER = 0x0800; // write only */
+ const STRIP_FILLER_BEFORE = 0x0800; // write only
+ const STRIP_FILLER_AFTER = 0x1000; // write only */
+ const GRAY_TO_RGB = 0x2000; // read only */
+ const EXPAND_16 = 0x4000; // read only */
+ const SCALE_16 = 0x8000; // read only */
+ }
+}
+
+/// Mod to encapsulate the converters depending on the `deflate` crate.
+///
+/// Since this only contains trait impls, there is no need to make this public, they are simply
+/// available when the mod is compiled as well.
+#[cfg(feature = "png-encoding")]
+mod deflate_convert {
+ extern crate deflate;
+ use super::Compression;
+
+ impl From<deflate::Compression> for Compression {
+ fn from(c: deflate::Compression) -> Self {
+ match c {
+ deflate::Compression::Default => Compression::Default,
+ deflate::Compression::Fast => Compression::Fast,
+ deflate::Compression::Best => Compression::Best,
+ }
+ }
+ }
+
+ impl From<Compression> for deflate::CompressionOptions {
+ fn from(c: Compression) -> Self {
+ match c {
+ Compression::Default => deflate::CompressionOptions::default(),
+ Compression::Fast => deflate::CompressionOptions::fast(),
+ Compression::Best => deflate::CompressionOptions::high(),
+ Compression::Huffman => deflate::CompressionOptions::huffman_only(),
+ Compression::Rle => deflate::CompressionOptions::rle(),
+ }
+ }
+ }
+}
+