Avisynth "Autolevels" Plugin Comparision

autolevels() version 0.5 and earlier compute range of luma for a sequence of frames, then uses those statistics to decide how much to alter the current frame's range of Y (luma) by adjusting all the pixels' luma up or down, while leaving U and V alone. This would be the right thing to do for a colorspace like HSL, as the L (luminance) component is orthogonal to H and S components.

For the YUV colorspace, this is a mistake; Y, U, and V are not orthogonal, as scaling Y requires scaling U and V to keep the same color saturation. As Y is increased, U and V must be scaled away from the midpoint (128), and as Y is decreased, U and V must be scaled toward the midpoint.

Another problem is that the TV version of the YUV color space requires that luma stay in the range 16 to 235. autolevels() version 0.5 and earlier scale luma values outside of this range, as can be seen from the histograms below.

Version 0.6 of autolevels() fixes these two problems: for images in the YUV colorspace, the resulting luma is constrained to the range 16..235, unless the parameters output_high and output_low change it. The U and V planes are also adjusted when luma is adjusted, resulting in more saturated colors when an image is made brighter, or less saturated when the image is made darker.

Hover your mouse over an image to compare two different versions of the image, taking from an 8mm film restoration. Note the range of the luma histogram, which is the top of the three histograms on the right of the image. Note too that as autolevels() is brightening the image here, version 0.6 produces a more saturated result than 0.3. Look at the rusted garbage can in the bottom right of the image: in autolevels 0.3 reduces the redness, while 0.6 preserves it while making it brighter.

Original vs. autolevels() version 0.3 invisible spacer image

Original vs. autolevels() version 0.6 invisible spacer image

autolevels() version 0.3 vs. autolevels() version 0.6 invisible spacer image