Skip to content

BilateralDither

dnjulek edited this page Jun 23, 2026 · 1 revision

Port of Dither_bilateral16 from AviSynth's Dither tools.

An edge-preserving bilateral filter: each output pixel is a weighted average of its window neighbours, where the weight falls off with how far a neighbour's value is from the center (controlled by thr/flat), with a wmin flat-area protection floor.

Note

This is a different algorithm from Bilateral.

Usage

vszip.BilateralDither(vnode clip[, vnode ref, int[] radius=16, float[] thr=2.5, float[] flat=0.4, float[] wmin=0.0, float[] subspl=0.0, int[] planes=[0, 1, 2]])

radius, thr, flat, wmin and subspl are per-plane: pass an array to set a value for each plane (a single value applies to all). Each processed plane is filtered with its own settings; a plane's radius must not exceed that plane's own (subsampled) dimensions.

Parameters:

  • clip:
    Constant-format 8..16 bit integer or 32-bit float. Minimum size is 16x16, and each plane's dimensions must be >= radius for that plane.
  • ref:
    Optional weighting reference clip.
  • radius: (Default: 16)
    Half window size, 2 or above. Unlike the AviSynth wrapper the chroma radius is not auto-reduced for subsampled formats — pass an array (e.g. radius=[16, 8, 8] for 4:2:0) if you want a smaller chroma radius.
  • thr: (Default: 2.5)
    Range threshold, in 8-bit value units. Larger thr admits more neighbours into the average (stronger smoothing).
  • flat: (Default: 0.4)
    Weight shape, 0.0..1.0. 0 = triangular peak at the center; 1 = box filter (every in-threshold neighbour gets the same weight, a hard range threshold).
  • wmin: (Default: 0.0)
    Flat-area protection: raises the minimum total weight so low-contrast regions are flattened less.
  • subspl: (Default: 0.0)
    Sub-sampling rate. 0 = auto (radius_h + radius_v); >= 4 sub-samples explicitly (faster, fewer samples); 1e-3..4 disables it for the dense full window (slowest, highest quality).
  • planes: (Default: [0, 1, 2])
    Which planes to process; planes not listed are copied straight from the source. The default processes every plane.

Sub-sampling adds a blue-noise dither

Sub-sampling is not only a speed knob — it changes the look. Each output pixel averages a different rotating subset of the window (the point list is picked per row and per 4-pixel column from 23 blue-noise / spiral patterns), so the approximation error lands as a high-frequency, blue-noise-like dither texture rather than a uniform blur. This is often helpful for debanding. Disable it (subspl in [1e-3, 4), e.g. subspl=2) to get the smooth, exact full-window result.

Examples

out = core.vszip.BilateralDither(src, radius=16)              # subspl=0: auto sub-sample (default)
out = core.vszip.BilateralDither(src, radius=16, subspl=2.0)  # dense full window (slowest, no dither)
out = core.vszip.BilateralDither(src, radius=16, subspl=8.0)  # more sub-sampling (faster)
out = core.vszip.BilateralDither(src, ref=ref, radius=16)     # weighting driven by `ref`
out = core.vszip.BilateralDither(src, radius=[16, 8, 8], thr=[2.5, 4, 4])  # per-plane: smaller chroma radius, stronger chroma thr
out = core.vszip.BilateralDither(src, planes=[0])                          # luma only (chroma copied)

Clone this wiki locally