Skip to content

Commit a4e2851

Browse files
committed
perf: process whole pixels in parallel
1 parent 5383bf5 commit a4e2851

File tree

1 file changed

+20
-6
lines changed

1 file changed

+20
-6
lines changed

src/main.rs

+20-6
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@ use anyhow::Result;
33
use clap::Parser;
44
use image::{
55
imageops::{resize, FilterType},
6-
ImageBuffer, Pixel, Rgb, Rgba,
6+
ImageBuffer, Rgb, Rgba,
77
};
88
use kmeans_colors::get_kmeans;
99
use palette::{cast::ComponentsAs, FromColor, Srgb, Srgba};
10-
use rayon::iter::{ParallelIterator, IntoParallelRefIterator};
10+
use rayon::{
11+
iter::{IntoParallelRefIterator, ParallelIterator},
12+
};
13+
use rayon::slice::ParallelSliceMut;
1114
use tracing::info;
1215
use tracing_subscriber::FmtSubscriber;
1316

@@ -123,14 +126,25 @@ fn find_palette(image: &Image, num_colors: usize, transparent: bool) -> Result<V
123126
///
124127
/// If the palette is empty, all pixel colors will become black (`Rgb([0, 0, 0])`).
125128
fn reduce_colors(image: &mut Image, palette: &[Rgb<u8>]) {
126-
image.enumerate_pixels_mut().for_each(|(_, _, pixel)| {
129+
// Obtain a mutable reference to the underlying raw pixel buffer. Each pixel consists of 4 u8 channels (RGBA)
130+
let raw_pixels = image.as_mut();
131+
132+
raw_pixels.par_chunks_mut(4).for_each(|p| {
133+
// Interpret the first three bytes as the RGB values.
134+
let pixel_rgb = Rgb([p[0], p[1], p[2]]);
135+
136+
// Iterate sequentially over the small palette to compute the closest color.
127137
let closest_color = palette
128-
.par_iter()
138+
.iter()
139+
.min_by_key(|&color| compute_squared_distance(&pixel_rgb, color))
129140
.copied()
130-
.min_by_key(|&color| compute_squared_distance(&color, &pixel.to_rgb()))
131141
.unwrap_or(Rgb([0, 0, 0]));
132142

133-
*pixel = Rgba([closest_color[0], closest_color[1], closest_color[2], pixel[3]]);
143+
// Update the pixel with the closest color, leaving the alpha channel unchanged.
144+
p[0] = closest_color[0];
145+
p[1] = closest_color[1];
146+
p[2] = closest_color[2];
147+
// p[3] (alpha) remains unchanged
134148
});
135149
}
136150

0 commit comments

Comments
 (0)