Analysis attribution: This issue analysis was created by Gemini 3.7 Flash.
The GitHub user who submits this issue does not claim authorship of the analysis.
Finding
- Finding ID:
F33-tweak-float-dither-luma-bias
- Status: Reproduced defect
- Severity: Medium
- Affected component:
Tweak
- Source location:
avs_core/filters/levels.cpp:1642-1666
Summary
In Tweak::Tweak(), bias_dither_luma subtracts 1 unconditionally when dither == true. For 32-bit float clips (pixelsize == 4), where dither_strength has been scaled down by 65536, the unscaled -1 term produces a large positive DC offset (+0.498046875), causing all luma pixels to be brightened by ~ +0.001945 in float dithering.
Affected Code
if (pixelsize == 4)
dither_strength /= 65536.0f; // same dither range as for a 16 bit clip
if (dither) {
// lut scale settings
scale_dither_luma = 256; // lower 256 is dither value
divisor_dither_luma *= 256;
bias_dither_luma = -(256.0f * dither_strength - 1) / 2;
...
scale_dither_chroma = 16; // lower 16 is dither value
divisor_dither_chroma *= 16;
bias_dither_chroma = -(16.0f * dither_strength - (pixelsize==4 ? 1/256.0f : 1)) / 2; // -7.5
}
void Tweak::tweak_calc_luma(BYTE *srcp, int src_pitch, float minY, float maxY, int width, int height)
{
float ditherval = 0.0f;
for (int y = 0; y < height; ++y) {
const int _y = (y << 4) & 0xf0;
for (int x = 0; x < width; ++x) {
if (dither)
ditherval = (ditherMap[(x & 0x0f) | _y] * dither_strength + bias_dither_luma) / (float)scale_dither_luma;
Correct Behavior
Adjust bias_dither_luma for 32-bit float similarly to chroma ((pixelsize == 4 ? 1/256.0f : 1) or appropriate float scaling), centering ditherval around zero.
Reproduction
Call Tweak(clip, hue=0.0, sat=1.0, bright=0.0, cont=1.0, dither=true) on a 32-bit float clip (CS_YUV444PS).
Observed Result
observed: output luma is shifted upwards by ~ +0.00195 due to unbalanced positive dither bias
expected: output luma dither is zero-centered and preserves overall average brightness
Impact
Applying Tweak(dither=true) on float video introduces a visible whitening/brightening artifact across the luma plane.
Validation Criteria
Float luma dithering values are symmetric and zero-centered without introducing a DC bias offset.
Version and Environment
- AviSynthPlus revision:
80da03a5ee437c2b103dbebc9fab43480a9d97c6
- Platform and compiler: Linux x86_64 / Windows x64 GCC/MSVC
- CPU features used: host-default build.
Finding
F33-tweak-float-dither-luma-biasTweakavs_core/filters/levels.cpp:1642-1666Summary
In
Tweak::Tweak(),bias_dither_lumasubtracts1unconditionally whendither == true. For 32-bit float clips (pixelsize == 4), wheredither_strengthhas been scaled down by 65536, the unscaled-1term produces a large positive DC offset (+0.498046875), causing all luma pixels to be brightened by~ +0.001945in float dithering.Affected Code
Correct Behavior
Adjust
bias_dither_lumafor 32-bit float similarly to chroma ((pixelsize == 4 ? 1/256.0f : 1)or appropriate float scaling), centeringdithervalaround zero.Reproduction
Call
Tweak(clip, hue=0.0, sat=1.0, bright=0.0, cont=1.0, dither=true)on a 32-bit float clip (CS_YUV444PS).Observed Result
Impact
Applying
Tweak(dither=true)on float video introduces a visible whitening/brightening artifact across the luma plane.Validation Criteria
Float luma dithering values are symmetric and zero-centered without introducing a DC bias offset.
Version and Environment
80da03a5ee437c2b103dbebc9fab43480a9d97c6