Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- pub fn jfa_preprocess(target: &mut Rgba32FImage) {
- let (width, height) = target.dimensions();
- target.par_enumerate_pixels_mut().for_each(|(x, y, pixel)| {
- let uv = Vec2::new(x as f32 / width as f32, y as f32 / height as f32);
- pixel[2] = 0.;
- pixel[3] = 0.;
- if pixel[3] > 0.5 {
- // Inside
- pixel[0] = uv.x;
- pixel[1] = uv.y;
- pixel[3] = 1.;
- } else {
- // Outside
- pixel[0] = -uv.x;
- pixel[1] = -uv.y;
- pixel[3] = 1.;
- }
- });
- }
- pub fn jfa(src: &Rgba32FImage, dest: &mut Rgba32FImage, iteration: u32, width: u32, height: u32) {
- let step = (width.max(height) >> (iteration + 1)).max(1);
- let tex_fsize = Vec2::new(width as f32, height as f32);
- let tex_isize = IVec2::new(width as i32, height as i32);
- dest.par_enumerate_pixels_mut().for_each(|(x, y, pixel)| {
- let px = IVec2::new(x as i32, y as i32);
- let mut best_distance_sqr = f32::INFINITY;
- let mut best_uv = Vec2::ZERO;
- let is_inside = src.get_pixel(px.x as u32, px.y as u32)[0] > 0.;
- for mut dx in -1..=1 {
- dx *= step as i32;
- for mut dy in -1..=1 {
- dy *= step as i32;
- let neighbor_px = px + IVec2::new(dx, dy);
- if neighbor_px.x < 0
- || neighbor_px.x >= tex_isize.x
- || neighbor_px.y < 0
- || neighbor_px.y >= tex_isize.y
- {
- continue;
- }
- let neighbor_saved_px = src.get_pixel(neighbor_px.x as u32, neighbor_px.y as u32);
- if neighbor_saved_px[3] < 0.5 {
- continue;
- }
- let mut neighbor_saved_px =
- Vec2::new(neighbor_saved_px[0], neighbor_saved_px[1]) * tex_fsize;
- if !is_inside {
- neighbor_saved_px = -neighbor_saved_px;
- }
- let distance = neighbor_saved_px.distance_squared(px.as_vec2());
- if distance < best_distance_sqr {
- best_distance_sqr = distance;
- best_uv = neighbor_saved_px / tex_fsize;
- }
- }
- }
- if is_inside {
- pixel[0] = best_uv.x;
- pixel[1] = best_uv.y;
- } else {
- pixel[0] = -best_uv.x;
- pixel[1] = -best_uv.y;
- }
- });
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement