diff options
Diffstat (limited to 'vendor/png/src/common.rs')
-rw-r--r-- | vendor/png/src/common.rs | 808 |
1 files changed, 0 insertions, 808 deletions
diff --git a/vendor/png/src/common.rs b/vendor/png/src/common.rs deleted file mode 100644 index 6e5dbff..0000000 --- a/vendor/png/src/common.rs +++ /dev/null @@ -1,808 +0,0 @@ -//! Common types shared between the encoder and decoder -use crate::text_metadata::{EncodableTextChunk, ITXtChunk, TEXtChunk, ZTXtChunk}; -use crate::{chunk, encoder}; -use io::Write; -use std::{borrow::Cow, convert::TryFrom, fmt, io}; - -/// Describes how a pixel is encoded. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -#[repr(u8)] -pub enum ColorType { - /// 1 grayscale sample. - Grayscale = 0, - /// 1 red sample, 1 green sample, 1 blue sample. - Rgb = 2, - /// 1 sample for the palette index. - Indexed = 3, - /// 1 grayscale sample, then 1 alpha sample. - GrayscaleAlpha = 4, - /// 1 red sample, 1 green sample, 1 blue sample, and finally, 1 alpha sample. - Rgba = 6, -} - -impl ColorType { - /// Returns the number of samples used per pixel encoded in this way. - pub fn samples(self) -> usize { - self.samples_u8().into() - } - - pub(crate) fn samples_u8(self) -> u8 { - 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, - } - } - - pub(crate) fn checked_raw_row_length(self, depth: BitDepth, width: u32) -> Option<usize> { - // No overflow can occur in 64 bits, we multiply 32-bit with 5 more bits. - let bits = u64::from(width) * u64::from(self.samples_u8()) * u64::from(depth.into_u8()); - TryFrom::try_from(1 + (bits + 7) / 8).ok() - } - - pub(crate) fn raw_row_length_from_width(self, depth: BitDepth, width: u32) -> usize { - let samples = width as usize * self.samples(); - 1 + match depth { - BitDepth::Sixteen => samples * 2, - BitDepth::Eight => samples, - subbyte => { - let samples_per_byte = 8 / subbyte as usize; - let whole = samples / samples_per_byte; - let fract = usize::from(samples % samples_per_byte > 0); - whole + fract - } - } - } - - pub(crate) fn is_combination_invalid(self, bit_depth: BitDepth) -> bool { - // Section 11.2.2 of the PNG standard disallows several combinations - // of bit depth and color type - ((bit_depth == BitDepth::One || bit_depth == BitDepth::Two || bit_depth == BitDepth::Four) - && (self == ColorType::Rgb - || self == ColorType::GrayscaleAlpha - || self == ColorType::Rgba)) - || (bit_depth == BitDepth::Sixteen && self == ColorType::Indexed) - } -} - -/// Bit depth of the PNG file. -/// Specifies the number of bits per sample. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -#[repr(u8)] -pub enum BitDepth { - One = 1, - Two = 2, - Four = 4, - Eight = 8, - Sixteen = 16, -} - -/// Internal count of bytes per pixel. -/// This is used for filtering which never uses sub-byte units. This essentially reduces the number -/// of possible byte chunk lengths to a very small set of values appropriate to be defined as an -/// enum. -#[derive(Debug, Clone, Copy)] -#[repr(u8)] -pub(crate) enum BytesPerPixel { - One = 1, - Two = 2, - Three = 3, - Four = 4, - Six = 6, - Eight = 8, -} - -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, - } - } - - pub(crate) fn into_u8(self) -> u8 { - self as u8 - } -} - -/// 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; - } - - pub fn encode<W: Write>(self, w: &mut W) -> encoder::Result<()> { - let mut data = [0u8; 26]; - data[..4].copy_from_slice(&self.sequence_number.to_be_bytes()); - data[4..8].copy_from_slice(&self.width.to_be_bytes()); - data[8..12].copy_from_slice(&self.height.to_be_bytes()); - data[12..16].copy_from_slice(&self.x_offset.to_be_bytes()); - data[16..20].copy_from_slice(&self.y_offset.to_be_bytes()); - data[20..22].copy_from_slice(&self.delay_num.to_be_bytes()); - data[22..24].copy_from_slice(&self.delay_den.to_be_bytes()); - data[24] = self.dispose_op as u8; - data[25] = self.blend_op as u8; - - encoder::write_chunk(w, chunk::fcTL, &data) - } -} - -/// 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, -} - -impl AnimationControl { - pub fn encode<W: Write>(self, w: &mut W) -> encoder::Result<()> { - let mut data = [0; 8]; - data[..4].copy_from_slice(&self.num_frames.to_be_bytes()); - data[4..].copy_from_slice(&self.num_plays.to_be_bytes()); - encoder::write_chunk(w, chunk::acTL, &data) - } -} - -/// The type and strength of applied compression. -#[derive(Debug, Clone, Copy)] -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, - #[deprecated( - since = "0.17.6", - note = "use one of the other compression levels instead, such as 'fast'" - )] - Huffman, - #[deprecated( - since = "0.17.6", - note = "use one of the other compression levels instead, such as 'fast'" - )] - Rle, -} - -impl Default for Compression { - fn default() -> Self { - Self::Default - } -} - -/// An unsigned integer scaled version of a floating point value, -/// equivalent to an integer quotient with fixed denominator (100_000)). -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub struct ScaledFloat(u32); - -impl ScaledFloat { - const SCALING: f32 = 100_000.0; - - /// Gets whether the value is within the clamped range of this type. - pub fn in_range(value: f32) -> bool { - value >= 0.0 && (value * Self::SCALING).floor() <= std::u32::MAX as f32 - } - - /// Gets whether the value can be exactly converted in round-trip. - #[allow(clippy::float_cmp)] // Stupid tool, the exact float compare is _the entire point_. - pub fn exact(value: f32) -> bool { - let there = Self::forward(value); - let back = Self::reverse(there); - value == back - } - - fn forward(value: f32) -> u32 { - (value.max(0.0) * Self::SCALING).floor() as u32 - } - - fn reverse(encoded: u32) -> f32 { - encoded as f32 / Self::SCALING - } - - /// Slightly inaccurate scaling and quantization. - /// Clamps the value into the representable range if it is negative or too large. - pub fn new(value: f32) -> Self { - Self(Self::forward(value)) - } - - /// Fully accurate construction from a value scaled as per specification. - pub fn from_scaled(val: u32) -> Self { - Self(val) - } - - /// Get the accurate encoded value. - pub fn into_scaled(self) -> u32 { - self.0 - } - - /// Get the unscaled value as a floating point. - pub fn into_value(self) -> f32 { - Self::reverse(self.0) - } - - pub(crate) fn encode_gama<W: Write>(self, w: &mut W) -> encoder::Result<()> { - encoder::write_chunk(w, chunk::gAMA, &self.into_scaled().to_be_bytes()) - } -} - -/// Chromaticities of the color space primaries -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub struct SourceChromaticities { - pub white: (ScaledFloat, ScaledFloat), - pub red: (ScaledFloat, ScaledFloat), - pub green: (ScaledFloat, ScaledFloat), - pub blue: (ScaledFloat, ScaledFloat), -} - -impl SourceChromaticities { - pub fn new(white: (f32, f32), red: (f32, f32), green: (f32, f32), blue: (f32, f32)) -> Self { - SourceChromaticities { - white: (ScaledFloat::new(white.0), ScaledFloat::new(white.1)), - red: (ScaledFloat::new(red.0), ScaledFloat::new(red.1)), - green: (ScaledFloat::new(green.0), ScaledFloat::new(green.1)), - blue: (ScaledFloat::new(blue.0), ScaledFloat::new(blue.1)), - } - } - - #[rustfmt::skip] - pub fn to_be_bytes(self) -> [u8; 32] { - let white_x = self.white.0.into_scaled().to_be_bytes(); - let white_y = self.white.1.into_scaled().to_be_bytes(); - let red_x = self.red.0.into_scaled().to_be_bytes(); - let red_y = self.red.1.into_scaled().to_be_bytes(); - let green_x = self.green.0.into_scaled().to_be_bytes(); - let green_y = self.green.1.into_scaled().to_be_bytes(); - let blue_x = self.blue.0.into_scaled().to_be_bytes(); - let blue_y = self.blue.1.into_scaled().to_be_bytes(); - [ - white_x[0], white_x[1], white_x[2], white_x[3], - white_y[0], white_y[1], white_y[2], white_y[3], - red_x[0], red_x[1], red_x[2], red_x[3], - red_y[0], red_y[1], red_y[2], red_y[3], - green_x[0], green_x[1], green_x[2], green_x[3], - green_y[0], green_y[1], green_y[2], green_y[3], - blue_x[0], blue_x[1], blue_x[2], blue_x[3], - blue_y[0], blue_y[1], blue_y[2], blue_y[3], - ] - } - - pub fn encode<W: Write>(self, w: &mut W) -> encoder::Result<()> { - encoder::write_chunk(w, chunk::cHRM, &self.to_be_bytes()) - } -} - -/// The rendering intent for an sRGB image. -/// -/// Presence of this data also indicates that the image conforms to the sRGB color space. -#[repr(u8)] -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum SrgbRenderingIntent { - /// For images preferring good adaptation to the output device gamut at the expense of colorimetric accuracy, such as photographs. - Perceptual = 0, - /// For images requiring colour appearance matching (relative to the output device white point), such as logos. - RelativeColorimetric = 1, - /// For images preferring preservation of saturation at the expense of hue and lightness, such as charts and graphs. - Saturation = 2, - /// For images requiring preservation of absolute colorimetry, such as previews of images destined for a different output device (proofs). - AbsoluteColorimetric = 3, -} - -impl SrgbRenderingIntent { - pub(crate) fn into_raw(self) -> u8 { - self as u8 - } - - pub(crate) fn from_raw(raw: u8) -> Option<Self> { - match raw { - 0 => Some(SrgbRenderingIntent::Perceptual), - 1 => Some(SrgbRenderingIntent::RelativeColorimetric), - 2 => Some(SrgbRenderingIntent::Saturation), - 3 => Some(SrgbRenderingIntent::AbsoluteColorimetric), - _ => None, - } - } - - pub fn encode<W: Write>(self, w: &mut W) -> encoder::Result<()> { - encoder::write_chunk(w, chunk::sRGB, &[self.into_raw()]) - } -} - -/// PNG info struct -#[derive(Clone, Debug)] -#[non_exhaustive] -pub struct Info<'a> { - pub width: u32, - pub height: u32, - pub bit_depth: BitDepth, - /// How colors are stored in the image. - pub color_type: ColorType, - pub interlaced: bool, - /// The image's `tRNS` chunk, if present; contains the alpha channel of the image's palette, 1 byte per entry. - pub trns: Option<Cow<'a, [u8]>>, - pub pixel_dims: Option<PixelDimensions>, - /// The image's `PLTE` chunk, if present; contains the RGB channels (in that order) of the image's palettes, 3 bytes per entry (1 per channel). - pub palette: Option<Cow<'a, [u8]>>, - /// The contents of the image's gAMA chunk, if present. - /// Prefer `source_gamma` to also get the derived replacement gamma from sRGB chunks. - pub gama_chunk: Option<ScaledFloat>, - /// The contents of the image's `cHRM` chunk, if present. - /// Prefer `source_chromaticities` to also get the derived replacements from sRGB chunks. - pub chrm_chunk: Option<SourceChromaticities>, - - pub frame_control: Option<FrameControl>, - pub animation_control: Option<AnimationControl>, - pub compression: Compression, - /// Gamma of the source system. - /// Set by both `gAMA` as well as to a replacement by `sRGB` chunk. - pub source_gamma: Option<ScaledFloat>, - /// Chromaticities of the source system. - /// Set by both `cHRM` as well as to a replacement by `sRGB` chunk. - pub source_chromaticities: Option<SourceChromaticities>, - /// The rendering intent of an SRGB image. - /// - /// Presence of this value also indicates that the image conforms to the SRGB color space. - pub srgb: Option<SrgbRenderingIntent>, - /// The ICC profile for the image. - pub icc_profile: Option<Cow<'a, [u8]>>, - /// tEXt field - pub uncompressed_latin1_text: Vec<TEXtChunk>, - /// zTXt field - pub compressed_latin1_text: Vec<ZTXtChunk>, - /// iTXt field - pub utf8_text: Vec<ITXtChunk>, -} - -impl Default for Info<'_> { - fn default() -> Info<'static> { - Info { - width: 0, - height: 0, - bit_depth: BitDepth::Eight, - color_type: ColorType::Grayscale, - interlaced: false, - palette: None, - trns: None, - gama_chunk: None, - chrm_chunk: None, - pixel_dims: None, - frame_control: None, - animation_control: None, - // Default to `deflate::Compression::Fast` and `filter::FilterType::Sub` - // to maintain backward compatible output. - compression: Compression::Fast, - source_gamma: None, - source_chromaticities: None, - srgb: None, - icc_profile: None, - uncompressed_latin1_text: Vec::new(), - compressed_latin1_text: Vec::new(), - utf8_text: Vec::new(), - } - } -} - -impl Info<'_> { - /// A utility constructor for a default info with width and height. - pub fn with_size(width: u32, height: u32) -> Self { - Info { - width, - height, - ..Default::default() - } - } - - /// Size of the image, width then height. - 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 number of bits per pixel. - pub fn bits_per_pixel(&self) -> usize { - self.color_type.samples() * self.bit_depth as usize - } - - /// Returns the number of bytes per pixel. - pub fn bytes_per_pixel(&self) -> usize { - // If adjusting this for expansion or other transformation passes, remember to keep the old - // implementation for bpp_in_prediction, which is internal to the png specification. - self.color_type.samples() * ((self.bit_depth as usize + 7) >> 3) - } - - /// Return the number of bytes for this pixel used in prediction. - /// - /// Some filters use prediction, over the raw bytes of a scanline. Where a previous pixel is - /// require for such forms the specification instead references previous bytes. That is, for - /// a gray pixel of bit depth 2, the pixel used in prediction is actually 4 pixels prior. This - /// has the consequence that the number of possible values is rather small. To make this fact - /// more obvious in the type system and the optimizer we use an explicit enum here. - pub(crate) fn bpp_in_prediction(&self) -> BytesPerPixel { - match self.bytes_per_pixel() { - 1 => BytesPerPixel::One, - 2 => BytesPerPixel::Two, - 3 => BytesPerPixel::Three, - 4 => BytesPerPixel::Four, - 6 => BytesPerPixel::Six, // Only rgb×16bit - 8 => BytesPerPixel::Eight, // Only rgba×16bit - _ => unreachable!("Not a possible byte rounded pixel width"), - } - } - - /// 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 { - self.raw_row_length_from_width(self.width) - } - - pub(crate) fn checked_raw_row_length(&self) -> Option<usize> { - self.color_type - .checked_raw_row_length(self.bit_depth, self.width) - } - - /// Returns the number of bytes needed for one deinterlaced row of width `width`. - pub fn raw_row_length_from_width(&self, width: u32) -> usize { - self.color_type - .raw_row_length_from_width(self.bit_depth, width) - } - - /// Encode this header to the writer. - /// - /// Note that this does _not_ include the PNG signature, it starts with the IHDR chunk and then - /// includes other chunks that were added to the header. - pub fn encode<W: Write>(&self, mut w: W) -> encoder::Result<()> { - // Encode the IHDR chunk - let mut data = [0; 13]; - data[..4].copy_from_slice(&self.width.to_be_bytes()); - data[4..8].copy_from_slice(&self.height.to_be_bytes()); - data[8] = self.bit_depth as u8; - data[9] = self.color_type as u8; - data[12] = self.interlaced as u8; - encoder::write_chunk(&mut w, chunk::IHDR, &data)?; - // Encode the pHYs chunk - if let Some(pd) = self.pixel_dims { - let mut phys_data = [0; 9]; - phys_data[0..4].copy_from_slice(&pd.xppu.to_be_bytes()); - phys_data[4..8].copy_from_slice(&pd.yppu.to_be_bytes()); - match pd.unit { - Unit::Meter => phys_data[8] = 1, - Unit::Unspecified => phys_data[8] = 0, - } - encoder::write_chunk(&mut w, chunk::pHYs, &phys_data)?; - } - - if let Some(p) = &self.palette { - encoder::write_chunk(&mut w, chunk::PLTE, p)?; - }; - - if let Some(t) = &self.trns { - encoder::write_chunk(&mut w, chunk::tRNS, t)?; - } - - // If specified, the sRGB information overrides the source gamma and chromaticities. - if let Some(srgb) = &self.srgb { - let gamma = crate::srgb::substitute_gamma(); - let chromaticities = crate::srgb::substitute_chromaticities(); - srgb.encode(&mut w)?; - gamma.encode_gama(&mut w)?; - chromaticities.encode(&mut w)?; - } else { - if let Some(gma) = self.source_gamma { - gma.encode_gama(&mut w)? - } - if let Some(chrms) = self.source_chromaticities { - chrms.encode(&mut w)?; - } - } - if let Some(actl) = self.animation_control { - actl.encode(&mut w)?; - } - - for text_chunk in &self.uncompressed_latin1_text { - text_chunk.encode(&mut w)?; - } - - for text_chunk in &self.compressed_latin1_text { - text_chunk.encode(&mut w)?; - } - - for text_chunk in &self.utf8_text { - text_chunk.encode(&mut w)?; - } - - Ok(()) - } -} - -impl BytesPerPixel { - pub(crate) fn into_usize(self) -> usize { - self as usize - } -} - -bitflags! { - /// Output transformations - /// - /// Many flags from libpng are not yet supported. A PR discussing/adding them would be nice. - /// - #[doc = " - ```c - /// 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 - /// 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 - /// Similar to STRIP_16 but in libpng considering gamma? - /// Not entirely sure the documentation says it is more - /// accurate but doesn't say precisely how. - const SCALE_16 = 0x8000; // read only - ``` - "] - pub struct Transformations: u32 { - /// No transformation - const IDENTITY = 0x00000; // read and write */ - /// Strip 16-bit samples to 8 bits - const STRIP_16 = 0x00001; // read only */ - /// 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 = 0x00010; // read only */ - /// Expand paletted images to include an alpha channel. Implies `EXPAND`. - const ALPHA = 0x10000; // read only */ - } -} - -impl Transformations { - /// Transform every input to 8bit grayscale or color. - /// - /// This sets `EXPAND` and `STRIP_16` which is similar to the default transformation used by - /// this library prior to `0.17`. - pub fn normalize_to_color8() -> Transformations { - Transformations::EXPAND | Transformations::STRIP_16 - } -} - -/// Instantiate the default transformations, the identity transform. -impl Default for Transformations { - fn default() -> Transformations { - Transformations::IDENTITY - } -} - -#[derive(Debug)] -pub struct ParameterError { - inner: ParameterErrorKind, -} - -#[derive(Debug)] -pub(crate) enum ParameterErrorKind { - /// A provided buffer must be have the exact size to hold the image data. Where the buffer can - /// be allocated by the caller, they must ensure that it has a minimum size as hinted previously. - /// Even though the size is calculated from image data, this does counts as a parameter error - /// because they must react to a value produced by this library, which can have been subjected - /// to limits. - ImageBufferSize { expected: usize, actual: usize }, - /// A bit like return `None` from an iterator. - /// We use it to differentiate between failing to seek to the next image in a sequence and the - /// absence of a next image. This is an error of the caller because they should have checked - /// the number of images by inspecting the header data returned when opening the image. This - /// library will perform the checks necessary to ensure that data was accurate or error with a - /// format error otherwise. - PolledAfterEndOfImage, -} - -impl From<ParameterErrorKind> for ParameterError { - fn from(inner: ParameterErrorKind) -> Self { - ParameterError { inner } - } -} - -impl fmt::Display for ParameterError { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - use ParameterErrorKind::*; - match self.inner { - ImageBufferSize { expected, actual } => { - write!(fmt, "wrong data size, expected {} got {}", expected, actual) - } - PolledAfterEndOfImage => write!(fmt, "End of image has been reached"), - } - } -} |