aboutsummaryrefslogtreecommitdiff
path: root/vendor/png/src/common.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/png/src/common.rs')
-rw-r--r--vendor/png/src/common.rs808
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"),
- }
- }
-}