OpenImageIO/oiio — pull request #962 by lgritz (2014-09-22 21:53:51+00:00)
Title: Fix TIFF loss of precision when auto-premultiplying unassociated alpha images

Frédéric Devernay points out in GH issue #960 that we auto-premultiply unassociated alpha TIFF images BEFORE converting from native data type. So if the native data is uint8, we do a premultiply from uint8 -> uint8, thereby losing precision, even if the call ultimately asks us to convert to the a higher-precision (e.g., float) data type in the caller's buffer.

The root of the evil is that we do the auto-premultiply inside read_native_scanline (and tile), which operates entirely in native data type and is unaware of what buffer data type the user has supplied. Ugh.

The solution is:

1. Add a premult() utility function in imageio.h/imageio.cpp (for easy reuse elsewhere).

2. Do NOT do the multiply in the 'native' functions.

3. Add TIFFInput::read_scanline(s)/read_tile(s) functions, which call the base class version first, and then (if requested) do the un-premultiplication. Seems to work! It's a little roundabout, but necessary because the base class read_blah functions do not have the TIFF-specific knowledge of whether or not the premultiplication is desired. Those methods are already virtual and it's always been legal to override them on a format-specific basis, though we've never had a reason to do so before.

Note that this only helps if the user specifies a higher-precision buffer. I think that's a fine limitation. If they read an 8 bit file into a supplied 8 bit buffer, and don't specifically ask for unassociated values to be preserved, I think this is the best they can hope for anyway.

Fixes #960