~ubuntu-branches/ubuntu/saucy/argyll/saucy

« back to all changes in this revision

Viewing changes to gamut/gammap.c

  • Committer: Package Import Robot
  • Author(s): Christian Marillat
  • Date: 2012-04-25 07:46:07 UTC
  • mfrom: (1.2.2) (13.1.15 sid)
  • Revision ID: package-import@ubuntu.com-20120425074607-yjqadetw8kum9skc
Tags: 1.4.0-4
Should Build-Depends on libusb-dev (Closes: #670329).

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
 *  as well as offering different profile (xicc/xlut.c) black point options
25
25
 *  (neutral, K hue max density, CMY max density, any max density).
26
26
 *
 
27
 *  The gamut mapping code here and the near smooth code don't actually mesh
 
28
 *  very well. For instance, the black point bend approach in < V1.3.4
 
29
 *  means that the dest gamut isn't actually contained within the source,
 
30
 *  messing up the guide vector mappings. Even if this is fixed, the
 
31
 *  actual neutral aim point within nearsmooth is Jab 0,0, while
 
32
 *  the mapping in gammap is from the source neutral to the chosen
27
33
 */
28
34
 
29
35
 
52
58
#undef CHECK_NEARMAP    /* [Und] Check how accurately near map vectors are represented by rspl */
53
59
 
54
60
#define USE_GLUMKNF             /* [Define] Enable luminence knee function points */
 
61
#define USE_GREYMAP             /* [Define] Enable 3D->3D mapping points down the grey axis */
55
62
#define USE_GAMKNF              /* [Define] Enable 3D knee function points */
56
63
#define USE_BOUND               /* [Define] Enable grid boundary anchor points */
57
64
 
70
77
        double col[3];  /* RGB color */
71
78
} markers[] = {
72
79
        { 0, },                                                         /* End marker */
 
80
        { 1, { 12.062, -0.87946, 0.97008 }, { 1.0, 0.3, 0.3 } },        /* Black point */
73
81
        { 1, { 67.575411, -37.555250, -36.612862 }, { 1.0, 0.3, 0.3 } },        /* bad source in red (Red) */
74
82
        { 1, { 61.003078, -44.466554, 1.922585 }, { 0.0, 1.0, 0.3 } },  /* good source in green */
75
83
        { 2, { 49.294793, 50.749543, -51.383167 }, { 1.0, 0.0, 0.0 } }, 
297
305
                gmm_end,
298
306
        }
299
307
};
300
 
double psmooth = 5.0;           /* Level of RSPL smoothing for perceptual, 1 = nominal */
 
308
double psmooth = 5.0;           /* [5.0] Level of RSPL smoothing for perceptual, 1 = nominal */
301
309
 
302
310
/* Saturation mapping weights, where saturation has priority over smoothness */
303
311
gammapweights sweights[] = {
318
326
                },
319
327
                {                       /* Weighting of absolute error of destination from source */
320
328
                        1.0,    /* Absolute error overall weight */
321
 
                        0.3,    /* Hue dominance vs l+c, 0 - 1 */
 
329
                        0.4,    /* Hue dominance vs l+c, 0 - 1 */
322
330
 
323
331
                        0.6,    /* White l dominance vs, c, 0 - 1 */
324
332
                        0.4,    /* Grey l dominance vs, c, 0 - 1 */
455
463
        double sr_ga_bp[3];     /* Source rotated (image) gamut black point */
456
464
        double dr_cs_wp[3];     /* Target (gmi->greymf aligned) white point */
457
465
        double dr_cs_bp[3];     /* Target (gmi->greymf aligned) black point */
458
 
        double dr_be_bp[3];     /* Bend at end Target black point (Same as dr_cs_bp[] otherwise) */
459
 
                                                /* == end target destination black point */
 
466
        double dr_be_bp[3];     /* Bend at start in source neutral axis direction */
 
467
                                                /* Target black point (Same as dr_cs_bp[] otherwise) */
460
468
 
461
469
        double sl_cs_wp[3];     /* Source rotated and L mapped colorspace white point */
462
470
        double sl_cs_bp[3];     /* Source rotated and L mapped colorspace black point */
715
723
                }
716
724
 
717
725
                /* Now decide the detail of the white and black alignment */
718
 
                if (bph == gmm_BPadpt) {        /* Adapt to destination white and black */
 
726
                if (bph == gmm_BPadpt || bph == gmm_bendBP) {   /* Adapt to destination white and black */
 
727
 
719
728
 
720
729
                        /* Use the fully adapted white and black points */
721
730
                        for (j = 0; j < 3; j++) {
723
732
                                dr_cs_bp[j] = fabp[j];
724
733
                        }
725
734
 
726
 
                        /* Set bent black point target to be the same as our actual */
727
 
                        /* black point target, so that the "bend" code does nothing. */ 
728
 
                        for (j = 0; j < 3; j++)
729
 
                                dr_be_bp[j] = dr_cs_bp[j];
 
735
                        if (bph == gmm_bendBP) {
 
736
 
 
737
                                /* Extend the half adapted (white = dst, black = src) black point */
 
738
                                /* to the same L as the target (dst), to use as the initial (bent) black point */
 
739
                                t = (dr_cs_bp[0] - dr_cs_wp[0])/(habp[0] - dr_cs_wp[0]);
 
740
                                for (j = 0; j < 3; j++)
 
741
                                        dr_be_bp[j] = dr_cs_wp[j] + t * (habp[j] - dr_cs_wp[j]);
 
742
 
 
743
                        } else {
 
744
 
 
745
                                /* Set bent black point target to be the same as our actual */
 
746
                                /* black point target, so that the "bend" code does nothing. */ 
 
747
                                for (j = 0; j < 3; j++)
 
748
                                        dr_be_bp[j] = dr_cs_bp[j];
 
749
                        }
730
750
 
731
751
                } else {                                        /* Adapt to destination white but not black */
732
752
 
733
 
                        /* Use the half adapted (full white, not black) white and black points */
 
753
                        /* Use the half adapted (white = dst, black = src) white and black points */
734
754
                        for (j = 0; j < 3; j++) {
735
755
                                dr_cs_wp[j] = hawp[j];
736
756
                                dr_cs_bp[j] = habp[j];
742
762
                                        dr_cs_wp[0], dr_cs_wp[1], dr_cs_wp[2], dr_cs_bp[0], dr_cs_bp[1], dr_cs_bp[2]);
743
763
                        }
744
764
#endif
745
 
                        if (bph == gmm_clipBP || bph == gmm_bendBP) {
 
765
                        if (bph == gmm_clipBP) {
746
766
 
747
767
                                /* Extend the target black point to accomodate the */
748
768
                                /* bent or clipped destination space L* range */
753
773
                                }
754
774
                        }
755
775
                
756
 
                        if (bph == gmm_bendBP) {
757
 
 
758
 
                                /* Set the destination "bent" black target value to */
759
 
                                /* be the fully adapted target black point, for use */
760
 
                                /* by the 3D neutral axis bend code. */
761
 
                                for (j = 0; j < 3; j++)
762
 
                                        dr_be_bp[j] = fabp[j];
763
 
 
764
 
                        } else {
765
 
 
766
 
                                /* Set the bent black point target to be the same as our actual */
767
 
                                /* black point target, so that the "bend" code does nothing. */ 
768
 
                                for (j = 0; j < 3; j++)
769
 
                                        dr_be_bp[j] = dr_cs_bp[j];
770
 
                        }
 
776
                        /* Set the bent black point target to be the same as our actual */
 
777
                        /* black point target, so that the "bend" code does nothing. */ 
 
778
                        for (j = 0; j < 3; j++)
 
779
                                dr_be_bp[j] = dr_cs_bp[j];
771
780
                }
772
781
 
773
782
#ifdef VERBOSE
774
783
                if (verb) {
775
784
                        printf("Adapted & extended tgt wp/bp = %f %f %f, %f %f %f\n",
776
785
                                dr_cs_wp[0], dr_cs_wp[1], dr_cs_wp[2], dr_cs_bp[0], dr_cs_bp[1], dr_cs_bp[2]);
777
 
                        printf("Bend target                                              bp = %f %f %f\n",
778
 
                        dr_be_bp[0], dr_be_bp[1], dr_be_bp[2]);
779
786
                }
780
787
#endif /* VERBOSE */
781
788
 
782
789
                /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
783
790
                /* Now we need to figure out what origin alignment is needed, as well as */
784
791
                /* making sure the vectors are the same length to avoid rescaling. */
785
 
                /* (Scaling is meant to be done with the L curve.) */
 
792
                /* (Scaling is meant to be done with the L curve though.) */
786
793
 
787
794
                /* Create temporary source white point that has the same L as the */
788
795
                /* target destination white point. */
830
837
 
831
838
#ifdef VERBOSE
832
839
                if (verb) {
 
840
                        printf("Bend target                                              bp = %f %f %f\n",
 
841
                        dr_be_bp[0], dr_be_bp[1], dr_be_bp[2]);
833
842
                        printf("Rotated source grey axis wp/bp %f %f %f, %f %f %f\n",
834
843
                                sr_cs_wp[0], sr_cs_wp[1], sr_cs_wp[2], sr_cs_bp[0], sr_cs_bp[1], sr_cs_bp[2]);
835
844
                        printf("Rotated gamut grey axis wp/bp  %f %f %f, %f %f %f\n",
980
989
                
981
990
                        lpnts[ngreyp].p[0] = kbl;
982
991
                        lpnts[ngreyp].v[0] = kbv;
983
 
                        lpnts[ngreyp++].w  = gmi->glumknf * gmi->glumknf;       
 
992
                        lpnts[ngreyp++].w  = 1.5 * gmi->glumknf * 1.5 * gmi->glumknf;   
984
993
                }
985
994
#endif /* USE_GLUMKNF */
986
995
 
1009
1018
                for (j = 0; j < 3; j++)
1010
1019
                        d_mt_wp[j] = dr_cs_bp[j] + t * (dr_cs_wp[j] - dr_cs_bp[j]);
1011
1020
 
1012
 
                /* Overal black point takes into account possible bend to fully adapted bp */
1013
 
                t = (dbL - dr_cs_wp[0])/(dr_be_bp[0] - dr_cs_wp[0]);
1014
1021
                for (j = 0; j < 3; j++)
1015
 
                        d_mt_bp[j] = dr_cs_wp[j] + t * (dr_be_bp[j] - dr_cs_wp[j]);
 
1022
                        d_mt_bp[j] = dr_cs_wp[j] + t * (dr_cs_bp[j] - dr_cs_wp[j]);
1016
1023
        }
1017
1024
 
1018
1025
        /* We now create the 1D rspl L map, that compresses or expands the luminence */
1215
1222
                /* destination gamut) */
1216
1223
 
1217
1224
                /* See how much to bend the black - compute the color difference */
 
1225
                /* We start out in the direction of dr_be_bp at white, and at */
 
1226
                /* the end we bend towards the overall bp dr_cs_bp */
1218
1227
                /* (brad will be 0 for non gmm_bendBP because dr_be_bp dr_cs_bp */
1219
1228
                for (brad = 0.0, i = 1; i < 3; i++) {
1220
 
                        double tt = dr_cs_bp[i] - dr_be_bp[i];
 
1229
                        double tt = dr_be_bp[i] - dr_cs_bp[i];
1221
1230
                        brad += tt * tt;
1222
1231
                }
1223
1232
                brad = sqrt(brad);
1224
1233
 
1225
 
                for (i = 0; i < nres; i++) {
 
1234
//printf("~1 brad = %f, Bend target = %f %f %f, straight = %f %f %f\n",
 
1235
//brad, dr_be_bp[0], dr_be_bp[1], dr_be_bp[2], dr_cs_bp[0], dr_cs_bp[1], dr_cs_bp[2]);
 
1236
 
 
1237
#ifdef USE_GREYMAP
 
1238
                for (i = 0; i < nres; i++) {    /* From black to white */
1226
1239
                        double t;
1227
 
                        double dv[3];           /* Straight destination value */
1228
 
                        double bv[3];           /* Bent destination value */
 
1240
                        double bv[3];           /* Bent (initial) destination value */
 
1241
                        double dv[3];           /* Straight (final) destination value */
1229
1242
                        double wt = 1.0;        /* Default grey axis point weighting */
1230
1243
 
1231
1244
                        /* Create source grey axis point */
1232
1245
                        t = i/(nres - 1.0);
1233
1246
 
1234
 
                        /* Cover 0.0 to 100.0 */
 
1247
                        /* Cover L = 0.0 to 100.0 */
1235
1248
                        t = ((100.0 * t) - sl_cs_bp[0])/(sl_cs_wp[0] - sl_cs_bp[0]);
1236
1249
                        for (j = 0; j < 3; j++)
1237
1250
                                gpnts[ngamp].p[j] = sl_cs_bp[j] + t * (sl_cs_wp[j] - sl_cs_bp[j]);
1239
1252
                        /* L values are the same, as they have been mapped prior to 3D */
1240
1253
                        gpnts[ngamp].v[0] = gpnts[ngamp].p[0];
1241
1254
 
1242
 
                        /* Figure destination point on destination grey axis */
 
1255
                        /* Figure destination point on initial bent grey axis */
 
1256
                        t = (gpnts[ngamp].v[0] - dr_cs_wp[0])/(dr_be_bp[0] - dr_cs_wp[0]);
 
1257
                        for (j = 0; j < 3; j++)
 
1258
                                bv[j] = dr_cs_wp[j] + t * (dr_be_bp[j] - dr_cs_wp[j]);
 
1259
//printf("~1 t = %f, bent dest     %f %f %f\n",t, bv[0], bv[1],bv[2]);
 
1260
                        
 
1261
                        /* Figure destination point on final straight grey axis */
1243
1262
                        t = (gpnts[ngamp].v[0] - dr_cs_wp[0])/(dr_cs_bp[0] - dr_cs_wp[0]);
1244
1263
                        for (j = 0; j < 3; j++)
1245
1264
                                dv[j] = dr_cs_wp[j] + t * (dr_cs_bp[j] - dr_cs_wp[j]);
1246
 
                        
1247
 
                        /* Figure destination point on bent grey axis */
1248
 
                        t = (gpnts[ngamp].v[0] - dr_cs_wp[0])/(dr_be_bp[0] - dr_cs_wp[0]);
1249
 
                        for (j = 0; j < 3; j++)
1250
 
                                bv[j] = dr_cs_wp[j] + t * (dr_be_bp[j] - dr_cs_wp[j]);
1251
 
                        
1252
 
                        /* Figure out a blend value between the straight value */
1253
 
                        /* and the bent value, so that it curves smoothly from */
1254
 
                        /* one to the other. (This seems to look worse, so not used.) */
 
1265
//printf("~1 t = %f, straight dest %f %f %f\n",t, dv[0], dv[1],dv[2]);
 
1266
                        
 
1267
                        /* Figure out a blend value between the bent value */
 
1268
                        /* and the straight value, so that it curves smoothly from */
 
1269
                        /* one to the other. */
1255
1270
                        if (brad > 0.001) {
1256
1271
                                double ty;
1257
1272
                                t = ((dr_cs_bp[0] + brad)  - gpnts[ngamp].v[0])/brad;
1270
1285
                                t = 0.0;        /* stick to straight, it will be close anyway. */
1271
1286
                        }
1272
1287
 
1273
 
                        for (j = 0; j < 3; j++)         /* full bend when t == 1 */
1274
 
                                gpnts[ngamp].v[j] = t * bv[j] + (1.0 - t) * dv[j];
 
1288
                        for (j = 0; j < 3; j++)         /* full straight when t == 1 */
 
1289
                                gpnts[ngamp].v[j] = t * dv[j] + (1.0 - t) * bv[j];
1275
1290
                        gpnts[ngamp].w = wt;
 
1291
//printf("~1 t = %f,      blended  %f %f %f\n",t, gpnts[ngamp].v[0], gpnts[ngamp].v[1],gpnts[ngamp].v[2]);
1276
1292
 
1277
1293
#ifdef NEVER
1278
1294
                        printf("Grey axis %d maps %f %f %f -> %f %f %f wit %f\n",ngamp,
1282
1298
#endif
1283
1299
                        ngamp++;
1284
1300
                }
 
1301
#endif /* USE_GREYMAP */
1285
1302
 
1286
1303
                /* ---------------------------------------------------- */
1287
1304
                /* Do preliminary computation of the rspl input and output bounding values */
1367
1384
                /* Create the near point mapping, which is our fundamental gamut */
1368
1385
                /* hull to gamut hull mapping. */
1369
1386
                nsm = near_smooth(verb, &nnsm, scl_gam, sil_gam, d_gam, src_kbp, dst_kbp,
1370
 
                                  dr_be_bp, xwh, gmi->gamcknf, gmi->gamxknf,
 
1387
                                  dr_cs_bp, xwh, gmi->gamcknf, gmi->gamxknf,
1371
1388
                                  gmi->gamcpf > 1e-6, gmi->gamexf > 1e-6,
1372
1389
                                  xvra, mapres, smooth, il, ih, ol, oh);
1373
1390
                if (nsm == NULL) {
2182
2199
 
2183
2200
 
2184
2201
                free_nearsmth(nsm, nnsm);
 
2202
 
 
2203
        } else if (diagname != NULL && verb) {
 
2204
                printf("Warning: Won't create '%s' because there is no 3D gamut mapping\n",diagname);
2185
2205
        }
2186
2206
 
2187
2207
#ifdef PLOT_GAMUTS