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
This commit is contained in:
parent
36af4198ed
commit
c97572be3e
17 changed files with 866 additions and 836 deletions
120
src/colors.rs
120
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<u16>,
|
||||
},
|
||||
/// 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<RGB16>,
|
||||
},
|
||||
/// 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<RGBA8>,
|
||||
},
|
||||
/// 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<u8> for BitDepth {
|
||||
type Error = PngError;
|
||||
|
||||
fn try_from(value: u8) -> Result<Self, Self::Error> {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<IhdrData> {
|
||||
pub fn parse_ihdr_header(
|
||||
byte_data: &[u8],
|
||||
palette_data: Option<Vec<u8>>,
|
||||
trns_data: Option<Vec<u8>>,
|
||||
) -> PngResult<IhdrData> {
|
||||
// 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<IhdrData> {
|
|||
})
|
||||
}
|
||||
|
||||
/// Construct an RGBA palette from the raw palette and transparency data
|
||||
fn palette_to_rgba(
|
||||
palette_data: Option<Vec<u8>>,
|
||||
trns_data: Option<Vec<u8>>,
|
||||
) -> Result<Vec<RGBA8>, 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<T: AsRef<[u8]>>(rdr: &mut Cursor<T>) -> Result<u32, io::Error> {
|
||||
let mut int_buf = [0; 4];
|
||||
|
|
|
|||
|
|
@ -45,11 +45,11 @@ pub fn interlace_image(png: &PngImage) -> PngImage {
|
|||
let bit_vec = line.data.view_bits::<Msb0>();
|
||||
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<u8> {
|
||||
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<BitVec<u8, Msb0>> =
|
||||
vec![bitvec![u8, Msb0; 0; bits_per_line]; png.ihdr.height as usize];
|
||||
|
|
@ -128,22 +126,22 @@ fn deinterlace_bits(png: &PngImage) -> Vec<u8> {
|
|||
+ 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<u8> {
|
|||
/// Deinterlace by bytes, for images with at least 8bpp
|
||||
fn deinterlace_bytes(png: &PngImage) -> Vec<u8> {
|
||||
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<u8>> = 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<u8> {
|
|||
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<u8> {
|
|||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
147
src/png/mod.rs
147
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<u8>,
|
||||
/// The palette containing colors used in an Indexed image
|
||||
/// Contains 3 bytes per color (R+G+B), up to 768
|
||||
pub palette: Option<Vec<RGBA8>>,
|
||||
/// The pixel value that should be rendered as transparent
|
||||
pub transparency_pixel: Option<Vec<u8>>,
|
||||
/// All non-critical headers from the PNG are stored here
|
||||
pub aux_headers: IndexMap<[u8; 4], Vec<u8>>,
|
||||
}
|
||||
|
|
@ -51,8 +45,6 @@ pub struct PngData {
|
|||
pub filtered: Vec<u8>,
|
||||
}
|
||||
|
||||
type PaletteWithTrns = (Option<Vec<RGBA8>>, Option<Vec<u8>>);
|
||||
|
||||
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<Vec<u8>>,
|
||||
trns_data: Option<Vec<u8>>,
|
||||
) -> Result<PaletteWithTrns, PngError> {
|
||||
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<u8> {
|
||||
// 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<Vec<u8>, 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<u8> = 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<u8> {
|
||||
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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<PngImage> {
|
||||
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<PngImage> {
|
|||
|
||||
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<PngImage> {
|
||||
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<Png
|
|||
|
||||
let transparency_pixel = if has_transparency {
|
||||
// If no unused color was found we will have to fail here
|
||||
// Otherwise, proceed to construct the tRNS chunk
|
||||
let unused_color = used_colors.iter().position(|b| !*b)? as u8;
|
||||
Some(match png.ihdr.bit_depth {
|
||||
BitDepth::Sixteen => 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<Png
|
|||
let mut raw_data = Vec::with_capacity(png.data.len());
|
||||
for pixel in png.data.chunks(bpp) {
|
||||
match transparency_pixel {
|
||||
Some(ref trns) if pixel.iter().skip(colored_bytes).all(|b| *b == 0) => {
|
||||
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<Png
|
|||
..png.ihdr
|
||||
},
|
||||
aux_headers,
|
||||
transparency_pixel,
|
||||
palette: None,
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,13 +2,11 @@ use crate::colors::{BitDepth, ColorType};
|
|||
use crate::headers::IhdrData;
|
||||
use crate::png::PngImage;
|
||||
|
||||
/// Attempt to reduce the bit depth of the image
|
||||
/// Returns true if the bit depth was reduced, false otherwise
|
||||
/// Attempt to reduce the bit depth of the image, returning the reduced image if successful
|
||||
#[must_use]
|
||||
pub fn reduce_bit_depth(png: &PngImage, minimum_bits: usize) -> Option<PngImage> {
|
||||
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<PngImage>
|
|||
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<PngImage>
|
|||
#[must_use]
|
||||
pub fn reduce_bit_depth_8_or_less(png: &PngImage, mut minimum_bits: usize) -> Option<PngImage> {
|
||||
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,
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<PngImage> {
|
|||
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<PngImage> {
|
|||
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<PngImage> {
|
||||
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<PngImage> {
|
|||
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<PngImage> {
|
|||
}
|
||||
}
|
||||
|
||||
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,
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<PngImage> {
|
||||
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<PngImage>
|
|||
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<PngImage>
|
|||
}
|
||||
}
|
||||
|
||||
do_palette_reduction(png, &palette_map)
|
||||
do_palette_reduction(png, palette, &palette_map)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
fn do_palette_reduction(png: &PngImage, palette_map: &[Option<u8>; 256]) -> Option<PngImage> {
|
||||
fn do_palette_reduction(
|
||||
png: &PngImage,
|
||||
palette: &[RGBA8],
|
||||
palette_map: &[Option<u8>; 256],
|
||||
) -> Option<PngImage> {
|
||||
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<u8>; 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<u8>; 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<PngImage> {
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
284
tests/filters.rs
284
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,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<CBPRE, CBPOST>(
|
|||
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<CBPRE, CBPOST>(
|
|||
{
|
||||
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<CBPRE, CBPOST>(
|
|||
}
|
||||
};
|
||||
|
||||
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,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue