commit 35c95974ca1d21c3afb919fc269979cfe93af8a6
parent 363034b39ed539e8fac3a3f56bd2a6cbce243dbf
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Tue, 2 Jul 2019 12:10:57 +0200
Fix the XYZ to sRGB conversion and the gamma correction
Diffstat:
2 files changed, 22 insertions(+), 18 deletions(-)
diff --git a/doc/htpp.1.txt b/doc/htpp.1.txt
@@ -54,9 +54,9 @@ either defined by the user through the *-w* option or automatically computed
as the luminance from which roughly all image pixels have a luminance less
than _white-scale_. Currently, *htpp* empirically defines _white-scale_ as the
luminance greater than the luminance of 99.5% of the pixels. Once tone mapped,
-the pixels are transformed from the CIE 1931 XYZ color space to the sRGB color
-space. Finally, the resulting pixel components are clamped to [0, 1] and
-encoded on 8-bits.
+the pixels are transformed from the CIE 1931 XYZ color space to the sRGB
+linear color space before to be gamma corrected. Finally, the resulting pixel
+components are clamped to [0, 1] and encoded on 8-bits.
OPTIONS
-------
diff --git a/src/htpp.c b/src/htpp.c
@@ -285,32 +285,36 @@ filmic_tone_mapping(double pixel[3], const double exposure, const double Ymax)
}
static double*
-XYZ_to_RGB(double XYZ[3])
+XYZ_to_sRGB(double XYZ[3])
{
- const double mat[9] = { /* D65 */
+ #define D65_x 0.31271
+ #define D65_y 0.32902
+ const double D65[3] = {D65_x / D65_y, 1.0, (1 - D65_x - D65_y) / D65_y};
+ const double mat[9] = { /* XYZ to sRGB matrix */
3.2404542, -0.9692660, 0.0556434,
-1.5371385, 1.8760108, -0.2040259,
-0.4985314, 0.0415560, 1.0572252
};
- double* RGB = XYZ;
+ double* sRGB = XYZ;
+ double* XYZ_D65 = XYZ;
ASSERT(XYZ);
- d33_muld3(RGB, mat, XYZ);
- RGB[0] = MMAX(RGB[0], 0);
- RGB[1] = MMAX(RGB[1], 0);
- RGB[2] = MMAX(RGB[2], 0);
- return RGB;
+ d3_mul(XYZ_D65, XYZ, D65);
+ d33_muld3(sRGB, mat, XYZ_D65);
+ sRGB[0] = MMAX(sRGB[0], 0);
+ sRGB[1] = MMAX(sRGB[1], 0);
+ sRGB[2] = MMAX(sRGB[2], 0);
+ return sRGB;
}
static double*
-RGB_to_sRGB(double RGB[3])
+sRGB_gamma_correct(double sRGB[3])
{
- double* sRGB = RGB;
int i;
FOR_EACH(i, 0, 3) {
- if(RGB[i] <= 0.0031308) {
- sRGB[i] = RGB[i] * 12.92;
+ if(sRGB[i] <= 0.0031308) {
+ sRGB[i] = sRGB[i] * 12.92;
} else {
- sRGB[i] = 1.055 * pow(RGB[i], 1.0/2.4);
+ sRGB[i] = 1.055 * pow(sRGB[i], 1.0/2.4) - 0.055;
}
}
return sRGB;
@@ -566,8 +570,8 @@ main(int argc, char** argv)
filmic_tone_mapping(pixel, args.exposure, Ymax); /* Tone map the RGB pixel */
if(args.pixdata == PIXEL_RADIANCE) {
- XYZ_to_RGB(pixel); /* Convert in RGB color space */
- RGB_to_sRGB(pixel); /* Convert in sRGB color space (i.e. gamma correction) */
+ XYZ_to_sRGB(pixel); /* Convert in RGB color space */
+ sRGB_gamma_correct(pixel); /* Convert in sRGB color space (i.e. gamma correction) */
}
}