You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

64 lines
2.2 KiB

use image::{Rgb, GenericImage};
pub const NCOLORS: usize = 3;
#[derive(Debug, Clone)]
#[repr(C)]
pub struct Transform {
pub color_matrix: [f32; NCOLORS * NCOLORS],
// TODO: make these f32s
pub from_corner: (u32, u32),
pub from_extents: (u32, u32),
pub to_corner: (f32, f32),
pub to_extents: [(f32, f32); 2],
}
impl Transform {
pub fn apply_add<I: GenericImage<Pixel=Rgb<f32>>, O: GenericImage<Pixel=Rgb<f32>>>(&self, input: &I, output: &mut O, dims: (u32, u32), c: f32) {
for x_off in 0..self.from_extents.0 {
let x = x_off as f32 / self.from_extents.0 as f32;
for y_off in 0..self.from_extents.1 {
let y = y_off as f32 / self.from_extents.1 as f32;
let x_in = (self.to_corner.0 + x * self.to_extents[0].0 + y * self.to_extents[0].1) * dims.0 as f32;
let y_in = (self.to_corner.1 + x * self.to_extents[1].0 + y * self.to_extents[1].1) * dims.1 as f32;
let in_coords = (x_in, y_in);
// Get input color from pixels near sample
let mut in_pix = [0.0; NCOLORS];
let in_coords_i32 = (in_coords.0.floor() as i32, in_coords.1.floor() as i32);
for x in in_coords_i32.0..=in_coords_i32.0 + 1 {
for y in in_coords_i32.1..=in_coords_i32.1 + 1 {
if x < 0 || y < 0 || x >= dims.0 as i32 || y >= dims.1 as i32 {
continue;
}
let val = input.get_pixel(x as u32, y as u32).0;
let frac = (x as f32 - in_coords.0, y as f32 - in_coords.1);
let area = (1.0 - frac.0.abs()) * (1.0 - frac.1.abs());
for i in 0..NCOLORS {
in_pix[i] += val[i] * area;
}
}
}
// Compute the transformed color
let mut color = [0.0; NCOLORS];
for i in 0..NCOLORS {
for j in 0..NCOLORS {
color[i] += self.color_matrix[i * NCOLORS + j] * in_pix[j];
}
}
// Put the resulting color into the output image
let x_out = self.from_corner.0 + x_off;
let y_out = self.from_corner.1 + y_off;
let mut pix = output.get_pixel(x_out, y_out).0;
for i in 0..NCOLORS {
pix[i] += color[i] * c;
}
output.put_pixel(x_out, y_out, Rgb(pix));
}
}
}
}