htpp

htrdr-image post-processing
git clone git://git.meso-star.fr/htpp.git
Log | Files | Refs | README | LICENSE

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:
Mdoc/htpp.1.txt | 6+++---
Msrc/htpp.c | 34+++++++++++++++++++---------------
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) */ } }