|
|
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
|
|