Move main.rs to a test, drop dep on png crate

The codec library doesn't use any external dependencies. The PNG crate
is only to load some source material for testing the codec. Turning the
test driver into a real test lets me turn the PNG dependency into a
dev-dependency.
This commit is contained in:
2025-10-12 21:18:32 -05:00
parent 5ae4aa5823
commit e31aa5decb
2 changed files with 2 additions and 1 deletions

91
tests/codec.rs Normal file
View File

@@ -0,0 +1,91 @@
use qoicodec::DecodeError;
use qoicodec::Decoder;
use qoicodec::PixelRGBA;
use std::io::BufWriter;
use std::path::Path;
use std::{fs::File, io::Read};
#[test]
fn main() -> Result<(), DecodeError> {
let file = File::open("qoi_test_images/dice.qoi").unwrap();
let mut bytes = file.bytes()
.map(|maybe_bytes|
{
match maybe_bytes {
Ok(byte) => byte,
Err(oops) => panic!("Oops, the file failed to load: {}", oops)
}
});
let decoder = Decoder::try_new(bytes)?;
let test_out_path = Path::new("test_output.png");
let file = File::create(test_out_path).unwrap();
let ref mut w = BufWriter::new(file);
let mut encoder = png::Encoder::new(w, decoder.width, decoder.height);
encoder.set_color(match decoder.channels {
3 => png::ColorType::Rgb,
4 => png::ColorType::Rgba,
_ => panic!("Bad colorspace in qoicodec::Decoder!")
});
encoder.set_depth(png::BitDepth::Eight);
encoder.set_source_gamma(png::ScaledFloat::from_scaled(45455));
encoder.set_source_gamma(png::ScaledFloat::new(1.0 / 2.2));
let source_chromaticities = png::SourceChromaticities::new(
(0.31270, 0.32900),
(0.64000, 0.33000),
(0.30000, 0.60000),
(0.15000, 0.06000),
);
encoder.set_source_chromaticities(source_chromaticities);
let mut writer = encoder.write_header().unwrap();
let data: Vec<u8> = PixelIterExpander::try_new(decoder).unwrap().collect();
let result = writer.write_image_data(&data);
if let Err(res) = result {
eprintln!("{}", res);
}
return Ok(())
}
struct PixelIterExpander <I: Iterator<Item = qoicodec::PixelRGBA>> {
wrapped_iterator: I,
current_pixel: qoicodec::PixelRGBA,
color_element_idx: u8,
}
impl <I: std::iter::Iterator<Item = PixelRGBA>> PixelIterExpander <I> {
fn try_new(mut pixels: I) -> Option<Self> {
let px = pixels.next()?;
Some(Self {
wrapped_iterator: pixels,
current_pixel: px,
color_element_idx: 0,
})
}
}
impl <I: Iterator<Item=PixelRGBA>> Iterator for PixelIterExpander<I> {
type Item = u8;
fn next(&mut self) -> Option<Self::Item> {
// at index 4, reset counter and get next pixel
if self.color_element_idx == 4 {
self.color_element_idx = 0;
self.current_pixel = self.wrapped_iterator.next()?;
}
// increment pixel value, match over index and return that byte
self.color_element_idx += 1;
match self.color_element_idx {
1 => Some(self.current_pixel.r),
2 => Some(self.current_pixel.g),
3 => Some(self.current_pixel.b),
4 => Some(self.current_pixel.a),
_ => None
}
}
}