POV-Ray : Newsgroups : povray.beta-test : Gamma in POV-Ray 3.6 vs. 3.7 : Gamma in POV-Ray 3.6 vs. 3.7 Server Time
6 Jul 2024 05:30:15 EDT (-0400)
  Gamma in POV-Ray 3.6 vs. 3.7  
From: clipka
Date: 11 Sep 2009 09:55:33
Message: <4aaa56d5$1@news.povray.org>
I've spent some time on digging through the gamma handling as currently 
done by POV-Ray 3.7, as well as examining how exactly POV-Ray 3.6 
handles things.

This is what I found how 3.6 apparently does behave, and how I think 
POV-Ray theoretically should behave.


Depending on whether assumed_gamma is specified or not, two operational 
modes can be distinguished in 3.6, which I will call "Assumed Gamma 
Mode" and "Screwed-Up Mode".


(A) "Assumed Gamma Mode":

If an assumed_gamma is specified, POV-Ray 3.6 presumes that all "raw" 
colors - whether literal color values in the SDL file, encoded color 
data in input files or the encoded output image - are gamma 
pre-corrected for the specified gamma value, unless noted otherwise. It 
further assumes that computations should be performed on these raw color 
values, without converting them to linear values first.

Therefore, gamma correction is only performed on the preview display, 
taking into account both the assumed_gamma as well as the Display_Gamma 
setting.

PNG files with a gAMA chunk make an exception:

PNG output data undergoes the very same gamma transformation as the 
preview output, i.e. the encoded data will be pre-corrected for the 
specified Display_Gamma. In addition, a gAMA chunk is written matching 
the Display_Gamma, so that the image displays as previewed (provided 
Display_Gamma was set properly) on any computer, provided the viewing 
software respects the gAMA chunk and knows about its own display gamma.

For PNG input files coming with a gAMA chunk, the encoding gamma 
information stored in the chunk is honored, and full gamma correction is 
performed to account for (a) the encoding gamma as per the gAMA chunk, 
and (b) the assumed_gamma.

(Input files used in situations where the image is obviously(!) used as 
a mere data container, such as with height fields, are exempt from this 
rule: They never undergo gamma adjustment, even if they are stored as 
PNG files with a gAMA chunk.)


(B) "Screwed-Up Mode":

If no assumed_gamma is specified, POV-Ray 3.6 presumes that all "raw" 
colors - whether literal color values in the SDL file, encoded color 
data in input files or the encoded output image - are gamma 
pre-corrected to match whatever Display_Gamma happens to be set to.

Therefore, no gamma correction is performed whatsoever... in general.

Indeed, no gamma correction or -encoding is performed on PNG output 
files; however, a gAMA chunk is written matching the Display_Gamma, so 
that the image again displays as previewed.

As for PNG input files coming with a gAMA chunk, these *are* 
gamma-adjusted, for rather obscure reasons, in a rather obscure way: 
Aside from taking into account both the encoding gamma as per the gAMA 
chunk, as well as the Display_Gamma, an additional constant gamma of 2.2 
seems to have been mixed in.

(Again, input files obviously used as a mere data container are exempt 
from this gamma adjustment.)


Neither mode is really any good, for the following reasons:

(A) with a gamma of 2.2 (or anything other than 1.0, for that matter) 
will produce physically incorrect results, because the computations are 
designed to work on linear values, not gamma pre-corrected data 
(although the latter is how they had been typically used for decades, 
but that's a different story).

(A) with a gamma of 1.0 (or anything other than 2.2, for that matter) is 
unable to properly handle any non-PNG input images that use gamma 
pre-correction (which is virtually all material out in the wild). In 
addition, it will require image post-processing (format conversion or 
gamma adjustment) if any format other than PNG, HDR or OpenEXR is 
required with gamma pre-correction applied; output will also be 
percieved to exhibit a loss of precision, due to using linear instead of 
gamma encoding, unless a high color depth or a high dynamic range file 
format is used for output. (The current implementation also suffers from 
PNG input quality being degraded due to the gamma transformation.)

(B) suffers from the same problems as (A), except that it perfectly 
screws up on PNG input files.


This is exactly the reason why 3.7 is moving towards yet another gamma 
handling mode, which I'll call "Proper Gamma Mode":


(C) "Proper Gamma Mode":

The proper way of handling gamma is to perform all computations on 
proper linear color values, while allowing for both input and output 
files to use gamma encoding or pre-correction.

Therefore, gamma adjustment must be performed (or at least considered) 
on *all* output (both files and preview), as well as any input files 
(unless obviously used as a mere data container). The same should go for 
colors explicitly specified in the scene file.

For output, this gamma correction is governed by Display_Gamma, 
specifying the gamma pre-correction to be used for preview, as well as 
File_Gamma, governing the gamma encoding or pre-correction to be used.

Furthermore, for file formats defining a standard way to handle gamma, 
the standard should be adhered to, ignoring File_Gamma if necessary. 
This allows for one and the same File_Gamma setting to give good results 
  with all output file formats, whether they are typically expected to 
be gamma pre-corrected due to lack of explicit specification (e.g. BMP 
or JPEG), explicitly specified to use a variable encoding gamma (e.g. 
PNG with gAMA chunk), or explicitly specified to use linear encoding 
(e.g. OpenEXR). This allows a casual user to define a sane File_Gamma in 
his global povray.ini, and not worry about the setting regardless of 
output file format.

For input files, there is no proper handling implemented yet. However, I 
propose the following solution:

- A global SDL setting "file_gamma", to specify the gamma pre-correction 
to assume for input files.

- File format specifications take precedence over the global 
"file_gamma" setting, e.g. PNG files with a gAMA chunk are 
gamma-adjusted according to the gAMA information alone, and OpenEXR and 
Radiance HDR files are not subject to any gamma-adjustment as they are 
defined to carry linear data. This is consistent with handling of the 
File_Gamma INI setting.

(Again, as in (A) and (B), input files obviously used as a mere data 
container will be exempt from this gamma adjustment.)

- An optional per-file SDL setting "file_gamma", to specify the gamma to 
apply to the raw encoded data, irregardless of the global setting or 
file format specifications. This allows for using files that do not 
follow the specification for some reason or another.

(If an individual file_gamma is specified for an input file, it *will* 
be subject to the appropriate gamma conversion even if it is obviously 
used as a mere data container: It is expected that the user knows what 
he's doing when overriding gamma.)

- As for colors explicitly specified in the scene file, I do not have a 
concrete proposal for now, but I'm thinking along the lines of a 
color/vector function, as in:

     color gamma( rgbt <0.5,0.5,0.5, 0.2>, 2.2 )

(note that this would leave the transmit component unchanged) or 
possibly an infix operator, as in:

     color rgbt <0.5,0.5,0.5, 0.2> gamma 2.2

Not sure about it yet; the former is pretty unambiguous, but seems a bit 
cumbersome to me, while the latter looks much nicer but may provide some 
pitfalls.

Then again, maybe the best way to go would be to introduce a new syntax 
for vectors/colors to be subject to some default gamma correction, as in:

default_settings {
   color_gamma 2.2
}
...
#declare MyPigment = pigment { color rgbt #<0.5,0.5,0.5,0.2> }

Any distinctive syntax would do; I just happened to pick this one as an 
example because of its similarity with the current color syntax while 
alluding to the HTML color syntax. Note that the "#" could actually be 
defined as a prefix operator, and in that case could also be used in 
"color red #0.5" or "color rgb #(<0.2,0,2,0,2>*0.3)".

Maybe we can even go so far as to allow HTML colors in SDL code? Those 
would automatically be subject to gamma correction.

Then again, ambiguities would arise whether for instance "#version" 
would be the version statement, or the version variable subject to gamma 
correction, so maybe "#" would not be ideal to be used for that purpose. 
There are other symbols though which are not used at present, such as 
the caret (^, used in various languages as an infix operator for the 
pow() function, which would allude to the mathematical background of 
gamma adjustment), dollar ($), at (@), percent (%, though that's 
typically associated with the modulus function) or tilde (~, used in 
some languages to denote binary inverse). Grave (`) is also still 
available (though it's possibly too easy to mix up with single quote), 
as well as the backslash (\). (If unicode characters were an option, I 
would suggest \u0393 for obvious reasons - but only because I don't 
intend to use gamma pre-corrected colors frequently :-))

Then again, it could be simply ruled that the "#" as an operator must 
either be followed by a number literal, vector literal ("<...>"), or 
parenthesized expression ("(...)")... or possibly a 6-digit hexadecimal 
value :-).

(The more I think about this, the more I like this particular way of 
handling gamma-pre-corrected colors. The only true caveat I see so far 
would be the use in include files, which might want their own gamma 
setting.)

If we'd go for such a syntax, it might also be prudent to merge the 
"file_gamma" and "color_gamma" into a single "gamma" statement.


So, having said all that: Any comments / corrections / further suggestions?


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.