Author: abrander
Date: 2010-01-29 14:33:31 +0100 (Fri, 29 Jan 2010)
New Revision: 3117

Modified:
   branches/rawstudio-ng-color/plugins/colorspace-transform/Makefile.am
   branches/rawstudio-ng-color/plugins/colorspace-transform/rs-cmm.c
Log:
Added working gamma-correction detection.

Modified: branches/rawstudio-ng-color/plugins/colorspace-transform/Makefile.am
===================================================================
--- branches/rawstudio-ng-color/plugins/colorspace-transform/Makefile.am        
2010-01-28 22:07:17 UTC (rev 3116)
+++ branches/rawstudio-ng-color/plugins/colorspace-transform/Makefile.am        
2010-01-29 13:33:31 UTC (rev 3117)
@@ -1,7 +1,7 @@
 plugindir = $(libdir)/rawstudio/plugins
 
 AM_CFLAGS =\
-       -Wall\
+       -Wall -fno-strict-aliasing\
        -O4
 
 AM_CXXFLAGS = $(AM_CFLAGS)

Modified: branches/rawstudio-ng-color/plugins/colorspace-transform/rs-cmm.c
===================================================================
--- branches/rawstudio-ng-color/plugins/colorspace-transform/rs-cmm.c   
2010-01-28 22:07:17 UTC (rev 3116)
+++ branches/rawstudio-ng-color/plugins/colorspace-transform/rs-cmm.c   
2010-01-29 13:33:31 UTC (rev 3117)
@@ -20,6 +20,8 @@
 #include <lcms.h>
 #include "rs-cmm.h"
 
+static gushort gammatable22[65536];
+
 struct _RSCmm {
        GObject parent;
 
@@ -52,9 +54,19 @@
 static void
 rs_cmm_class_init(RSCmmClass *klass)
 {
+       gint n;
+       gdouble nd;
        GObjectClass *object_class = G_OBJECT_CLASS(klass);
 
        object_class->dispose = rs_cmm_dispose;
+
+       /* Build our 2.2 gamma table */
+       for (n=0;n<65536;n++)
+       {
+               nd = ((gdouble) n) / 65535.0;
+               nd = pow(nd, 1.0/2.2);
+               gammatable22[n] = CLAMP((gint) (nd*65535.0), 0, 65535);
+       }
 }
 
 static void
@@ -159,6 +171,16 @@
        return(accum);
 }
 
+static guchar *
+unroll_rgb_w4_gammatable22(void *info, register WORD wIn[], register LPBYTE 
accum)
+{
+       wIn[0] = gammatable22[*(LPWORD) accum]; accum+= 2;
+       wIn[1] = gammatable22[*(LPWORD) accum]; accum+= 2;
+       wIn[2] = gammatable22[*(LPWORD) accum]; accum+= 4;
+
+       return(accum);
+}
+
 static void
 load_profile(RSCmm *cmm, const RSIccProfile *profile, const RSIccProfile 
**profile_target, cmsHPROFILE *lcms_target)
 {
@@ -193,26 +215,75 @@
 {
 }
 
-gdouble
-estimate_gamma(cmsHPROFILE *profile)
+static gboolean
+is_profile_gamma_22_corrected(cmsHPROFILE *profile)
 {
-       gdouble gamma_value[3] = {1.0, 1.0, 1.0};
-       LPGAMMATABLE gamma[3];
+       cmsHTRANSFORM testtransform;
+       cmsHPROFILE linear = NULL;
+       gint n;
+       gint lin = 0;
+       gint g045 = 0;
 
-       gamma[0] = cmsReadICCGamma(profile, icSigRedTRCTag);
-       gamma[1] = cmsReadICCGamma(profile, icSigGreenTRCTag);
-       gamma[2] = cmsReadICCGamma(profile, icSigBlueTRCTag);
+       gushort buffer[27];
+       gushort table_lin[] = {
+               6553,   6553,  6553,
+               13107, 13107, 13107,
+               19661, 19661, 19661,
+               26214, 26214, 26214,
+               32768, 32768, 32768,
+               39321, 39321, 39321,
+               45875, 45875, 45875,
+               52428, 52428, 52428,
+               58981, 58981, 58981
+               };
 
-       if (gamma[0] && gamma[1] && gamma[2])
+       const gushort table_g045[] = {
+               392,   392,   392,
+               1833,  1833,  1833,
+               4514,  4514,  4514,
+               8554,  8554,  8554,
+               14045, 14045, 14045,
+               21061, 21061, 21061,
+               29665, 29665, 29665,
+               39913, 39913, 39913,
+               51855, 51855, 51855
+               };
+
+       GStaticMutex lock = G_STATIC_MUTEX_INIT;
+
+       g_static_mutex_lock(&lock);
+       if (linear == NULL)
        {
-               gamma_value[0] = cmsEstimateGamma(gamma[0]);
-               gamma_value[1] = cmsEstimateGamma(gamma[1]);
-               gamma_value[2] = cmsEstimateGamma(gamma[2]);
+               static cmsCIExyYTRIPLE srgb_primaries = {
+                       {0.64, 0.33, 0.212656},
+                       {0.115, 0.826, 0.724938},
+                       {0.157, 0.018, 0.016875}};
+               cmsCIExyY D65;
+               LPGAMMATABLE gamma[3];
+
+               cmsWhitePointFromTemp(6504, &D65);
+               gamma[0] = gamma[1] = gamma[2] = cmsBuildGamma(2,1.0);
+               linear = cmsCreateRGBProfile(&D65, &srgb_primaries, gamma);
        }
-       else
-               printf("No tables\n");
+       g_static_mutex_unlock(&lock);
 
-       return (gamma_value[0] + gamma_value[1] + gamma_value[2]) / 3.0;
+       testtransform = cmsCreateTransform(profile, TYPE_RGB_16, linear, 
TYPE_RGB_16, INTENT_PERCEPTUAL, 0);
+       cmsDoTransform(testtransform, table_lin, buffer, 9);
+       cmsDeleteTransform(testtransform);
+
+       /* We compare the transformed values to the original linear values to
+          determine if we're closer to a gamma 2.2 correction or 1.0 */
+       for (n=0;n<9;n++)
+       {
+               lin += abs(buffer[n*3]-table_lin[n*3]);
+               lin += abs(buffer[n*3+1]-table_lin[n*3+1]);
+               lin += abs(buffer[n*3+2]-table_lin[n*3+2]);
+               g045 += abs(buffer[n*3]-table_g045[n*3]);
+               g045 += abs(buffer[n*3+1]-table_g045[n*3+1]);
+               g045 += abs(buffer[n*3+2]-table_g045[n*3+2]);
+       }
+
+       return (g045 < lin);
 }
 
 static void
@@ -224,9 +295,6 @@
        if (cmm->lcms_transform16)
                cmsDeleteTransform(cmm->lcms_transform16);
 
-       printf("INPUT GAMMA: %f\n", estimate_gamma(cmm->lcms_input_profile));
-       printf("OUTPUT GAMMA: %f\n", estimate_gamma(cmm->lcms_output_profile));
-
        cmm->lcms_transform16 = cmsCreateTransform(
                cmm->lcms_input_profile, TYPE_RGB_16,
                cmm->lcms_output_profile, TYPE_RGB_16,
@@ -235,9 +303,16 @@
        g_warn_if_fail(cmm->lcms_transform16 != NULL);
 
        /* Enable packing/unpacking for pixelsize==4 */
-       cmsSetUserFormatters(cmm->lcms_transform16,
-               TYPE_RGB_16, unroll_rgb_w4,
-               TYPE_RGB_16, pack_rgb_w4);
+       /* If we estimate that the input profile will apply gamma correction,
+          we try to undo it in 16 bit transform */
+       if (is_profile_gamma_22_corrected(cmm->lcms_input_profile))
+               cmsSetUserFormatters(cmm->lcms_transform16,
+                       TYPE_RGB_16, unroll_rgb_w4_gammatable22,
+                       TYPE_RGB_16, pack_rgb_w4);
+       else
+               cmsSetUserFormatters(cmm->lcms_transform16,
+                       TYPE_RGB_16, unroll_rgb_w4,
+                       TYPE_RGB_16, pack_rgb_w4);
 
        cmm->dirty16 = FALSE;
 }


_______________________________________________
Rawstudio-commit mailing list
[email protected]
http://rawstudio.org/cgi-bin/mailman/listinfo/rawstudio-commit

Reply via email to