From c97572be3e10fac85361c0ee800e59517c901c1c Mon Sep 17 00:00:00 2001 From: andrews05 Date: Fri, 28 Apr 2023 11:49:54 +1200 Subject: [PATCH] ColorType Refactor (#500) * Refactor ColorType Move transparency and palette data into the ColorType * Fixup tests * Make more use of helper functions * Change BitDepth to u8 representation with TryFrom * Fix clippy lints * Don't use unstable language features * Restore documentation on transparency/palette --- src/colors.rs | 120 +++++++------- src/headers.rs | 63 ++++++-- src/interlace.rs | 30 ++-- src/lib.rs | 6 +- src/png/mod.rs | 147 ++++++++--------- src/png/scan_lines.rs | 8 +- src/reduction/alpha.rs | 65 ++++---- src/reduction/bit_depth.rs | 45 +++--- src/reduction/color.rs | 48 +++--- src/reduction/mod.rs | 48 +++--- tests/filters.rs | 284 ++++++++++++++++---------------- tests/flags.rs | 41 ++--- tests/interlaced.rs | 234 ++++++++++++++------------- tests/interlacing.rs | 59 +++---- tests/reduction.rs | 322 ++++++++++++++++++++----------------- tests/regression.rs | 143 ++++++++-------- tests/strategies.rs | 39 ++--- 17 files changed, 866 insertions(+), 836 deletions(-) diff --git a/src/colors.rs b/src/colors.rs index e339092b..32999849 100644 --- a/src/colors.rs +++ b/src/colors.rs @@ -1,14 +1,26 @@ +use rgb::{RGB16, RGBA8}; use std::fmt; -#[derive(Debug, PartialEq, Eq, Clone, Copy)] +use crate::PngError; + +#[derive(Debug, PartialEq, Eq, Clone)] /// The color type used to represent this image pub enum ColorType { /// Grayscale, with one color channel - Grayscale, + Grayscale { + /// Optional shade of gray that should be rendered as transparent + transparent_shade: Option, + }, /// RGB, with three color channels - RGB, - /// Indexed, with one byte per pixel representing one of up to 256 colors in the image - Indexed, + RGB { + /// Optional color value that should be rendered as transparent + transparent_color: Option, + }, + /// Indexed, with one byte per pixel representing a color from the palette + Indexed { + /// The palette containing the colors used, up to 256 entries + palette: Vec, + }, /// Grayscale + Alpha, with two color channels GrayscaleAlpha, /// RGBA, with four color channels @@ -22,9 +34,9 @@ impl fmt::Display for ColorType { f, "{}", match *self { - ColorType::Grayscale => "Grayscale", - ColorType::RGB => "RGB", - ColorType::Indexed => "Indexed", + ColorType::Grayscale { .. } => "Grayscale", + ColorType::RGB { .. } => "RGB", + ColorType::Indexed { .. } => "Indexed", ColorType::GrayscaleAlpha => "Grayscale + Alpha", ColorType::RGBA => "RGB + Alpha", } @@ -35,85 +47,71 @@ impl fmt::Display for ColorType { impl ColorType { /// Get the code used by the PNG specification to denote this color type #[inline] - pub fn png_header_code(self) -> u8 { + pub fn png_header_code(&self) -> u8 { match self { - ColorType::Grayscale => 0, - ColorType::RGB => 2, - ColorType::Indexed => 3, + ColorType::Grayscale { .. } => 0, + ColorType::RGB { .. } => 2, + ColorType::Indexed { .. } => 3, ColorType::GrayscaleAlpha => 4, ColorType::RGBA => 6, } } #[inline] - pub fn channels_per_pixel(self) -> u8 { + pub fn channels_per_pixel(&self) -> u8 { match self { - ColorType::Grayscale | ColorType::Indexed => 1, + ColorType::Grayscale { .. } | ColorType::Indexed { .. } => 1, ColorType::GrayscaleAlpha => 2, - ColorType::RGB => 3, + ColorType::RGB { .. } => 3, ColorType::RGBA => 4, } } + + #[inline] + pub fn is_rgb(&self) -> bool { + matches!(self, ColorType::RGB { .. } | ColorType::RGBA) + } + + #[inline] + pub fn has_alpha(&self) -> bool { + matches!(self, ColorType::GrayscaleAlpha | ColorType::RGBA) + } } +#[repr(u8)] #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] /// The number of bits to be used per channel per pixel pub enum BitDepth { /// One bit per channel per pixel - One, + One = 1, /// Two bits per channel per pixel - Two, + Two = 2, /// Four bits per channel per pixel - Four, + Four = 4, /// Eight bits per channel per pixel - Eight, + Eight = 8, /// Sixteen bits per channel per pixel - Sixteen, + Sixteen = 16, +} + +impl TryFrom for BitDepth { + type Error = PngError; + + fn try_from(value: u8) -> Result { + match value { + 1 => Ok(Self::One), + 2 => Ok(Self::Two), + 4 => Ok(Self::Four), + 8 => Ok(Self::Eight), + 16 => Ok(Self::Sixteen), + _ => Err(PngError::new("Unexpected bit depth")), + } + } } impl fmt::Display for BitDepth { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "{}", - match *self { - BitDepth::One => "1", - BitDepth::Two => "2", - BitDepth::Four => "4", - BitDepth::Eight => "8", - BitDepth::Sixteen => "16", - } - ) - } -} - -impl BitDepth { - /// Retrieve the number of bits per channel per pixel as a `u8` - #[inline] - pub fn as_u8(self) -> u8 { - match self { - BitDepth::One => 1, - BitDepth::Two => 2, - BitDepth::Four => 4, - BitDepth::Eight => 8, - BitDepth::Sixteen => 16, - } - } - /// Parse a number of bits per channel per pixel into a `BitDepth` - /// - /// # Panics - /// - /// If depth is unsupported - #[inline] - pub fn from_u8(depth: u8) -> BitDepth { - match depth { - 1 => BitDepth::One, - 2 => BitDepth::Two, - 4 => BitDepth::Four, - 8 => BitDepth::Eight, - 16 => BitDepth::Sixteen, - _ => panic!("Unsupported bit depth"), - } + write!(f, "{}", *self as u8) } } diff --git a/src/headers.rs b/src/headers.rs index 7fdeef1e..a3e2b4f9 100644 --- a/src/headers.rs +++ b/src/headers.rs @@ -4,10 +4,11 @@ use crate::error::PngError; use crate::interlace::Interlacing; use crate::PngResult; use indexmap::IndexSet; +use rgb::{RGB16, RGBA8}; use std::io; use std::io::{Cursor, Read}; -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone)] /// Headers from the IHDR chunk of the image pub struct IhdrData { /// The width of the image in pixels @@ -30,8 +31,8 @@ impl IhdrData { /// Bits per pixel #[must_use] #[inline] - pub fn bpp(&self) -> u8 { - self.bit_depth.as_u8() * self.color_type.channels_per_pixel() + pub fn bpp(&self) -> usize { + self.bit_depth as usize * self.color_type.channels_per_pixel() as usize } /// Byte length of IDAT that is correct for this IHDR @@ -41,8 +42,8 @@ impl IhdrData { let h = self.height as usize; let bpp = self.bpp(); - fn bitmap_size(bpp: u8, w: usize, h: usize) -> usize { - (((w / 8) * bpp as usize) + ((w & 7) * bpp as usize + 7) / 8) * h + fn bitmap_size(bpp: usize, w: usize, h: usize) -> usize { + ((w * bpp + 7) / 8) * h } if self.interlaced == Interlacing::None { @@ -143,27 +144,36 @@ pub fn parse_next_header<'a>( Ok(Some(RawHeader { name, data })) } -pub fn parse_ihdr_header(byte_data: &[u8]) -> PngResult { +pub fn parse_ihdr_header( + byte_data: &[u8], + palette_data: Option>, + trns_data: Option>, +) -> PngResult { // This eliminates bounds checks for the rest of the function let interlaced = byte_data.get(12).copied().ok_or(PngError::TruncatedData)?; let mut rdr = Cursor::new(&byte_data[0..8]); Ok(IhdrData { color_type: match byte_data[9] { - 0 => ColorType::Grayscale, - 2 => ColorType::RGB, - 3 => ColorType::Indexed, + 0 => ColorType::Grayscale { + transparent_shade: trns_data + .filter(|t| t.len() >= 2) + .map(|t| u16::from_be_bytes([t[0], t[1]])), + }, + 2 => ColorType::RGB { + transparent_color: trns_data.filter(|t| t.len() >= 6).map(|t| RGB16 { + r: u16::from_be_bytes([t[0], t[1]]), + g: u16::from_be_bytes([t[2], t[3]]), + b: u16::from_be_bytes([t[4], t[5]]), + }), + }, + 3 => ColorType::Indexed { + palette: palette_to_rgba(palette_data, trns_data).unwrap_or_default(), + }, 4 => ColorType::GrayscaleAlpha, 6 => ColorType::RGBA, _ => return Err(PngError::new("Unexpected color type in header")), }, - bit_depth: match byte_data[8] { - 1 => BitDepth::One, - 2 => BitDepth::Two, - 4 => BitDepth::Four, - 8 => BitDepth::Eight, - 16 => BitDepth::Sixteen, - _ => return Err(PngError::new("Unexpected bit depth in header")), - }, + bit_depth: byte_data[8].try_into()?, width: read_be_u32(&mut rdr).map_err(|_| PngError::TruncatedData)?, height: read_be_u32(&mut rdr).map_err(|_| PngError::TruncatedData)?, compression: byte_data[10], @@ -172,6 +182,25 @@ pub fn parse_ihdr_header(byte_data: &[u8]) -> PngResult { }) } +/// Construct an RGBA palette from the raw palette and transparency data +fn palette_to_rgba( + palette_data: Option>, + trns_data: Option>, +) -> Result, PngError> { + let palette_data = palette_data.ok_or_else(|| PngError::new("no palette in indexed image"))?; + let mut palette: Vec<_> = palette_data + .chunks(3) + .map(|color| RGBA8::new(color[0], color[1], color[2], 255)) + .collect(); + + if let Some(trns_data) = trns_data { + for (color, trns) in palette.iter_mut().zip(trns_data) { + color.a = trns; + } + } + Ok(palette) +} + #[inline] fn read_be_u32>(rdr: &mut Cursor) -> Result { let mut int_buf = [0; 4]; diff --git a/src/interlace.rs b/src/interlace.rs index 8ac0fdc7..88c146ff 100644 --- a/src/interlace.rs +++ b/src/interlace.rs @@ -45,11 +45,11 @@ pub fn interlace_image(png: &PngImage) -> PngImage { let bit_vec = line.data.view_bits::(); for (i, bit) in bit_vec.iter().by_vals().enumerate() { // Avoid moving padded 0's into new image - if i >= (png.ihdr.width * u32::from(bits_per_pixel)) as usize { + if i >= (png.ihdr.width as usize * bits_per_pixel) { break; } // Copy pixels into interlaced passes - let pix_modulo = (i / bits_per_pixel as usize) % 8; + let pix_modulo = (i / bits_per_pixel) % 8; match index % 8 { 0 => match pix_modulo { 0 => passes[0].push(bit), @@ -87,12 +87,11 @@ pub fn interlace_image(png: &PngImage) -> PngImage { PngImage { data: output, ihdr: IhdrData { + color_type: png.ihdr.color_type.clone(), interlaced: Interlacing::Adam7, ..png.ihdr }, aux_headers: png.aux_headers.clone(), - palette: png.palette.clone(), - transparency_pixel: png.transparency_pixel.clone(), } } @@ -103,19 +102,18 @@ pub fn deinterlace_image(png: &PngImage) -> PngImage { _ => deinterlace_bits(png), }, ihdr: IhdrData { + color_type: png.ihdr.color_type.clone(), interlaced: Interlacing::None, ..png.ihdr }, aux_headers: png.aux_headers.clone(), - palette: png.palette.clone(), - transparency_pixel: png.transparency_pixel.clone(), } } /// Deinterlace by bits, for images with less than 8bpp fn deinterlace_bits(png: &PngImage) -> Vec { let bits_per_pixel = png.ihdr.bpp(); - let bits_per_line = bits_per_pixel as usize * png.ihdr.width as usize; + let bits_per_line = bits_per_pixel * png.ihdr.width as usize; // Initialize each output line with blank data let mut lines: Vec> = vec![bitvec![u8, Msb0; 0; bits_per_line]; png.ihdr.height as usize]; @@ -128,22 +126,22 @@ fn deinterlace_bits(png: &PngImage) -> Vec { + u32::from(pass_constants.x_step) - 1) / u32::from(pass_constants.x_step)) as usize - * bits_per_pixel as usize; + * bits_per_pixel; for (i, bit) in bit_vec.iter().by_vals().enumerate() { // Avoid moving padded 0's into new image if i >= bits_in_line { break; } let current_x: usize = pass_constants.x_shift as usize - + (i / bits_per_pixel as usize) * pass_constants.x_step as usize; + + (i / bits_per_pixel) * pass_constants.x_step as usize; // Copy this bit into the output line - let index = (i % bits_per_pixel as usize) + current_x * bits_per_pixel as usize; + let index = (i % bits_per_pixel) + current_x * bits_per_pixel; lines[current_y].set(index, bit); } // Calculate the next line and move to next pass if necessary current_y += pass_constants.y_step as usize; if current_y >= png.ihdr.height as usize { - if !increment_pass(&mut current_pass, png.ihdr) { + if !increment_pass(&mut current_pass, &png.ihdr) { break; } pass_constants = interlaced_constants(current_pass); @@ -163,7 +161,7 @@ fn deinterlace_bits(png: &PngImage) -> Vec { /// Deinterlace by bytes, for images with at least 8bpp fn deinterlace_bytes(png: &PngImage) -> Vec { let bytes_per_pixel = png.ihdr.bpp() / 8; - let bytes_per_line = bytes_per_pixel as usize * png.ihdr.width as usize; + let bytes_per_line = bytes_per_pixel * png.ihdr.width as usize; // Initialize each output line with some blank data let mut lines: Vec> = vec![vec![0; bytes_per_line]; png.ihdr.height as usize]; let mut current_pass = 1; @@ -172,15 +170,15 @@ fn deinterlace_bytes(png: &PngImage) -> Vec { for line in png.scan_lines(false) { for (i, byte) in line.data.iter().enumerate() { let current_x: usize = pass_constants.x_shift as usize - + (i / bytes_per_pixel as usize) * pass_constants.x_step as usize; + + (i / bytes_per_pixel) * pass_constants.x_step as usize; // Copy this byte into the output line - let index = (i % bytes_per_pixel as usize) + current_x * bytes_per_pixel as usize; + let index = (i % bytes_per_pixel) + current_x * bytes_per_pixel; lines[current_y][index] = *byte; } // Calculate the next line and move to next pass if necessary current_y += pass_constants.y_step as usize; if current_y >= png.ihdr.height as usize { - if !increment_pass(&mut current_pass, png.ihdr) { + if !increment_pass(&mut current_pass, &png.ihdr) { break; } pass_constants = interlaced_constants(current_pass); @@ -190,7 +188,7 @@ fn deinterlace_bytes(png: &PngImage) -> Vec { lines.concat() } -fn increment_pass(current_pass: &mut u8, ihdr: IhdrData) -> bool { +fn increment_pass(current_pass: &mut u8, ihdr: &IhdrData) -> bool { if *current_pass == 7 { return false; } diff --git a/src/lib.rs b/src/lib.rs index 0f5b637f..d88746b7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -25,7 +25,7 @@ extern crate rayon; mod rayon; use crate::atomicmin::AtomicMin; -use crate::colors::BitDepth; +use crate::colors::{BitDepth, ColorType}; use crate::deflate::{crc32, inflate}; use crate::evaluate::Evaluator; use crate::png::PngData; @@ -569,7 +569,7 @@ fn optimize_png( if filters.is_empty() { // Pick a filter automatically - if png.raw.ihdr.bit_depth.as_u8() >= 8 { + if png.raw.ihdr.bit_depth as u8 >= 8 { // Bigrams is the best all-rounder when there's at least one byte per pixel filters.insert(RowFilter::Bigrams); } else { @@ -814,7 +814,7 @@ impl Deadline { /// Display the format of the image data fn report_format(prefix: &str, png: &PngImage) { - if let Some(ref palette) = png.palette { + if let ColorType::Indexed { palette } = &png.ihdr.color_type { debug!( "{}{} bits/pixel, {} colors in palette ({})", prefix, diff --git a/src/png/mod.rs b/src/png/mod.rs index f3d712d0..32870581 100644 --- a/src/png/mod.rs +++ b/src/png/mod.rs @@ -1,4 +1,4 @@ -use crate::colors::ColorType; +use crate::colors::{BitDepth, ColorType}; use crate::deflate; use crate::error::PngError; use crate::filters::*; @@ -8,7 +8,6 @@ use bitvec::bitarr; use indexmap::IndexMap; use libdeflater::{CompressionLvl, Compressor}; use rgb::ComponentSlice; -use rgb::RGBA8; use rustc_hash::FxHashMap; use std::fs::File; use std::io::{BufReader, Read, Write}; @@ -31,11 +30,6 @@ pub struct PngImage { pub ihdr: IhdrData, /// The uncompressed, unfiltered data from the IDAT chunk pub data: Vec, - /// The palette containing colors used in an Indexed image - /// Contains 3 bytes per color (R+G+B), up to 768 - pub palette: Option>, - /// The pixel value that should be rendered as transparent - pub transparency_pixel: Option>, /// All non-critical headers from the PNG are stored here pub aux_headers: IndexMap<[u8; 4], Vec>, } @@ -51,8 +45,6 @@ pub struct PngData { pub filtered: Vec, } -type PaletteWithTrns = (Option>, Option>); - impl PngData { /// Create a new `PngData` struct by opening a file #[inline] @@ -116,7 +108,11 @@ impl PngData { Some(ihdr) => ihdr, None => return Err(PngError::ChunkMissing("IHDR")), }; - let ihdr_header = parse_ihdr_header(&ihdr)?; + let ihdr_header = parse_ihdr_header( + &ihdr, + aux_headers.remove(b"PLTE"), + aux_headers.remove(b"tRNS"), + )?; let raw_data = deflate::inflate(idat_headers.as_ref(), ihdr_header.raw_data_size())?; // Reject files with incorrect width/height or truncated data @@ -124,17 +120,9 @@ impl PngData { return Err(PngError::TruncatedData); } - let (palette, transparency_pixel) = Self::palette_to_rgba( - ihdr_header.color_type, - aux_headers.remove(b"PLTE"), - aux_headers.remove(b"tRNS"), - )?; - let mut raw = PngImage { ihdr: ihdr_header, data: raw_data, - palette, - transparency_pixel, aux_headers, }; let unfiltered = raw.unfilter_image()?; @@ -146,31 +134,6 @@ impl PngData { }) } - /// Handle transparency header - fn palette_to_rgba( - color_type: ColorType, - palette_data: Option>, - trns_data: Option>, - ) -> Result { - if color_type == ColorType::Indexed { - let palette_data = - palette_data.ok_or_else(|| PngError::new("no palette in indexed image"))?; - let mut palette: Vec<_> = palette_data - .chunks(3) - .map(|color| RGBA8::new(color[0], color[1], color[2], 255)) - .collect(); - - if let Some(trns_data) = trns_data { - for (color, trns) in palette.iter_mut().zip(trns_data) { - color.a = trns; - } - } - Ok((Some(palette), None)) - } else { - Ok((None, trns_data)) - } - } - /// Format the `PngData` struct into a valid PNG bytestream pub fn output(&self) -> Vec { // PNG header @@ -181,7 +144,7 @@ impl PngData { ihdr_data .write_all(&self.raw.ihdr.height.to_be_bytes()) .ok(); - ihdr_data.write_all(&[self.raw.ihdr.bit_depth.as_u8()]).ok(); + ihdr_data.write_all(&[self.raw.ihdr.bit_depth as u8]).ok(); ihdr_data .write_all(&[self.raw.ihdr.color_type.png_header_code()]) .ok(); @@ -198,40 +161,49 @@ impl PngData { { write_png_block(key, header, &mut output); } - // Palette - if let Some(ref palette) = self.raw.palette { - let mut palette_data = Vec::with_capacity(palette.len() * 3); - let mut max_palette_size = 1 << (self.raw.ihdr.bit_depth.as_u8() as usize); - // Ensure bKGD color doesn't get truncated from palette - if let Some(&idx) = self.raw.aux_headers.get(b"bKGD").and_then(|b| b.first()) { - max_palette_size = max_palette_size.max(idx as usize + 1); + // Palette and transparency + match &self.raw.ihdr.color_type { + ColorType::Indexed { palette } => { + let mut palette_data = Vec::with_capacity(palette.len() * 3); + let mut max_palette_size = 1 << (self.raw.ihdr.bit_depth as u8); + // Ensure bKGD color doesn't get truncated from palette + if let Some(&idx) = self.raw.aux_headers.get(b"bKGD").and_then(|b| b.first()) { + max_palette_size = max_palette_size.max(idx as usize + 1); + } + for px in palette.iter().take(max_palette_size) { + palette_data.extend_from_slice(px.rgb().as_slice()); + } + write_png_block(b"PLTE", &palette_data, &mut output); + let num_transparent = palette.iter().take(max_palette_size).enumerate().fold( + 0, + |prev, (index, px)| { + if px.a == 255 { + prev + } else { + index + 1 + } + }, + ); + if num_transparent > 0 { + let trns_data: Vec<_> = + palette[0..num_transparent].iter().map(|px| px.a).collect(); + write_png_block(b"tRNS", &trns_data, &mut output); + } } - for px in palette.iter().take(max_palette_size) { - palette_data.extend_from_slice(px.rgb().as_slice()); + ColorType::Grayscale { + transparent_shade: Some(trns), + } => { + // Transparency pixel - 2 byte u16 + write_png_block(b"tRNS", &trns.to_be_bytes(), &mut output); } - write_png_block(b"PLTE", &palette_data, &mut output); - let num_transparent = - palette - .iter() - .take(max_palette_size) - .enumerate() - .fold( - 0, - |prev, (index, px)| { - if px.a == 255 { - prev - } else { - index + 1 - } - }, - ); - if num_transparent > 0 { - let trns_data: Vec<_> = palette[0..num_transparent].iter().map(|px| px.a).collect(); + ColorType::RGB { + transparent_color: Some(trns), + } => { + // Transparency pixel - 6 byte RGB16 + let trns_data: Vec<_> = trns.iter().flat_map(|c| c.to_be_bytes()).collect(); write_png_block(b"tRNS", &trns_data, &mut output); } - } else if let Some(ref transparency_pixel) = self.raw.transparency_pixel { - // Transparency pixel - write_png_block(b"tRNS", transparency_pixel, &mut output); + _ => {} } // Special ancillary headers that need to come after PLTE but before IDAT for (key, header) in self @@ -274,8 +246,18 @@ impl PngImage { /// Return the number of channels in the image, based on color type #[inline] - pub fn channels_per_pixel(&self) -> u8 { - self.ihdr.color_type.channels_per_pixel() + pub fn channels_per_pixel(&self) -> usize { + self.ihdr.color_type.channels_per_pixel() as usize + } + + /// Return the number of bytes per channel in the image + #[inline] + pub fn bytes_per_channel(&self) -> usize { + match self.ihdr.bit_depth { + BitDepth::Sixteen => 2, + // Depths lower than 8 will round up to 1 byte + _ => 1, + } } /// Return an iterator over the scanlines of the image @@ -287,7 +269,7 @@ impl PngImage { /// Reverse all filters applied on the image, returning an unfiltered IDAT bytestream fn unfilter_image(&self) -> Result, PngError> { let mut unfiltered = Vec::with_capacity(self.data.len()); - let bpp = ((self.ihdr.bit_depth.as_u8() * self.channels_per_pixel() + 7) / 8) as usize; + let bpp = self.bytes_per_channel() * self.channels_per_pixel(); let mut last_line: Vec = Vec::new(); let mut last_pass = None; let mut unfiltered_buf = Vec::new(); @@ -309,13 +291,12 @@ impl PngImage { /// Apply the specified filter type to all rows in the image pub fn filter_image(&self, filter: RowFilter, optimize_alpha: bool) -> Vec { let mut filtered = Vec::with_capacity(self.data.len()); - let bpp = ((self.ihdr.bit_depth.as_u8() * self.channels_per_pixel() + 7) / 8) as usize; + let bpp = self.bytes_per_channel() * self.channels_per_pixel(); // If alpha optimization is enabled, determine how many bytes of alpha there are per pixel - let alpha_bytes = match self.ihdr.color_type { - ColorType::RGBA | ColorType::GrayscaleAlpha if optimize_alpha => { - (self.ihdr.bit_depth.as_u8() / 8) as usize - } - _ => 0, + let alpha_bytes = if optimize_alpha && self.ihdr.color_type.has_alpha() { + self.bytes_per_channel() + } else { + 0 }; let mut prev_line = Vec::new(); diff --git a/src/png/scan_lines.rs b/src/png/scan_lines.rs index 509373b2..1c612f89 100644 --- a/src/png/scan_lines.rs +++ b/src/png/scan_lines.rs @@ -43,7 +43,7 @@ impl<'a> Iterator for ScanLines<'a> { struct ScanLineRanges { /// Current pass number, and 0-indexed row within the pass pass: Option<(u8, u32)>, - bits_per_pixel: u8, + bits_per_pixel: usize, width: u32, height: u32, left: usize, @@ -53,7 +53,7 @@ struct ScanLineRanges { impl ScanLineRanges { pub fn new(png: &PngImage, has_filter: bool) -> Self { Self { - bits_per_pixel: png.ihdr.bit_depth.as_u8() * png.channels_per_pixel(), + bits_per_pixel: png.ihdr.bpp(), width: png.ihdr.width, height: png.ihdr.height, left: png.data.len(), @@ -143,8 +143,8 @@ impl Iterator for ScanLineRanges { // Standard, non-interlaced PNG scanlines (self.width, None) }; - let bits_per_line = pixels_per_line * u32::from(self.bits_per_pixel); - let mut len = ((bits_per_line + 7) / 8) as usize; + let bits_per_line = pixels_per_line as usize * self.bits_per_pixel; + let mut len = (bits_per_line + 7) / 8; if self.has_filter { len += 1; } diff --git a/src/reduction/alpha.rs b/src/reduction/alpha.rs index cf8c22ad..4b9fd439 100644 --- a/src/reduction/alpha.rs +++ b/src/reduction/alpha.rs @@ -1,23 +1,21 @@ +use rgb::RGB16; + use crate::colors::{BitDepth, ColorType}; use crate::headers::IhdrData; use crate::png::PngImage; /// Clean the alpha channel by setting the color of all fully transparent pixels to black pub fn cleaned_alpha_channel(png: &PngImage) -> Option { - let (bpc, bpp) = match png.ihdr.color_type { - ColorType::RGBA | ColorType::GrayscaleAlpha => { - let cpp = png.channels_per_pixel(); - let bpc = png.ihdr.bit_depth.as_u8() / 8; - (bpc as usize, (bpc * cpp) as usize) - } - _ => { - return None; - } - }; + if !png.ihdr.color_type.has_alpha() { + return None; + } + let byte_depth = png.bytes_per_channel(); + let bpp = png.channels_per_pixel() * byte_depth; + let colored_bytes = bpp - byte_depth; let mut reduced = Vec::with_capacity(png.data.len()); for pixel in png.data.chunks(bpp) { - if pixel.iter().skip(bpp - bpc).all(|b| *b == 0) { + if pixel.iter().skip(colored_bytes).all(|b| *b == 0) { reduced.resize(reduced.len() + bpp, 0); } else { reduced.extend_from_slice(pixel); @@ -26,23 +24,18 @@ pub fn cleaned_alpha_channel(png: &PngImage) -> Option { Some(PngImage { data: reduced, - ihdr: png.ihdr, - palette: png.palette.clone(), - transparency_pixel: png.transparency_pixel.clone(), + ihdr: png.ihdr.clone(), aux_headers: png.aux_headers.clone(), }) } #[must_use] pub fn reduced_alpha_channel(png: &PngImage, optimize_alpha: bool) -> Option { - let target_color_type = match png.ihdr.color_type { - ColorType::GrayscaleAlpha => ColorType::Grayscale, - ColorType::RGBA => ColorType::RGB, - _ => return None, - }; - let byte_depth = (png.ihdr.bit_depth.as_u8() >> 3) as usize; - let channels = png.channels_per_pixel() as usize; - let bpp = channels * byte_depth; + if !png.ihdr.color_type.has_alpha() { + return None; + } + let byte_depth = png.bytes_per_channel(); + let bpp = png.channels_per_pixel() * byte_depth; let colored_bytes = bpp - byte_depth; // If alpha optimisation is enabled, see if the image contains only fully opaque and fully transparent pixels. @@ -66,13 +59,7 @@ pub fn reduced_alpha_channel(png: &PngImage, optimize_alpha: bool) -> Option vec![unused_color; colored_bytes], - // 8-bit is still stored as 16-bit, with the high byte set to 0 - _ => [0, unused_color].repeat(colored_bytes), - }) + Some(used_colors.iter().position(|b| !*b)? as u8) } else { None }; @@ -80,13 +67,27 @@ pub fn reduced_alpha_channel(png: &PngImage, optimize_alpha: bool) -> Option { - raw_data.resize(raw_data.len() + colored_bytes, trns[1]); + Some(trns) if pixel.iter().skip(colored_bytes).all(|b| *b == 0) => { + raw_data.resize(raw_data.len() + colored_bytes, trns); } _ => raw_data.extend_from_slice(&pixel[0..colored_bytes]), }; } + // Construct the color type with appropriate transparency data + let transparent = transparency_pixel.map(|trns| match png.ihdr.bit_depth { + BitDepth::Sixteen => (trns as u16) << 8 | trns as u16, + _ => trns as u16, + }); + let target_color_type = match png.ihdr.color_type { + ColorType::GrayscaleAlpha => ColorType::Grayscale { + transparent_shade: transparent, + }, + _ => ColorType::RGB { + transparent_color: transparent.map(|t| RGB16::new(t, t, t)), + }, + }; + let mut aux_headers = png.aux_headers.clone(); // sBIT contains information about alpha channel's original depth, // and alpha has just been removed @@ -102,7 +103,5 @@ pub fn reduced_alpha_channel(png: &PngImage, optimize_alpha: bool) -> Option Option { if png.ihdr.bit_depth != BitDepth::Sixteen { - if png.ihdr.color_type == ColorType::Indexed || png.ihdr.color_type == ColorType::Grayscale - { + if png.channels_per_pixel() == 1 { return reduce_bit_depth_8_or_less(png, minimum_bits); } return None; @@ -23,11 +21,10 @@ pub fn reduce_bit_depth(png: &PngImage, minimum_bits: usize) -> Option Some(PngImage { data: png.data.iter().step_by(2).cloned().collect(), ihdr: IhdrData { + color_type: png.ihdr.color_type.clone(), bit_depth: BitDepth::Eight, ..png.ihdr }, - palette: None, - transparency_pixel: png.transparency_pixel.clone(), aux_headers: png.aux_headers.clone(), }) } @@ -35,14 +32,14 @@ pub fn reduce_bit_depth(png: &PngImage, minimum_bits: usize) -> Option #[must_use] pub fn reduce_bit_depth_8_or_less(png: &PngImage, mut minimum_bits: usize) -> Option { assert!((1..8).contains(&minimum_bits)); - let bit_depth: usize = png.ihdr.bit_depth.as_u8() as usize; + let bit_depth = png.ihdr.bit_depth as usize; if minimum_bits >= bit_depth || bit_depth > 8 { return None; } // Calculate the current number of pixels per byte let ppb = 8 / bit_depth; - if png.ihdr.color_type == ColorType::Indexed { + if let ColorType::Indexed { .. } = png.ihdr.color_type { for line in png.scan_lines(false) { let line_max = line .data @@ -129,12 +126,11 @@ pub fn reduce_bit_depth_8_or_less(png: &PngImage, mut minimum_bits: usize) -> Op } // If the image is grayscale we also need to reduce the transparency pixel - let mut transparency_pixel = png - .transparency_pixel - .clone() - .filter(|t| png.ihdr.color_type == ColorType::Grayscale && t.len() >= 2); - if let Some(trans) = transparency_pixel { - let reduced_trans = trans[1] >> (bit_depth - minimum_bits); + let color_type = if let ColorType::Grayscale { + transparent_shade: Some(trans), + } = png.ihdr.color_type + { + let reduced_trans = (trans & 0xFF) >> (bit_depth - minimum_bits); // Verify the reduction is valid by restoring back to original bit depth let mut check = reduced_trans; let mut bits = minimum_bits; @@ -142,22 +138,25 @@ pub fn reduce_bit_depth_8_or_less(png: &PngImage, mut minimum_bits: usize) -> Op check = check << bits | check; bits <<= 1; } - if trans[0] == 0 && trans[1] == check { - transparency_pixel = Some(vec![0, reduced_trans]); - } else { - // The transparency doesn't fit the new bit depth and is therefore unused - set it to None - transparency_pixel = None; + // If the transparency doesn't fit the new bit depth it is therefore unused - set it to None + ColorType::Grayscale { + transparent_shade: if trans == check { + Some(reduced_trans) + } else { + None + }, } - } + } else { + png.ihdr.color_type.clone() + }; Some(PngImage { data: reduced, ihdr: IhdrData { - bit_depth: BitDepth::from_u8(minimum_bits as u8), + color_type, + bit_depth: (minimum_bits as u8).try_into().unwrap(), ..png.ihdr }, aux_headers: png.aux_headers.clone(), - palette: png.palette.clone(), - transparency_pixel, }) } diff --git a/src/reduction/color.rs b/src/reduction/color.rs index 5e7135f8..e8d5e73f 100644 --- a/src/reduction/color.rs +++ b/src/reduction/color.rs @@ -2,7 +2,7 @@ use crate::colors::{BitDepth, ColorType}; use crate::headers::IhdrData; use crate::png::PngImage; use indexmap::IndexMap; -use rgb::{FromSlice, RGB8, RGBA, RGBA8}; +use rgb::{ComponentMap, FromSlice, RGBA, RGBA8}; use rustc_hash::FxHasher; use std::hash::{BuildHasherDefault, Hash}; @@ -41,12 +41,9 @@ pub fn reduce_to_palette(png: &PngImage) -> Option { let mut raw_data = Vec::with_capacity(png.data.len()); let mut palette = FxIndexMap::default(); palette.reserve(257); - let transparency_pixel = png - .transparency_pixel - .as_ref() - .filter(|t| png.ihdr.color_type == ColorType::RGB && t.len() >= 6) - .map(|t| RGB8::new(t[1], t[3], t[5])); - let ok = if png.ihdr.color_type == ColorType::RGB { + let ok = if let ColorType::RGB { transparent_color } = png.ihdr.color_type { + // Convert the RGB16 transparency to RGB8 + let transparency_pixel = transparent_color.map(|t| t.map(|c| c as u8)); reduce_scanline_to_palette( png.data.as_rgb().iter().cloned().map(|px| { px.alpha(if Some(px) != transparency_pixel { @@ -132,20 +129,20 @@ pub fn reduce_to_palette(png: &PngImage) -> Option { Some(PngImage { data: raw_data, ihdr: IhdrData { - color_type: ColorType::Indexed, + color_type: ColorType::Indexed { + palette: palette_vec, + }, ..png.ihdr }, aux_headers, - transparency_pixel: None, - palette: Some(palette_vec), }) } #[must_use] pub fn reduce_rgb_to_grayscale(png: &PngImage) -> Option { let mut reduced = Vec::with_capacity(png.data.len()); - let byte_depth = png.ihdr.bit_depth.as_u8() as usize >> 3; - let bpp = png.channels_per_pixel() as usize * byte_depth; + let byte_depth = png.bytes_per_channel(); + let bpp = png.channels_per_pixel() * byte_depth; let last_color = 2 * byte_depth; for pixel in png.data.chunks(bpp) { if byte_depth == 1 { @@ -158,16 +155,6 @@ pub fn reduce_rgb_to_grayscale(png: &PngImage) -> Option { reduced.extend_from_slice(&pixel[last_color..]); } - let transparency_pixel = if let Some(ref trns) = png.transparency_pixel { - if trns.len() != 6 || trns[0..2] != trns[2..4] || trns[2..4] != trns[4..6] { - None - } else { - Some(trns[0..2].to_owned()) - } - } else { - png.transparency_pixel.clone() - }; - let mut aux_headers = png.aux_headers.clone(); if let Some(sbit_header) = png.aux_headers.get(b"sBIT") { if let Some(&byte) = sbit_header.first() { @@ -180,17 +167,22 @@ pub fn reduce_rgb_to_grayscale(png: &PngImage) -> Option { } } + let color_type = match png.ihdr.color_type { + ColorType::RGB { transparent_color } => ColorType::Grayscale { + // Copy the transparent component if it is also gray + transparent_shade: transparent_color + .filter(|t| t.r == t.g && t.g == t.b) + .map(|t| t.r), + }, + _ => ColorType::GrayscaleAlpha, + }; + Some(PngImage { data: reduced, ihdr: IhdrData { - color_type: match png.ihdr.color_type { - ColorType::RGBA => ColorType::GrayscaleAlpha, - _ => ColorType::Grayscale, - }, + color_type, ..png.ihdr }, aux_headers, - palette: None, - transparency_pixel, }) } diff --git a/src/reduction/mod.rs b/src/reduction/mod.rs index defd0eab..8154189c 100644 --- a/src/reduction/mod.rs +++ b/src/reduction/mod.rs @@ -18,10 +18,11 @@ pub(crate) use crate::bit_depth::reduce_bit_depth; /// Attempt to reduce the number of colors in the palette /// Returns `None` if palette hasn't changed pub fn reduced_palette(png: &PngImage, optimize_alpha: bool) -> Option { - if png.ihdr.color_type != ColorType::Indexed { + let palette = match &png.ihdr.color_type { + ColorType::Indexed { palette } => palette, // Can't reduce if there is no palette - return None; - } + _ => return None, + }; if png.ihdr.bit_depth == BitDepth::One { // Gains from 1-bit images will be at most 1 byte // Not worth the CPU time @@ -31,8 +32,6 @@ pub fn reduced_palette(png: &PngImage, optimize_alpha: bool) -> Option let mut palette_map = [None; 256]; let mut used = [false; 256]; { - let palette = png.palette.as_ref()?; - // Find palette entries that are never used match png.ihdr.bit_depth { BitDepth::Eight => { @@ -109,11 +108,15 @@ pub fn reduced_palette(png: &PngImage, optimize_alpha: bool) -> Option } } - do_palette_reduction(png, &palette_map) + do_palette_reduction(png, palette, &palette_map) } #[must_use] -fn do_palette_reduction(png: &PngImage, palette_map: &[Option; 256]) -> Option { +fn do_palette_reduction( + png: &PngImage, + palette: &[RGBA8], + palette_map: &[Option; 256], +) -> Option { let byte_map = palette_map_to_byte_map(png, palette_map)?; // Reassign data bytes to new indices @@ -131,12 +134,12 @@ fn do_palette_reduction(png: &PngImage, palette_map: &[Option; 256]) -> Opti Some(PngImage { ihdr: IhdrData { - color_type: ColorType::Indexed, + color_type: ColorType::Indexed { + palette: reordered_palette(palette, palette_map), + }, ..png.ihdr }, data: raw_data, - transparency_pixel: None, - palette: Some(reordered_palette(png.palette.as_ref()?, palette_map)), aux_headers, }) } @@ -187,22 +190,20 @@ fn reordered_palette(palette: &[RGBA8], palette_map: &[Option; 256]) -> Vec< new_palette } -/// Attempt to reduce the color type of the image -/// Returns true if the color type was reduced, false otherwise +/// Attempt to reduce the color type of the image, returning the reduced image if successful pub fn reduce_color_type( png: &PngImage, grayscale_reduction: bool, optimize_alpha: bool, ) -> Option { - let mut should_reduce_bit_depth = false; + let was_single_channel = png.channels_per_pixel() == 1; let mut reduced = Cow::Borrowed(png); - // Go down one step at a time - // Maybe not the most efficient, but it's safe - if grayscale_reduction && matches!(reduced.ihdr.color_type, ColorType::RGBA | ColorType::RGB) { + // Go down one step at a time - maybe not the most efficient, but it's safe + // Attempt to reduce RGB to grayscale + if grayscale_reduction && reduced.ihdr.color_type.is_rgb() { if let Some(r) = reduce_rgb_to_grayscale(&reduced) { reduced = Cow::Owned(r); - should_reduce_bit_depth = reduced.ihdr.color_type == ColorType::Grayscale; } } @@ -210,17 +211,13 @@ pub fn reduce_color_type( if reduced.ihdr.color_type == ColorType::GrayscaleAlpha { if let Some(r) = reduced_alpha_channel(&reduced, optimize_alpha) { reduced = Cow::Owned(r); - should_reduce_bit_depth = true; } } - if matches!( - reduced.ihdr.color_type, - ColorType::RGBA | ColorType::RGB | ColorType::GrayscaleAlpha - ) { + // Attempt to reduce to palette, if not already a single channel + if reduced.channels_per_pixel() != 1 { if let Some(r) = reduce_to_palette(&reduced) { reduced = Cow::Owned(r); - should_reduce_bit_depth = true; // Make sure that palette gets sorted. Ideally, this should be done within reduce_to_palette. if let Some(r) = reduced_palette(&reduced, optimize_alpha) { @@ -236,9 +233,8 @@ pub fn reduce_color_type( } } - if should_reduce_bit_depth { - // Some conversions will allow us to perform bit depth reduction that - // wasn't possible before + // Some conversions will allow us to perform bit depth reduction that wasn't possible before + if !was_single_channel && reduced.channels_per_pixel() == 1 { if let Some(r) = reduce_bit_depth_8_or_less(&reduced, 1) { reduced = Cow::Owned(r); } diff --git a/tests/filters.rs b/tests/filters.rs index e1dbad40..065c1259 100644 --- a/tests/filters.rs +++ b/tests/filters.rs @@ -5,6 +5,12 @@ use std::fs::remove_file; use std::path::Path; use std::path::PathBuf; +const GRAYSCALE: u8 = 0; +const RGB: u8 = 2; +const INDEXED: u8 = 3; +const GRAYSCALE_ALPHA: u8 = 4; +const RGBA: u8 = 6; + fn get_opts(input: &Path) -> (OutFile, oxipng::Options) { let mut options = oxipng::Options { force: true, @@ -23,9 +29,9 @@ fn get_opts(input: &Path) -> (OutFile, oxipng::Options) { fn test_it_converts( input: &str, filter: RowFilter, - color_type_in: ColorType, + color_type_in: u8, bit_depth_in: BitDepth, - color_type_out: ColorType, + color_type_out: u8, bit_depth_out: BitDepth, ) { let input = PathBuf::from(input); @@ -34,7 +40,7 @@ fn test_it_converts( let png = PngData::new(&input, opts.fix_errors).unwrap(); opts.filter = IndexSet::new(); opts.filter.insert(filter); - assert_eq!(png.raw.ihdr.color_type, color_type_in); + assert_eq!(png.raw.ihdr.color_type.png_header_code(), color_type_in); assert_eq!(png.raw.ihdr.bit_depth, bit_depth_in); match oxipng::optimize(&InFile::Path(input), &output, &opts) { @@ -52,12 +58,10 @@ fn test_it_converts( } }; - assert_eq!(png.raw.ihdr.color_type, color_type_out); + assert_eq!(png.raw.ihdr.color_type.png_header_code(), color_type_out); assert_eq!(png.raw.ihdr.bit_depth, bit_depth_out); - if let Some(palette) = png.raw.palette.as_ref() { - assert!(palette.len() <= 1 << (png.raw.ihdr.bit_depth.as_u8() as usize)); - } else { - assert_ne!(png.raw.ihdr.color_type, ColorType::Indexed); + if let ColorType::Indexed { palette } = &png.raw.ihdr.color_type { + assert!(palette.len() <= 1 << (png.raw.ihdr.bit_depth as u8)); } remove_file(output).ok(); @@ -68,9 +72,9 @@ fn filter_0_for_rgba_16() { test_it_converts( "tests/files/filter_0_for_rgba_16.png", RowFilter::None, - ColorType::RGBA, + RGBA, BitDepth::Sixteen, - ColorType::RGBA, + RGBA, BitDepth::Sixteen, ); } @@ -80,9 +84,9 @@ fn filter_1_for_rgba_16() { test_it_converts( "tests/files/filter_1_for_rgba_16.png", RowFilter::Sub, - ColorType::RGBA, + RGBA, BitDepth::Sixteen, - ColorType::RGBA, + RGBA, BitDepth::Sixteen, ); } @@ -92,9 +96,9 @@ fn filter_2_for_rgba_16() { test_it_converts( "tests/files/filter_2_for_rgba_16.png", RowFilter::Up, - ColorType::RGBA, + RGBA, BitDepth::Sixteen, - ColorType::RGBA, + RGBA, BitDepth::Sixteen, ); } @@ -104,9 +108,9 @@ fn filter_3_for_rgba_16() { test_it_converts( "tests/files/filter_3_for_rgba_16.png", RowFilter::Average, - ColorType::RGBA, + RGBA, BitDepth::Sixteen, - ColorType::RGBA, + RGBA, BitDepth::Sixteen, ); } @@ -116,9 +120,9 @@ fn filter_4_for_rgba_16() { test_it_converts( "tests/files/filter_4_for_rgba_16.png", RowFilter::Paeth, - ColorType::RGBA, + RGBA, BitDepth::Sixteen, - ColorType::RGBA, + RGBA, BitDepth::Sixteen, ); } @@ -128,9 +132,9 @@ fn filter_5_for_rgba_16() { test_it_converts( "tests/files/filter_5_for_rgba_16.png", RowFilter::MinSum, - ColorType::RGBA, + RGBA, BitDepth::Sixteen, - ColorType::RGBA, + RGBA, BitDepth::Sixteen, ); } @@ -140,9 +144,9 @@ fn filter_0_for_rgba_8() { test_it_converts( "tests/files/filter_0_for_rgba_8.png", RowFilter::None, - ColorType::RGBA, + RGBA, BitDepth::Eight, - ColorType::RGBA, + RGBA, BitDepth::Eight, ); } @@ -152,9 +156,9 @@ fn filter_1_for_rgba_8() { test_it_converts( "tests/files/filter_1_for_rgba_8.png", RowFilter::Sub, - ColorType::RGBA, + RGBA, BitDepth::Eight, - ColorType::RGBA, + RGBA, BitDepth::Eight, ); } @@ -164,9 +168,9 @@ fn filter_2_for_rgba_8() { test_it_converts( "tests/files/filter_2_for_rgba_8.png", RowFilter::Up, - ColorType::RGBA, + RGBA, BitDepth::Eight, - ColorType::RGBA, + RGBA, BitDepth::Eight, ); } @@ -176,9 +180,9 @@ fn filter_3_for_rgba_8() { test_it_converts( "tests/files/filter_3_for_rgba_8.png", RowFilter::Average, - ColorType::RGBA, + RGBA, BitDepth::Eight, - ColorType::RGBA, + RGBA, BitDepth::Eight, ); } @@ -188,9 +192,9 @@ fn filter_4_for_rgba_8() { test_it_converts( "tests/files/filter_4_for_rgba_8.png", RowFilter::Paeth, - ColorType::RGBA, + RGBA, BitDepth::Eight, - ColorType::RGBA, + RGBA, BitDepth::Eight, ); } @@ -200,9 +204,9 @@ fn filter_5_for_rgba_8() { test_it_converts( "tests/files/filter_5_for_rgba_8.png", RowFilter::MinSum, - ColorType::RGBA, + RGBA, BitDepth::Eight, - ColorType::RGBA, + RGBA, BitDepth::Eight, ); } @@ -212,9 +216,9 @@ fn filter_0_for_rgb_16() { test_it_converts( "tests/files/filter_0_for_rgb_16.png", RowFilter::None, - ColorType::RGB, + RGB, BitDepth::Sixteen, - ColorType::RGB, + RGB, BitDepth::Sixteen, ); } @@ -224,9 +228,9 @@ fn filter_1_for_rgb_16() { test_it_converts( "tests/files/filter_1_for_rgb_16.png", RowFilter::Sub, - ColorType::RGB, + RGB, BitDepth::Sixteen, - ColorType::RGB, + RGB, BitDepth::Sixteen, ); } @@ -236,9 +240,9 @@ fn filter_2_for_rgb_16() { test_it_converts( "tests/files/filter_2_for_rgb_16.png", RowFilter::Up, - ColorType::RGB, + RGB, BitDepth::Sixteen, - ColorType::RGB, + RGB, BitDepth::Sixteen, ); } @@ -248,9 +252,9 @@ fn filter_3_for_rgb_16() { test_it_converts( "tests/files/filter_3_for_rgb_16.png", RowFilter::Average, - ColorType::RGB, + RGB, BitDepth::Sixteen, - ColorType::RGB, + RGB, BitDepth::Sixteen, ); } @@ -260,9 +264,9 @@ fn filter_4_for_rgb_16() { test_it_converts( "tests/files/filter_4_for_rgb_16.png", RowFilter::Paeth, - ColorType::RGB, + RGB, BitDepth::Sixteen, - ColorType::RGB, + RGB, BitDepth::Sixteen, ); } @@ -272,9 +276,9 @@ fn filter_5_for_rgb_16() { test_it_converts( "tests/files/filter_5_for_rgb_16.png", RowFilter::MinSum, - ColorType::RGB, + RGB, BitDepth::Sixteen, - ColorType::RGB, + RGB, BitDepth::Sixteen, ); } @@ -284,9 +288,9 @@ fn filter_0_for_rgb_8() { test_it_converts( "tests/files/filter_0_for_rgb_8.png", RowFilter::None, - ColorType::RGB, + RGB, BitDepth::Eight, - ColorType::RGB, + RGB, BitDepth::Eight, ); } @@ -296,9 +300,9 @@ fn filter_1_for_rgb_8() { test_it_converts( "tests/files/filter_1_for_rgb_8.png", RowFilter::Sub, - ColorType::RGB, + RGB, BitDepth::Eight, - ColorType::RGB, + RGB, BitDepth::Eight, ); } @@ -308,9 +312,9 @@ fn filter_2_for_rgb_8() { test_it_converts( "tests/files/filter_2_for_rgb_8.png", RowFilter::Up, - ColorType::RGB, + RGB, BitDepth::Eight, - ColorType::RGB, + RGB, BitDepth::Eight, ); } @@ -320,9 +324,9 @@ fn filter_3_for_rgb_8() { test_it_converts( "tests/files/filter_3_for_rgb_8.png", RowFilter::Average, - ColorType::RGB, + RGB, BitDepth::Eight, - ColorType::RGB, + RGB, BitDepth::Eight, ); } @@ -332,9 +336,9 @@ fn filter_4_for_rgb_8() { test_it_converts( "tests/files/filter_4_for_rgb_8.png", RowFilter::Paeth, - ColorType::RGB, + RGB, BitDepth::Eight, - ColorType::RGB, + RGB, BitDepth::Eight, ); } @@ -344,9 +348,9 @@ fn filter_5_for_rgb_8() { test_it_converts( "tests/files/filter_5_for_rgb_8.png", RowFilter::MinSum, - ColorType::RGB, + RGB, BitDepth::Eight, - ColorType::RGB, + RGB, BitDepth::Eight, ); } @@ -356,9 +360,9 @@ fn filter_0_for_grayscale_alpha_16() { test_it_converts( "tests/files/filter_0_for_grayscale_alpha_16.png", RowFilter::None, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Sixteen, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Sixteen, ); } @@ -368,9 +372,9 @@ fn filter_1_for_grayscale_alpha_16() { test_it_converts( "tests/files/filter_1_for_grayscale_alpha_16.png", RowFilter::Sub, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Sixteen, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Sixteen, ); } @@ -380,9 +384,9 @@ fn filter_2_for_grayscale_alpha_16() { test_it_converts( "tests/files/filter_2_for_grayscale_alpha_16.png", RowFilter::Up, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Sixteen, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Sixteen, ); } @@ -392,9 +396,9 @@ fn filter_3_for_grayscale_alpha_16() { test_it_converts( "tests/files/filter_3_for_grayscale_alpha_16.png", RowFilter::Average, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Sixteen, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Sixteen, ); } @@ -404,9 +408,9 @@ fn filter_4_for_grayscale_alpha_16() { test_it_converts( "tests/files/filter_4_for_grayscale_alpha_16.png", RowFilter::Paeth, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Sixteen, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Sixteen, ); } @@ -416,9 +420,9 @@ fn filter_5_for_grayscale_alpha_16() { test_it_converts( "tests/files/filter_5_for_grayscale_alpha_16.png", RowFilter::MinSum, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Sixteen, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Sixteen, ); } @@ -428,9 +432,9 @@ fn filter_0_for_grayscale_alpha_8() { test_it_converts( "tests/files/filter_0_for_grayscale_alpha_8.png", RowFilter::None, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Eight, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Eight, ); } @@ -440,9 +444,9 @@ fn filter_1_for_grayscale_alpha_8() { test_it_converts( "tests/files/filter_1_for_grayscale_alpha_8.png", RowFilter::Sub, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Eight, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Eight, ); } @@ -452,9 +456,9 @@ fn filter_2_for_grayscale_alpha_8() { test_it_converts( "tests/files/filter_2_for_grayscale_alpha_8.png", RowFilter::Up, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Eight, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Eight, ); } @@ -464,9 +468,9 @@ fn filter_3_for_grayscale_alpha_8() { test_it_converts( "tests/files/filter_3_for_grayscale_alpha_8.png", RowFilter::Average, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Eight, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Eight, ); } @@ -476,9 +480,9 @@ fn filter_4_for_grayscale_alpha_8() { test_it_converts( "tests/files/filter_4_for_grayscale_alpha_8.png", RowFilter::Paeth, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Eight, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Eight, ); } @@ -488,9 +492,9 @@ fn filter_5_for_grayscale_alpha_8() { test_it_converts( "tests/files/filter_5_for_grayscale_alpha_8.png", RowFilter::MinSum, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Eight, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Eight, ); } @@ -500,9 +504,9 @@ fn filter_0_for_grayscale_16() { test_it_converts( "tests/files/filter_0_for_grayscale_16.png", RowFilter::None, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Sixteen, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Sixteen, ); } @@ -512,9 +516,9 @@ fn filter_1_for_grayscale_16() { test_it_converts( "tests/files/filter_1_for_grayscale_16.png", RowFilter::Sub, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Sixteen, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Sixteen, ); } @@ -524,9 +528,9 @@ fn filter_2_for_grayscale_16() { test_it_converts( "tests/files/filter_2_for_grayscale_16.png", RowFilter::Up, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Sixteen, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Sixteen, ); } @@ -536,9 +540,9 @@ fn filter_3_for_grayscale_16() { test_it_converts( "tests/files/filter_3_for_grayscale_16.png", RowFilter::Average, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Sixteen, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Sixteen, ); } @@ -548,9 +552,9 @@ fn filter_4_for_grayscale_16() { test_it_converts( "tests/files/filter_4_for_grayscale_16.png", RowFilter::Paeth, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Sixteen, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Sixteen, ); } @@ -560,9 +564,9 @@ fn filter_5_for_grayscale_16() { test_it_converts( "tests/files/filter_5_for_grayscale_16.png", RowFilter::MinSum, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Sixteen, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Sixteen, ); } @@ -572,9 +576,9 @@ fn filter_0_for_grayscale_8() { test_it_converts( "tests/files/filter_0_for_grayscale_8.png", RowFilter::None, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, ); } @@ -584,9 +588,9 @@ fn filter_1_for_grayscale_8() { test_it_converts( "tests/files/filter_1_for_grayscale_8.png", RowFilter::Sub, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, ); } @@ -596,9 +600,9 @@ fn filter_2_for_grayscale_8() { test_it_converts( "tests/files/filter_2_for_grayscale_8.png", RowFilter::Up, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, ); } @@ -608,9 +612,9 @@ fn filter_3_for_grayscale_8() { test_it_converts( "tests/files/filter_3_for_grayscale_8.png", RowFilter::Average, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, ); } @@ -620,9 +624,9 @@ fn filter_4_for_grayscale_8() { test_it_converts( "tests/files/filter_4_for_grayscale_8.png", RowFilter::Paeth, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, ); } @@ -632,9 +636,9 @@ fn filter_5_for_grayscale_8() { test_it_converts( "tests/files/filter_5_for_grayscale_8.png", RowFilter::MinSum, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, ); } @@ -644,9 +648,9 @@ fn filter_0_for_palette_4() { test_it_converts( "tests/files/filter_0_for_palette_4.png", RowFilter::None, - ColorType::Indexed, + INDEXED, BitDepth::Four, - ColorType::Indexed, + INDEXED, BitDepth::Four, ); } @@ -656,9 +660,9 @@ fn filter_1_for_palette_4() { test_it_converts( "tests/files/filter_1_for_palette_4.png", RowFilter::Sub, - ColorType::Indexed, + INDEXED, BitDepth::Four, - ColorType::Indexed, + INDEXED, BitDepth::Four, ); } @@ -668,9 +672,9 @@ fn filter_2_for_palette_4() { test_it_converts( "tests/files/filter_2_for_palette_4.png", RowFilter::Up, - ColorType::Indexed, + INDEXED, BitDepth::Four, - ColorType::Indexed, + INDEXED, BitDepth::Four, ); } @@ -680,9 +684,9 @@ fn filter_3_for_palette_4() { test_it_converts( "tests/files/filter_3_for_palette_4.png", RowFilter::Average, - ColorType::Indexed, + INDEXED, BitDepth::Four, - ColorType::Indexed, + INDEXED, BitDepth::Four, ); } @@ -692,9 +696,9 @@ fn filter_4_for_palette_4() { test_it_converts( "tests/files/filter_4_for_palette_4.png", RowFilter::Paeth, - ColorType::Indexed, + INDEXED, BitDepth::Four, - ColorType::Indexed, + INDEXED, BitDepth::Four, ); } @@ -704,9 +708,9 @@ fn filter_5_for_palette_4() { test_it_converts( "tests/files/filter_5_for_palette_4.png", RowFilter::MinSum, - ColorType::Indexed, + INDEXED, BitDepth::Four, - ColorType::Indexed, + INDEXED, BitDepth::Four, ); } @@ -716,9 +720,9 @@ fn filter_0_for_palette_2() { test_it_converts( "tests/files/filter_0_for_palette_2.png", RowFilter::None, - ColorType::Indexed, + INDEXED, BitDepth::Two, - ColorType::Indexed, + INDEXED, BitDepth::Two, ); } @@ -728,9 +732,9 @@ fn filter_1_for_palette_2() { test_it_converts( "tests/files/filter_1_for_palette_2.png", RowFilter::Sub, - ColorType::Indexed, + INDEXED, BitDepth::Two, - ColorType::Indexed, + INDEXED, BitDepth::Two, ); } @@ -740,9 +744,9 @@ fn filter_2_for_palette_2() { test_it_converts( "tests/files/filter_2_for_palette_2.png", RowFilter::Up, - ColorType::Indexed, + INDEXED, BitDepth::Two, - ColorType::Indexed, + INDEXED, BitDepth::Two, ); } @@ -752,9 +756,9 @@ fn filter_3_for_palette_2() { test_it_converts( "tests/files/filter_3_for_palette_2.png", RowFilter::Average, - ColorType::Indexed, + INDEXED, BitDepth::Two, - ColorType::Indexed, + INDEXED, BitDepth::Two, ); } @@ -764,9 +768,9 @@ fn filter_4_for_palette_2() { test_it_converts( "tests/files/filter_4_for_palette_2.png", RowFilter::Paeth, - ColorType::Indexed, + INDEXED, BitDepth::Two, - ColorType::Indexed, + INDEXED, BitDepth::Two, ); } @@ -776,9 +780,9 @@ fn filter_5_for_palette_2() { test_it_converts( "tests/files/filter_5_for_palette_2.png", RowFilter::MinSum, - ColorType::Indexed, + INDEXED, BitDepth::Two, - ColorType::Indexed, + INDEXED, BitDepth::Two, ); } @@ -788,9 +792,9 @@ fn filter_0_for_palette_1() { test_it_converts( "tests/files/filter_0_for_palette_1.png", RowFilter::None, - ColorType::Indexed, + INDEXED, BitDepth::One, - ColorType::Indexed, + INDEXED, BitDepth::One, ); } @@ -800,9 +804,9 @@ fn filter_1_for_palette_1() { test_it_converts( "tests/files/filter_1_for_palette_1.png", RowFilter::Sub, - ColorType::Indexed, + INDEXED, BitDepth::One, - ColorType::Indexed, + INDEXED, BitDepth::One, ); } @@ -812,9 +816,9 @@ fn filter_2_for_palette_1() { test_it_converts( "tests/files/filter_2_for_palette_1.png", RowFilter::Up, - ColorType::Indexed, + INDEXED, BitDepth::One, - ColorType::Indexed, + INDEXED, BitDepth::One, ); } @@ -824,9 +828,9 @@ fn filter_3_for_palette_1() { test_it_converts( "tests/files/filter_3_for_palette_1.png", RowFilter::Average, - ColorType::Indexed, + INDEXED, BitDepth::One, - ColorType::Indexed, + INDEXED, BitDepth::One, ); } @@ -836,9 +840,9 @@ fn filter_4_for_palette_1() { test_it_converts( "tests/files/filter_4_for_palette_1.png", RowFilter::Paeth, - ColorType::Indexed, + INDEXED, BitDepth::One, - ColorType::Indexed, + INDEXED, BitDepth::One, ); } @@ -848,9 +852,9 @@ fn filter_5_for_palette_1() { test_it_converts( "tests/files/filter_5_for_palette_1.png", RowFilter::MinSum, - ColorType::Indexed, + INDEXED, BitDepth::One, - ColorType::Indexed, + INDEXED, BitDepth::One, ); } diff --git a/tests/flags.rs b/tests/flags.rs index fc7ace9e..d31f70e2 100644 --- a/tests/flags.rs +++ b/tests/flags.rs @@ -11,6 +11,11 @@ use std::ops::Deref; use std::path::Path; use std::path::PathBuf; +const GRAYSCALE: u8 = 0; +const RGB: u8 = 2; +const INDEXED: u8 = 3; +const RGBA: u8 = 6; + fn get_opts(input: &Path) -> (OutFile, oxipng::Options) { let mut options = oxipng::Options { force: true, @@ -32,9 +37,9 @@ fn test_it_converts_callbacks( input: PathBuf, output: &OutFile, opts: &oxipng::Options, - color_type_in: ColorType, + color_type_in: u8, bit_depth_in: BitDepth, - color_type_out: ColorType, + color_type_out: u8, bit_depth_out: BitDepth, mut callback_pre: CBPRE, mut callback_post: CBPOST, @@ -44,7 +49,7 @@ fn test_it_converts_callbacks( { let png = PngData::new(&input, opts.fix_errors).unwrap(); - assert_eq!(png.raw.ihdr.color_type, color_type_in); + assert_eq!(png.raw.ihdr.color_type.png_header_code(), color_type_in); assert_eq!(png.raw.ihdr.bit_depth, bit_depth_in); callback_pre(&input); @@ -66,7 +71,7 @@ fn test_it_converts_callbacks( } }; - assert_eq!(png.raw.ihdr.color_type, color_type_out); + assert_eq!(png.raw.ihdr.color_type.png_header_code(), color_type_out); assert_eq!(png.raw.ihdr.bit_depth, bit_depth_out); remove_file(output).ok(); @@ -77,9 +82,9 @@ fn test_it_converts( input: PathBuf, output: &OutFile, opts: &oxipng::Options, - color_type_in: ColorType, + color_type_in: u8, bit_depth_in: BitDepth, - color_type_out: ColorType, + color_type_out: u8, bit_depth_out: BitDepth, ) { test_it_converts_callbacks( @@ -153,9 +158,9 @@ fn verbose_mode() { input, &output, &opts, - ColorType::RGB, + RGB, BitDepth::Eight, - ColorType::RGB, + RGB, BitDepth::Eight, ); }; @@ -411,7 +416,7 @@ fn interlacing_0_to_1_small_files() { let png = PngData::new(&input, opts.fix_errors).unwrap(); assert_eq!(png.raw.ihdr.interlaced, Interlacing::None); - assert_eq!(png.raw.ihdr.color_type, ColorType::Indexed); + assert_eq!(png.raw.ihdr.color_type.png_header_code(), INDEXED); assert_eq!(png.raw.ihdr.bit_depth, BitDepth::Eight); match oxipng::optimize(&InFile::Path(input), &output, &opts) { @@ -430,7 +435,7 @@ fn interlacing_0_to_1_small_files() { }; assert_eq!(png.raw.ihdr.interlaced, Interlacing::Adam7); - assert_eq!(png.raw.ihdr.color_type, ColorType::Indexed); + assert_eq!(png.raw.ihdr.color_type.png_header_code(), INDEXED); assert_eq!(png.raw.ihdr.bit_depth, BitDepth::One); remove_file(output).ok(); @@ -445,7 +450,7 @@ fn interlacing_1_to_0_small_files() { let png = PngData::new(&input, opts.fix_errors).unwrap(); assert_eq!(png.raw.ihdr.interlaced, Interlacing::Adam7); - assert_eq!(png.raw.ihdr.color_type, ColorType::Indexed); + assert_eq!(png.raw.ihdr.color_type.png_header_code(), INDEXED); assert_eq!(png.raw.ihdr.bit_depth, BitDepth::Eight); match oxipng::optimize(&InFile::Path(input), &output, &opts) { @@ -464,7 +469,7 @@ fn interlacing_1_to_0_small_files() { }; assert_eq!(png.raw.ihdr.interlaced, Interlacing::None); - assert_eq!(png.raw.ihdr.color_type, ColorType::Indexed); + assert_eq!(png.raw.ihdr.color_type.png_header_code(), INDEXED); // the depth can't be asserted reliably, because on such small file different zlib implementations pick different depth as the best remove_file(output).ok(); @@ -556,9 +561,9 @@ fn preserve_attrs() { input, &output, &opts, - ColorType::RGB, + RGB, BitDepth::Eight, - ColorType::RGB, + RGB, BitDepth::Eight, callback_pre, callback_post, @@ -575,7 +580,7 @@ fn fix_errors() { let png = PngData::new(&input, opts.fix_errors).unwrap(); - assert_eq!(png.raw.ihdr.color_type, ColorType::RGBA); + assert_eq!(png.raw.ihdr.color_type.png_header_code(), RGBA); assert_eq!(png.raw.ihdr.bit_depth, BitDepth::Eight); match oxipng::optimize(&InFile::Path(input), &output, &opts) { @@ -593,7 +598,7 @@ fn fix_errors() { } }; - assert_eq!(png.raw.ihdr.color_type, ColorType::Grayscale); + assert_eq!(png.raw.ihdr.color_type.png_header_code(), GRAYSCALE); assert_eq!(png.raw.ihdr.bit_depth, BitDepth::Eight); // Cannot check if pixels are equal because image crate cannot read corrupt (input) PNGs @@ -613,9 +618,9 @@ fn zopfli_mode() { input, &output, &opts, - ColorType::RGB, + RGB, BitDepth::Eight, - ColorType::RGB, + RGB, BitDepth::Eight, ); } diff --git a/tests/interlaced.rs b/tests/interlaced.rs index 747c1253..ff884b1a 100644 --- a/tests/interlaced.rs +++ b/tests/interlaced.rs @@ -5,6 +5,12 @@ use std::fs::remove_file; use std::path::Path; use std::path::PathBuf; +const GRAYSCALE: u8 = 0; +const RGB: u8 = 2; +const INDEXED: u8 = 3; +const GRAYSCALE_ALPHA: u8 = 4; +const RGBA: u8 = 6; + fn get_opts(input: &Path) -> (OutFile, oxipng::Options) { let mut options = oxipng::Options { force: true, @@ -22,16 +28,16 @@ fn get_opts(input: &Path) -> (OutFile, oxipng::Options) { fn test_it_converts( input: &str, - color_type_in: ColorType, + color_type_in: u8, bit_depth_in: BitDepth, - color_type_out: ColorType, + color_type_out: u8, bit_depth_out: BitDepth, ) { let input = PathBuf::from(input); let (output, opts) = get_opts(&input); let png = PngData::new(&input, opts.fix_errors).unwrap(); - assert_eq!(png.raw.ihdr.color_type, color_type_in); + assert_eq!(png.raw.ihdr.color_type.png_header_code(), color_type_in); assert_eq!(png.raw.ihdr.bit_depth, bit_depth_in); assert_eq!(png.raw.ihdr.interlaced, Interlacing::Adam7); @@ -50,7 +56,7 @@ fn test_it_converts( } }; - assert_eq!(png.raw.ihdr.color_type, color_type_out); + assert_eq!(png.raw.ihdr.color_type.png_header_code(), color_type_out); assert_eq!(png.raw.ihdr.bit_depth, bit_depth_out); remove_file(output).ok(); @@ -60,9 +66,9 @@ fn test_it_converts( fn interlaced_rgba_16_should_be_rgba_16() { test_it_converts( "tests/files/interlaced_rgba_16_should_be_rgba_16.png", - ColorType::RGBA, + RGBA, BitDepth::Sixteen, - ColorType::RGBA, + RGBA, BitDepth::Sixteen, ); } @@ -71,9 +77,9 @@ fn interlaced_rgba_16_should_be_rgba_16() { fn interlaced_rgba_16_should_be_rgba_8() { test_it_converts( "tests/files/interlaced_rgba_16_should_be_rgba_8.png", - ColorType::RGBA, + RGBA, BitDepth::Sixteen, - ColorType::RGBA, + RGBA, BitDepth::Eight, ); } @@ -82,9 +88,9 @@ fn interlaced_rgba_16_should_be_rgba_8() { fn interlaced_rgba_8_should_be_rgba_8() { test_it_converts( "tests/files/interlaced_rgba_8_should_be_rgba_8.png", - ColorType::RGBA, + RGBA, BitDepth::Eight, - ColorType::RGBA, + RGBA, BitDepth::Eight, ); } @@ -93,9 +99,9 @@ fn interlaced_rgba_8_should_be_rgba_8() { fn interlaced_rgba_16_should_be_rgb_16() { test_it_converts( "tests/files/interlaced_rgba_16_should_be_rgb_16.png", - ColorType::RGBA, + RGBA, BitDepth::Sixteen, - ColorType::RGB, + RGB, BitDepth::Sixteen, ); } @@ -104,9 +110,9 @@ fn interlaced_rgba_16_should_be_rgb_16() { fn interlaced_rgba_16_should_be_rgb_8() { test_it_converts( "tests/files/interlaced_rgba_16_should_be_rgb_8.png", - ColorType::RGBA, + RGBA, BitDepth::Sixteen, - ColorType::RGB, + RGB, BitDepth::Eight, ); } @@ -115,9 +121,9 @@ fn interlaced_rgba_16_should_be_rgb_8() { fn interlaced_rgba_8_should_be_rgb_8() { test_it_converts( "tests/files/interlaced_rgba_8_should_be_rgb_8.png", - ColorType::RGBA, + RGBA, BitDepth::Eight, - ColorType::RGB, + RGB, BitDepth::Eight, ); } @@ -126,9 +132,9 @@ fn interlaced_rgba_8_should_be_rgb_8() { fn interlaced_rgba_16_should_be_palette_8() { test_it_converts( "tests/files/interlaced_rgba_16_should_be_palette_8.png", - ColorType::RGBA, + RGBA, BitDepth::Sixteen, - ColorType::Indexed, + INDEXED, BitDepth::Eight, ); } @@ -137,9 +143,9 @@ fn interlaced_rgba_16_should_be_palette_8() { fn interlaced_rgba_8_should_be_palette_8() { test_it_converts( "tests/files/interlaced_rgba_8_should_be_palette_8.png", - ColorType::RGBA, + RGBA, BitDepth::Eight, - ColorType::Indexed, + INDEXED, BitDepth::Eight, ); } @@ -148,9 +154,9 @@ fn interlaced_rgba_8_should_be_palette_8() { fn interlaced_rgba_16_should_be_palette_4() { test_it_converts( "tests/files/interlaced_rgba_16_should_be_palette_4.png", - ColorType::RGBA, + RGBA, BitDepth::Sixteen, - ColorType::Indexed, + INDEXED, BitDepth::Four, ); } @@ -159,9 +165,9 @@ fn interlaced_rgba_16_should_be_palette_4() { fn interlaced_rgba_8_should_be_palette_4() { test_it_converts( "tests/files/interlaced_rgba_8_should_be_palette_4.png", - ColorType::RGBA, + RGBA, BitDepth::Eight, - ColorType::Indexed, + INDEXED, BitDepth::Four, ); } @@ -170,9 +176,9 @@ fn interlaced_rgba_8_should_be_palette_4() { fn interlaced_rgba_16_should_be_palette_2() { test_it_converts( "tests/files/interlaced_rgba_16_should_be_palette_2.png", - ColorType::RGBA, + RGBA, BitDepth::Sixteen, - ColorType::Indexed, + INDEXED, BitDepth::Two, ); } @@ -181,9 +187,9 @@ fn interlaced_rgba_16_should_be_palette_2() { fn interlaced_rgba_8_should_be_palette_2() { test_it_converts( "tests/files/interlaced_rgba_8_should_be_palette_2.png", - ColorType::RGBA, + RGBA, BitDepth::Eight, - ColorType::Indexed, + INDEXED, BitDepth::Two, ); } @@ -192,9 +198,9 @@ fn interlaced_rgba_8_should_be_palette_2() { fn interlaced_rgba_16_should_be_palette_1() { test_it_converts( "tests/files/interlaced_rgba_16_should_be_palette_1.png", - ColorType::RGBA, + RGBA, BitDepth::Sixteen, - ColorType::Indexed, + INDEXED, BitDepth::One, ); } @@ -203,9 +209,9 @@ fn interlaced_rgba_16_should_be_palette_1() { fn interlaced_rgba_8_should_be_palette_1() { test_it_converts( "tests/files/interlaced_rgba_8_should_be_palette_1.png", - ColorType::RGBA, + RGBA, BitDepth::Eight, - ColorType::Indexed, + INDEXED, BitDepth::One, ); } @@ -214,9 +220,9 @@ fn interlaced_rgba_8_should_be_palette_1() { fn interlaced_rgba_16_should_be_grayscale_alpha_16() { test_it_converts( "tests/files/interlaced_rgba_16_should_be_grayscale_alpha_16.png", - ColorType::RGBA, + RGBA, BitDepth::Sixteen, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Sixteen, ); } @@ -225,9 +231,9 @@ fn interlaced_rgba_16_should_be_grayscale_alpha_16() { fn interlaced_rgba_16_should_be_grayscale_alpha_8() { test_it_converts( "tests/files/interlaced_rgba_16_should_be_grayscale_alpha_8.png", - ColorType::RGBA, + RGBA, BitDepth::Sixteen, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Eight, ); } @@ -236,9 +242,9 @@ fn interlaced_rgba_16_should_be_grayscale_alpha_8() { fn interlaced_rgba_8_should_be_grayscale_alpha_8() { test_it_converts( "tests/files/interlaced_rgba_8_should_be_grayscale_alpha_8.png", - ColorType::RGBA, + RGBA, BitDepth::Eight, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Eight, ); } @@ -247,9 +253,9 @@ fn interlaced_rgba_8_should_be_grayscale_alpha_8() { fn interlaced_rgba_16_should_be_grayscale_16() { test_it_converts( "tests/files/interlaced_rgba_16_should_be_grayscale_16.png", - ColorType::RGBA, + RGBA, BitDepth::Sixteen, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Sixteen, ); } @@ -258,9 +264,9 @@ fn interlaced_rgba_16_should_be_grayscale_16() { fn interlaced_rgba_16_should_be_grayscale_8() { test_it_converts( "tests/files/interlaced_rgba_16_should_be_grayscale_8.png", - ColorType::RGBA, + RGBA, BitDepth::Sixteen, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, ); } @@ -269,9 +275,9 @@ fn interlaced_rgba_16_should_be_grayscale_8() { fn interlaced_rgba_8_should_be_grayscale_8() { test_it_converts( "tests/files/interlaced_rgba_8_should_be_grayscale_8.png", - ColorType::RGBA, + RGBA, BitDepth::Eight, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, ); } @@ -280,9 +286,9 @@ fn interlaced_rgba_8_should_be_grayscale_8() { fn interlaced_rgb_16_should_be_rgb_16() { test_it_converts( "tests/files/interlaced_rgb_16_should_be_rgb_16.png", - ColorType::RGB, + RGB, BitDepth::Sixteen, - ColorType::RGB, + RGB, BitDepth::Sixteen, ); } @@ -291,9 +297,9 @@ fn interlaced_rgb_16_should_be_rgb_16() { fn interlaced_rgb_16_should_be_rgb_8() { test_it_converts( "tests/files/interlaced_rgb_16_should_be_rgb_8.png", - ColorType::RGB, + RGB, BitDepth::Sixteen, - ColorType::RGB, + RGB, BitDepth::Eight, ); } @@ -302,9 +308,9 @@ fn interlaced_rgb_16_should_be_rgb_8() { fn interlaced_rgb_8_should_be_rgb_8() { test_it_converts( "tests/files/interlaced_rgb_8_should_be_rgb_8.png", - ColorType::RGB, + RGB, BitDepth::Eight, - ColorType::RGB, + RGB, BitDepth::Eight, ); } @@ -313,9 +319,9 @@ fn interlaced_rgb_8_should_be_rgb_8() { fn interlaced_rgb_16_should_be_palette_8() { test_it_converts( "tests/files/interlaced_rgb_16_should_be_palette_8.png", - ColorType::RGB, + RGB, BitDepth::Sixteen, - ColorType::Indexed, + INDEXED, BitDepth::Eight, ); } @@ -324,9 +330,9 @@ fn interlaced_rgb_16_should_be_palette_8() { fn interlaced_rgb_8_should_be_palette_8() { test_it_converts( "tests/files/interlaced_rgb_8_should_be_palette_8.png", - ColorType::RGB, + RGB, BitDepth::Eight, - ColorType::Indexed, + INDEXED, BitDepth::Eight, ); } @@ -335,9 +341,9 @@ fn interlaced_rgb_8_should_be_palette_8() { fn interlaced_rgb_16_should_be_palette_4() { test_it_converts( "tests/files/interlaced_rgb_16_should_be_palette_4.png", - ColorType::RGB, + RGB, BitDepth::Sixteen, - ColorType::Indexed, + INDEXED, BitDepth::Four, ); } @@ -346,9 +352,9 @@ fn interlaced_rgb_16_should_be_palette_4() { fn interlaced_rgb_8_should_be_palette_4() { test_it_converts( "tests/files/interlaced_rgb_8_should_be_palette_4.png", - ColorType::RGB, + RGB, BitDepth::Eight, - ColorType::Indexed, + INDEXED, BitDepth::Four, ); } @@ -357,9 +363,9 @@ fn interlaced_rgb_8_should_be_palette_4() { fn interlaced_rgb_16_should_be_palette_2() { test_it_converts( "tests/files/interlaced_rgb_16_should_be_palette_2.png", - ColorType::RGB, + RGB, BitDepth::Sixteen, - ColorType::Indexed, + INDEXED, BitDepth::Two, ); } @@ -368,9 +374,9 @@ fn interlaced_rgb_16_should_be_palette_2() { fn interlaced_rgb_8_should_be_palette_2() { test_it_converts( "tests/files/interlaced_rgb_8_should_be_palette_2.png", - ColorType::RGB, + RGB, BitDepth::Eight, - ColorType::Indexed, + INDEXED, BitDepth::Two, ); } @@ -379,9 +385,9 @@ fn interlaced_rgb_8_should_be_palette_2() { fn interlaced_rgb_16_should_be_palette_1() { test_it_converts( "tests/files/interlaced_rgb_16_should_be_palette_1.png", - ColorType::RGB, + RGB, BitDepth::Sixteen, - ColorType::Indexed, + INDEXED, BitDepth::One, ); } @@ -390,9 +396,9 @@ fn interlaced_rgb_16_should_be_palette_1() { fn interlaced_rgb_8_should_be_palette_1() { test_it_converts( "tests/files/interlaced_rgb_8_should_be_palette_1.png", - ColorType::RGB, + RGB, BitDepth::Eight, - ColorType::Indexed, + INDEXED, BitDepth::One, ); } @@ -401,9 +407,9 @@ fn interlaced_rgb_8_should_be_palette_1() { fn interlaced_rgb_16_should_be_grayscale_16() { test_it_converts( "tests/files/interlaced_rgb_16_should_be_grayscale_16.png", - ColorType::RGB, + RGB, BitDepth::Sixteen, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Sixteen, ); } @@ -412,9 +418,9 @@ fn interlaced_rgb_16_should_be_grayscale_16() { fn interlaced_rgb_16_should_be_grayscale_8() { test_it_converts( "tests/files/interlaced_rgb_16_should_be_grayscale_8.png", - ColorType::RGB, + RGB, BitDepth::Sixteen, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, ); } @@ -423,9 +429,9 @@ fn interlaced_rgb_16_should_be_grayscale_8() { fn interlaced_rgb_8_should_be_grayscale_8() { test_it_converts( "tests/files/interlaced_rgb_8_should_be_grayscale_8.png", - ColorType::RGB, + RGB, BitDepth::Eight, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, ); } @@ -434,9 +440,9 @@ fn interlaced_rgb_8_should_be_grayscale_8() { fn interlaced_palette_8_should_be_palette_8() { test_it_converts( "tests/files/interlaced_palette_8_should_be_palette_8.png", - ColorType::Indexed, + INDEXED, BitDepth::Eight, - ColorType::Indexed, + INDEXED, BitDepth::Eight, ); } @@ -445,9 +451,9 @@ fn interlaced_palette_8_should_be_palette_8() { fn interlaced_palette_8_should_be_palette_4() { test_it_converts( "tests/files/interlaced_palette_8_should_be_palette_4.png", - ColorType::Indexed, + INDEXED, BitDepth::Eight, - ColorType::Indexed, + INDEXED, BitDepth::Four, ); } @@ -456,9 +462,9 @@ fn interlaced_palette_8_should_be_palette_4() { fn interlaced_palette_4_should_be_palette_4() { test_it_converts( "tests/files/interlaced_palette_4_should_be_palette_4.png", - ColorType::Indexed, + INDEXED, BitDepth::Four, - ColorType::Indexed, + INDEXED, BitDepth::Four, ); } @@ -467,9 +473,9 @@ fn interlaced_palette_4_should_be_palette_4() { fn interlaced_palette_8_should_be_palette_2() { test_it_converts( "tests/files/interlaced_palette_8_should_be_palette_2.png", - ColorType::Indexed, + INDEXED, BitDepth::Eight, - ColorType::Indexed, + INDEXED, BitDepth::Two, ); } @@ -478,9 +484,9 @@ fn interlaced_palette_8_should_be_palette_2() { fn interlaced_palette_4_should_be_palette_2() { test_it_converts( "tests/files/interlaced_palette_4_should_be_palette_2.png", - ColorType::Indexed, + INDEXED, BitDepth::Four, - ColorType::Indexed, + INDEXED, BitDepth::Two, ); } @@ -489,9 +495,9 @@ fn interlaced_palette_4_should_be_palette_2() { fn interlaced_palette_2_should_be_palette_2() { test_it_converts( "tests/files/interlaced_palette_2_should_be_palette_2.png", - ColorType::Indexed, + INDEXED, BitDepth::Two, - ColorType::Indexed, + INDEXED, BitDepth::Two, ); } @@ -500,9 +506,9 @@ fn interlaced_palette_2_should_be_palette_2() { fn interlaced_palette_8_should_be_palette_1() { test_it_converts( "tests/files/interlaced_palette_8_should_be_palette_1.png", - ColorType::Indexed, + INDEXED, BitDepth::Eight, - ColorType::Indexed, + INDEXED, BitDepth::One, ); } @@ -511,9 +517,9 @@ fn interlaced_palette_8_should_be_palette_1() { fn interlaced_palette_4_should_be_palette_1() { test_it_converts( "tests/files/interlaced_palette_4_should_be_palette_1.png", - ColorType::Indexed, + INDEXED, BitDepth::Four, - ColorType::Indexed, + INDEXED, BitDepth::One, ); } @@ -522,9 +528,9 @@ fn interlaced_palette_4_should_be_palette_1() { fn interlaced_palette_2_should_be_palette_1() { test_it_converts( "tests/files/interlaced_palette_2_should_be_palette_1.png", - ColorType::Indexed, + INDEXED, BitDepth::Two, - ColorType::Indexed, + INDEXED, BitDepth::One, ); } @@ -533,9 +539,9 @@ fn interlaced_palette_2_should_be_palette_1() { fn interlaced_palette_1_should_be_palette_1() { test_it_converts( "tests/files/interlaced_palette_1_should_be_palette_1.png", - ColorType::Indexed, + INDEXED, BitDepth::One, - ColorType::Indexed, + INDEXED, BitDepth::One, ); } @@ -544,9 +550,9 @@ fn interlaced_palette_1_should_be_palette_1() { fn interlaced_grayscale_alpha_16_should_be_grayscale_alpha_16() { test_it_converts( "tests/files/interlaced_grayscale_alpha_16_should_be_grayscale_alpha_16.png", - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Sixteen, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Sixteen, ); } @@ -555,9 +561,9 @@ fn interlaced_grayscale_alpha_16_should_be_grayscale_alpha_16() { fn interlaced_grayscale_alpha_16_should_be_grayscale_alpha_8() { test_it_converts( "tests/files/interlaced_grayscale_alpha_16_should_be_grayscale_alpha_8.png", - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Sixteen, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Eight, ); } @@ -566,9 +572,9 @@ fn interlaced_grayscale_alpha_16_should_be_grayscale_alpha_8() { fn interlaced_grayscale_alpha_8_should_be_grayscale_alpha_8() { test_it_converts( "tests/files/interlaced_grayscale_alpha_8_should_be_grayscale_alpha_8.png", - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Eight, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Eight, ); } @@ -577,9 +583,9 @@ fn interlaced_grayscale_alpha_8_should_be_grayscale_alpha_8() { fn interlaced_grayscale_alpha_16_should_be_grayscale_16() { test_it_converts( "tests/files/interlaced_grayscale_alpha_16_should_be_grayscale_16.png", - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Sixteen, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Sixteen, ); } @@ -588,9 +594,9 @@ fn interlaced_grayscale_alpha_16_should_be_grayscale_16() { fn interlaced_grayscale_alpha_16_should_be_grayscale_8() { test_it_converts( "tests/files/interlaced_grayscale_alpha_16_should_be_grayscale_8.png", - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Sixteen, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, ); } @@ -599,9 +605,9 @@ fn interlaced_grayscale_alpha_16_should_be_grayscale_8() { fn interlaced_grayscale_alpha_8_should_be_grayscale_8() { test_it_converts( "tests/files/interlaced_grayscale_alpha_8_should_be_grayscale_8.png", - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Eight, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, ); } @@ -610,9 +616,9 @@ fn interlaced_grayscale_alpha_8_should_be_grayscale_8() { fn interlaced_grayscale_16_should_be_grayscale_16() { test_it_converts( "tests/files/interlaced_grayscale_16_should_be_grayscale_16.png", - ColorType::Grayscale, + GRAYSCALE, BitDepth::Sixteen, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Sixteen, ); } @@ -621,9 +627,9 @@ fn interlaced_grayscale_16_should_be_grayscale_16() { fn interlaced_grayscale_16_should_be_grayscale_8() { test_it_converts( "tests/files/interlaced_grayscale_16_should_be_grayscale_8.png", - ColorType::Grayscale, + GRAYSCALE, BitDepth::Sixteen, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, ); } @@ -632,9 +638,9 @@ fn interlaced_grayscale_16_should_be_grayscale_8() { fn interlaced_grayscale_8_should_be_grayscale_8() { test_it_converts( "tests/files/interlaced_grayscale_8_should_be_grayscale_8.png", - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, ); } @@ -643,9 +649,9 @@ fn interlaced_grayscale_8_should_be_grayscale_8() { fn interlaced_small_files() { test_it_converts( "tests/files/interlaced_small_files.png", - ColorType::Indexed, + INDEXED, BitDepth::Eight, - ColorType::Indexed, + INDEXED, BitDepth::One, ); } @@ -654,9 +660,9 @@ fn interlaced_small_files() { fn interlaced_odd_width() { test_it_converts( "tests/files/interlaced_odd_width.png", - ColorType::RGB, + RGB, BitDepth::Eight, - ColorType::RGB, + RGB, BitDepth::Eight, ); } diff --git a/tests/interlacing.rs b/tests/interlacing.rs index e0841c88..10f558e6 100644 --- a/tests/interlacing.rs +++ b/tests/interlacing.rs @@ -5,6 +5,9 @@ use std::fs::remove_file; use std::path::Path; use std::path::PathBuf; +const RGB: u8 = 2; +const INDEXED: u8 = 3; + fn get_opts(input: &Path) -> (OutFile, oxipng::Options) { let mut options = oxipng::Options { force: true, @@ -23,16 +26,16 @@ fn get_opts(input: &Path) -> (OutFile, oxipng::Options) { fn test_it_converts( input: &str, interlace: Interlacing, - color_type_in: ColorType, + color_type_in: u8, bit_depth_in: BitDepth, - color_type_out: ColorType, + color_type_out: u8, bit_depth_out: BitDepth, ) { let input = PathBuf::from(input); let (output, mut opts) = get_opts(&input); let png = PngData::new(&input, opts.fix_errors).unwrap(); opts.interlace = Some(interlace); - assert_eq!(png.raw.ihdr.color_type, color_type_in); + assert_eq!(png.raw.ihdr.color_type.png_header_code(), color_type_in); assert_eq!(png.raw.ihdr.bit_depth, bit_depth_in); assert_eq!( png.raw.ihdr.interlaced, @@ -58,7 +61,7 @@ fn test_it_converts( } }; - assert_eq!(png.raw.ihdr.color_type, color_type_out); + assert_eq!(png.raw.ihdr.color_type.png_header_code(), color_type_out); assert_eq!(png.raw.ihdr.bit_depth, bit_depth_out); remove_file(output).ok(); @@ -69,9 +72,9 @@ fn deinterlace_rgb_16() { test_it_converts( "tests/files/interlaced_rgb_16_should_be_rgb_16.png", Interlacing::None, - ColorType::RGB, + RGB, BitDepth::Sixteen, - ColorType::RGB, + RGB, BitDepth::Sixteen, ); } @@ -81,9 +84,9 @@ fn deinterlace_rgb_8() { test_it_converts( "tests/files/interlaced_rgb_8_should_be_rgb_8.png", Interlacing::None, - ColorType::RGB, + RGB, BitDepth::Eight, - ColorType::RGB, + RGB, BitDepth::Eight, ); } @@ -93,9 +96,9 @@ fn deinterlace_palette_8() { test_it_converts( "tests/files/interlaced_palette_8_should_be_palette_8.png", Interlacing::None, - ColorType::Indexed, + INDEXED, BitDepth::Eight, - ColorType::Indexed, + INDEXED, BitDepth::Eight, ); } @@ -105,9 +108,9 @@ fn deinterlace_palette_4() { test_it_converts( "tests/files/interlaced_palette_4_should_be_palette_4.png", Interlacing::None, - ColorType::Indexed, + INDEXED, BitDepth::Four, - ColorType::Indexed, + INDEXED, BitDepth::Four, ); } @@ -117,9 +120,9 @@ fn deinterlace_palette_2() { test_it_converts( "tests/files/interlaced_palette_2_should_be_palette_2.png", Interlacing::None, - ColorType::Indexed, + INDEXED, BitDepth::Two, - ColorType::Indexed, + INDEXED, BitDepth::Two, ); } @@ -129,9 +132,9 @@ fn deinterlace_palette_1() { test_it_converts( "tests/files/interlaced_palette_1_should_be_palette_1.png", Interlacing::None, - ColorType::Indexed, + INDEXED, BitDepth::One, - ColorType::Indexed, + INDEXED, BitDepth::One, ); } @@ -141,9 +144,9 @@ fn interlace_rgb_16() { test_it_converts( "tests/files/rgb_16_should_be_rgb_16.png", Interlacing::Adam7, - ColorType::RGB, + RGB, BitDepth::Sixteen, - ColorType::RGB, + RGB, BitDepth::Sixteen, ); } @@ -153,9 +156,9 @@ fn interlace_rgb_8() { test_it_converts( "tests/files/rgb_8_should_be_rgb_8.png", Interlacing::Adam7, - ColorType::RGB, + RGB, BitDepth::Eight, - ColorType::RGB, + RGB, BitDepth::Eight, ); } @@ -165,9 +168,9 @@ fn interlace_palette_8() { test_it_converts( "tests/files/palette_8_should_be_palette_8.png", Interlacing::Adam7, - ColorType::Indexed, + INDEXED, BitDepth::Eight, - ColorType::Indexed, + INDEXED, BitDepth::Eight, ); } @@ -177,9 +180,9 @@ fn interlace_palette_4() { test_it_converts( "tests/files/palette_4_should_be_palette_4.png", Interlacing::Adam7, - ColorType::Indexed, + INDEXED, BitDepth::Four, - ColorType::Indexed, + INDEXED, BitDepth::Four, ); } @@ -189,9 +192,9 @@ fn interlace_palette_2() { test_it_converts( "tests/files/palette_2_should_be_palette_2.png", Interlacing::Adam7, - ColorType::Indexed, + INDEXED, BitDepth::Two, - ColorType::Indexed, + INDEXED, BitDepth::Two, ); } @@ -201,9 +204,9 @@ fn interlace_palette_1() { test_it_converts( "tests/files/palette_1_should_be_palette_1.png", Interlacing::Adam7, - ColorType::Indexed, + INDEXED, BitDepth::One, - ColorType::Indexed, + INDEXED, BitDepth::One, ); } diff --git a/tests/reduction.rs b/tests/reduction.rs index d88cc58c..040375af 100644 --- a/tests/reduction.rs +++ b/tests/reduction.rs @@ -5,6 +5,12 @@ use std::fs::remove_file; use std::path::Path; use std::path::PathBuf; +const GRAYSCALE: u8 = 0; +const RGB: u8 = 2; +const INDEXED: u8 = 3; +const GRAYSCALE_ALPHA: u8 = 4; +const RGBA: u8 = 6; + fn get_opts(input: &Path) -> (OutFile, oxipng::Options) { let mut options = oxipng::Options { force: true, @@ -23,9 +29,9 @@ fn get_opts(input: &Path) -> (OutFile, oxipng::Options) { fn test_it_converts( input: &str, optimize_alpha: bool, - color_type_in: ColorType, + color_type_in: u8, bit_depth_in: BitDepth, - color_type_out: ColorType, + color_type_out: u8, bit_depth_out: BitDepth, ) { let input = PathBuf::from(input); @@ -33,7 +39,7 @@ fn test_it_converts( opts.optimize_alpha = optimize_alpha; let png = PngData::new(&input, opts.fix_errors).unwrap(); - assert_eq!(png.raw.ihdr.color_type, color_type_in); + assert_eq!(png.raw.ihdr.color_type.png_header_code(), color_type_in); assert_eq!(png.raw.ihdr.bit_depth, bit_depth_in, "test file is broken"); assert_eq!(png.raw.ihdr.interlaced, Interlacing::None); @@ -52,7 +58,7 @@ fn test_it_converts( } }; - assert_eq!(png.raw.ihdr.color_type, color_type_out); + assert_eq!(png.raw.ihdr.color_type.png_header_code(), color_type_out); assert_eq!(png.raw.ihdr.bit_depth, bit_depth_out); remove_file(output).ok(); @@ -63,9 +69,9 @@ fn rgba_16_should_be_rgba_16() { test_it_converts( "tests/files/rgba_16_should_be_rgba_16.png", false, - ColorType::RGBA, + RGBA, BitDepth::Sixteen, - ColorType::RGBA, + RGBA, BitDepth::Sixteen, ); } @@ -75,9 +81,9 @@ fn rgba_16_should_be_rgba_8() { test_it_converts( "tests/files/rgba_16_should_be_rgba_8.png", false, - ColorType::RGBA, + RGBA, BitDepth::Sixteen, - ColorType::RGBA, + RGBA, BitDepth::Eight, ); } @@ -87,9 +93,9 @@ fn rgba_8_should_be_rgba_8() { test_it_converts( "tests/files/rgba_8_should_be_rgba_8.png", false, - ColorType::RGBA, + RGBA, BitDepth::Eight, - ColorType::RGBA, + RGBA, BitDepth::Eight, ); } @@ -99,9 +105,9 @@ fn rgba_16_should_be_rgb_16() { test_it_converts( "tests/files/rgba_16_should_be_rgb_16.png", false, - ColorType::RGBA, + RGBA, BitDepth::Sixteen, - ColorType::RGB, + RGB, BitDepth::Sixteen, ); } @@ -111,9 +117,9 @@ fn rgba_16_should_be_rgb_8() { test_it_converts( "tests/files/rgba_16_should_be_rgb_8.png", false, - ColorType::RGBA, + RGBA, BitDepth::Sixteen, - ColorType::RGB, + RGB, BitDepth::Eight, ); } @@ -123,9 +129,9 @@ fn rgba_8_should_be_rgb_8() { test_it_converts( "tests/files/rgba_8_should_be_rgb_8.png", false, - ColorType::RGBA, + RGBA, BitDepth::Eight, - ColorType::RGB, + RGB, BitDepth::Eight, ); } @@ -135,9 +141,9 @@ fn rgba_16_should_be_rgb_trns_16() { test_it_converts( "tests/files/rgba_16_should_be_rgb_trns_16.png", true, - ColorType::RGBA, + RGBA, BitDepth::Sixteen, - ColorType::RGB, + RGB, BitDepth::Sixteen, ); } @@ -147,9 +153,9 @@ fn rgba_8_should_be_rgb_trns_8() { test_it_converts( "tests/files/rgba_8_should_be_rgb_trns_8.png", true, - ColorType::RGBA, + RGBA, BitDepth::Eight, - ColorType::RGB, + RGB, BitDepth::Eight, ); } @@ -159,9 +165,9 @@ fn rgba_16_should_be_palette_8() { test_it_converts( "tests/files/rgba_16_should_be_palette_8.png", false, - ColorType::RGBA, + RGBA, BitDepth::Sixteen, - ColorType::Indexed, + INDEXED, BitDepth::Eight, ); } @@ -171,9 +177,9 @@ fn rgba_8_should_be_palette_8() { test_it_converts( "tests/files/rgba_8_should_be_palette_8.png", false, - ColorType::RGBA, + RGBA, BitDepth::Eight, - ColorType::Indexed, + INDEXED, BitDepth::Eight, ); } @@ -183,9 +189,9 @@ fn rgba_16_should_be_palette_4() { test_it_converts( "tests/files/rgba_16_should_be_palette_4.png", false, - ColorType::RGBA, + RGBA, BitDepth::Sixteen, - ColorType::Indexed, + INDEXED, BitDepth::Four, ); } @@ -195,9 +201,9 @@ fn rgba_8_should_be_palette_4() { test_it_converts( "tests/files/rgba_8_should_be_palette_4.png", false, - ColorType::RGBA, + RGBA, BitDepth::Eight, - ColorType::Indexed, + INDEXED, BitDepth::Four, ); } @@ -207,9 +213,9 @@ fn rgba_16_should_be_palette_2() { test_it_converts( "tests/files/rgba_16_should_be_palette_2.png", false, - ColorType::RGBA, + RGBA, BitDepth::Sixteen, - ColorType::Indexed, + INDEXED, BitDepth::Two, ); } @@ -219,9 +225,9 @@ fn rgba_8_should_be_palette_2() { test_it_converts( "tests/files/rgba_8_should_be_palette_2.png", false, - ColorType::RGBA, + RGBA, BitDepth::Eight, - ColorType::Indexed, + INDEXED, BitDepth::Two, ); } @@ -231,9 +237,9 @@ fn rgba_16_should_be_palette_1() { test_it_converts( "tests/files/rgba_16_should_be_palette_1.png", false, - ColorType::RGBA, + RGBA, BitDepth::Sixteen, - ColorType::Indexed, + INDEXED, BitDepth::One, ); } @@ -243,9 +249,9 @@ fn rgba_8_should_be_palette_1() { test_it_converts( "tests/files/rgba_8_should_be_palette_1.png", false, - ColorType::RGBA, + RGBA, BitDepth::Eight, - ColorType::Indexed, + INDEXED, BitDepth::One, ); } @@ -255,9 +261,9 @@ fn rgba_16_should_be_grayscale_alpha_16() { test_it_converts( "tests/files/rgba_16_should_be_grayscale_alpha_16.png", false, - ColorType::RGBA, + RGBA, BitDepth::Sixteen, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Sixteen, ); } @@ -267,9 +273,9 @@ fn rgba_16_should_be_grayscale_alpha_8() { test_it_converts( "tests/files/rgba_16_should_be_grayscale_alpha_8.png", false, - ColorType::RGBA, + RGBA, BitDepth::Sixteen, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Eight, ); } @@ -279,9 +285,9 @@ fn rgba_8_should_be_grayscale_alpha_8() { test_it_converts( "tests/files/rgba_8_should_be_grayscale_alpha_8.png", false, - ColorType::RGBA, + RGBA, BitDepth::Eight, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Eight, ); } @@ -291,9 +297,9 @@ fn rgba_16_should_be_grayscale_16() { test_it_converts( "tests/files/rgba_16_should_be_grayscale_16.png", false, - ColorType::RGBA, + RGBA, BitDepth::Sixteen, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Sixteen, ); } @@ -303,9 +309,9 @@ fn rgba_16_should_be_grayscale_8() { test_it_converts( "tests/files/rgba_16_should_be_grayscale_8.png", false, - ColorType::RGBA, + RGBA, BitDepth::Sixteen, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, ); } @@ -315,9 +321,9 @@ fn rgba_8_should_be_grayscale_8() { test_it_converts( "tests/files/rgba_8_should_be_grayscale_8.png", false, - ColorType::RGBA, + RGBA, BitDepth::Eight, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, ); } @@ -327,9 +333,9 @@ fn rgb_16_should_be_rgb_16() { test_it_converts( "tests/files/rgb_16_should_be_rgb_16.png", false, - ColorType::RGB, + RGB, BitDepth::Sixteen, - ColorType::RGB, + RGB, BitDepth::Sixteen, ); } @@ -339,9 +345,9 @@ fn rgb_16_should_be_rgb_8() { test_it_converts( "tests/files/rgb_16_should_be_rgb_8.png", false, - ColorType::RGB, + RGB, BitDepth::Sixteen, - ColorType::RGB, + RGB, BitDepth::Eight, ); } @@ -351,9 +357,9 @@ fn rgb_8_should_be_rgb_8() { test_it_converts( "tests/files/rgb_8_should_be_rgb_8.png", false, - ColorType::RGB, + RGB, BitDepth::Eight, - ColorType::RGB, + RGB, BitDepth::Eight, ); } @@ -363,9 +369,9 @@ fn rgb_16_should_be_palette_8() { test_it_converts( "tests/files/rgb_16_should_be_palette_8.png", false, - ColorType::RGB, + RGB, BitDepth::Sixteen, - ColorType::Indexed, + INDEXED, BitDepth::Eight, ); } @@ -375,9 +381,9 @@ fn rgb_8_should_be_palette_8() { test_it_converts( "tests/files/rgb_8_should_be_palette_8.png", false, - ColorType::RGB, + RGB, BitDepth::Eight, - ColorType::Indexed, + INDEXED, BitDepth::Eight, ); } @@ -387,9 +393,9 @@ fn rgb_16_should_be_palette_4() { test_it_converts( "tests/files/rgb_16_should_be_palette_4.png", false, - ColorType::RGB, + RGB, BitDepth::Sixteen, - ColorType::Indexed, + INDEXED, BitDepth::Four, ); } @@ -399,9 +405,9 @@ fn rgb_8_should_be_palette_4() { test_it_converts( "tests/files/rgb_8_should_be_palette_4.png", false, - ColorType::RGB, + RGB, BitDepth::Eight, - ColorType::Indexed, + INDEXED, BitDepth::Four, ); } @@ -411,9 +417,9 @@ fn rgb_16_should_be_palette_2() { test_it_converts( "tests/files/rgb_16_should_be_palette_2.png", false, - ColorType::RGB, + RGB, BitDepth::Sixteen, - ColorType::Indexed, + INDEXED, BitDepth::Two, ); } @@ -423,9 +429,9 @@ fn rgb_8_should_be_palette_2() { test_it_converts( "tests/files/rgb_8_should_be_palette_2.png", false, - ColorType::RGB, + RGB, BitDepth::Eight, - ColorType::Indexed, + INDEXED, BitDepth::Two, ); } @@ -435,9 +441,9 @@ fn rgb_16_should_be_palette_1() { test_it_converts( "tests/files/rgb_16_should_be_palette_1.png", false, - ColorType::RGB, + RGB, BitDepth::Sixteen, - ColorType::Indexed, + INDEXED, BitDepth::One, ); } @@ -447,9 +453,9 @@ fn rgb_8_should_be_palette_1() { test_it_converts( "tests/files/rgb_8_should_be_palette_1.png", false, - ColorType::RGB, + RGB, BitDepth::Eight, - ColorType::Indexed, + INDEXED, BitDepth::One, ); } @@ -459,9 +465,9 @@ fn rgb_16_should_be_grayscale_16() { test_it_converts( "tests/files/rgb_16_should_be_grayscale_16.png", false, - ColorType::RGB, + RGB, BitDepth::Sixteen, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Sixteen, ); } @@ -471,9 +477,9 @@ fn rgb_16_should_be_grayscale_8() { test_it_converts( "tests/files/rgb_16_should_be_grayscale_8.png", false, - ColorType::RGB, + RGB, BitDepth::Sixteen, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, ); } @@ -483,9 +489,9 @@ fn rgb_8_should_be_grayscale_8() { test_it_converts( "tests/files/rgb_8_should_be_grayscale_8.png", false, - ColorType::RGB, + RGB, BitDepth::Eight, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, ); } @@ -495,9 +501,9 @@ fn palette_8_should_be_palette_8() { test_it_converts( "tests/files/palette_8_should_be_palette_8.png", false, - ColorType::Indexed, + INDEXED, BitDepth::Eight, - ColorType::Indexed, + INDEXED, BitDepth::Eight, ); } @@ -507,9 +513,9 @@ fn palette_8_should_be_palette_4() { test_it_converts( "tests/files/palette_8_should_be_palette_4.png", false, - ColorType::Indexed, + INDEXED, BitDepth::Eight, - ColorType::Indexed, + INDEXED, BitDepth::Four, ); } @@ -519,9 +525,9 @@ fn palette_4_should_be_palette_4() { test_it_converts( "tests/files/palette_4_should_be_palette_4.png", false, - ColorType::Indexed, + INDEXED, BitDepth::Four, - ColorType::Indexed, + INDEXED, BitDepth::Four, ); } @@ -531,9 +537,9 @@ fn palette_8_should_be_palette_2() { test_it_converts( "tests/files/palette_8_should_be_palette_2.png", false, - ColorType::Indexed, + INDEXED, BitDepth::Eight, - ColorType::Indexed, + INDEXED, BitDepth::Two, ); } @@ -543,9 +549,9 @@ fn palette_4_should_be_palette_2() { test_it_converts( "tests/files/palette_4_should_be_palette_2.png", false, - ColorType::Indexed, + INDEXED, BitDepth::Four, - ColorType::Indexed, + INDEXED, BitDepth::Two, ); } @@ -555,9 +561,9 @@ fn palette_2_should_be_palette_2() { test_it_converts( "tests/files/palette_2_should_be_palette_2.png", false, - ColorType::Indexed, + INDEXED, BitDepth::Two, - ColorType::Indexed, + INDEXED, BitDepth::Two, ); } @@ -567,9 +573,9 @@ fn palette_8_should_be_palette_1() { test_it_converts( "tests/files/palette_8_should_be_palette_1.png", false, - ColorType::Indexed, + INDEXED, BitDepth::Eight, - ColorType::Indexed, + INDEXED, BitDepth::One, ); } @@ -579,9 +585,9 @@ fn palette_4_should_be_palette_1() { test_it_converts( "tests/files/palette_4_should_be_palette_1.png", false, - ColorType::Indexed, + INDEXED, BitDepth::Four, - ColorType::Indexed, + INDEXED, BitDepth::One, ); } @@ -591,9 +597,9 @@ fn palette_2_should_be_palette_1() { test_it_converts( "tests/files/palette_2_should_be_palette_1.png", false, - ColorType::Indexed, + INDEXED, BitDepth::Two, - ColorType::Indexed, + INDEXED, BitDepth::One, ); } @@ -603,9 +609,9 @@ fn palette_1_should_be_palette_1() { test_it_converts( "tests/files/palette_1_should_be_palette_1.png", false, - ColorType::Indexed, + INDEXED, BitDepth::One, - ColorType::Indexed, + INDEXED, BitDepth::One, ); } @@ -615,9 +621,9 @@ fn grayscale_alpha_16_should_be_grayscale_alpha_16() { test_it_converts( "tests/files/grayscale_alpha_16_should_be_grayscale_alpha_16.png", false, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Sixteen, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Sixteen, ); } @@ -627,9 +633,9 @@ fn grayscale_alpha_16_should_be_grayscale_alpha_8() { test_it_converts( "tests/files/grayscale_alpha_16_should_be_grayscale_alpha_8.png", false, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Sixteen, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Eight, ); } @@ -639,9 +645,9 @@ fn grayscale_alpha_8_should_be_grayscale_alpha_8() { test_it_converts( "tests/files/grayscale_alpha_8_should_be_grayscale_alpha_8.png", false, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Eight, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Eight, ); } @@ -651,9 +657,9 @@ fn grayscale_alpha_16_should_be_grayscale_16() { test_it_converts( "tests/files/grayscale_alpha_16_should_be_grayscale_16.png", false, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Sixteen, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Sixteen, ); } @@ -663,9 +669,9 @@ fn grayscale_alpha_16_should_be_grayscale_8() { test_it_converts( "tests/files/grayscale_alpha_16_should_be_grayscale_8.png", false, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Sixteen, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, ); } @@ -675,9 +681,9 @@ fn grayscale_alpha_8_should_be_grayscale_8() { test_it_converts( "tests/files/grayscale_alpha_8_should_be_grayscale_8.png", false, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Eight, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, ); } @@ -687,9 +693,9 @@ fn grayscale_16_should_be_grayscale_16() { test_it_converts( "tests/files/grayscale_16_should_be_grayscale_16.png", false, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Sixteen, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Sixteen, ); } @@ -699,9 +705,9 @@ fn grayscale_16_should_be_grayscale_8() { test_it_converts( "tests/files/grayscale_16_should_be_grayscale_8.png", false, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Sixteen, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, ); } @@ -711,9 +717,9 @@ fn grayscale_8_should_be_grayscale_8() { test_it_converts( "tests/files/grayscale_8_should_be_grayscale_8.png", false, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, ); } @@ -723,9 +729,9 @@ fn grayscale_8_should_be_grayscale_4() { test_it_converts( "tests/files/grayscale_8_should_be_grayscale_4.png", false, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Four, ); } @@ -735,9 +741,9 @@ fn grayscale_8_should_be_grayscale_2() { test_it_converts( "tests/files/grayscale_8_should_be_grayscale_2.png", false, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Two, ); } @@ -747,9 +753,9 @@ fn grayscale_4_should_be_grayscale_2() { test_it_converts( "tests/files/grayscale_4_should_be_grayscale_2.png", false, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Four, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Two, ); } @@ -759,9 +765,9 @@ fn grayscale_8_should_be_grayscale_1() { test_it_converts( "tests/files/grayscale_8_should_be_grayscale_1.png", false, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, - ColorType::Grayscale, + GRAYSCALE, BitDepth::One, ); } @@ -771,9 +777,9 @@ fn grayscale_4_should_be_grayscale_1() { test_it_converts( "tests/files/grayscale_4_should_be_grayscale_1.png", false, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Four, - ColorType::Grayscale, + GRAYSCALE, BitDepth::One, ); } @@ -783,9 +789,9 @@ fn grayscale_2_should_be_grayscale_1() { test_it_converts( "tests/files/grayscale_2_should_be_grayscale_1.png", false, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Two, - ColorType::Grayscale, + GRAYSCALE, BitDepth::One, ); } @@ -795,9 +801,9 @@ fn grayscale_alpha_16_should_be_grayscale_trns_16() { test_it_converts( "tests/files/grayscale_alpha_16_should_be_grayscale_trns_16.png", true, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Sixteen, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Sixteen, ); } @@ -807,9 +813,9 @@ fn grayscale_alpha_8_should_be_grayscale_trns_8() { test_it_converts( "tests/files/grayscale_alpha_8_should_be_grayscale_trns_8.png", true, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Eight, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, ); } @@ -821,7 +827,7 @@ fn small_files() { let png = PngData::new(&input, opts.fix_errors).unwrap(); - assert_eq!(png.raw.ihdr.color_type, ColorType::Indexed); + assert_eq!(png.raw.ihdr.color_type.png_header_code(), INDEXED); assert_eq!(png.raw.ihdr.bit_depth, BitDepth::Eight); match oxipng::optimize(&InFile::Path(input), &output, &opts) { @@ -839,7 +845,7 @@ fn small_files() { } }; - assert_eq!(png.raw.ihdr.color_type, ColorType::Indexed); + assert_eq!(png.raw.ihdr.color_type.png_header_code(), INDEXED); // depth varies depending on zlib implementation used remove_file(output).ok(); @@ -852,9 +858,11 @@ fn palette_should_be_reduced_with_dupes() { let png = PngData::new(&input, opts.fix_errors).unwrap(); - assert_eq!(png.raw.ihdr.color_type, ColorType::Indexed); + assert_eq!(png.raw.ihdr.color_type.png_header_code(), INDEXED); assert_eq!(png.raw.ihdr.bit_depth, BitDepth::Eight); - assert_eq!(png.raw.palette.as_ref().unwrap().len(), 43); + if let ColorType::Indexed { palette } = &png.raw.ihdr.color_type { + assert_eq!(palette.len(), 43); + } match oxipng::optimize(&InFile::Path(input), &output, &opts) { Ok(_) => (), @@ -871,9 +879,11 @@ fn palette_should_be_reduced_with_dupes() { } }; - assert_eq!(png.raw.ihdr.color_type, ColorType::Indexed); + assert_eq!(png.raw.ihdr.color_type.png_header_code(), INDEXED); assert_eq!(png.raw.ihdr.bit_depth, BitDepth::Eight); - assert_eq!(png.raw.palette.as_ref().unwrap().len(), 35); + if let ColorType::Indexed { palette } = &png.raw.ihdr.color_type { + assert_eq!(palette.len(), 35); + } remove_file(output).ok(); } @@ -885,9 +895,11 @@ fn palette_should_be_reduced_with_unused() { let png = PngData::new(&input, opts.fix_errors).unwrap(); - assert_eq!(png.raw.ihdr.color_type, ColorType::Indexed); + assert_eq!(png.raw.ihdr.color_type.png_header_code(), INDEXED); assert_eq!(png.raw.ihdr.bit_depth, BitDepth::Eight); - assert_eq!(png.raw.palette.as_ref().unwrap().len(), 35); + if let ColorType::Indexed { palette } = &png.raw.ihdr.color_type { + assert_eq!(palette.len(), 35); + } match oxipng::optimize(&InFile::Path(input), &output, &opts) { Ok(_) => (), @@ -904,9 +916,11 @@ fn palette_should_be_reduced_with_unused() { } }; - assert_eq!(png.raw.ihdr.color_type, ColorType::Indexed); + assert_eq!(png.raw.ihdr.color_type.png_header_code(), INDEXED); assert_eq!(png.raw.ihdr.bit_depth, BitDepth::Eight); - assert_eq!(png.raw.palette.as_ref().unwrap().len(), 33); + if let ColorType::Indexed { palette } = &png.raw.ihdr.color_type { + assert_eq!(palette.len(), 33); + } remove_file(output).ok(); } @@ -918,9 +932,11 @@ fn palette_should_be_reduced_with_both() { let png = PngData::new(&input, opts.fix_errors).unwrap(); - assert_eq!(png.raw.ihdr.color_type, ColorType::Indexed); + assert_eq!(png.raw.ihdr.color_type.png_header_code(), INDEXED); assert_eq!(png.raw.ihdr.bit_depth, BitDepth::Eight); - assert_eq!(png.raw.palette.as_ref().unwrap().len(), 43); + if let ColorType::Indexed { palette } = &png.raw.ihdr.color_type { + assert_eq!(palette.len(), 43); + } match oxipng::optimize(&InFile::Path(input), &output, &opts) { Ok(_) => (), @@ -937,9 +953,11 @@ fn palette_should_be_reduced_with_both() { } }; - assert_eq!(png.raw.ihdr.color_type, ColorType::Indexed); + assert_eq!(png.raw.ihdr.color_type.png_header_code(), INDEXED); assert_eq!(png.raw.ihdr.bit_depth, BitDepth::Eight); - assert_eq!(png.raw.palette.as_ref().unwrap().len(), 33); + if let ColorType::Indexed { palette } = &png.raw.ihdr.color_type { + assert_eq!(palette.len(), 33); + } remove_file(output).ok(); } @@ -949,9 +967,9 @@ fn rgba_16_reduce_alpha() { test_it_converts( "tests/files/rgba_16_reduce_alpha.png", true, - ColorType::RGBA, + RGBA, BitDepth::Sixteen, - ColorType::RGBA, + RGBA, BitDepth::Eight, ); } @@ -961,9 +979,9 @@ fn rgba_8_reduce_alpha() { test_it_converts( "tests/files/rgba_8_reduce_alpha.png", true, - ColorType::RGBA, + RGBA, BitDepth::Eight, - ColorType::RGBA, + RGBA, BitDepth::Eight, ); } @@ -973,9 +991,9 @@ fn grayscale_alpha_16_reduce_alpha() { test_it_converts( "tests/files/grayscale_alpha_16_reduce_alpha.png", true, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Sixteen, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Eight, ); } @@ -985,9 +1003,9 @@ fn grayscale_alpha_8_reduce_alpha() { test_it_converts( "tests/files/grayscale_alpha_8_reduce_alpha.png", true, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Eight, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Eight, ); } diff --git a/tests/regression.rs b/tests/regression.rs index e88cd077..06833b25 100644 --- a/tests/regression.rs +++ b/tests/regression.rs @@ -5,6 +5,12 @@ use std::fs::remove_file; use std::path::Path; use std::path::PathBuf; +const GRAYSCALE: u8 = 0; +const RGB: u8 = 2; +const INDEXED: u8 = 3; +const GRAYSCALE_ALPHA: u8 = 4; +const RGBA: u8 = 6; + fn get_opts(input: &Path) -> (OutFile, oxipng::Options) { let mut options = oxipng::Options { force: true, @@ -23,9 +29,9 @@ fn get_opts(input: &Path) -> (OutFile, oxipng::Options) { fn test_it_converts( input: &str, custom: Option<(OutFile, oxipng::Options)>, - color_type_in: ColorType, + color_type_in: u8, bit_depth_in: BitDepth, - color_type_out: ColorType, + color_type_out: u8, bit_depth_out: BitDepth, ) { let input = PathBuf::from(input); @@ -33,7 +39,8 @@ fn test_it_converts( let png = PngData::new(&input, opts.fix_errors).unwrap(); assert_eq!( - png.raw.ihdr.color_type, color_type_in, + png.raw.ihdr.color_type.png_header_code(), + color_type_in, "test file is broken" ); assert_eq!(png.raw.ihdr.bit_depth, bit_depth_in, "test file is broken"); @@ -54,23 +61,22 @@ fn test_it_converts( }; assert_eq!( - png.raw.ihdr.color_type, color_type_out, + png.raw.ihdr.color_type.png_header_code(), + color_type_out, "optimized to wrong color type" ); assert_eq!( png.raw.ihdr.bit_depth, bit_depth_out, "optimized to wrong bit depth" ); - if let Some(palette) = png.raw.palette.as_ref() { - let mut max_palette_size = 1 << (png.raw.ihdr.bit_depth.as_u8() as usize); + if let ColorType::Indexed { palette } = &png.raw.ihdr.color_type { + let mut max_palette_size = 1 << (png.raw.ihdr.bit_depth as u8); // Ensure bKGD color is valid if let Some(&idx) = png.raw.aux_headers.get(b"bKGD").and_then(|b| b.first()) { assert!(palette.len() > idx as usize); max_palette_size = max_palette_size.max(idx as usize + 1); } assert!(palette.len() <= max_palette_size); - } else { - assert_ne!(png.raw.ihdr.color_type, ColorType::Indexed); } remove_file(output).ok(); @@ -81,9 +87,9 @@ fn issue_29() { test_it_converts( "tests/files/issue-29.png", None, - ColorType::RGB, + RGB, BitDepth::Eight, - ColorType::RGB, + RGB, BitDepth::Eight, ); } @@ -127,9 +133,9 @@ fn issue_52_01() { test_it_converts( "tests/files/issue-52-01.png", None, - ColorType::RGBA, + RGBA, BitDepth::Eight, - ColorType::Indexed, + INDEXED, BitDepth::Eight, ); } @@ -139,9 +145,9 @@ fn issue_52_02() { test_it_converts( "tests/files/issue-52-02.png", None, - ColorType::RGBA, + RGBA, BitDepth::Eight, - ColorType::Indexed, + INDEXED, BitDepth::Eight, ); } @@ -151,9 +157,9 @@ fn issue_52_03() { test_it_converts( "tests/files/issue-52-03.png", None, - ColorType::RGBA, + RGBA, BitDepth::Eight, - ColorType::Indexed, + INDEXED, BitDepth::Eight, ); } @@ -163,9 +169,9 @@ fn issue_52_04() { test_it_converts( "tests/files/issue-52-04.png", None, - ColorType::RGBA, + RGBA, BitDepth::Eight, - ColorType::Indexed, + INDEXED, BitDepth::One, ); } @@ -175,9 +181,9 @@ fn issue_52_05() { test_it_converts( "tests/files/issue-52-05.png", None, - ColorType::RGBA, + RGBA, BitDepth::Eight, - ColorType::Indexed, + INDEXED, BitDepth::One, ); } @@ -187,9 +193,9 @@ fn issue_52_06() { test_it_converts( "tests/files/issue-52-06.png", None, - ColorType::RGBA, + RGBA, BitDepth::Eight, - ColorType::Indexed, + INDEXED, BitDepth::Two, ); } @@ -199,9 +205,9 @@ fn issue_56() { test_it_converts( "tests/files/issue-56.png", None, - ColorType::Indexed, + INDEXED, BitDepth::Four, - ColorType::Indexed, + INDEXED, BitDepth::Four, ); } @@ -211,9 +217,9 @@ fn issue_58() { test_it_converts( "tests/files/issue-58.png", None, - ColorType::Indexed, + INDEXED, BitDepth::Four, - ColorType::Indexed, + INDEXED, BitDepth::Four, ); } @@ -223,9 +229,9 @@ fn issue_59() { test_it_converts( "tests/files/issue-59.png", None, - ColorType::RGBA, + RGBA, BitDepth::Eight, - ColorType::RGBA, + RGBA, BitDepth::Eight, ); } @@ -235,9 +241,9 @@ fn issue_60() { test_it_converts( "tests/files/issue-60.png", None, - ColorType::RGBA, + RGBA, BitDepth::Eight, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Eight, ); } @@ -247,9 +253,9 @@ fn issue_80() { test_it_converts( "tests/files/issue-80.png", None, - ColorType::Indexed, + INDEXED, BitDepth::Two, - ColorType::Indexed, + INDEXED, BitDepth::One, ); } @@ -259,9 +265,9 @@ fn issue_82() { test_it_converts( "tests/files/issue-82.png", None, - ColorType::Indexed, + INDEXED, BitDepth::Four, - ColorType::Indexed, + INDEXED, BitDepth::Four, ); } @@ -271,9 +277,9 @@ fn issue_89() { test_it_converts( "tests/files/issue-89.png", None, - ColorType::RGBA, + RGBA, BitDepth::Eight, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, ); } @@ -283,9 +289,9 @@ fn issue_92_filter_0() { test_it_converts( "tests/files/issue-92.png", None, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, ); } @@ -300,9 +306,9 @@ fn issue_92_filter_5() { test_it_converts( input, Some((output, opts)), - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, ); } @@ -316,9 +322,9 @@ fn issue_113() { test_it_converts( input, Some((output, opts)), - ColorType::RGBA, + RGBA, BitDepth::Eight, - ColorType::GrayscaleAlpha, + GRAYSCALE_ALPHA, BitDepth::Eight, ); } @@ -326,14 +332,7 @@ fn issue_113() { #[test] fn issue_129() { let input = "tests/files/issue-129.png"; - test_it_converts( - input, - None, - ColorType::RGB, - BitDepth::Eight, - ColorType::Indexed, - BitDepth::Eight, - ); + test_it_converts(input, None, RGB, BitDepth::Eight, INDEXED, BitDepth::Eight); } #[test] @@ -344,9 +343,9 @@ fn issue_133() { test_it_converts( input, Some((output, opts)), - ColorType::RGBA, + RGBA, BitDepth::Eight, - ColorType::RGBA, + RGBA, BitDepth::Eight, ); } @@ -356,9 +355,9 @@ fn issue_140() { test_it_converts( "tests/files/issue-140.png", None, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Two, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Two, ); } @@ -368,9 +367,9 @@ fn issue_141() { test_it_converts( "tests/files/issue-141.png", None, - ColorType::RGBA, + RGBA, BitDepth::Eight, - ColorType::RGB, + RGB, BitDepth::Eight, ); } @@ -380,9 +379,9 @@ fn issue_153() { test_it_converts( "tests/files/issue-153.png", None, - ColorType::RGBA, + RGBA, BitDepth::Eight, - ColorType::Indexed, + INDEXED, BitDepth::Eight, ); } @@ -392,9 +391,9 @@ fn issue_159() { test_it_converts( "tests/files/issue-159.png", None, - ColorType::Indexed, + INDEXED, BitDepth::One, - ColorType::Indexed, + INDEXED, BitDepth::One, ); } @@ -404,9 +403,9 @@ fn issue_171() { test_it_converts( "tests/files/issue-171.png", None, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, ); } @@ -416,9 +415,9 @@ fn issue_175() { test_it_converts( "tests/files/issue-175.png", None, - ColorType::Grayscale, + GRAYSCALE, BitDepth::One, - ColorType::Grayscale, + GRAYSCALE, BitDepth::One, ); } @@ -432,9 +431,9 @@ fn issue_182() { test_it_converts( input, Some((output, opts)), - ColorType::Grayscale, + GRAYSCALE, BitDepth::One, - ColorType::Grayscale, + GRAYSCALE, BitDepth::One, ); } @@ -444,9 +443,9 @@ fn issue_195() { test_it_converts( "tests/files/issue-195.png", None, - ColorType::RGBA, + RGBA, BitDepth::Eight, - ColorType::Indexed, + INDEXED, BitDepth::Eight, ); } @@ -456,9 +455,9 @@ fn issue_426_01() { test_it_converts( "tests/files/issue-426-01.png", None, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, - ColorType::Grayscale, + GRAYSCALE, BitDepth::One, ); } @@ -468,9 +467,9 @@ fn issue_426_02() { test_it_converts( "tests/files/issue-426-02.png", None, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, - ColorType::Grayscale, + GRAYSCALE, BitDepth::One, ); } diff --git a/tests/strategies.rs b/tests/strategies.rs index aa5d80f4..415014fe 100644 --- a/tests/strategies.rs +++ b/tests/strategies.rs @@ -5,6 +5,11 @@ use std::fs::remove_file; use std::path::Path; use std::path::PathBuf; +const GRAYSCALE: u8 = 0; +const RGB: u8 = 2; +const INDEXED: u8 = 3; +const RGBA: u8 = 6; + fn get_opts(input: &Path) -> (OutFile, oxipng::Options) { let mut options = oxipng::Options { force: true, @@ -23,9 +28,9 @@ fn get_opts(input: &Path) -> (OutFile, oxipng::Options) { fn test_it_converts( input: &str, filter: RowFilter, - color_type_in: ColorType, + color_type_in: u8, bit_depth_in: BitDepth, - color_type_out: ColorType, + color_type_out: u8, bit_depth_out: BitDepth, ) { let input = PathBuf::from(input); @@ -34,7 +39,7 @@ fn test_it_converts( let png = PngData::new(&input, opts.fix_errors).unwrap(); opts.filter = IndexSet::new(); opts.filter.insert(filter); - assert_eq!(png.raw.ihdr.color_type, color_type_in); + assert_eq!(png.raw.ihdr.color_type.png_header_code(), color_type_in); assert_eq!(png.raw.ihdr.bit_depth, bit_depth_in); match oxipng::optimize(&InFile::Path(input), &output, &opts) { @@ -52,12 +57,10 @@ fn test_it_converts( } }; - assert_eq!(png.raw.ihdr.color_type, color_type_out); + assert_eq!(png.raw.ihdr.color_type.png_header_code(), color_type_out); assert_eq!(png.raw.ihdr.bit_depth, bit_depth_out); - if let Some(palette) = png.raw.palette.as_ref() { - assert!(palette.len() <= 1 << (png.raw.ihdr.bit_depth.as_u8() as usize)); - } else { - assert_ne!(png.raw.ihdr.color_type, ColorType::Indexed); + if let ColorType::Indexed { palette } = &png.raw.ihdr.color_type { + assert!(palette.len() <= 1 << (png.raw.ihdr.bit_depth as u8)); } remove_file(output).ok(); @@ -68,9 +71,9 @@ fn filter_minsum() { test_it_converts( "tests/files/rgb_16_should_be_rgb_16.png", RowFilter::MinSum, - ColorType::RGB, + RGB, BitDepth::Sixteen, - ColorType::RGB, + RGB, BitDepth::Sixteen, ); } @@ -80,9 +83,9 @@ fn filter_entropy() { test_it_converts( "tests/files/rgb_8_should_be_rgb_8.png", RowFilter::Entropy, - ColorType::RGB, + RGB, BitDepth::Eight, - ColorType::RGB, + RGB, BitDepth::Eight, ); } @@ -92,9 +95,9 @@ fn filter_bigrams() { test_it_converts( "tests/files/rgba_8_should_be_rgba_8.png", RowFilter::Bigrams, - ColorType::RGBA, + RGBA, BitDepth::Eight, - ColorType::RGBA, + RGBA, BitDepth::Eight, ); } @@ -104,9 +107,9 @@ fn filter_bigent() { test_it_converts( "tests/files/grayscale_8_should_be_grayscale_8.png", RowFilter::BigEnt, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, - ColorType::Grayscale, + GRAYSCALE, BitDepth::Eight, ); } @@ -116,9 +119,9 @@ fn filter_brute() { test_it_converts( "tests/files/palette_8_should_be_palette_8.png", RowFilter::Brute, - ColorType::Indexed, + INDEXED, BitDepth::Eight, - ColorType::Indexed, + INDEXED, BitDepth::Eight, ); }