Skip to content

imazen/fast-ssim2

 
 

Repository files navigation

fast-ssim2 CI crates.io lib.rs docs.rs codecov MSRV license

Fast SIMD-accelerated Rust implementation of SSIMULACRA2, a perceptual image quality metric.

Quick Start

[dependencies]
fast-ssim2 = { version = "0.8", features = ["imgref"] }
use fast_ssim2::compute_ssimulacra2;
use imgref::ImgVec;

let source: ImgVec<[u8; 3]> = /* your source image */;
let distorted: ImgVec<[u8; 3]> = /* compressed/modified version */;

let score = compute_ssimulacra2(source.as_ref(), distorted.as_ref())?;
// 100 = identical, 90+ = imperceptible, <50 = significant degradation

Score Interpretation

Score Quality
100 Identical
90+ Imperceptible difference
70-90 Minor, subtle difference
50-70 Noticeable difference
<50 Significant degradation

API Overview

Primary Functions

Function Use Case
compute_ssimulacra2 Compare two images (recommended)
Ssimulacra2Reference::new Precompute for batch comparisons (~2x faster)

Input Types

With the imgref feature:

Type Color Space
ImgRef<[u8; 3]> sRGB (8-bit)
ImgRef<[u16; 3]> sRGB (16-bit)
ImgRef<[f32; 3]> Linear RGB
ImgRef<u8>, ImgRef<f32> Grayscale

Convention: Integer types = sRGB gamma. Float types = linear RGB.

Without imgref, use yuvxyb::Rgb or yuvxyb::LinearRgb (add yuvxyb to your own dependencies), or implement ToLinearRgb for custom types.

Batch Comparisons

When comparing multiple images against the same reference (e.g., testing compression levels), precompute the reference:

use fast_ssim2::Ssimulacra2Reference;

let reference = Ssimulacra2Reference::new(source.as_ref())?;

for distorted in compressed_variants {
    let score = reference.compare(distorted.as_ref())?;
}

Features

Feature Default Description
imgref No Support for imgref image types
rayon No Parallel computation

SIMD is always available — runtime CPU detection via archmage selects the best backend automatically (AVX2+FMA on x86_64, NEON on aarch64, SIMD128 on wasm32, scalar fallback elsewhere).

Performance

Benchmarked on AMD Ryzen 9 7950X (x86_64, AVX2+FMA), full SSIMULACRA2 computation vs upstream ssimulacra2 crate:

Resolution ssimulacra2 (scalar) fast-ssim2 (SIMD) Speedup
320x240 139ms 8.7ms 16x
1920x1080 1,006ms 316ms 3.2x
3840x2160 3,615ms 1,317ms 2.7x

Run your own benchmarks:

cargo bench -p fast-ssim2

Advanced Usage

Custom Input Types

use fast_ssim2::{ToLinearRgb, LinearRgbImage, srgb_u8_to_linear};

struct MyImage { /* ... */ }

impl ToLinearRgb for MyImage {
    fn to_linear_rgb(&self) -> LinearRgbImage {
        let data: Vec<[f32; 3]> = self.pixels.iter()
            .map(|[r, g, b]| [
                srgb_u8_to_linear(*r),
                srgb_u8_to_linear(*g),
                srgb_u8_to_linear(*b),
            ])
            .collect();
        LinearRgbImage::new(data, self.width, self.height)
    }
}

Explicit SIMD Backend

use fast_ssim2::{compute_ssimulacra2_with_config, Ssimulacra2Config};

// Force scalar (for comparison/debugging)
let score = compute_ssimulacra2_with_config(source, distorted, Ssimulacra2Config::scalar())?;

// Use SIMD (default — auto-detects AVX2/NEON/WASM128)
let score = compute_ssimulacra2_with_config(source, distorted, Ssimulacra2Config::simd())?;

Using yuvxyb Types Directly

use fast_ssim2::compute_ssimulacra2;
use yuvxyb::{Rgb, TransferCharacteristic, ColorPrimaries};

let source = Rgb::new(
    pixel_data,
    width,
    height,
    TransferCharacteristic::SRGB,
    ColorPrimaries::BT709,
)?;
let score = compute_ssimulacra2(source, distorted)?;

Requirements

  • Minimum image size: 8x8 pixels
  • MSRV: 1.89.0

Attribution

Fork of rust-av/ssimulacra2. Thank you to the rust-av team for the original implementation.

What's different: Cross-platform SIMD acceleration (x86_64/aarch64/wasm32 via archmage), precomputed reference API, imgref support, #![forbid(unsafe_code)].

Image tech I maintain

State of the art codecs* zenjpeg · zenpng · zenwebp · zengif · zenavif (rav1d-safe · zenrav1e · zenavif-parse · zenavif-serialize) · zenjxl (jxl-encoder · zenjxl-decoder) · zentiff · zenbitmaps · heic · zenraw · zenpdf · ultrahdr · mozjpeg-rs · webpx
Compression zenflate · zenzop
Processing zenresize · zenfilters · zenquant · zenblend
Metrics zensim · fast-ssim2 · butteraugli · resamplescope-rs · codec-eval · codec-corpus
Pixel types & color zenpixels · zenpixels-convert · linear-srgb · garb
Pipeline zenpipe · zencodec · zencodecs · zenlayout · zennode
ImageResizer ImageResizer (C#) — 24M+ NuGet downloads across all packages
Imageflow Image optimization engine (Rust) — .NET · node · go — 9M+ NuGet downloads across all packages
Imageflow Server The fast, safe image server (Rust+C#) — 552K+ NuGet downloads, deployed by Fortune 500s and major brands

* as of 2026

General Rust awesomeness

archmage · magetypes · enough · whereat · zenbench · cargo-copter

And other projects · GitHub @imazen · GitHub @lilith · lib.rs/~lilith · NuGet (over 30 million downloads / 87 packages)

License

BSD-2-Clause (same as upstream)

Upstream Contribution

This is a fork of rust-av/ssimulacra2 (BSD-2-Clause). We are willing to release our improvements under the original BSD-2-Clause license if upstream takes over maintenance of those improvements. We'd rather contribute back than maintain a parallel codebase. Open an issue or reach out.

About

Rust implementation of the SSIMULACRA2 quality metric

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages

  • Rust 100.0%