OpenImageIO/oiio — pull request #569 by lgritz (2013-04-09 21:46:10+00:00)
Title: Highlight compensation

This subsumes #568, which presented the 'clamp' features in isolation.

Problem: when you use a "good" filter, which may include negative lobes (e.g. lanczos3), to resize an image (including MIP map generation), you may have unsightly ringing or even negative pixels if there are high contrast features in the image. This is a particular problem for very bright specular highlights in HDR captured or rendered images.

Solution, courtesy of SPI donating the technique and magic constants: prior to the resize, do "range compression" to re-encode the image pixel intensities, keeping values <= 1 the same, but using a logarithmic scale for the excess value > 1. Do the resize on the transformed values. Then do "range expansion" in exactly the opposite manner to restore everything to a fully linear scale after the resize. You may also want to clamp the resulting values to a minimum of zero.

This patch implements all the features you need to accomplish this explicitly with oiiotool:

oiiotool --rangecompress
oiiotool --rangeexpand
oiiotool --clamp:min=...:max=...:clampalpha=1

And the underlying ImageBufAlgo functions rangecompress(), rangeexpand(), clamp().

Also, an optional argument to maketx:

maketx --hicomp ...

to turn on highlight compensation, which does the range compression before, and the range expansion and clamping after, every resize step that generates the successive MIPmap levels. We recommend using this if you are using filters with negative lobes (e.g. --filter lanczos3) and your source image has values >> 1.

Enjoy.