some optimisations
This commit is contained in:
parent
7234064f12
commit
5450144797
3 changed files with 95 additions and 66 deletions
|
@ -7,20 +7,29 @@ pub fn mat_editor<const R: usize, const C: usize>(
|
|||
id: &str,
|
||||
skip_last: bool,
|
||||
) -> egui::Response {
|
||||
egui::Grid::new(id)
|
||||
let mut any_change = false;
|
||||
let mut r = egui::Grid::new(id)
|
||||
.show(ui, |ui| {
|
||||
mat.row_iter_mut().enumerate().for_each(|(i, mut row)| {
|
||||
if !skip_last || i + 1 < R {
|
||||
row.iter_mut().for_each(|item| {
|
||||
ui.add(
|
||||
egui::DragValue::new(item)
|
||||
.speed(0.01)
|
||||
.clamp_range(-10.0..=10.0),
|
||||
);
|
||||
any_change |= ui
|
||||
.add(
|
||||
egui::DragValue::new(item)
|
||||
.speed(0.01)
|
||||
.clamp_range(-10.0..=10.0),
|
||||
)
|
||||
.changed();
|
||||
});
|
||||
ui.end_row();
|
||||
}
|
||||
})
|
||||
})
|
||||
.response
|
||||
.response;
|
||||
|
||||
if any_change {
|
||||
r.mark_changed()
|
||||
}
|
||||
|
||||
r
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ use std::{
|
|||
|
||||
use eframe::egui::{self, TextureOptions};
|
||||
use image::{DynamicImage, Pixel, Rgb, Rgb32FImage};
|
||||
use nalgebra::{SMatrix, Vector3, Vector4};
|
||||
use nalgebra::{ComplexField, Const, Matrix, OMatrix, SMatrix, Vector3, Vector4};
|
||||
use rayon::prelude::*;
|
||||
|
||||
use image::EncodableLayout;
|
||||
|
@ -16,6 +16,7 @@ struct ProcessorInstruction {
|
|||
ret: oneshot::Sender<(egui::TextureHandle, (f32, f32))>,
|
||||
ctx: egui::Context,
|
||||
handle: Option<egui::TextureHandle>,
|
||||
realloc: bool,
|
||||
}
|
||||
|
||||
pub struct Processor {
|
||||
|
@ -26,6 +27,7 @@ impl Processor {
|
|||
pub fn init() -> Self {
|
||||
let (tx, rx) = mpsc::channel();
|
||||
thread::spawn(|| {
|
||||
let mut working_img = DynamicImage::new_rgb32f(1, 1);
|
||||
for ProcessorInstruction {
|
||||
img,
|
||||
color_matrix,
|
||||
|
@ -33,51 +35,81 @@ impl Processor {
|
|||
ret,
|
||||
ctx,
|
||||
handle,
|
||||
realloc,
|
||||
} in rx
|
||||
{
|
||||
let (width, height) = img.dimensions();
|
||||
|
||||
// let mut r = (*img).clone();
|
||||
let mut r = Rgb32FImage::new(width, height);
|
||||
if !pos_matrix.is_identity(f32::EPSILON) && pos_matrix.is_invertible() {
|
||||
let mut inv_mat = pos_matrix.try_inverse().unwrap();
|
||||
let mut cols_mut = inv_mat.column_part_mut(2, 2);
|
||||
if realloc {
|
||||
working_img = DynamicImage::new_rgb32f(width, height);
|
||||
}
|
||||
|
||||
let do_pos_trans =
|
||||
!pos_matrix.is_identity(f32::EPSILON) && pos_matrix.is_invertible();
|
||||
let do_color_trans = !color_matrix.is_identity(f32::EPSILON);
|
||||
|
||||
let mut inv_pos_mat = OMatrix::<f32, Const<3>, Const<3>>::identity();
|
||||
if do_pos_trans {
|
||||
inv_pos_mat = pos_matrix.try_inverse().unwrap();
|
||||
let mut cols_mut = inv_pos_mat.column_part_mut(2, 2);
|
||||
*(cols_mut.get_mut(0).unwrap()) *= width as f32;
|
||||
*(cols_mut.get_mut(1).unwrap()) *= height as f32;
|
||||
|
||||
r.par_enumerate_pixels_mut().for_each(|(x, y, px)| {
|
||||
let r = inv_mat * Vector3::new(x as f32, y as f32, 1.0);
|
||||
*px = if r.x.is_sign_positive() && r.y.is_sign_positive() {
|
||||
*img.get_pixel_checked(r.x as u32, r.y as u32)
|
||||
.unwrap_or(&Rgb([0., 0., 0.]))
|
||||
} else {
|
||||
Rgb([0., 0., 0.])
|
||||
};
|
||||
});
|
||||
} else {
|
||||
r = (*img).clone()
|
||||
}
|
||||
|
||||
if !color_matrix.is_identity(f32::EPSILON) {
|
||||
r.par_pixels_mut().for_each(|px| {
|
||||
*px = Rgb::from(
|
||||
TryInto::<[f32; 3]>::try_into(
|
||||
(color_matrix * Vector4::new(px.0[0], px.0[1], px.0[2], 1.))
|
||||
.as_slice(),
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
});
|
||||
{
|
||||
let working_img = working_img.as_mut_rgb32f().unwrap();
|
||||
match (do_pos_trans, do_color_trans) {
|
||||
(true, true) => {
|
||||
working_img
|
||||
.par_enumerate_pixels_mut()
|
||||
.for_each(|(x, y, px)| {
|
||||
let org_pos =
|
||||
inv_pos_mat * Vector3::new(x as f32, y as f32, 1.0);
|
||||
|
||||
let Rgb([r, g, b]) = *img
|
||||
.get_pixel_checked(
|
||||
org_pos.x.abs() as u32 % width,
|
||||
org_pos.y.abs() as u32 % height,
|
||||
)
|
||||
.unwrap_or(&Rgb([0., 0., 0.]));
|
||||
*px = Rgb::from(Into::<[f32; 3]>::into(
|
||||
color_matrix * Vector4::new(r, g, b, 1.0),
|
||||
));
|
||||
})
|
||||
}
|
||||
(true, false) => {
|
||||
working_img
|
||||
.par_enumerate_pixels_mut()
|
||||
.for_each(|(x, y, px)| {
|
||||
let r = inv_pos_mat * Vector3::new(x as f32, y as f32, 1.0);
|
||||
*px = *img
|
||||
.get_pixel_checked(
|
||||
r.x.abs() as u32 % width,
|
||||
r.y.abs() as u32 % height,
|
||||
)
|
||||
.unwrap_or(&Rgb([0., 0., 0.]))
|
||||
});
|
||||
}
|
||||
(false, true) => {
|
||||
working_img
|
||||
.par_enumerate_pixels_mut()
|
||||
.for_each(|(x, y, px)| {
|
||||
let Rgb([r, g, b]) = *img.get_pixel(x, y);
|
||||
*px = Rgb::from(Into::<[f32; 3]>::into(
|
||||
color_matrix * Vector4::new(r, g, b, 1.0),
|
||||
));
|
||||
});
|
||||
}
|
||||
(false, false) => {
|
||||
*working_img = (*img).clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let color_image = {
|
||||
let image = DynamicImage::from(r).to_rgb8();
|
||||
|
||||
egui::ColorImage::from_rgb(
|
||||
[image.width() as usize, image.height() as usize],
|
||||
image.as_bytes(),
|
||||
)
|
||||
};
|
||||
let color_image = egui::ColorImage::from_rgb(
|
||||
[working_img.width() as usize, working_img.height() as usize],
|
||||
working_img.to_rgb8().as_bytes(),
|
||||
);
|
||||
let handle = if let Some(mut handle) = handle {
|
||||
handle.set(color_image, TextureOptions::default());
|
||||
handle
|
||||
|
@ -99,6 +131,7 @@ impl Processor {
|
|||
pos_matrix: SMatrix<f32, 3, 3>,
|
||||
ctx: egui::Context,
|
||||
handle: Option<egui::TextureHandle>,
|
||||
realloc: bool,
|
||||
) -> oneshot::Receiver<(egui::TextureHandle, (f32, f32))> {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
|
@ -109,6 +142,7 @@ impl Processor {
|
|||
ret: tx,
|
||||
ctx,
|
||||
handle,
|
||||
realloc,
|
||||
});
|
||||
dbg!(r).unwrap();
|
||||
|
||||
|
|
32
src/lib.rs
32
src/lib.rs
|
@ -64,36 +64,33 @@ impl eframe::App for App {
|
|||
self.pos_matrix,
|
||||
ctx.clone(),
|
||||
self.cur_res.clone(),
|
||||
true,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ui.add_space(8.);
|
||||
let old_color_mat = self.color_matrix;
|
||||
let old_pos_mat = self.pos_matrix;
|
||||
ui.label("Color Matrix Editor");
|
||||
let color_mat_edited =
|
||||
components::mat_editor(ui, &mut self.color_matrix, "color_matrix", false).dragged();
|
||||
components::mat_editor(ui, &mut self.color_matrix, "color_matrix", false).changed();
|
||||
ui.add_space(8.);
|
||||
ui.label("Position Matrix Editor");
|
||||
let pos_mat_edited =
|
||||
components::mat_editor(ui, &mut self.pos_matrix, "pos_matrix", true).dragged();
|
||||
mats_changed |= old_color_mat == self.color_matrix || old_pos_mat == self.pos_matrix;
|
||||
components::mat_editor(ui, &mut self.pos_matrix, "pos_matrix", true).changed();
|
||||
|
||||
if mats_changed
|
||||
&& self.cur_img.is_some()
|
||||
&& self.cur_res.is_some()
|
||||
&& !color_mat_edited
|
||||
&& !pos_mat_edited
|
||||
&& self.cur_rx.is_none()
|
||||
if dbg!(self.cur_img.is_some())
|
||||
&& dbg!((color_mat_edited || pos_mat_edited))
|
||||
&& dbg!(self.cur_res.is_some())
|
||||
&& dbg!(self.cur_rx.is_none())
|
||||
{
|
||||
self.cur_rx = Some(self.proc.exec(
|
||||
self.cur_img.clone().unwrap(),
|
||||
self.color_matrix,
|
||||
dbg!(self.color_matrix),
|
||||
self.pos_matrix,
|
||||
ctx.clone(),
|
||||
self.cur_res.clone(),
|
||||
false,
|
||||
));
|
||||
}
|
||||
});
|
||||
|
@ -119,17 +116,6 @@ impl eframe::App for App {
|
|||
let img = egui::Image::from_texture(sized_img);
|
||||
ui.add(img);
|
||||
}
|
||||
// if let Some(dimensions) = self.cur_img_size {
|
||||
// egui::Frame::canvas(ui.style()).show(ui, |ui| {
|
||||
// let (rect, response) = ui.allocate_exact_size(dimensions, egui::Sense::drag());
|
||||
|
||||
// let callback = egui_wgpu::Callback::new_paint_callback(
|
||||
// rect,
|
||||
// CustomTriangleCallback { angle: 0.5 },
|
||||
// );
|
||||
// ui.painter().add(callback);
|
||||
// });
|
||||
// }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue