Big batch of renames: strip qoi prefix everywhere

This commit is contained in:
Ivan Smirnov 2022-01-03 21:40:24 +03:00
parent cb10dd3629
commit 328cfac40d
13 changed files with 73 additions and 72 deletions

View file

@ -25,7 +25,7 @@ reference = [] # follows reference encoder implementation precisely, but may be
bytemuck = "1.7" bytemuck = "1.7"
[workspace] [workspace]
members = ["qoi-bench"] members = ["bench"]
[dev-dependencies] [dev-dependencies]
anyhow = "1.0" anyhow = "1.0"

View file

@ -4,6 +4,7 @@ version = "0.1.0"
edition = "2018" edition = "2018"
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
authors = ["Ivan Smirnov <rust@ivan.smirnov.ie>"] authors = ["Ivan Smirnov <rust@ivan.smirnov.ie>"]
publish = false
[dependencies] [dependencies]
# internal # internal

View file

@ -123,11 +123,11 @@ impl Codec for CodecQoiFast {
} }
fn encode(img: &Image) -> Result<Vec<u8>> { fn encode(img: &Image) -> Result<Vec<u8>> {
Ok(qoi_fast::qoi_encode_to_vec(&img.data, img.width, img.height)?) Ok(qoi_fast::encode_to_vec(&img.data, img.width, img.height)?)
} }
fn decode(data: &[u8], _img: &Image) -> Result<Vec<u8>> { fn decode(data: &[u8], _img: &Image) -> Result<Vec<u8>> {
Ok(qoi_fast::qoi_decode_to_vec(data)?.1) Ok(qoi_fast::decode_to_vec(data)?.1)
} }
} }
@ -165,8 +165,7 @@ impl Codec for CodecQoiC {
fn encode(img: &Image) -> Result<Vec<u8>> { fn encode(img: &Image) -> Result<Vec<u8>> {
unsafe { unsafe {
let (ptr, len) = Self::qoi_encode(img)?; let (ptr, len) = Self::qoi_encode(img)?;
let mut vec = Vec::with_capacity(len); let mut vec = vec![0; len];
vec.set_len(len);
ptr::copy_nonoverlapping(ptr, vec.as_mut_ptr(), len); ptr::copy_nonoverlapping(ptr, vec.as_mut_ptr(), len);
libc::free(ptr as _); libc::free(ptr as _);
Ok(vec) Ok(vec)
@ -185,8 +184,7 @@ impl Codec for CodecQoiC {
unsafe { unsafe {
let (ptr, desc) = Self::qoi_decode(data, img)?; let (ptr, desc) = Self::qoi_decode(data, img)?;
let len = desc.width as usize * desc.height as usize * desc.channels as usize; let len = desc.width as usize * desc.height as usize * desc.channels as usize;
let mut vec = Vec::with_capacity(len); let mut vec = vec![0; len];
vec.set_len(len);
ptr::copy_nonoverlapping(ptr, vec.as_mut_ptr(), len); ptr::copy_nonoverlapping(ptr, vec.as_mut_ptr(), len);
libc::free(ptr as _); libc::free(ptr as _);
Ok(vec) Ok(vec)

View file

@ -19,13 +19,13 @@ libfuzzer-sys = "0.4"
members = ["."] members = ["."]
[[bin]] [[bin]]
name = "qoi_encode" name = "encode"
path = "fuzz_targets/qoi_encode.rs" path = "fuzz_targets/encode.rs"
test = false test = false
doc = false doc = false
[[bin]] [[bin]]
name = "qoi_decode" name = "decode"
path = "fuzz_targets/qoi_decode.rs" path = "fuzz_targets/decode.rs"
test = false test = false
doc = false doc = false

View file

@ -1,6 +1,8 @@
#![no_main] #![no_main]
use libfuzzer_sys::fuzz_target; use libfuzzer_sys::fuzz_target;
use qoi_fast::{decode_header, decode_to_vec, Channels, ColorSpace, Header};
fuzz_target!(|input: (u16, u16, bool, &[u8])| { fuzz_target!(|input: (u16, u16, bool, &[u8])| {
let (w, h, is_4, data) = input; let (w, h, is_4, data) = input;
let (w, h) = (1 + w % 260, 1 + h % 260); let (w, h) = (1 + w % 260, 1 + h % 260);
@ -25,15 +27,15 @@ fuzz_target!(|input: (u16, u16, bool, &[u8])| {
vec.extend(&*data); vec.extend(&*data);
vec.extend(&[0, 0, 0, 0, 0, 0, 0, 1]); vec.extend(&[0, 0, 0, 0, 0, 0, 0, 1]);
let header_expected = qoi_fast::Header { let header_expected = Header {
width: w as u32, width: w as u32,
height: h as u32, height: h as u32,
channels: qoi_fast::Channels::try_from(channels).unwrap(), channels: Channels::try_from(channels).unwrap(),
colorspace: qoi_fast::ColorSpace::try_from(0).unwrap(), colorspace: ColorSpace::try_from(0).unwrap(),
}; };
assert_eq!(qoi_fast::qoi_decode_header(&vec).unwrap(), header_expected); assert_eq!(decode_header(&vec).unwrap(), header_expected);
if let Ok((header, out)) = qoi_fast::qoi_decode_to_vec(&vec) { if let Ok((header, out)) = decode_to_vec(&vec) {
assert_eq!(header, header_expected); assert_eq!(header, header_expected);
assert_eq!(out.len(), header.n_bytes()); assert_eq!(out.len(), header.n_bytes());
} }

View file

@ -1,6 +1,8 @@
#![no_main] #![no_main]
use libfuzzer_sys::fuzz_target; use libfuzzer_sys::fuzz_target;
use qoi_fast::{encode_size_limit, encode_to_vec};
fuzz_target!(|input: (bool, u8, &[u8])| { fuzz_target!(|input: (bool, u8, &[u8])| {
let (is_4, w_frac, data) = input; let (is_4, w_frac, data) = input;
let channels = if is_4 { 4 } else { 3 }; let channels = if is_4 { 4 } else { 3 };
@ -13,10 +15,10 @@ fuzz_target!(|input: (bool, u8, &[u8])| {
let h = n_pixels / w; let h = n_pixels / w;
(w, h) (w, h)
}; };
let out = qoi_fast::qoi_encode_to_vec(&data[..(w * h * channels as usize)], w as u32, h as u32); let out = encode_to_vec(&data[..(w * h * channels as usize)], w as u32, h as u32);
if w * h != 0 { if w * h != 0 {
let out = out.unwrap(); let out = out.unwrap();
assert!(out.len() <= qoi_fast::encoded_size_limit(w as u32, h as u32, channels)); assert!(out.len() <= encode_size_limit(w as u32, h as u32, channels));
} else { } else {
assert!(out.is_err()); assert!(out.is_err());
} }

View file

@ -22,9 +22,7 @@ const QOI_OP_DIFF_END: u8 = QOI_OP_DIFF | 0x3f;
const QOI_OP_LUMA_END: u8 = QOI_OP_LUMA | 0x3f; const QOI_OP_LUMA_END: u8 = QOI_OP_LUMA | 0x3f;
#[inline] #[inline]
fn qoi_decode_impl_slice<const N: usize, const RGBA: bool>( fn decode_impl_slice<const N: usize, const RGBA: bool>(data: &[u8], out: &mut [u8]) -> Result<usize>
data: &[u8], out: &mut [u8],
) -> Result<usize>
where where
Pixel<N>: SupportedChannels, Pixel<N>: SupportedChannels,
[u8; N]: Pod, [u8; N]: Pod,
@ -92,14 +90,14 @@ where
} }
#[inline] #[inline]
fn qoi_decode_impl_slice_all( fn decode_impl_slice_all(
data: &[u8], out: &mut [u8], channels: u8, src_channels: u8, data: &[u8], out: &mut [u8], channels: u8, src_channels: u8,
) -> Result<usize> { ) -> Result<usize> {
match (channels, src_channels) { match (channels, src_channels) {
(3, 3) => qoi_decode_impl_slice::<3, false>(data, out), (3, 3) => decode_impl_slice::<3, false>(data, out),
(3, 4) => qoi_decode_impl_slice::<3, true>(data, out), (3, 4) => decode_impl_slice::<3, true>(data, out),
(4, 3) => qoi_decode_impl_slice::<4, false>(data, out), (4, 3) => decode_impl_slice::<4, false>(data, out),
(4, 4) => qoi_decode_impl_slice::<4, true>(data, out), (4, 4) => decode_impl_slice::<4, true>(data, out),
_ => { _ => {
cold(); cold();
Err(Error::InvalidChannels { channels }) Err(Error::InvalidChannels { channels })
@ -108,33 +106,33 @@ fn qoi_decode_impl_slice_all(
} }
#[inline] #[inline]
pub fn qoi_decode_to_buf(buf: impl AsMut<[u8]>, data: impl AsRef<[u8]>) -> Result<Header> { pub fn decode_to_buf(buf: impl AsMut<[u8]>, data: impl AsRef<[u8]>) -> Result<Header> {
let mut decoder = QoiDecoder::new(&data)?; let mut decoder = Decoder::new(&data)?;
decoder.decode_to_buf(buf)?; decoder.decode_to_buf(buf)?;
Ok(*decoder.header()) Ok(*decoder.header())
} }
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
#[inline] #[inline]
pub fn qoi_decode_to_vec(data: impl AsRef<[u8]>) -> Result<(Header, Vec<u8>)> { pub fn decode_to_vec(data: impl AsRef<[u8]>) -> Result<(Header, Vec<u8>)> {
let mut decoder = QoiDecoder::new(&data)?; let mut decoder = Decoder::new(&data)?;
let out = decoder.decode_to_vec()?; let out = decoder.decode_to_vec()?;
Ok((*decoder.header(), out)) Ok((*decoder.header(), out))
} }
#[inline] #[inline]
pub fn qoi_decode_header(data: impl AsRef<[u8]>) -> Result<Header> { pub fn decode_header(data: impl AsRef<[u8]>) -> Result<Header> {
Header::decode(data) Header::decode(data)
} }
#[derive(Clone)] #[derive(Clone)]
pub struct QoiDecoder<'a> { pub struct Decoder<'a> {
data: &'a [u8], data: &'a [u8],
header: Header, header: Header,
channels: Channels, channels: Channels,
} }
impl<'a> QoiDecoder<'a> { impl<'a> Decoder<'a> {
#[inline] #[inline]
pub fn new(data: &'a (impl AsRef<[u8]> + ?Sized)) -> Result<Self> { pub fn new(data: &'a (impl AsRef<[u8]> + ?Sized)) -> Result<Self> {
let data = data.as_ref(); let data = data.as_ref();
@ -171,7 +169,7 @@ impl<'a> QoiDecoder<'a> {
if unlikely(buf.len() < size) { if unlikely(buf.len() < size) {
return Err(Error::OutputBufferTooSmall { size: buf.len(), required: size }); return Err(Error::OutputBufferTooSmall { size: buf.len(), required: size });
} }
let n_read = qoi_decode_impl_slice_all( let n_read = decode_impl_slice_all(
self.data, self.data,
buf, buf,
self.channels.as_u8(), self.channels.as_u8(),
@ -191,7 +189,7 @@ impl<'a> QoiDecoder<'a> {
#[cfg(any(feature = "std"))] #[cfg(any(feature = "std"))]
#[inline] #[inline]
fn qoi_decode_impl_stream<R: Read, const N: usize, const RGBA: bool>( fn decode_impl_stream<R: Read, const N: usize, const RGBA: bool>(
data: &mut R, out: &mut [u8], data: &mut R, out: &mut [u8],
) -> Result<()> ) -> Result<()>
where where
@ -261,14 +259,14 @@ where
#[cfg(feature = "std")] #[cfg(feature = "std")]
#[inline] #[inline]
fn qoi_decode_impl_stream_all<R: Read>( fn decode_impl_stream_all<R: Read>(
data: &mut R, out: &mut [u8], channels: u8, src_channels: u8, data: &mut R, out: &mut [u8], channels: u8, src_channels: u8,
) -> Result<()> { ) -> Result<()> {
match (channels, src_channels) { match (channels, src_channels) {
(3, 3) => qoi_decode_impl_stream::<_, 3, false>(data, out), (3, 3) => decode_impl_stream::<_, 3, false>(data, out),
(3, 4) => qoi_decode_impl_stream::<_, 3, true>(data, out), (3, 4) => decode_impl_stream::<_, 3, true>(data, out),
(4, 3) => qoi_decode_impl_stream::<_, 4, false>(data, out), (4, 3) => decode_impl_stream::<_, 4, false>(data, out),
(4, 4) => qoi_decode_impl_stream::<_, 4, true>(data, out), (4, 4) => decode_impl_stream::<_, 4, true>(data, out),
_ => { _ => {
cold(); cold();
Err(Error::InvalidChannels { channels }) Err(Error::InvalidChannels { channels })
@ -277,14 +275,14 @@ fn qoi_decode_impl_stream_all<R: Read>(
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub struct QoiStreamDecoder<R> { pub struct StreamDecoder<R> {
reader: R, reader: R,
header: Header, header: Header,
channels: Channels, channels: Channels,
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
impl<R: Read> QoiStreamDecoder<R> { impl<R: Read> StreamDecoder<R> {
#[inline] #[inline]
pub fn new(mut reader: R) -> Result<Self> { pub fn new(mut reader: R) -> Result<Self> {
let mut b = [0; QOI_HEADER_SIZE]; let mut b = [0; QOI_HEADER_SIZE];
@ -325,7 +323,7 @@ impl<R: Read> QoiStreamDecoder<R> {
if unlikely(buf.len() < size) { if unlikely(buf.len() < size) {
return Err(Error::OutputBufferTooSmall { size: buf.len(), required: size }); return Err(Error::OutputBufferTooSmall { size: buf.len(), required: size });
} }
qoi_decode_impl_stream_all( decode_impl_stream_all(
&mut self.reader, &mut self.reader,
buf, buf,
self.channels.as_u8(), self.channels.as_u8(),

View file

@ -14,7 +14,7 @@ use crate::utils::GenericWriter;
use crate::utils::{unlikely, BytesMut, Writer}; use crate::utils::{unlikely, BytesMut, Writer};
#[allow(clippy::cast_possible_truncation, unused_assignments)] #[allow(clippy::cast_possible_truncation, unused_assignments)]
fn qoi_encode_impl<W: Writer, const N: usize>(mut buf: W, data: &[u8]) -> Result<usize> fn encode_impl<W: Writer, const N: usize>(mut buf: W, data: &[u8]) -> Result<usize>
where where
Pixel<N>: SupportedChannels, Pixel<N>: SupportedChannels,
{ {
@ -70,15 +70,15 @@ where
} }
#[inline] #[inline]
fn qoi_encode_impl_all<W: Writer>(out: W, data: &[u8], channels: Channels) -> Result<usize> { fn encode_impl_all<W: Writer>(out: W, data: &[u8], channels: Channels) -> Result<usize> {
match channels { match channels {
Channels::Rgb => qoi_encode_impl::<_, 3>(out, data), Channels::Rgb => encode_impl::<_, 3>(out, data),
Channels::Rgba => qoi_encode_impl::<_, 4>(out, data), Channels::Rgba => encode_impl::<_, 4>(out, data),
} }
} }
#[inline] #[inline]
pub fn encoded_size_limit(width: u32, height: u32, channels: impl Into<u8>) -> usize { pub fn encode_size_limit(width: u32, height: u32, channels: impl Into<u8>) -> usize {
let (width, height) = (width as usize, height as usize); let (width, height) = (width as usize, height as usize);
let n_pixels = width.saturating_mul(height); let n_pixels = width.saturating_mul(height);
QOI_HEADER_SIZE QOI_HEADER_SIZE
@ -88,24 +88,24 @@ pub fn encoded_size_limit(width: u32, height: u32, channels: impl Into<u8>) -> u
} }
#[inline] #[inline]
pub fn qoi_encode_to_buf( pub fn encode_to_buf(
buf: impl AsMut<[u8]>, data: impl AsRef<[u8]>, width: u32, height: u32, buf: impl AsMut<[u8]>, data: impl AsRef<[u8]>, width: u32, height: u32,
) -> Result<usize> { ) -> Result<usize> {
QoiEncoder::new(&data, width, height)?.encode_to_buf(buf) Encoder::new(&data, width, height)?.encode_to_buf(buf)
} }
#[cfg(any(feature = "alloc", feature = "std"))] #[cfg(any(feature = "alloc", feature = "std"))]
#[inline] #[inline]
pub fn qoi_encode_to_vec(data: impl AsRef<[u8]>, width: u32, height: u32) -> Result<Vec<u8>> { pub fn encode_to_vec(data: impl AsRef<[u8]>, width: u32, height: u32) -> Result<Vec<u8>> {
QoiEncoder::new(&data, width, height)?.encode_to_vec() Encoder::new(&data, width, height)?.encode_to_vec()
} }
pub struct QoiEncoder<'a> { pub struct Encoder<'a> {
data: &'a [u8], data: &'a [u8],
header: Header, header: Header,
} }
impl<'a> QoiEncoder<'a> { impl<'a> Encoder<'a> {
#[inline] #[inline]
#[allow(clippy::cast_possible_truncation)] #[allow(clippy::cast_possible_truncation)]
pub fn new(data: &'a (impl AsRef<[u8]> + ?Sized), width: u32, height: u32) -> Result<Self> { pub fn new(data: &'a (impl AsRef<[u8]> + ?Sized), width: u32, height: u32) -> Result<Self> {
@ -138,27 +138,27 @@ impl<'a> QoiEncoder<'a> {
} }
#[inline] #[inline]
pub fn encoded_size_limit(&self) -> usize { pub fn encode_size_limit(&self) -> usize {
self.header.encoded_size_limit() self.header.encode_size_limit()
} }
#[inline] #[inline]
pub fn encode_to_buf(&self, mut buf: impl AsMut<[u8]>) -> Result<usize> { pub fn encode_to_buf(&self, mut buf: impl AsMut<[u8]>) -> Result<usize> {
let buf = buf.as_mut(); let buf = buf.as_mut();
let size_required = self.encoded_size_limit(); let size_required = self.encode_size_limit();
if unlikely(buf.len() < size_required) { if unlikely(buf.len() < size_required) {
return Err(Error::OutputBufferTooSmall { size: buf.len(), required: size_required }); return Err(Error::OutputBufferTooSmall { size: buf.len(), required: size_required });
} }
let (head, tail) = buf.split_at_mut(QOI_HEADER_SIZE); // can't panic let (head, tail) = buf.split_at_mut(QOI_HEADER_SIZE); // can't panic
head.copy_from_slice(&self.header.encode()); head.copy_from_slice(&self.header.encode());
let n_written = qoi_encode_impl_all(BytesMut::new(tail), self.data, self.header.channels)?; let n_written = encode_impl_all(BytesMut::new(tail), self.data, self.header.channels)?;
Ok(QOI_HEADER_SIZE + n_written) Ok(QOI_HEADER_SIZE + n_written)
} }
#[cfg(any(feature = "alloc", feature = "std"))] #[cfg(any(feature = "alloc", feature = "std"))]
#[inline] #[inline]
pub fn encode_to_vec(&self) -> Result<Vec<u8>> { pub fn encode_to_vec(&self) -> Result<Vec<u8>> {
let mut out = vec![0_u8; self.encoded_size_limit()]; let mut out = vec![0_u8; self.encode_size_limit()];
let size = self.encode_to_buf(&mut out)?; let size = self.encode_to_buf(&mut out)?;
out.truncate(size); out.truncate(size);
Ok(out) Ok(out)
@ -169,7 +169,7 @@ impl<'a> QoiEncoder<'a> {
pub fn encode_to_stream<W: Write>(&self, writer: &mut W) -> Result<usize> { pub fn encode_to_stream<W: Write>(&self, writer: &mut W) -> Result<usize> {
writer.write_all(&self.header.encode())?; writer.write_all(&self.header.encode())?;
let n_written = let n_written =
qoi_encode_impl_all(GenericWriter::new(writer), self.data, self.header.channels)?; encode_impl_all(GenericWriter::new(writer), self.data, self.header.channels)?;
Ok(n_written + QOI_HEADER_SIZE) Ok(n_written + QOI_HEADER_SIZE)
} }
} }

View file

@ -3,7 +3,7 @@ use core::convert::TryInto;
use bytemuck::cast_slice; use bytemuck::cast_slice;
use crate::consts::{QOI_HEADER_SIZE, QOI_MAGIC, QOI_PIXELS_MAX}; use crate::consts::{QOI_HEADER_SIZE, QOI_MAGIC, QOI_PIXELS_MAX};
use crate::encoded_size_limit; use crate::encode_size_limit;
use crate::error::{Error, Result}; use crate::error::{Error, Result};
use crate::types::{Channels, ColorSpace}; use crate::types::{Channels, ColorSpace};
use crate::utils::unlikely; use crate::utils::unlikely;
@ -112,7 +112,7 @@ impl Header {
/// ///
/// This comes useful when pre-allocating a buffer to encode the image into. /// This comes useful when pre-allocating a buffer to encode the image into.
#[inline] #[inline]
pub fn encoded_size_limit(&self) -> usize { pub fn encode_size_limit(&self) -> usize {
encoded_size_limit(self.width, self.height, self.channels) encode_size_limit(self.width, self.height, self.channels)
} }
} }

View file

@ -26,14 +26,14 @@ mod utils;
pub mod consts; pub mod consts;
#[cfg(any(feature = "alloc", feature = "std"))] #[cfg(any(feature = "alloc", feature = "std"))]
pub use crate::decode::qoi_decode_to_vec; pub use crate::decode::decode_to_vec;
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use crate::decode::QoiStreamDecoder; pub use crate::decode::StreamDecoder;
pub use crate::decode::{qoi_decode_header, qoi_decode_to_buf, QoiDecoder}; pub use crate::decode::{decode_header, decode_to_buf, Decoder};
#[cfg(any(feature = "alloc", feature = "std"))] #[cfg(any(feature = "alloc", feature = "std"))]
pub use crate::encode::qoi_encode_to_vec; pub use crate::encode::encode_to_vec;
pub use crate::encode::{encoded_size_limit, qoi_encode_to_buf, QoiEncoder}; pub use crate::encode::{encode_size_limit, encode_to_buf, Encoder};
pub use crate::error::{Error, Result}; pub use crate::error::{Error, Result};
pub use crate::header::Header; pub use crate::header::Header;
pub use crate::types::{Channels, ColorSpace}; pub use crate::types::{Channels, ColorSpace};

View file

@ -5,7 +5,7 @@ use anyhow::{bail, Result};
use cfg_if::cfg_if; use cfg_if::cfg_if;
use walkdir::{DirEntry, WalkDir}; use walkdir::{DirEntry, WalkDir};
use qoi_fast::{qoi_decode_to_vec, qoi_encode_to_vec}; use qoi_fast::{decode_to_vec, encode_to_vec};
fn find_qoi_png_pairs(root: impl AsRef<Path>) -> Vec<(PathBuf, PathBuf)> { fn find_qoi_png_pairs(root: impl AsRef<Path>) -> Vec<(PathBuf, PathBuf)> {
let root = root.as_ref(); let root = root.as_ref();
@ -96,7 +96,7 @@ fn test_reference_images() -> Result<()> {
let png_name = png_path.file_name().unwrap_or_default().to_string_lossy(); let png_name = png_path.file_name().unwrap_or_default().to_string_lossy();
let img = Image::from_png(png_path)?; let img = Image::from_png(png_path)?;
println!("{} {} {} {}", png_name, img.width, img.height, img.channels); println!("{} {} {} {}", png_name, img.width, img.height, img.channels);
let encoded = qoi_encode_to_vec(&img.data, img.width, img.height)?; let encoded = encode_to_vec(&img.data, img.width, img.height)?;
let expected = fs::read(qoi_path)?; let expected = fs::read(qoi_path)?;
assert_eq!(encoded.len(), expected.len()); // this should match regardless assert_eq!(encoded.len(), expected.len()); // this should match regardless
cfg_if! { cfg_if! {
@ -104,8 +104,8 @@ fn test_reference_images() -> Result<()> {
compare_slices(&png_name, "encoding", &encoded, &expected)?; compare_slices(&png_name, "encoding", &encoded, &expected)?;
} }
} }
let (_header1, decoded1) = qoi_decode_to_vec(&encoded)?; let (_header1, decoded1) = decode_to_vec(&encoded)?;
let (_header2, decoded2) = qoi_decode_to_vec(&expected)?; let (_header2, decoded2) = decode_to_vec(&expected)?;
compare_slices(&png_name, "decoding [1]", &decoded1, &img.data)?; compare_slices(&png_name, "decoding [1]", &decoded1, &img.data)?;
compare_slices(&png_name, "decoding [2]", &decoded2, &img.data)?; compare_slices(&png_name, "decoding [2]", &decoded2, &img.data)?;
} }