use rayon::prelude::*;
use image::RgbImage;
#[inline]
fn lerp(pct: f32, a: f32, b: f32) -> f32 {
pct.mul_add(b - a, a)
}
#[inline]
fn distance(x: i32, y: i32) -> f32 {
((x * x + y * y) as f32).sqrt()
}
struct ColorCalculator {
from: [f32; 3],
to: [f32; 3],
center_x: i32,
center_y: i32,
max_dist: f32,
}
impl ColorCalculator {
fn new(from: [u8; 3], to: [u8; 3], width: u32, height: u32) -> Self {
let center_x = width as i32 / 2;
let center_y = height as i32 / 2;
Self {
from: from.map(|channel| channel as f32),
to: to.map(|channel| channel as f32),
center_x,
center_y,
max_dist: distance(center_x, center_y),
}
}
fn calculate(&self, x: u32, y: u32) -> [u8; 3] {
let x_dist = self.center_x - x as i32;
let y_dist = self.center_y - y as i32;
let t = distance(x_dist, y_dist) / self.max_dist;
}
}
pub fn radial_gradient_mirror(
geometry: [u32; 2],
inner_color: [u8; 3],
outer_color: [u8; 3],
) -> RgbImage {
let [width, height] = geometry;
let color_calculator = ColorCalculator::new(inner_color, outer_color, geometry[0], geometry[1]);
let mut buf: Vec<_> = (0..(height / 2))
.into_par_iter()
.flat_map(|y| {
let mut row: Vec<[u8; 3]> = Vec::with_capacity(width as usize);
for x in 0..(width / 2) {
row.push(color_calculator.calculate(x, y))
}
row.extend(row.clone().iter().rev());
row
})
.collect();
buf.extend(buf.clone().iter().rev());
let buf = buf.into_iter().flatten().collect();
RgbImage::from_raw(width, height, buf).unwrap()
}
I have an algorithm to generate a radial gradient. The original version would calculate the color of each pixel but because there is a horizontal and vertical line of symmetry I can calculate the colors for the top left corner and use some vector manipulation to mirror. I managed to do this by cloning and reversing the iterator buf.clone().iter().rev() although this is slow. How can I avoid this and are there any other optimizations I could use?