Skip to main content

Crate dithr

Crate dithr 

Source
Expand description

Buffer-first rust dithering and halftoning library.

Quantizing grayscale/RGB/RGBA buffers without dithering creates visible banding and contouring. dithr provides deterministic ordered dithering, diffusion, stochastic binary methods, palette-constrained workflows, and advanced halftoning methods over typed mutable slices.

§Overview

  • Buffer-first API: Operates on mutable pixel slices with explicit width/height/stride.
  • Typed sample support: u8, u16, and f32.
  • Typed layout support: Gray, Rgb, and Rgba.
  • Shared quantization model: QuantizeMode is used across families.
  • Algorithm coverage: Stochastic, ordered, palette-oriented ordered, diffusion, variable diffusion, and advanced halftoning.
  • Optional integrations: image adapters and rayon parallel wrappers.

§Quick Start

use dithr::{gray_u8, QuantizeMode, Result};
use dithr::ordered::bayer_8x8_in_place;

fn main() -> Result<()> {
    let width = 64_usize;
    let height = 64_usize;
    let mut data = Vec::with_capacity(width * height);

    for y in 0..height {
        for x in 0..width {
            let value = ((x + y * width) * 255 / (width * height - 1)) as u8;
            data.push(value);
        }
    }

    let mut buffer = gray_u8(&mut data, width, height, width)?;
    bayer_8x8_in_place(&mut buffer, QuantizeMode::gray_bits(1)?)?;

    assert!(data.iter().all(|&v| v == 0 || v == 255));
    Ok(())
}

§Core Types and Buffer Model

Buffer and format types:

Generic and typed buffer aliases:

Constructors:

Runtime kinds covered by BufferKind:

  • Gray8, Rgb8, Rgba8
  • Gray16, Rgb16, Rgba16
  • Gray32F, Rgb32F, Rgba32F

§Quantization API

Quantization mode enum:

Quantization constructors/helpers:

Quantization functions:

Error alias:

§Palette and Indexed Output API

Palette types:

Indexed image types:

Built-in palette helpers:

§Algorithm Families

Binary stochastic:

  • [threshold_binary_in_place]
  • [random_binary_in_place]

Ordered:

  • Bayer: [bayer_2x2_in_place], [bayer_4x4_in_place], [bayer_8x8_in_place], [bayer_16x16_in_place]
  • Cluster-dot: [cluster_dot_4x4_in_place], [cluster_dot_8x8_in_place]
  • Custom map: [custom_ordered_in_place]
  • Void-and-cluster: ordered::void_and_cluster_in_place
  • Adaptive ordered: ordered::adaptive_ordered_dither_in_place
  • Space-filling curve ordered: ordered::space_filling_curve_ordered_dither_in_place
  • Ranked dither: ordered::ranked_dither_in_place
  • Image-based dither screens: ordered::image_based_dither_screen_in_place
  • Polyomino ordered: ordered::polyomino_ordered_dither_in_place
  • Stochastic clustered-dot: ordered::stochastic_clustered_dot_in_place
  • AM/FM hybrid halftoning: ordered::am_fm_hybrid_halftoning_in_place
  • Clustered AM/FM halftoning: ordered::clustered_am_fm_halftoning_in_place
  • Blue-noise multitone dithering: ordered::blue_noise_multitone_dither_in_place

Palette-oriented ordered (Yliluoma):

  • [yliluoma_1_in_place]
  • [yliluoma_2_in_place]
  • [yliluoma_3_in_place]

Diffusion (classic):

  • [floyd_steinberg_in_place]
  • [false_floyd_steinberg_in_place]
  • [jarvis_judice_ninke_in_place]
  • [stucki_in_place]
  • [burkes_in_place]
  • [sierra_in_place]
  • [two_row_sierra_in_place]
  • [sierra_lite_in_place]
  • [stevenson_arce_in_place]
  • [atkinson_in_place]

Diffusion (extended):

  • [fan_in_place]
  • [shiau_fan_in_place]
  • [shiau_fan_2_in_place]

Diffusion (block):

  • diffusion::block_error_diffusion_in_place

Variable diffusion:

  • [ostromoukhov_in_place]
  • [zhou_fang_in_place]
  • [hvs_optimized_error_diffusion_in_place]
  • [gradient_based_error_diffusion_in_place]
  • [multiscale_error_diffusion_in_place]
  • [feature_preserving_msed_in_place]
  • [green_noise_msed_in_place]
  • [linear_pixel_shuffling_in_place]
  • [tone_dependent_error_diffusion_in_place]
  • [structure_aware_error_diffusion_in_place]
  • [adaptive_vector_error_diffusion_in_place]
  • [vector_error_diffusion_in_place]
  • [semivector_error_diffusion_in_place]
  • [hierarchical_error_diffusion_in_place]
  • diffusion::mbvq_color_error_diffusion_in_place
  • diffusion::neugebauer_color_error_diffusion_in_place
  • diffusion::multichannel_green_noise_error_diffusion_in_place

Advanced halftoning:

  • [riemersma_in_place]
  • [knuth_dot_diffusion_in_place]
  • [optimized_dot_diffusion_in_place]
  • [direct_binary_search_in_place]
  • dbs::clustered_dot_direct_multibit_search_in_place
  • dbs::direct_pattern_control_in_place
  • dbs::hierarchical_colorant_dbs_in_place
  • [lattice_boltzmann_in_place]
  • [electrostatic_halftoning_in_place]
  • [model_based_med_in_place]
  • [least_squares_model_based_in_place]

Scope notes:

  • [ostromoukhov_in_place], [zhou_fang_in_place], and [hvs_optimized_error_diffusion_in_place], and [gradient_based_error_diffusion_in_place], and [multiscale_error_diffusion_in_place], and [feature_preserving_msed_in_place], and [green_noise_msed_in_place], and [linear_pixel_shuffling_in_place], and [tone_dependent_error_diffusion_in_place], and [structure_aware_error_diffusion_in_place] are grayscale-only.
  • [adaptive_vector_error_diffusion_in_place] supports Rgb and Rgba layouts; alpha is preserved for Rgba.
  • [vector_error_diffusion_in_place] and [semivector_error_diffusion_in_place] support Rgb and Rgba layouts; alpha is preserved for Rgba.
  • [hierarchical_error_diffusion_in_place] supports Rgb and Rgba layouts; alpha is preserved for Rgba.
  • diffusion::mbvq_color_error_diffusion_in_place and diffusion::neugebauer_color_error_diffusion_in_place support Rgb and Rgba layouts; alpha is preserved for Rgba.
  • diffusion::multichannel_green_noise_error_diffusion_in_place supports Rgb and Rgba layouts; alpha is preserved for Rgba.
  • diffusion::block_error_diffusion_in_place is grayscale-only.
  • ordered::am_fm_hybrid_halftoning_in_place and ordered::clustered_am_fm_halftoning_in_place are grayscale-only.
  • ordered::blue_noise_multitone_dither_in_place is grayscale-only.
  • [direct_binary_search_in_place], [lattice_boltzmann_in_place], and [electrostatic_halftoning_in_place] are integer grayscale-only.
  • [model_based_med_in_place] and [least_squares_model_based_in_place] are integer grayscale-only.
  • dbs::clustered_dot_direct_multibit_search_in_place is integer grayscale-only.
  • dbs::direct_pattern_control_in_place supports integer Rgb/Rgba buffers; alpha is preserved for Rgba.
  • dbs::hierarchical_colorant_dbs_in_place supports integer Rgb buffers.

§Parallel API (rayon feature)

Parallel ordered wrappers:

  • bayer_2x2_in_place_par
  • bayer_4x4_in_place_par
  • bayer_8x8_in_place_par
  • bayer_16x16_in_place_par
  • cluster_dot_4x4_in_place_par
  • cluster_dot_8x8_in_place_par
  • custom_ordered_in_place_par
  • yliluoma_1_in_place_par
  • yliluoma_2_in_place_par
  • yliluoma_3_in_place_par

Parallel stochastic wrappers:

  • threshold_binary_in_place_par
  • random_binary_in_place_par

§Image Adapter API (image feature)

Adapter enum:

  • DynamicImageBuffer
    • Gray8, Rgb8, Rgba8
    • Gray16, Rgb16, Rgba16
    • Rgb32F, Rgba32F

Typed adapters:

  • gray8_image_as_buffer
  • rgb8_image_as_buffer
  • rgba8_image_as_buffer
  • gray16_image_as_buffer
  • rgb16_image_as_buffer
  • rgba16_image_as_buffer
  • rgb32f_image_as_buffer
  • rgba32f_image_as_buffer

Dynamic adapter:

  • dynamic_image_as_buffer
  • DynamicImage::ImageLumaA8 is promoted to DynamicImageBuffer::Rgba8
  • DynamicImage::ImageLumaA16 is promoted to DynamicImageBuffer::Rgba16

§Errors and Result Types

Crate-level error/result:

Family-specific error types re-exported at crate root:

For complete workflows and runnable examples, see examples/ and the repository README.

Re-exports§

pub use buffer::gray_32f;
pub use buffer::gray_32f_packed;
pub use buffer::gray_u16;
pub use buffer::gray_u16_packed;
pub use buffer::gray_u8;
pub use buffer::gray_u8_packed;
pub use buffer::rgb_32f;
pub use buffer::rgb_32f_packed;
pub use buffer::rgb_u16;
pub use buffer::rgb_u16_packed;
pub use buffer::rgb_u8;
pub use buffer::rgb_u8_packed;
pub use buffer::rgba_32f;
pub use buffer::rgba_32f_packed;
pub use buffer::rgba_u16;
pub use buffer::rgba_u16_packed;
pub use buffer::rgba_u8;
pub use buffer::rgba_u8_packed;
pub use buffer::Buffer;
pub use buffer::BufferError;
pub use buffer::BufferKind;
pub use buffer::GrayBuffer;
pub use buffer::GrayBuffer16;
pub use buffer::GrayBuffer32F;
pub use buffer::GrayBuffer8;
pub use buffer::PixelFormat;
pub use buffer::RgbBuffer;
pub use buffer::RgbBuffer16;
pub use buffer::RgbBuffer32F;
pub use buffer::RgbBuffer8;
pub use buffer::RgbaBuffer;
pub use buffer::RgbaBuffer16;
pub use buffer::RgbaBuffer32F;
pub use buffer::RgbaBuffer8;
pub use data::cga_palette;
pub use data::grayscale_16;
pub use data::grayscale_2;
pub use data::grayscale_4;
pub use error::Error;
pub use error::Result;
pub use ordered::OrderedError;
pub use palette::IndexedImage;
pub use palette::IndexedImage16;
pub use palette::IndexedImage32F;
pub use palette::IndexedImage8;
pub use palette::Palette;
pub use palette::Palette16;
pub use palette::Palette32F;
pub use palette::Palette8;
pub use palette::PaletteError;
pub use quantize::levels_from_bits;
pub use quantize::quantize_error;
pub use quantize::quantize_gray;
pub use quantize::quantize_gray_u8;
pub use quantize::quantize_pixel;
pub use quantize::quantize_rgb;
pub use quantize::quantize_rgb_u8;
pub use quantize::QuantizeError;
pub use quantize::QuantizeMode;

Modules§

buffer
core
data
dbs
diffusion
dot_diffusion
error
math
ordered
palette
quantize
riemersma
stochastic