I realized having to host this potentially indefinitely might not be the best idea, so I am going to shut down this gitea instance eventually.
You’ll have time, at least until the end of 2022, probably longer, but please just get all your stuff somewhere safe in case we ever disappear.
If any of your build scripts rely on my (kageru’s) projects hosted here, check my Github or IEW on Github for encoding projects. If you can’t find what you’re looking there, tell me to migrate it.
Reimplementation of the masking logic of adaptivegrain in rust. It’s almost safe :^)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kageru 1f3957f449
Update dependencies
2 years ago
benches No longer use LUT for 32bit input 2 years ago
src No longer use LUT for 32bit input 2 years ago
.gitignore Add Cargo.lock 3 years ago
Cargo.lock Update dependencies 2 years ago
Cargo.toml Update dependencies 2 years ago
README.md Link AUR package in README 3 years ago
build_release.sh add script to build release binaries 3 years ago



Reimplementation of the adaptive_grain mask as a Vapoursynth plugin. For a description of the math and the general idea, see the article.


core.adg.Mask(clip, luma_scaling: float)

You must call std.PlaneStats() before this plugin (or fill the PlaneStatsAverage frame property using some other method). Supported formats are YUV with 8-32 bit precision integer or single precision float. Half precision float input is not supported since no one seems to be using that anyway. Since the output is grey and only luma is processed, the subsampling of the input does not matter.

To replicate the original behaviour of adaptivegrain, a wrapper is provided in kagefunc. It behaves exactly like the original implementation (except for the performance, which is about 3x faster on my machine).


clip: vapoursynth.VideoNode

the input clip to generate a mask for.

luma_scaling: float = 10.0

the luma_scaling factor as described in the blog post. Lower values will make the mask brighter overall.

Build instructions

If you’re on Arch Linux, there’s an AUR package for this plugin. Otherwise you’ll have to build and install the package manually.

cargo build --release

That’s it. This is Rust, after all. No idea what the minimum version is, but it works with stable rust 1.41. That’s all I know. Binaries for Windows and Linux are in the release tab.


Why do I have to call std.PlaneStats() manually?

Because I didn’t want to reimplement it. kagefunc.adaptive_grain(clip, show_mask=True) does that for you and then just returns the mask. Because I was too dumb to realize this exists. I’ll fix that at some point.

Why doesn’t this also add grain?

I was going to do that originally, but it just goes back to the same point about not wanting to reimplement something that already exists.