-
-
Notifications
You must be signed in to change notification settings - Fork 6
AdaptiveGrainMask
A port of kageru's Rust adaptivegrain plugin (adg.Mask).
Builds a grain mask from the luma plane: dark pixels get a high mask value and bright pixels a low one, so downstream grainers can add more grain to shadows and less to highlights. The strength of the falloff is shaped both by luma_scaling and by the frame's own average luma — brighter frames are masked more aggressively.
Unlike the Rust original, which reads the PlaneStatsAverage frame prop, this plugin computes the plane average internally (identical to std.PlaneStats), so no PlaneStats call is required beforehand.
vszip.AdaptiveGrainMask(vnode clip[, float luma_scaling=10.0])-
clip:
Clip to process. 8-16 bit integer or 32-bit float, any planar/gray color family. Half precision float (GRAYH) is not supported. Only plane 0 (luma) is read; the output is a single-plane Gray clip with the same bit depth and sample type as the input. -
luma_scaling: (Default: 10.0)
Shapes the falloff curve. Larger values push the mask toward zero more quickly as luma rises (less grain overall); smaller values keep more of the frame masked. Negative values invert the emphasis (mask grows with luma).
-
Integer output is bit-exact with the Rust
adg.Maskplugin; float output matches within ~1 ULP of the vectorizedpow(~1e-7). - Integer formats use a 256-entry LUT indexed by
src >> (bits − 8). For depths above 8 bit this is lossy by design — it faithfully reproduces the Rust reference, which does the same.
# more grain in the shadows, less in the highlights
mask = core.vszip.AdaptiveGrainMask(src, luma_scaling=10.0)
grained = core.std.MaskedMerge(src, src.noise.Add(...), mask)