Compare commits

..

No commits in common. "3302928cb7b4e608e74eddba19241bccbfd0ecc3" and "b239c47e63d546de2399366f68113c14c7e68960" have entirely different histories.

2 changed files with 17 additions and 30 deletions

View file

@ -1,27 +1,15 @@
use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion}; use criterion::{black_box, criterion_group, criterion_main, Criterion};
use image::{ImageReader, RgbImage};
use pi_frame_server::dither::{DitherMethod, DitheredImage, Palette}; fn fibonacci(n: u64) -> u64 {
match n {
0 => 1,
1 => 1,
n => fibonacci(n-1) + fibonacci(n-2),
}
}
fn criterion_benchmark(c: &mut Criterion) { fn criterion_benchmark(c: &mut Criterion) {
let sample_file = "sample_0.tiff"; c.bench_function("fib 20", |b| b.iter(|| fibonacci(black_box(20))));
let image: RgbImage = ImageReader::open(format!("samples/{sample_file}"))
.expect("file exists")
.decode()
.expect("file is valid")
.into_rgb8();
c.bench_with_input(BenchmarkId::new("dither", "sample_0"), &image, |b, i| {
b.iter(|| {
let mut method = DitherMethod::Atkinson.get_ditherer();
let mut result = DitheredImage::new(
image.width(),
image.height(),
Palette::Default.value().to_vec(),
);
method.dither(i, &mut result);
});
});
} }
criterion_group!(benches, criterion_benchmark); criterion_group!(benches, criterion_benchmark);

View file

@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
use tracing::instrument; use tracing::instrument;
use image::Rgb as imgRgb; use image::Rgb as imgRgb;
use palette::color_difference::{Ciede2000, HyAb}; use palette::color_difference::Ciede2000;
use palette::{cast::FromComponents, IntoColor, Lab, Srgb}; use palette::{cast::FromComponents, IntoColor, Lab, Srgb};
/// Palette used on the display; pixels can be one of these colors. /// Palette used on the display; pixels can be one of these colors.
@ -133,12 +133,13 @@ pub trait Ditherer {
/// Find the closest approximate palette color to the given sRGB value. /// Find the closest approximate palette color to the given sRGB value.
/// This uses euclidian distance in linear space. /// This uses euclidian distance in linear space.
fn nearest_neighbor(input_color: Lab, palette: &[Lab]) -> (u8, Lab) { fn nearest_neighbor(input_color: Lab, palette: &[Srgb]) -> (u8, Lab) {
let (nearest, _, color_diff) = palette let (nearest, _, color_diff) = palette
.iter() .iter()
.enumerate() .enumerate()
.map(|(idx, p_color)| { .map(|(idx, p_color)| {
(idx, input_color.difference(*p_color), input_color - *p_color) let c: Lab = Lab::from_color(*p_color);
(idx, input_color.difference(c), input_color - c)
}) })
.min_by(|(_, a, _), (_, b, _)| a.total_cmp(b)) .min_by(|(_, a, _), (_, b, _)| a.total_cmp(b))
.expect("Should always find a color"); .expect("Should always find a color");
@ -149,13 +150,12 @@ pub struct NearestNeighbor();
impl Ditherer for NearestNeighbor { impl Ditherer for NearestNeighbor {
fn dither(&mut self, img: &RgbImage, output: &mut DitheredImage) { fn dither(&mut self, img: &RgbImage, output: &mut DitheredImage) {
// sRGB view into the given image. zero copy! // sRGB view into the given image. zero copy!
let srgb = <&[Srgb<u8>]>::from_components(&**img); let srgb = <&[Srgb<u8>]>::from_components(&**img);
let lab_palette: Vec<Lab> = output.palette.iter().map(|c| Lab::from_color(*c)).collect();
for (idx, pix) in output.buf.iter_mut().enumerate() { for (idx, pix) in output.buf.iter_mut().enumerate() {
let (n, _) = nearest_neighbor(srgb[idx].into_format().into_color(), &lab_palette); let (n, _) = nearest_neighbor(srgb[idx].into_format().into_color(), &output.palette);
*pix = n; *pix = n;
} }
} }
@ -267,14 +267,13 @@ impl<'a> Ditherer for ErrorDiffusion<'a> {
for pix in srgb { for pix in srgb {
temp_img.push(pix.into_format().into_color()); temp_img.push(pix.into_format().into_color());
} }
let lab_palette: Vec<Lab> = output.palette.iter().map(|c| Lab::from_color(*c)).collect();
// TODO: rework this to make more sense. // TODO: rework this to make more sense.
for y in 0..ysize { for y in 0..ysize {
for x in 0..xsize { for x in 0..xsize {
let index = coord_to_idx(x, y, xsize); let index = coord_to_idx(x, y, xsize);
let curr_pix = temp_img[index]; let curr_pix = temp_img[index];
let (nearest, err) = nearest_neighbor(curr_pix, &lab_palette); let (nearest, err) = nearest_neighbor(curr_pix, &output.palette);
// set the color in the output buffer. // set the color in the output buffer.
*output *output
.buf .buf