awxkee
libblur
Rust

High performance blur in pure Rust

Last updated Jun 18, 2026
86
Stars
6
Forks
0
Issues
0
Stars/day
Attention Score
36
Language breakdown
No language data available.
โ–ธ Files click to expand
README

Fast blur algorithms library for Rust

There are some very good and blazing fast algorithms that do blurring images. Also providing convenient api for doing convolution and some edge detection filters.\ Best optimized for NEON, SSE and AVX, SVE, partially done WASM.

You may receive Gaussian blur in 100 FPS for 4K photo.

Much faster than image default blur.

When 4-channels mode is in use that always considered that alpha channel is the last.

Also there are some available options to perform blurring in linear colorspace, or if methods do not fit you f32 options also available

Performance

Most blur algorithms done very good and works at excellent speed. Where appropriate comparison with OpenCV is available.

Usage

cargo add libblur

Usage with image feature

let blurred = gaussianblurimage(
    img,
    GaussianBlurParams::newfromkernel(61.),
    EdgeMode2D::new(EdgeMode::Clamp),
    ConvolutionMode::FixedPoint,
    ThreadingPolicy::Adaptive,
)
.unwrap();

blurred .savewithformat("blurred.jpg", ImageFormat::Jpeg) .unwrap();

Transfer function

All blur methods assume that data is already linearized. If additional linearization is needed use API:

let cvt = BlurImage::borrow(
    &v_vec,
    dyn_image.width(),
    dyn_image.height(),
    FastBlurChannels::Channels4,
);
let image = cvt
    .linearize(libblur::TransferFunction::Srgb, true)
    .unwrap();
// perform blur
let dstref = dstimage.toimmutableref();
let backingamma = dst_ref.gamma8(libblur::TransferFunction::Srgb, true);

Gaussian blur

Excellent results. Have significant improvements, however, much slower than any approximations. Use when use need gaussian methods - smoothing, FFT, advanced analysis etc. There are two methods of convolution, fixed point approximation and exact, approximation in fixed point adds 1-3% of error. However, it is about two times faster.

Kernel size must be odd. Will panic if kernel size is not odd.

O(R) complexity.

libblur::gaussianblur( & bytes, srcstride, & mut dstbytes, dststride, width, height, kernel_size, sigma, FastBlurChannels::Channels3, GaussianPreciseLevel::EXACT);

Example comparison time for blurring image 3000x4000 RGB 8-bit in multithreaded mode with 151 kernel size.

| | Time(NEON) | Time(AVX) | |---------------------|:----------:|:---------:| | libblur(Exact) | 49.40ms | 43.41ms | | libblur(FixedPoint) | 26.68ms | 30.72ms | | OpenCV | 180.56ms | 182.44ms |

Example comparison time for blurring image 2828x4242 RGBA 8-bit in multithreaded mode with 151 kernel size.

| | time(NEON) | Time(AVX) | |---------------------|:----------:|:---------:| | libblur(Exact) | 65.13ms | 51.40ms | | libblur(FixedPoint) | 33.99ms | 38.91ms | | OpenCV | 134.60ms | 185.30ms |

Example comparison time for blurring image 3000x4000 single plane 8-bit in multithreaded mode with 151 kernel size.

| | time(NEON) | Time(SSE/AVX) | |---------------------|:----------:|:-------------:| | libblur(Exact) | 17.59ms | 15.51ms | | libblur(FixedPoint) | 8.50ms | 11.45ms | | OpenCV | 74.73ms | 64.20ms |

Stack blur

The fastest with acceptable results. Result are quite close to gaussian and look good. Sometimes noticeable changes may be observed. However, if you'll use advanced analysis algorithms non gaussian methods will be detected. Not suitable for advanced analysis. Results just a little worse than in 'fast gaussian', however it's faster.

O(1) complexity.

let mut dstimage = BlurImageMut::borrow(&mut srcbytes, dynimage.width(), dynimage.height(), FastBlurChannels::Channels3)
libblur::stackblur( &mut dstimage, 10, ThreadingPolicy::Single).unwrap();

Example comparison time for blurring image 3000x4000 RGB 8-bit in multithreaded mode with 77 radius.

| | time(NEON) | time(SSE) | |---------|:----------:|:---------:| | libblur | 4.95ms | 5.30ms | | OpenCV | 8.43ms | 10.36ms |

Example comparison time for blurring image 2828x4242 RGBA 8-bit in multithreaded mode with 77 radius.

| | time(NEON) | time(SSE) | |---------|:----------:|:---------:| | libblur | 4.97ms | 5.48ms | | OpenCV | 8.00ms | 8.55ms |

Fast gaussian

Very fast. Result are quite close to gaussian and look good. Sometimes noticeable changes may be observed. However, if you'll use advanced analysis algorithms non gaussian methods will be detected. Not suitable for advanced analysis. Do not use when you need gaussian. Based on binomial filter, generally speed close, might be a little faster than stack blur , however results are better.

O(log R) complexity.

let mut dstimage = BlurImageMut::borrow(&mut srcbytes, dynimage.width(), dynimage.height(), FastBlurChannels::Channels3)
libblur::fastgaussian(&mut dstimage, 10, ThreadingPolicy::Single, EdgeMode::Wrap).unwrap();

Example comparison time for blurring image 3000x4000 RGB 8-bit in multithreaded mode with 77 radius.

| | time(NEON) | time(SSE) | |---------|:----------:|:---------:| | libblur | 5.72ms | 6.42ms | | OpenCV | - | - |

Example comparison time for blurring image 2828x4242 RGBA 8-bit in multithreaded mode with 77 radius.

| | time(NEON) | time(SSE) | |---------|:----------:|:---------:| | libblur | 5.49ms | 5.77ms | | OpenCV | -- | -- |

Fast gaussian next

Very fast. Produces very pleasant results close to gaussian. Max radius ~150-180 for u8, for u16 will be less.

O(log R) complexity.

let mut dstimage = BlurImageMut::borrow(&mut srcbytes, dynimage.width(), dynimage.height(), FastBlurChannels::Channels3)
libblur::fastgaussiannext(&mut dst_image, 10, ThreadingPolicy::Single, EdgeMode::Wrap).unwrap();

Example comparison time for blurring image 2828x4242 RGBA 8-bit in multithreaded mode with 35 radius.

| | time(NEON) | time(SSE) | |---------|:----------:|:---------:| | libblur | 4.07ms | 6.08ms | | OpenCV | - | - |

Example comparison time for blurring image 3000x4000 RGB 8-bit in multithreaded mode with 77 radius.

| | time(NEON) | time(SSE) | |---------|:----------:|:---------:| | libblur | 4.71ms | 6.15ms | | OpenCV | - | - |

Tent blur

2 sequential box blur ( theory ) that produces a tent filter. Medium speed, good-looking results with large radius tents becoming more noticeable

O(1) complexity.

let image = BlurImage::borrow(
    &src_bytes,
    dyn_image.width(),
    dyn_image.height(),
    FastBlurChannels::Channels3,
);
let mut dst_image = BlurImageMut::default();
libblur::tentblur(&image, &mut dstimage,10f32, ThreadingPolicy::Single).unwrap();

Median blur

Median blur ( median filter ). Implementation is fast enough.

O(log R) complexity.

let image = BlurImage::borrow(
    &src_bytes,
    dyn_image.width(),
    dyn_image.height(),
    FastBlurChannels::Channels3,
);
let mut dst_image = BlurImageMut::default();
libblur::medianblur(&image, &mut dstimage,10, ThreadingPolicy::Single).unwrap();

Example comparison time for blurring image 3000x4000 RGB 8-bit in multithreaded mode with 35 radius.

| | time(NEON) | time(SSE) | |---------|:----------:|:---------:| | libblur | 603.51ms | 872.03ms | | OpenCV | 637.83ms | 959.07ms |

Example comparison time for blurring image 2828x4242 RGBA 8-bit in multithreaded mode with 35 radius.

| | time(NEON) | time(SSE) | |---------|:----------:|:---------:| | libblur | 643.22ms | 695.75ms | | OpenCV | 664.22ms | 808.21ms |

Gaussian box blur

Generally 3 sequential box blurs it is almost gaussian blur ( theory ), slow, really pleasant results. Medium speed.

O(1) complexity.

let image = BlurImage::borrow(
    &src_bytes,
    dyn_image.width(),
    dyn_image.height(),
    FastBlurChannels::Channels3,
);
let mut dst_image = BlurImageMut::default();
libblur::gaussianboxblur(&image, &mut dst_image, 10f32, ThreadingPolicy::Single).unwrap();

Box blur

Box blur. Compromise speed with bad looking results. Medium speed.

O(1) complexity.

let image = BlurImage::borrow(
    &src_bytes,
    dyn_image.width(),
    dyn_image.height(),
    FastBlurChannels::Channels3,
);
let mut dst_image = BlurImageMut::default();
libblur::boxblur(&image, &mut dstimage,10, ThreadingPolicy::Single).unwrap();

Example comparison time for blurring image 3000x4000 RGB 8-bit in multithreaded mode with 77 radius.

| | time(NEON) | time(SSE) | |---------|:----------:|:---------:| | libblur | 3.71ms | 6.08ms | | OpenCV | 15.73ms | 43.59ms |

Example comparison time for blurring image 2828x4242 RGBA 8-bit in multithreaded mode with 77 radius.

| | Time(NEON) | Time(SSE) | |---------|:----------:|:---------:| | libblur | 3.56ms | 6.16ms | | OpenCV | 15.77ms | 31.29ms |

Example comparison time for blurring image 2828x4242 RGBA 8-bit in single-thread mode with 15 radius on MacOS.

| | Time(NEON) | |------------------|:----------:| | libblur | 11.46ms | | Apple Accelerate | 11.65ms |

Fast bilateral blur

This is fast bilateral approximation, note this behaviour significantly differs from OpenCV. This method has high convergence and will completely blur an image very fast with increasing spatial sigma. By the nature of this filter the more spatial sigma are the faster method is.

let image = BlurImage::borrow(
    &src_bytes,
    dyn_image.width(),
    dyn_image.height(),
    FastBlurChannels::Channels3,
);
let mut dst_image = BlurImageMut::default();
libblur::fastbilateralfilter(&image, &mut dst_image, 25, 7f32, 7f32).unwrap();

Speed overview

The following shows the approximate relative speed of all methods in descending order:

boxblur โ†’ stackblur โ†’ fastgaussiannext โ†’ fastgaussian โ†’ fastgaussiansuperior โ†’ tentblur โ†’ gaussianboxblur โ†’ gaussian_blur โ†’ bilateral โ†’ median

This project is licensed under either of

  • BSD-3-Clause License (see LICENSE)
  • Apache License, Version 2.0 (see LICENSE)
at your option.
๐Ÿ”— More in this category

ยฉ 2026 GitRepoTrend ยท awxkee/libblur ยท Updated daily from GitHub