perf: speed up blur with rayon

This commit is contained in:
Aloxaf 2021-08-26 00:40:10 +08:00
parent 4c34d4701f
commit dfd25ae02c
No known key found for this signature in database
GPG Key ID: A07920B86500DE6C
3 changed files with 30 additions and 5 deletions

3
Cargo.lock generated
View File

@ -1,5 +1,7 @@
# This file is automatically @generated by Cargo. # This file is automatically @generated by Cargo.
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3
[[package]] [[package]]
name = "ab_glyph_rasterizer" name = "ab_glyph_rasterizer"
version = "0.1.4" version = "0.1.4"
@ -1305,6 +1307,7 @@ dependencies = [
"log", "log",
"pasteboard", "pasteboard",
"pathfinder_geometry", "pathfinder_geometry",
"rayon",
"shell-words", "shell-words",
"structopt", "structopt",
"syntect", "syntect",

View File

@ -20,6 +20,7 @@ pathfinder_geometry = "0.5.1"
log = "0.4.11" log = "0.4.11"
lazy_static = "1.4.0" lazy_static = "1.4.0"
shell-words = { version = "1.0.0", optional = true } shell-words = { version = "1.0.0", optional = true }
rayon = "1.5.1"
[target.'cfg(target_os = "macos")'.dependencies] [target.'cfg(target_os = "macos")'.dependencies]
pasteboard = "0.1.3" pasteboard = "0.1.3"

View File

@ -3,9 +3,22 @@
//! This file is originally from https://github.com/fschutt/fastblur //! This file is originally from https://github.com/fschutt/fastblur
//! Edited by aloxaf <aloxafx@gmail.com> to process RgbaImage //! Edited by aloxaf <aloxafx@gmail.com> to process RgbaImage
use image::RgbaImage;
use std::cmp::min; use std::cmp::min;
use image::RgbaImage;
use rayon::prelude::*;
#[derive(Copy, Clone)]
struct SharedMutPtr<>(*mut [[u8; 4]]);
unsafe impl Sync for SharedMutPtr {}
impl SharedMutPtr {
unsafe fn get(&self) -> &mut [[u8; 4]] {
&mut *self.0
}
}
pub fn gaussian_blur(image: RgbaImage, sigma: f32) -> RgbaImage { pub fn gaussian_blur(image: RgbaImage, sigma: f32) -> RgbaImage {
let (width, height) = image.dimensions(); let (width, height) = image.dimensions();
let mut raw = image.into_raw(); let mut raw = image.into_raw();
@ -109,7 +122,8 @@ fn box_blur_vert(
) { ) {
let iarr = 1.0 / (blur_radius + blur_radius + 1) as f32; let iarr = 1.0 / (blur_radius + blur_radius + 1) as f32;
for i in 0..width { let frontbuf = SharedMutPtr(frontbuf as *mut [[u8; 4]]);
(0..width).into_par_iter().for_each(|i| {
let col_start = i; //inclusive let col_start = i; //inclusive
let col_end = i + width * (height - 1); //inclusive let col_end = i + width * (height - 1); //inclusive
let mut ti: usize = i; let mut ti: usize = i;
@ -166,6 +180,7 @@ fn box_blur_vert(
val_b += isize::from(bb[2]) - isize::from(fv[2]); val_b += isize::from(bb[2]) - isize::from(fv[2]);
val_a += isize::from(bb[3]) - isize::from(fv[3]); val_a += isize::from(bb[3]) - isize::from(fv[3]);
let frontbuf = unsafe { frontbuf.get() };
frontbuf[ti] = [ frontbuf[ti] = [
round(val_r as f32 * iarr) as u8, round(val_r as f32 * iarr) as u8,
round(val_g as f32 * iarr) as u8, round(val_g as f32 * iarr) as u8,
@ -188,6 +203,7 @@ fn box_blur_vert(
val_b += isize::from(bb1[2]) - isize::from(bb2[2]); val_b += isize::from(bb1[2]) - isize::from(bb2[2]);
val_a += isize::from(bb1[3]) - isize::from(bb2[3]); val_a += isize::from(bb1[3]) - isize::from(bb2[3]);
let frontbuf = unsafe { frontbuf.get() };
frontbuf[ti] = [ frontbuf[ti] = [
round(val_r as f32 * iarr) as u8, round(val_r as f32 * iarr) as u8,
round(val_g as f32 * iarr) as u8, round(val_g as f32 * iarr) as u8,
@ -206,6 +222,7 @@ fn box_blur_vert(
val_b += isize::from(lv[2]) - isize::from(bb[2]); val_b += isize::from(lv[2]) - isize::from(bb[2]);
val_a += isize::from(lv[3]) - isize::from(bb[3]); val_a += isize::from(lv[3]) - isize::from(bb[3]);
let frontbuf = unsafe { frontbuf.get() };
frontbuf[ti] = [ frontbuf[ti] = [
round(val_r as f32 * iarr) as u8, round(val_r as f32 * iarr) as u8,
round(val_g as f32 * iarr) as u8, round(val_g as f32 * iarr) as u8,
@ -215,7 +232,7 @@ fn box_blur_vert(
ti += width; ti += width;
} }
} }
} });
} }
#[inline] #[inline]
@ -228,7 +245,8 @@ fn box_blur_horz(
) { ) {
let iarr = 1.0 / (blur_radius + blur_radius + 1) as f32; let iarr = 1.0 / (blur_radius + blur_radius + 1) as f32;
for i in 0..height { let frontbuf = SharedMutPtr(frontbuf as *mut [[u8; 4]]);
(0..height).into_par_iter().for_each(|i| {
let row_start: usize = i * width; // inclusive let row_start: usize = i * width; // inclusive
let row_end: usize = (i + 1) * width - 1; // inclusive let row_end: usize = (i + 1) * width - 1; // inclusive
let mut ti: usize = i * width; // VERTICAL: $i; let mut ti: usize = i * width; // VERTICAL: $i;
@ -286,6 +304,7 @@ fn box_blur_horz(
val_b += isize::from(bb[2]) - isize::from(fv[2]); val_b += isize::from(bb[2]) - isize::from(fv[2]);
val_a += isize::from(bb[3]) - isize::from(fv[3]); val_a += isize::from(bb[3]) - isize::from(fv[3]);
let frontbuf = unsafe { frontbuf.get() };
frontbuf[ti] = [ frontbuf[ti] = [
round(val_r as f32 * iarr) as u8, round(val_r as f32 * iarr) as u8,
round(val_g as f32 * iarr) as u8, round(val_g as f32 * iarr) as u8,
@ -310,6 +329,7 @@ fn box_blur_horz(
val_b += isize::from(bb1[2]) - isize::from(bb2[2]); val_b += isize::from(bb1[2]) - isize::from(bb2[2]);
val_a += isize::from(bb1[3]) - isize::from(bb2[3]); val_a += isize::from(bb1[3]) - isize::from(bb2[3]);
let frontbuf = unsafe { frontbuf.get() };
frontbuf[ti] = [ frontbuf[ti] = [
round(val_r as f32 * iarr) as u8, round(val_r as f32 * iarr) as u8,
round(val_g as f32 * iarr) as u8, round(val_g as f32 * iarr) as u8,
@ -329,6 +349,7 @@ fn box_blur_horz(
val_b += isize::from(lv[2]) - isize::from(bb[2]); val_b += isize::from(lv[2]) - isize::from(bb[2]);
val_a += isize::from(lv[3]) - isize::from(bb[3]); val_a += isize::from(lv[3]) - isize::from(bb[3]);
let frontbuf = unsafe { frontbuf.get() };
frontbuf[ti] = [ frontbuf[ti] = [
round(val_r as f32 * iarr) as u8, round(val_r as f32 * iarr) as u8,
round(val_g as f32 * iarr) as u8, round(val_g as f32 * iarr) as u8,
@ -338,7 +359,7 @@ fn box_blur_horz(
ti += 1; ti += 1;
} }
} }
} });
} }
#[inline] #[inline]