fix(png): Improve png write with alpha is low #3985
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
We found that PNG output (which is required to be unassociated alpha) had precision problems with low alpha values because it quantized to the final bit depth before doing the alpha deassociation.
Explanation:
PNG requires associated alpha to be stored in the file. So if you have (unassociated) pixel value [0.00235, 0.00106, 0.00117, 0.0025], that means that we need to divide the colors by alpha before storing in the file, so that's [0.94, 0.424, 0.468, 0.0025] if you have full precision. But you don't, because PNG only supports uint8 and uint16. For uint8, this should end up as [240, 108, 119, 1].
But it turns out that our png writer does the integer conversion before the un-premultiplication, so actually we first quantize from [0.00235, 0.00106, 0.00117, 0.0025] to [1 0 0 1], and THEN we un-premultiply, giving us the [255, 0, 0, 1] that made you think "Why is that red value clipped? And where did green and blue go?"
The solution, then, is to deassociate as floats first, then quantize to the final integer data type.
Also add a test for this, as well as a test that verifies correctly writing of 16 bit files that I had some problems with in the last png PR.