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

  1. use image::{Rgb, GenericImage};
  2. pub const NCOLORS: usize = 3;
  3. #[derive(Debug, Clone)]
  4. #[repr(C)]
  5. pub struct Transform {
  6. pub color_matrix: [f32; NCOLORS * NCOLORS],
  7. // TODO: make these f32s
  8. pub from_corner: (u32, u32),
  9. pub from_extents: (u32, u32),
  10. pub to_corner: (f32, f32),
  11. pub to_extents: [(f32, f32); 2],
  12. }
  13. impl Transform {
  14. 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) {
  15. for x_off in 0..self.from_extents.0 {
  16. let x = x_off as f32 / self.from_extents.0 as f32;
  17. for y_off in 0..self.from_extents.1 {
  18. let y = y_off as f32 / self.from_extents.1 as f32;
  19. let x_in = (self.to_corner.0 + x * self.to_extents[0].0 + y * self.to_extents[0].1) * dims.0 as f32;
  20. let y_in = (self.to_corner.1 + x * self.to_extents[1].0 + y * self.to_extents[1].1) * dims.1 as f32;
  21. let in_coords = (x_in, y_in);
  22. // Get input color from pixels near sample
  23. let mut in_pix = [0.0; NCOLORS];
  24. let in_coords_i32 = (in_coords.0.floor() as i32, in_coords.1.floor() as i32);
  25. for x in in_coords_i32.0..=in_coords_i32.0 + 1 {
  26. for y in in_coords_i32.1..=in_coords_i32.1 + 1 {
  27. if x < 0 || y < 0 || x >= dims.0 as i32 || y >= dims.1 as i32 {
  28. continue;
  29. }
  30. let val = input.get_pixel(x as u32, y as u32).0;
  31. let frac = (x as f32 - in_coords.0, y as f32 - in_coords.1);
  32. let area = (1.0 - frac.0.abs()) * (1.0 - frac.1.abs());
  33. for i in 0..NCOLORS {
  34. in_pix[i] += val[i] * area;
  35. }
  36. }
  37. }
  38. // Compute the transformed color
  39. let mut color = [0.0; NCOLORS];
  40. for i in 0..NCOLORS {
  41. for j in 0..NCOLORS {
  42. color[i] += self.color_matrix[i * NCOLORS + j] * in_pix[j];
  43. }
  44. }
  45. // Put the resulting color into the output image
  46. let x_out = self.from_corner.0 + x_off;
  47. let y_out = self.from_corner.1 + y_off;
  48. let mut pix = output.get_pixel(x_out, y_out).0;
  49. for i in 0..NCOLORS {
  50. pix[i] += color[i] * c;
  51. }
  52. output.put_pixel(x_out, y_out, Rgb(pix));
  53. }
  54. }
  55. }
  56. }