[OpenJDK 2D-Dev] MaskFill incorrect gamma correction (sRGB != linear RGB)

Laurent Bourgès bourges.laurent at gmail.com
Wed Aug 20 09:05:04 UTC 2014


2014-08-14 22:09 GMT+02:00 Jim Graham <james.graham at oracle.com>:

> Hi Laurent,
> Java2D has color correction code in it, but it is only really hooked up to
> the specific color correction classes so it pretty much has to be manually
> invoked.  The rendering pipeline usually punts on issues like color space
> other than if you specify an alternate color space for a BufferedImage then
> it may classify the image as "Custom" and use a lot of really slow custom
> rendering pipelines (as in, "I have no idea how colors are stored there so
> let's make method calls per pixel to read and write them").

Great, but how are color blended ? I tried the CS_Linear_RGB color space
and it gave me the same 'wrong' image. I suspect that pixels are converted
in sRGB via getRGB() / setRGB() methods that means that color blending
always happen in sRGB !
If not, could you give me an example with a custom color space ? I would
like to try color blending in the CIE-lch color space.

> By default it assumes that sRGB is a close enough approximation for any
> screen output device and just does pretty straightforward math on the pixel
> values and pretends that it is doing it all "in sRGB space".  In reality,
> it is doing it all in "just computing with the color components" space and
> assuming that since the output is a screen then it is essentially "sort of
> playing in sRGB space".  The assumption works fine for GUI and casual
> rendering, but more deliberate treatment of color spaces would really be
> needed for things like pre-press.

Exactly: in my case, I would like to choose between speed of quality
rendering for my image outputs (user defined).
As there are many rendering hints in Graphics2D (quality over speed), it
could be used to use different color blending approachs.

Moreover, is there any mean to provide custom java classes to perform the
mask fill or color blending ?
I hacked the GeneralComposite class (missing alpha coverage values) to
perform mine (slow but more accurate).
Is it possible to add such feature in JDK9 ?

In particular, it does no gamma correction except in the LCD text loops -
> those are so finicky when it comes to getting the AA just right in terms of
> quality that they really required us to do gamma corrected blending or the
> results just wouldn't be readable.  But, all other AA rendering (and alpha
> rendering) is done just linearly in the space of the component values.

It means blending in the sRGB color space ?
I looked a bit at the gamma correction on text but what does mean the
contrast ratio setting (140 by default) ?
Could you explain me in details ? does it modify the alpha coverage value ?
I tried in marlin but it seems to me visually not better.

> Note that to do the gamma correction for LCD text in the hw accelerated
> pipelines we have to read back the screen so that we can convert them into
> gamma space and back again. This greatly increases the cost of the
> rendering and if we did the same thing for regular shape rendering then
> there would be a significant performance hit.

Ok, slower but accurate: exactly what I want.
How much slower ? Does it depend on the GPU or API (d3d, opengl ...) ?
Maybe OpenCL could help for such intensive computing tasks but it is
another story ?

> I believe that future versions of D3D and OpenGL will eventually support
> gamma corrected blending natively, but for now the gamma decorrection on
> the destination has to be implemented with manual computations in a
> shader.  If you combine that with the fact that shaders cannot access the
> output pixel then there is no way to do that correction without reading
> back from the screen and providing those pixel values as a secondary input
> to the shader.  Note that you can't simply bind the output surface as an
> input texture because neither API allows a texture to be bound as both the
> input and output of the same operation - so a readback has to be done.
> (Grrr)

It is not obvious to me. I read several web pages describing gamma
correction in D3D or opengl extensions. Maybe GPU drivers are not
supporting them but it seems that in 2014 the API are able to perform sRGB
<=> linear RGB conversions on the fly. If not it is possible to provide a
pixel shader for that purpose.


To be investigated in depth ...

> Another possibility is to store all pixel values internally in a linear
> sRGB space and to de/re-gamma them as we copy them to the screen, then we
> could avoid the readback in most cases at the cost of a single gamma
> conversion on the final blit, but that would take a serious overhaul to the
> rendering pipelines to accomplish and we haven't even prototyped something
> like that.  Rendering directly to the screen via "Window.getGraphics()",
> though, would need to do the readback for every render operation...

I think there is two use case:
- direct rendering: it seems difficult (or to be fixed) to apply sRGB <=>
linear RGB conversions on the fly !
- image rendering: often the software pipeline is used (antialiasing for
example) and the mask fill / color blending is performed by the software
pipeline (C code): in that case, it seems possible to fix that code to
handle the gamma correction (quality setting).

If I can create a BufferedImage with Linear RGB, I expect the color
blending to use directly this data format (avoid sRGB conversions). Of
course if the image is drawn on the screen, it will require a conversion to
I would prefer this last solution as it will provide the best quality (less
conversion errors).

Ideally color blending should be made using 16bits linear components like
scRGB: http://en.wikipedia.org/wiki/ScRGB

Anybody has other ideas ? opinions ?

Laurent Bourgès
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/2d-dev/attachments/20140820/9b7318ec/attachment.html>

More information about the 2d-dev mailing list