summaryrefslogtreecommitdiff
path: root/profile
diff options
context:
space:
mode:
Diffstat (limited to 'profile')
-rw-r--r--profile/F1.sp106
-rw-r--r--profile/F5.sp106
-rw-r--r--profile/F8.sp106
-rw-r--r--profile/Jamfile6
-rw-r--r--profile/afiles5
-rw-r--r--profile/colprof.c96
-rw-r--r--profile/colverify.c (renamed from profile/verify.c)401
-rw-r--r--profile/prof.h2
-rw-r--r--profile/profcheck.c2
-rw-r--r--profile/profin.c9
-rw-r--r--profile/profout.c156
-rw-r--r--profile/txt2ti3.c6
12 files changed, 837 insertions, 164 deletions
diff --git a/profile/F1.sp b/profile/F1.sp
new file mode 100644
index 0000000..908cd72
--- /dev/null
+++ b/profile/F1.sp
@@ -0,0 +1,106 @@
+SPECT
+
+DESCRIPTOR "Argyll F1 illimunant spectral power"
+
+ORIGINATOR "Argyll CMS"
+
+CREATED "Fri Jul 06 17:49:57 2001"
+KEYWORD "SPECTRAL_BANDS"
+SPECTRAL_BANDS "81"
+KEYWORD "SPECTRAL_START_NM"
+SPECTRAL_START_NM "380.000000"
+KEYWORD "SPECTRAL_END_NM"
+SPECTRAL_END_NM "780.000000"
+KEYWORD "SPECTRAL_NORM"
+SPECTRAL_NORM "30.00"
+
+KEYWORD "SPEC_380"
+KEYWORD "SPEC_385"
+KEYWORD "SPEC_390"
+KEYWORD "SPEC_395"
+KEYWORD "SPEC_400"
+KEYWORD "SPEC_405"
+KEYWORD "SPEC_410"
+KEYWORD "SPEC_415"
+KEYWORD "SPEC_420"
+KEYWORD "SPEC_425"
+KEYWORD "SPEC_430"
+KEYWORD "SPEC_435"
+KEYWORD "SPEC_440"
+KEYWORD "SPEC_445"
+KEYWORD "SPEC_450"
+KEYWORD "SPEC_455"
+KEYWORD "SPEC_460"
+KEYWORD "SPEC_465"
+KEYWORD "SPEC_470"
+KEYWORD "SPEC_475"
+KEYWORD "SPEC_480"
+KEYWORD "SPEC_485"
+KEYWORD "SPEC_490"
+KEYWORD "SPEC_495"
+KEYWORD "SPEC_500"
+KEYWORD "SPEC_505"
+KEYWORD "SPEC_510"
+KEYWORD "SPEC_515"
+KEYWORD "SPEC_520"
+KEYWORD "SPEC_525"
+KEYWORD "SPEC_530"
+KEYWORD "SPEC_535"
+KEYWORD "SPEC_540"
+KEYWORD "SPEC_545"
+KEYWORD "SPEC_550"
+KEYWORD "SPEC_555"
+KEYWORD "SPEC_560"
+KEYWORD "SPEC_565"
+KEYWORD "SPEC_570"
+KEYWORD "SPEC_575"
+KEYWORD "SPEC_580"
+KEYWORD "SPEC_585"
+KEYWORD "SPEC_590"
+KEYWORD "SPEC_595"
+KEYWORD "SPEC_600"
+KEYWORD "SPEC_605"
+KEYWORD "SPEC_610"
+KEYWORD "SPEC_615"
+KEYWORD "SPEC_620"
+KEYWORD "SPEC_625"
+KEYWORD "SPEC_630"
+KEYWORD "SPEC_635"
+KEYWORD "SPEC_640"
+KEYWORD "SPEC_645"
+KEYWORD "SPEC_650"
+KEYWORD "SPEC_655"
+KEYWORD "SPEC_660"
+KEYWORD "SPEC_665"
+KEYWORD "SPEC_670"
+KEYWORD "SPEC_675"
+KEYWORD "SPEC_680"
+KEYWORD "SPEC_685"
+KEYWORD "SPEC_690"
+KEYWORD "SPEC_695"
+KEYWORD "SPEC_700"
+KEYWORD "SPEC_705"
+KEYWORD "SPEC_710"
+KEYWORD "SPEC_715"
+KEYWORD "SPEC_720"
+KEYWORD "SPEC_725"
+KEYWORD "SPEC_730"
+KEYWORD "SPEC_735"
+KEYWORD "SPEC_740"
+KEYWORD "SPEC_745"
+KEYWORD "SPEC_750"
+KEYWORD "SPEC_755"
+KEYWORD "SPEC_760"
+KEYWORD "SPEC_765"
+KEYWORD "SPEC_770"
+KEYWORD "SPEC_775"
+KEYWORD "SPEC_780"
+NUMBER_OF_FIELDS 81
+BEGIN_DATA_FORMAT
+SPEC_380 SPEC_385 SPEC_390 SPEC_395 SPEC_400 SPEC_405 SPEC_410 SPEC_415 SPEC_420 SPEC_425 SPEC_430 SPEC_435 SPEC_440 SPEC_445 SPEC_450 SPEC_455 SPEC_460 SPEC_465 SPEC_470 SPEC_475 SPEC_480 SPEC_485 SPEC_490 SPEC_495 SPEC_500 SPEC_505 SPEC_510 SPEC_515 SPEC_520 SPEC_525 SPEC_530 SPEC_535 SPEC_540 SPEC_545 SPEC_550 SPEC_555 SPEC_560 SPEC_565 SPEC_570 SPEC_575 SPEC_580 SPEC_585 SPEC_590 SPEC_595 SPEC_600 SPEC_605 SPEC_610 SPEC_615 SPEC_620 SPEC_625 SPEC_630 SPEC_635 SPEC_640 SPEC_645 SPEC_650 SPEC_655 SPEC_660 SPEC_665 SPEC_670 SPEC_675 SPEC_680 SPEC_685 SPEC_690 SPEC_695 SPEC_700 SPEC_705 SPEC_710 SPEC_715 SPEC_720 SPEC_725 SPEC_730 SPEC_735 SPEC_740 SPEC_745 SPEC_750 SPEC_755 SPEC_760 SPEC_765 SPEC_770 SPEC_775 SPEC_780
+END_DATA_FORMAT
+
+NUMBER_OF_SETS 1
+BEGIN_DATA
+1.87 2.36 2.94 3.47 5.17 19.49 6.13 6.24 7.01 7.79 8.56 43.67 16.94 10.72 11.35 11.89 12.37 12.75 13.00 13.15 13.23 13.17 13.13 12.85 12.52 12.20 11.83 11.50 11.22 11.05 11.03 11.18 11.53 27.74 17.05 13.55 14.33 15.01 15.52 18.29 19.55 15.48 14.91 14.15 13.22 12.19 11.12 10.03 8.95 7.96 7.02 6.20 5.42 4.73 4.15 3.64 3.20 2.81 2.47 2.18 1.93 1.72 1.67 1.43 1.29 1.19 1.08 0.96 0.88 0.81 0.77 0.75 0.73 0.68 0.69 0.64 0.68 0.69 0.61 0.52 0.43
+END_DATA
diff --git a/profile/F5.sp b/profile/F5.sp
new file mode 100644
index 0000000..4959a50
--- /dev/null
+++ b/profile/F5.sp
@@ -0,0 +1,106 @@
+SPECT
+
+DESCRIPTOR "Argyll F5 illimunant spectral power"
+
+ORIGINATOR "Argyll CMS"
+
+CREATED "Fri Jul 06 17:49:57 2001"
+KEYWORD "SPECTRAL_BANDS"
+SPECTRAL_BANDS "81"
+KEYWORD "SPECTRAL_START_NM"
+SPECTRAL_START_NM "380.000000"
+KEYWORD "SPECTRAL_END_NM"
+SPECTRAL_END_NM "780.000000"
+KEYWORD "SPECTRAL_NORM"
+SPECTRAL_NORM "30.00"
+
+KEYWORD "SPEC_380"
+KEYWORD "SPEC_385"
+KEYWORD "SPEC_390"
+KEYWORD "SPEC_395"
+KEYWORD "SPEC_400"
+KEYWORD "SPEC_405"
+KEYWORD "SPEC_410"
+KEYWORD "SPEC_415"
+KEYWORD "SPEC_420"
+KEYWORD "SPEC_425"
+KEYWORD "SPEC_430"
+KEYWORD "SPEC_435"
+KEYWORD "SPEC_440"
+KEYWORD "SPEC_445"
+KEYWORD "SPEC_450"
+KEYWORD "SPEC_455"
+KEYWORD "SPEC_460"
+KEYWORD "SPEC_465"
+KEYWORD "SPEC_470"
+KEYWORD "SPEC_475"
+KEYWORD "SPEC_480"
+KEYWORD "SPEC_485"
+KEYWORD "SPEC_490"
+KEYWORD "SPEC_495"
+KEYWORD "SPEC_500"
+KEYWORD "SPEC_505"
+KEYWORD "SPEC_510"
+KEYWORD "SPEC_515"
+KEYWORD "SPEC_520"
+KEYWORD "SPEC_525"
+KEYWORD "SPEC_530"
+KEYWORD "SPEC_535"
+KEYWORD "SPEC_540"
+KEYWORD "SPEC_545"
+KEYWORD "SPEC_550"
+KEYWORD "SPEC_555"
+KEYWORD "SPEC_560"
+KEYWORD "SPEC_565"
+KEYWORD "SPEC_570"
+KEYWORD "SPEC_575"
+KEYWORD "SPEC_580"
+KEYWORD "SPEC_585"
+KEYWORD "SPEC_590"
+KEYWORD "SPEC_595"
+KEYWORD "SPEC_600"
+KEYWORD "SPEC_605"
+KEYWORD "SPEC_610"
+KEYWORD "SPEC_615"
+KEYWORD "SPEC_620"
+KEYWORD "SPEC_625"
+KEYWORD "SPEC_630"
+KEYWORD "SPEC_635"
+KEYWORD "SPEC_640"
+KEYWORD "SPEC_645"
+KEYWORD "SPEC_650"
+KEYWORD "SPEC_655"
+KEYWORD "SPEC_660"
+KEYWORD "SPEC_665"
+KEYWORD "SPEC_670"
+KEYWORD "SPEC_675"
+KEYWORD "SPEC_680"
+KEYWORD "SPEC_685"
+KEYWORD "SPEC_690"
+KEYWORD "SPEC_695"
+KEYWORD "SPEC_700"
+KEYWORD "SPEC_705"
+KEYWORD "SPEC_710"
+KEYWORD "SPEC_715"
+KEYWORD "SPEC_720"
+KEYWORD "SPEC_725"
+KEYWORD "SPEC_730"
+KEYWORD "SPEC_735"
+KEYWORD "SPEC_740"
+KEYWORD "SPEC_745"
+KEYWORD "SPEC_750"
+KEYWORD "SPEC_755"
+KEYWORD "SPEC_760"
+KEYWORD "SPEC_765"
+KEYWORD "SPEC_770"
+KEYWORD "SPEC_775"
+KEYWORD "SPEC_780"
+NUMBER_OF_FIELDS 81
+BEGIN_DATA_FORMAT
+SPEC_380 SPEC_385 SPEC_390 SPEC_395 SPEC_400 SPEC_405 SPEC_410 SPEC_415 SPEC_420 SPEC_425 SPEC_430 SPEC_435 SPEC_440 SPEC_445 SPEC_450 SPEC_455 SPEC_460 SPEC_465 SPEC_470 SPEC_475 SPEC_480 SPEC_485 SPEC_490 SPEC_495 SPEC_500 SPEC_505 SPEC_510 SPEC_515 SPEC_520 SPEC_525 SPEC_530 SPEC_535 SPEC_540 SPEC_545 SPEC_550 SPEC_555 SPEC_560 SPEC_565 SPEC_570 SPEC_575 SPEC_580 SPEC_585 SPEC_590 SPEC_595 SPEC_600 SPEC_605 SPEC_610 SPEC_615 SPEC_620 SPEC_625 SPEC_630 SPEC_635 SPEC_640 SPEC_645 SPEC_650 SPEC_655 SPEC_660 SPEC_665 SPEC_670 SPEC_675 SPEC_680 SPEC_685 SPEC_690 SPEC_695 SPEC_700 SPEC_705 SPEC_710 SPEC_715 SPEC_720 SPEC_725 SPEC_730 SPEC_735 SPEC_740 SPEC_745 SPEC_750 SPEC_755 SPEC_760 SPEC_765 SPEC_770 SPEC_775 SPEC_780
+END_DATA_FORMAT
+
+NUMBER_OF_SETS 1
+BEGIN_DATA
+1.87 2.35 2.92 3.45 5.10 18.91 6.00 6.11 6.85 7.58 8.31 40.76 16.06 10.32 10.91 11.40 11.83 12.17 12.40 12.54 12.58 12.52 12.47 12.20 11.89 11.61 11.33 11.10 10.96 10.97 11.16 11.54 12.12 27.78 17.73 14.47 15.20 15.77 16.10 18.54 19.50 15.39 14.64 13.72 12.69 11.57 10.45 9.35 8.29 7.32 6.41 5.63 4.90 4.26 3.72 3.25 2.83 2.49 2.19 1.93 1.71 1.52 1.43 1.26 1.13 1.05 0.96 0.85 0.78 0.72 0.68 0.67 0.65 0.61 0.62 0.59 0.62 0.64 0.55 0.47 0.40
+END_DATA
diff --git a/profile/F8.sp b/profile/F8.sp
new file mode 100644
index 0000000..f1e7beb
--- /dev/null
+++ b/profile/F8.sp
@@ -0,0 +1,106 @@
+SPECT
+
+DESCRIPTOR "Argyll F8 illimunant spectral power"
+
+ORIGINATOR "Argyll CMS"
+
+CREATED "Fri Jul 06 17:49:57 2001"
+KEYWORD "SPECTRAL_BANDS"
+SPECTRAL_BANDS "81"
+KEYWORD "SPECTRAL_START_NM"
+SPECTRAL_START_NM "380.000000"
+KEYWORD "SPECTRAL_END_NM"
+SPECTRAL_END_NM "780.000000"
+KEYWORD "SPECTRAL_NORM"
+SPECTRAL_NORM "30.00"
+
+KEYWORD "SPEC_380"
+KEYWORD "SPEC_385"
+KEYWORD "SPEC_390"
+KEYWORD "SPEC_395"
+KEYWORD "SPEC_400"
+KEYWORD "SPEC_405"
+KEYWORD "SPEC_410"
+KEYWORD "SPEC_415"
+KEYWORD "SPEC_420"
+KEYWORD "SPEC_425"
+KEYWORD "SPEC_430"
+KEYWORD "SPEC_435"
+KEYWORD "SPEC_440"
+KEYWORD "SPEC_445"
+KEYWORD "SPEC_450"
+KEYWORD "SPEC_455"
+KEYWORD "SPEC_460"
+KEYWORD "SPEC_465"
+KEYWORD "SPEC_470"
+KEYWORD "SPEC_475"
+KEYWORD "SPEC_480"
+KEYWORD "SPEC_485"
+KEYWORD "SPEC_490"
+KEYWORD "SPEC_495"
+KEYWORD "SPEC_500"
+KEYWORD "SPEC_505"
+KEYWORD "SPEC_510"
+KEYWORD "SPEC_515"
+KEYWORD "SPEC_520"
+KEYWORD "SPEC_525"
+KEYWORD "SPEC_530"
+KEYWORD "SPEC_535"
+KEYWORD "SPEC_540"
+KEYWORD "SPEC_545"
+KEYWORD "SPEC_550"
+KEYWORD "SPEC_555"
+KEYWORD "SPEC_560"
+KEYWORD "SPEC_565"
+KEYWORD "SPEC_570"
+KEYWORD "SPEC_575"
+KEYWORD "SPEC_580"
+KEYWORD "SPEC_585"
+KEYWORD "SPEC_590"
+KEYWORD "SPEC_595"
+KEYWORD "SPEC_600"
+KEYWORD "SPEC_605"
+KEYWORD "SPEC_610"
+KEYWORD "SPEC_615"
+KEYWORD "SPEC_620"
+KEYWORD "SPEC_625"
+KEYWORD "SPEC_630"
+KEYWORD "SPEC_635"
+KEYWORD "SPEC_640"
+KEYWORD "SPEC_645"
+KEYWORD "SPEC_650"
+KEYWORD "SPEC_655"
+KEYWORD "SPEC_660"
+KEYWORD "SPEC_665"
+KEYWORD "SPEC_670"
+KEYWORD "SPEC_675"
+KEYWORD "SPEC_680"
+KEYWORD "SPEC_685"
+KEYWORD "SPEC_690"
+KEYWORD "SPEC_695"
+KEYWORD "SPEC_700"
+KEYWORD "SPEC_705"
+KEYWORD "SPEC_710"
+KEYWORD "SPEC_715"
+KEYWORD "SPEC_720"
+KEYWORD "SPEC_725"
+KEYWORD "SPEC_730"
+KEYWORD "SPEC_735"
+KEYWORD "SPEC_740"
+KEYWORD "SPEC_745"
+KEYWORD "SPEC_750"
+KEYWORD "SPEC_755"
+KEYWORD "SPEC_760"
+KEYWORD "SPEC_765"
+KEYWORD "SPEC_770"
+KEYWORD "SPEC_775"
+KEYWORD "SPEC_780"
+NUMBER_OF_FIELDS 81
+BEGIN_DATA_FORMAT
+SPEC_380 SPEC_385 SPEC_390 SPEC_395 SPEC_400 SPEC_405 SPEC_410 SPEC_415 SPEC_420 SPEC_425 SPEC_430 SPEC_435 SPEC_440 SPEC_445 SPEC_450 SPEC_455 SPEC_460 SPEC_465 SPEC_470 SPEC_475 SPEC_480 SPEC_485 SPEC_490 SPEC_495 SPEC_500 SPEC_505 SPEC_510 SPEC_515 SPEC_520 SPEC_525 SPEC_530 SPEC_535 SPEC_540 SPEC_545 SPEC_550 SPEC_555 SPEC_560 SPEC_565 SPEC_570 SPEC_575 SPEC_580 SPEC_585 SPEC_590 SPEC_595 SPEC_600 SPEC_605 SPEC_610 SPEC_615 SPEC_620 SPEC_625 SPEC_630 SPEC_635 SPEC_640 SPEC_645 SPEC_650 SPEC_655 SPEC_660 SPEC_665 SPEC_670 SPEC_675 SPEC_680 SPEC_685 SPEC_690 SPEC_695 SPEC_700 SPEC_705 SPEC_710 SPEC_715 SPEC_720 SPEC_725 SPEC_730 SPEC_735 SPEC_740 SPEC_745 SPEC_750 SPEC_755 SPEC_760 SPEC_765 SPEC_770 SPEC_775 SPEC_780
+END_DATA_FORMAT
+
+NUMBER_OF_SETS 1
+BEGIN_DATA
+1.21 1.50 1.81 2.13 3.17 13.08 3.83 3.45 3.86 4.42 5.09 34.10 12.42 7.68 8.60 9.46 10.24 10.84 11.33 11.71 11.98 12.17 12.28 12.32 12.35 12.44 12.55 12.68 12.77 12.72 12.60 12.43 12.22 28.96 16.51 11.79 11.76 11.77 11.84 14.61 16.11 12.34 12.53 12.72 12.92 13.12 13.34 13.61 13.87 14.07 14.20 14.16 14.13 14.34 14.50 14.46 14.00 12.58 10.99 9.98 9.22 8.62 8.07 7.39 6.71 6.16 5.63 5.03 4.46 4.02 3.66 3.36 3.09 2.85 2.65 2.51 2.37 2.15 1.89 1.61 1.32
+END_DATA
diff --git a/profile/Jamfile b/profile/Jamfile
index 780f9a5..5c286b9 100644
--- a/profile/Jamfile
+++ b/profile/Jamfile
@@ -7,11 +7,11 @@ PREF_LINKFLAGS += $(LINKDEBUGFLAG) ;
#Products
Libraries = libprof ;
Executables = cb2ti3 kodak2ti3 txt2ti3 splitti3 mppcheck mppprof
- profcheck invprofcheck verify colprof printcal applycal ;
+ profcheck invprofcheck colverify colprof printcal applycal ;
Headers = prof.h ;
Samples = example.sp example121.sp 3dap5k.sp GTIPlus.sp Office.sp Trulux.sp TruluxPlus.sp
D50_0.0.sp D50_0.1.sp D50_0.3.sp D50_0.5.sp D50_0.7.sp D50_1.0.sp D50_1.2.sp
- D50_1.5.sp D50_1.7.sp D50_2.0.sp D50_2.5.sp D50_3.0.sp CIE_C.sp ;
+ D50_1.5.sp D50_1.7.sp D50_2.0.sp D50_2.5.sp D50_3.0.sp CIE_C.sp F1.sp F5.sp F8.sp ;
#Install
InstallBin $(DESTDIR)$(PREFIX)/bin : $(Executables) ;
@@ -63,7 +63,7 @@ Main mppcheck : mppcheck.c ;
LINKLIBS = ../plot/libvrml $(LINKLIBS) ;
# Verifyer
-Main verify : verify.c ;
+Main colverify : colverify.c ;
LINKLIBS = libprof ../gamut/libgammap $(LINKLIBS) $(TIFFLIB) $(JPEGLIB) ;
diff --git a/profile/afiles b/profile/afiles
index 986bf70..8b3b980 100644
--- a/profile/afiles
+++ b/profile/afiles
@@ -9,7 +9,7 @@ profout.c
colprof.c
profcheck.c
invprofcheck.c
-verify.c
+colverify.c
applycal.c
mppprof.c
mppcheck.c
@@ -25,6 +25,9 @@ Trulux.sp
TruluxPlus.sp
example.sp
example121.sp
+F1.sp
+F5.sp
+F8.sp
CIE_C.sp
D50_0.0.sp
D50_0.1.sp
diff --git a/profile/colprof.c b/profile/colprof.c
index 99e02cf..b80f13c 100644
--- a/profile/colprof.c
+++ b/profile/colprof.c
@@ -59,13 +59,15 @@
#define DEFAVGDEV 0.5 /* Default average deviation percentage */
/* This equates to a uniform added error of +/- 1% */
+#define DEMPH_DEFAULT 1.0 /* Default dark region emphasis == none */
+
/*
Flags used:
ABCDEFGHIJKLMNOPQRSTUVWXYZ
upper . .. . ... .. .... .
- lower .... .. . .. ......... .
+ lower .... .. . .. .........
*/
@@ -94,7 +96,6 @@ void usage(char *diag, ...) {
// fprintf(stderr," -q fmsu Speed - Fast, Medium (def), Slow, Ultra Slow\n");
fprintf(stderr," -b [lmhun] Low quality B2A table - or specific B2A quality or none for input device\n");
// fprintf(stderr," -b [fmsun] B2A Speed - Fast, Medium, Slow, Ultra Slow, None, same as -q (def)\n");
- fprintf(stderr," -y Verify A2B profile\n");
fprintf(stderr," -ni Don't create input (Device) shaper curves\n");
fprintf(stderr," -np Don't create input (Device) grid position curves\n");
fprintf(stderr," -no Don't create output (PCS) shaper curves\n");
@@ -121,6 +122,7 @@ void usage(char *diag, ...) {
fprintf(stderr," -uc If input profile, clip cLUT values above WP\n");
fprintf(stderr," -U scale If input profile, scale media white point by scale\n");
fprintf(stderr," -R Restrict white <= 1.0, black and primaries to be +ve\n");
+ fprintf(stderr," -V demphasis Degree of dark region cLUT grid emphasis 1.0-4.0 (default %.2f = none)\n",DEMPH_DEFAULT);
fprintf(stderr," -f [illum] Use Fluorescent Whitening Agent compensation [opt. simulated inst. illum.:\n");
fprintf(stderr," M0, M1, M2, A, C, D50 (def.), D50M2, D65, F5, F8, F10 or file.sp]\n");
fprintf(stderr," -i illum Choose illuminant for computation of CIE XYZ from spectral data & FWA:\n");
@@ -172,7 +174,7 @@ int main(int argc, char *argv[]) {
int verb = 0;
int iquality = 1; /* A2B quality */
int oquality = -1; /* B2A quality same as A2B */
- int verify = 0;
+ int verify = 0; /* Not used anymore */
int noisluts = 0; /* No input shaper luts */
int noipluts = 0; /* No input position luts */
int nooluts = 0; /* No output shaper luts */
@@ -183,6 +185,7 @@ int main(int argc, char *argv[]) {
int autowpsc = 0; /* Auto scale the WP to prevent clipping above WP patch */
int clipovwp = 0; /* Clip cLUT values above WP */
int clipprims = 0; /* Clip white, black and primaries */
+ double demph = 0.0; /* Emphasise dark region grid resolution in cLUT */
double iwpscale = -1.0; /* Input white point scale factor */
int doinextrap = 1; /* Sythesize extra sample points for input device cLUT */
int doinb2a = 1; /* Create an input device B2A table */
@@ -238,7 +241,8 @@ int main(int argc, char *argv[]) {
ivc_p.Yb = -1.0;
ivc_p.Lv = -1.0;
ivc_p.Yf = -1.0;
- ivc_p.Fxyz[0] = -1.0; ivc_p.Fxyz[1] = -1.0; ivc_p.Fxyz[2] = -1.0;
+ ivc_p.Yg = -1.0;
+ ivc_p.Gxyz[0] = -1.0; ivc_p.Gxyz[1] = -1.0; ivc_p.Gxyz[2] = -1.0;
ovc_p.Ev = -1;
ovc_p.Wxyz[0] = -1.0; ovc_p.Wxyz[1] = -1.0; ovc_p.Wxyz[2] = -1.0;
@@ -246,7 +250,8 @@ int main(int argc, char *argv[]) {
ovc_p.Yb = -1.0;
ovc_p.Lv = -1.0;
ovc_p.Yf = -1.0;
- ovc_p.Fxyz[0] = -1.0; ovc_p.Fxyz[1] = -1.0; ovc_p.Fxyz[2] = -1.0;
+ ovc_p.Yg = -1.0;
+ ovc_p.Gxyz[0] = -1.0; ovc_p.Gxyz[1] = -1.0; ovc_p.Gxyz[2] = -1.0;
xicc_enum_gmapintent(&pgmi, icxPerceptualGMIntent, NULL);
xicc_enum_gmapintent(&sgmi, icxSaturationGMIntent, NULL);
@@ -276,7 +281,7 @@ int main(int argc, char *argv[]) {
if (argv[fa][1] == '?')
usage("Usage requested");
- else if (argv[fa][1] == 'v' || argv[fa][1] == 'V')
+ else if (argv[fa][1] == 'v')
verb = 1;
/* Manufacturer description string */
@@ -361,7 +366,7 @@ int main(int argc, char *argv[]) {
}
/* Quality */
- else if (argv[fa][1] == 'q' || argv[fa][1] == 'Q') {
+ else if (argv[fa][1] == 'q') {
fa = nfa;
// if (na == NULL) usage("Expect argument to quality flag -q");
if (na == NULL) usage("Expect argument to speed flag -q");
@@ -428,11 +433,8 @@ int main(int argc, char *argv[]) {
doinb2a = 0;
}
- else if (argv[fa][1] == 'y' || argv[fa][1] == 'Y')
- verify = 1;
-
/* Disable input or output luts */
- else if (argv[fa][1] == 'n' || argv[fa][1] == 'N') {
+ else if (argv[fa][1] == 'n') {
fa = nfa;
if (na == NULL) { /* Backwards compatible */
nooluts = 1;
@@ -468,7 +470,7 @@ int main(int argc, char *argv[]) {
fa = nfa;
if (na == NULL) usage("Expected argument to input white point scale flag -U");
iwpscale = atof(na);
- if (iwpscale < 0.0 || iwpscale > 100.0)
+ if (iwpscale < 0.0 || iwpscale > 200.0)
usage("Argument '%s' to flag -U out of range",na);
}
/* Clip primaries */
@@ -476,8 +478,18 @@ int main(int argc, char *argv[]) {
clipprims = 1;
}
+ /* Degree of dark region emphasis */
+ else if (argv[fa][1] == 'V') {
+ if (na == NULL) usage(0,"Expected argument to dark emphasis flag -V");
+ demph = atof(na);
+ if (demph < 1.0 || demph > 3.0)
+ usage("Dark weighting argument %f to '-V' is out of range",demph);
+ fa = nfa;
+ }
+
/* Inking rule */
- else if (argv[fa][1] == 'k' || argv[fa][1] == 'K') {
+ else if (argv[fa][1] == 'k'
+ || argv[fa][1] == 'K') {
fa = nfa;
if (na == NULL) usage("Expect argument to inking flag -k");
if (argv[fa][1] == 'k')
@@ -544,7 +556,7 @@ int main(int argc, char *argv[]) {
}
/* Algorithm type */
- else if (argv[fa][1] == 'a' || argv[fa][1] == 'A') {
+ else if (argv[fa][1] == 'a') {
fa = nfa;
if (na == NULL) usage("Expect argument to algorithm flag -a");
switch (na[0]) {
@@ -713,7 +725,8 @@ int main(int argc, char *argv[]) {
}
/* Percetual Source Gamut and Perceptual/Saturation Gamut Maping mode enable */
- else if (argv[fa][1] == 's' || argv[fa][1] == 'S') {
+ else if (argv[fa][1] == 's'
+ || argv[fa][1] == 'S') {
if (argv[fa][1] == 'S')
sepsat = 1;
if (na == NULL)
@@ -724,7 +737,7 @@ int main(int argc, char *argv[]) {
}
/* Source image gamut */
- else if (argv[fa][1] == 'g' || argv[fa][1] == 'G') {
+ else if (argv[fa][1] == 'g') {
if (na == NULL)
usage("Unrecognised argument to source image gamut flag -g",argv[fa][1]);
fa = nfa;
@@ -771,7 +784,8 @@ int main(int argc, char *argv[]) {
}
/* Viewing conditions */
- else if (argv[fa][1] == 'c' || argv[fa][1] == 'd') {
+ else if (argv[fa][1] == 'c'
+ || argv[fa][1] == 'd') {
icxViewCond *vc;
if (argv[fa][1] == 'c') {
@@ -781,7 +795,7 @@ int main(int argc, char *argv[]) {
}
fa = nfa;
- if (na == NULL) usage("Viewing conditions flag (-c) needs an argument");
+ if (na == NULL) usage("Viewing conditions flag (-%c) needs an argument",argv[fa][1]);
if (na[1] != ':') {
if (vc == &ivc_p) {
if ((ivc_e = xicc_enum_viewcond(NULL, NULL, -2, na, 1, NULL)) == -999)
@@ -792,7 +806,7 @@ int main(int argc, char *argv[]) {
}
} else if (na[0] == 's' || na[0] == 'S') {
if (na[1] != ':')
- usage("Viewing conditions (-cs) missing ':'");
+ usage("Viewing conditions (-%cs) missing ':'",argv[fa][1]);
if (na[2] == 'n' || na[2] == 'N') {
vc->Ev = vc_none; /* Automatic */
} else if (na[2] == 'a' || na[2] == 'A') {
@@ -804,7 +818,7 @@ int main(int argc, char *argv[]) {
} else if (na[2] == 'c' || na[2] == 'C') {
vc->Ev = vc_cut_sheet;
} else
- usage("Viewing condition (-c) unrecognised surround '%c'",na[2]);
+ usage("Viewing condition (-%c) unrecognised surround '%c'",argv[fa][1],na[2]);
} else if (na[0] == 'w' || na[0] == 'W') {
double x, y, z;
if (sscanf(na+1,":%lf:%lf:%lf",&x,&y,&z) == 3) {
@@ -812,31 +826,35 @@ int main(int argc, char *argv[]) {
} else if (sscanf(na+1,":%lf:%lf",&x,&y) == 2) {
vc->Wxyz[0] = x; vc->Wxyz[1] = y;
} else
- usage("Viewing condition (-cw) unrecognised white point '%s'",na+1);
+ usage("Viewing condition (-%cw) unrecognised white point '%s'",argv[fa][1],na+1);
} else if (na[0] == 'a' || na[0] == 'A') {
if (na[1] != ':')
- usage("Viewing conditions (-ca) missing ':'");
+ usage("Viewing conditions (-%ca) missing ':'",argv[fa][1]);
vc->La = atof(na+2);
} else if (na[0] == 'b' || na[0] == 'B') {
if (na[1] != ':')
- usage("Viewing conditions (-cb) missing ':'");
+ usage("Viewing conditions (-%cb) missing ':'",argv[fa][1]);
vc->Yb = atof(na+2)/100.0;
} else if (na[0] == 'l' || na[0] == 'L') {
if (na[1] != ':')
- usage("Viewing conditions (-[cd]l) missing ':'");
+ usage("Viewing conditions (-%cl) missing ':'",argv[fa][1]);
vc->Lv = atof(na+2);
} else if (na[0] == 'f' || na[0] == 'F') {
+ if (na[1] != ':')
+ usage("Viewing conditions (-%cf) missing ':'",argv[fa][1]);
+ vc->Yf = atof(na+2);
+ } else if (na[0] == 'g' || na[0] == 'G') {
double x, y, z;
if (sscanf(na+1,":%lf:%lf:%lf",&x,&y,&z) == 3) {
- vc->Fxyz[0] = x; vc->Fxyz[1] = y; vc->Fxyz[2] = z;
+ vc->Gxyz[0] = x; vc->Gxyz[1] = y; vc->Gxyz[2] = z;
} else if (sscanf(na+1,":%lf:%lf",&x,&y) == 2) {
- vc->Fxyz[0] = x; vc->Fxyz[1] = y;
+ vc->Gxyz[0] = x; vc->Gxyz[1] = y;
} else if (sscanf(na+1,":%lf",&x) == 1) {
- vc->Yf = x/100.0;
+ vc->Yg = x/100.0;
} else
- usage("Viewing condition (-cf) unrecognised flare '%s'",na+1);
+ usage("Viewing condition (-%cg) unrecognised flare '%s'",argv[fa][1],na+1);
} else
- usage("Viewing condition (-c) unrecognised sub flag '%c'",na[0]);
+ usage("Viewing condition (-%c) unrecognised sub flag '%c'",argv[fa][1],na[0]);
}
/* Gammut mapping diagnostic plots */
@@ -929,6 +947,18 @@ int main(int argc, char *argv[]) {
error ("Requested spectral interpretation when data not available");
}
+ /* If not set in arguments, set default demph from .ti1 or default none */
+ if (demph == 0.0) {
+ if ((ti = icg->find_kword(icg, 0, "DARK_REGION_EMPHASIS")) >= 0) {
+ demph = atof(icg->t[0].kdata[ti]);
+ demph = pow(demph, 0.7); /* Reduce intensity */
+ if (verb)
+ printf("Dark emphasis factor %f from targen\n",demph);
+ } else {
+ demph = DEMPH_DEFAULT;
+ }
+ }
+
/* read the device class, and call function to create profile. */
if ((ti = icg->find_kword(icg, 0, "DEVICE_CLASS")) < 0)
error ("Input file doesn't contain keyword DEVICE_CLASS");
@@ -1045,9 +1075,9 @@ int main(int argc, char *argv[]) {
make_output_icc(ptype, 0, iccver, verb, iquality, oquality,
noisluts, noipluts, nooluts, nocied, noptop, nostos,
- gamdiag, verify, clipprims, &ink, inname, outname, icg,
+ gamdiag, verify, clipprims, iwpscale, &ink, inname, outname, icg,
spec, tillum, &cust_tillum, illum, &cust_illum, observ, fwacomp,
- smooth, avgdev,
+ smooth, avgdev, 1.0,
ipname[0] != '\000' ? ipname : NULL,
sgname[0] != '\000' ? sgname : NULL,
absnames,
@@ -1083,9 +1113,9 @@ int main(int argc, char *argv[]) {
/* If a source gamut is provided for a Display, then a V2.4.0 profile will be created */
make_output_icc(ptype, mtxtoo, iccver, verb, iquality, oquality,
noisluts, noipluts, nooluts, nocied, noptop, nostos,
- gamdiag, verify, clipprims, NULL, inname, outname, icg,
+ gamdiag, verify, clipprims, iwpscale, NULL, inname, outname, icg,
spec, icxIT_none, NULL, illum, &cust_illum, observ, 0,
- smooth, avgdev,
+ smooth, avgdev, demph,
ipname[0] != '\000' ? ipname : NULL,
sgname[0] != '\000' ? sgname : NULL,
absnames,
diff --git a/profile/verify.c b/profile/colverify.c
index 849d7fc..ba09366 100644
--- a/profile/verify.c
+++ b/profile/colverify.c
@@ -46,9 +46,10 @@ usage(void) {
fprintf(stderr,"Verify CIE values, Version %s\n",ARGYLL_VERSION_STR);
fprintf(stderr,"Author: Graeme W. Gill, licensed under the AGPL Version 3\n");
fprintf(stderr,"usage: verify [-options] target.ti3 measured.ti3\n");
- fprintf(stderr," -v Verbose - print each patch value\n");
- fprintf(stderr," -n Normalise each files reading to white Y\n");
- fprintf(stderr," -N Normalise each files reading to white XYZ\n");
+ fprintf(stderr," -v [n] Verbose mode, n >= 2 print each value\n");
+ fprintf(stderr," -n Normalise each files reading to its white Y\n");
+ fprintf(stderr," -N Normalise each files reading to its white XYZ\n");
+ fprintf(stderr," -m Normalise each files reading to its white X+Y+Z\n");
fprintf(stderr," -D Use D50 100.0 as L*a*b* white reference\n");
fprintf(stderr," -c Show CIE94 delta E values\n");
fprintf(stderr," -k Show CIEDE2000 delta E values\n");
@@ -62,6 +63,7 @@ usage(void) {
fprintf(stderr," A, C, D50 (def.), D50M2, D65, F5, F8, F10 or file.sp\n");
fprintf(stderr," -o observ Choose CIE Observer for spectral data:\n");
fprintf(stderr," 1931_2 (def), 1964_10, S&B 1955_2, shaw, J&V 1978_2\n");
+ fprintf(stderr," -L profile.%s Skip any first file out of profile gamut patches\n",ICC_FILE_EXT_ND);
fprintf(stderr," -X file.ccmx Apply Colorimeter Correction Matrix to second file\n");
fprintf(stderr," target.ti3 Target (reference) PCS or spectral values.\n");
fprintf(stderr," measured.ti3 Measured (actual) PCS or spectral values\n");
@@ -71,16 +73,22 @@ usage(void) {
/* Patch value type */
typedef struct {
char sid[50]; /* sample id */
+ char loc[100]; /* sample location (empty if none) */
+ int og; /* Out of gamut flag */
+ double xyz[3]; /* XYZ value */
double v[3]; /* Lab value */
double de; /* Delta E */
+ double ixde[3]; /* XYZ Component DE */
+ double ide[3]; /* Lab Component DE */
} pval;
int main(int argc, char *argv[])
{
- int fa,nfa; /* current argument we're looking at */
- int verb = 0;
- int norm = 0; /* 1 = norm to Y, 2 = norm to XYZ */
- int usestdd50 = 0; /* Use standard D50 instead of scaled D50 as Lab reference */
+ int fa,nfa,mfa; /* current argument we're looking at */
+ int verb = 0; /* Verbose level */
+ int norm = 0; /* 1 = norm to White Y, 2 = norm to White XYZ */
+ /* 3 = norm to White X+Y+Z */
+ int usestdd50 = 0; /* Use standard D50 instead of avg white as reference */
int cie94 = 0;
int cie2k = 0;
int dovrml = 0;
@@ -88,12 +96,20 @@ int main(int argc, char *argv[])
int dosort = 0;
char ccmxname[MAXNAMEL+1] = "\000"; /* Colorimeter Correction Matrix name */
ccmx *cmx = NULL; /* Colorimeter Correction Matrix */
+ char gprofname[MAXNAMEL+1] = "\000"; /* Gamut limit profile name */
+ icmFile *fp = NULL;
+ icc *icco = NULL;
+ xicc *xicco = NULL;
+ icxLuBase *luo = NULL;
struct {
char name[MAXNAMEL+1]; /* Patch filename */
int isdisp; /* nz if display */
int isdnormed; /* Has display data been normalised to 100 ? */
int npat; /* Number of patches */
+ int nig; /* Number of patches in gamut */
+ double w[3]; /* XYZ of "white" */
+ double nw[3]; /* Normalised XYZ of "white" */
pval *pat; /* patch values */
} cg[2]; /* Target and current patch file information */
@@ -123,6 +139,7 @@ int main(int argc, char *argv[])
usage();
/* Process the arguments */
+ mfa = 2; /* Minimum final arguments */
for(fa = 1;fa < argc;fa++) {
nfa = fa; /* skip to nfa if next argument is used */
@@ -132,7 +149,7 @@ int main(int argc, char *argv[])
if (argv[fa][2] != '\000')
na = &argv[fa][2]; /* next is directly after flag */
else {
- if ((fa+1) < argc) {
+ if ((fa+1+mfa) < argc) {
if (argv[fa+1][0] != '-') {
nfa = fa + 1;
na = argv[nfa]; /* next is seperate non-flag argument */
@@ -143,16 +160,28 @@ int main(int argc, char *argv[])
if (argv[fa][1] == '?')
usage();
- else if (argv[fa][1] == 'v' || argv[fa][1] == 'V')
+ /* Verbose */
+ else if (argv[fa][1] == 'v') {
verb = 1;
+ if (na != NULL && na[0] >= '0' && na[0] <= '9') {
+ verb = atoi(na);
+ fa = nfa;
+ }
+ }
+
/* normalize */
- else if (argv[fa][1] == 'n' || argv[fa][1] == 'N') {
+ else if (argv[fa][1] == 'n'
+ || argv[fa][1] == 'N') {
norm = 1;
if (argv[fa][1] == 'N')
norm = 2;
}
+ else if (argv[fa][1] == 'm') {
+ norm = 3;
+ }
+
else if (argv[fa][1] == 'D')
usestdd50 = 1;
@@ -167,18 +196,18 @@ int main(int argc, char *argv[])
doaxes = 1;
/* CIE94 delta E */
- else if (argv[fa][1] == 'c' || argv[fa][1] == 'C') {
+ else if (argv[fa][1] == 'c') {
cie94 = 1;
cie2k = 0;
}
- else if (argv[fa][1] == 'k' || argv[fa][1] == 'K') {
+ else if (argv[fa][1] == 'k') {
cie94 = 0;
cie2k = 1;
}
/* Sort */
- else if (argv[fa][1] == 's' || argv[fa][1] == 'S')
+ else if (argv[fa][1] == 's')
dosort = 1;
/* FWA compensation */
@@ -224,7 +253,7 @@ int main(int argc, char *argv[])
}
/* Spectral to CIE Illuminant type */
- else if (argv[fa][1] == 'i' || argv[fa][1] == 'I') {
+ else if (argv[fa][1] == 'i') {
fa = nfa;
if (na == NULL) usage();
if (strcmp(na, "A") == 0) {
@@ -260,7 +289,7 @@ int main(int argc, char *argv[])
}
/* Spectral Observer type */
- else if (argv[fa][1] == 'o' || argv[fa][1] == 'O') {
+ else if (argv[fa][1] == 'o') {
fa = nfa;
if (na == NULL) usage();
if (strcmp(na, "1931_2") == 0) { /* Classic 2 degree */
@@ -282,6 +311,13 @@ int main(int argc, char *argv[])
usage();
}
+ /* Gamut limit profile for first file */
+ else if (argv[fa][1] == 'L') {
+ fa = nfa;
+ if (na == NULL) usage();
+ strncpy(gprofname,na,MAXNAMEL-1); gprofname[MAXNAMEL-1] = '\000';
+ }
+
/* Colorimeter Correction Matrix for second file */
else if (argv[fa][1] == 'X') {
fa = nfa;
@@ -313,6 +349,35 @@ int main(int argc, char *argv[])
if (fwacomp && spec == 0)
error ("FWA compensation only works when viewer and/or illuminant selected");
+ /* Gamut limit profile */
+ if (gprofname[0] != '\000') {
+ int rv;
+
+ if ((fp = new_icmFileStd_name(gprofname,"r")) == NULL)
+ error ("Can't open file '%s'",gprofname);
+
+ if ((icco = new_icc()) == NULL)
+ error ("Creation of ICC object failed");
+
+ if ((rv = icco->read(icco,fp,0)) != 0)
+ error("Reading profile '%s' failed failed with error %d:'%s'\n",
+ gprofname, icco->errc, icco->err);
+
+ if (icco->header->deviceClass != icSigInputClass
+ && icco->header->deviceClass != icSigDisplayClass
+ && icco->header->deviceClass != icSigOutputClass)
+ error("Profile '%s' must be a device profile to filter by gamut",gprofname);
+
+ /* Wrap with an expanded icc */
+ if ((xicco = new_xicc(icco)) == NULL)
+ error ("Creation of xicc failed");
+
+ /* Get a expanded color conversion object */
+ if ((luo = xicco->get_luobj(xicco, ICX_CLIP_NEAREST | ICX_FAST_SETUP,
+ icmFwd, icRelativeColorimetric, icSigXYZData, icmLuOrdNorm, NULL, NULL)) == NULL)
+ error ("%d, %s",xicco->errc, xicco->err);
+ }
+
/* Colorimeter Correction Matrix */
if (ccmxname[0] != '\000') {
if ((cmx = new_ccmx()) == NULL)
@@ -322,12 +387,14 @@ int main(int argc, char *argv[])
ccmxname, cmx->errc, cmx->err);
}
+
/* Open up each file in turn, target then measured, */
/* and read in the CIE values. */
for (n = 0; n < 2; n++) {
cgats *cgf = NULL; /* cgats file data */
int isLab = 0; /* 0 if file CIE is XYZ, 1 if is Lab */
int sidx; /* Sample ID index */
+ int sldx = -1; /* Sample location index, < 0 if invalid */
int xix, yix, zix;
/* Open CIE target values */
@@ -361,29 +428,41 @@ int main(int argc, char *argv[])
if (!spec && cgf->find_field(cgf, 0, "LAB_L") >= 0)
isLab = 1;
- cg[n].npat = cgf->t[0].nsets; /* Number of patches */
+ cg[n].nig = cg[n].npat = cgf->t[0].nsets; /* Number of patches */
/* Figure out what sort of device it is */
{
int ti;
cg[n].isdisp = 0;
+ cg[n].isdnormed = 0;
+ cg[n].w[0] = cg[n].w[1] = cg[n].w[2] = 0.0;
if ((ti = cgf->find_kword(cgf, 0, "DEVICE_CLASS")) < 0)
error ("Input file '%s' doesn't contain keyword DEVICE_CLASS",cg[n].name);
if (strcmp(cgf->t[0].kdata[ti],"DISPLAY") == 0) {
cg[n].isdisp = 1;
+ cg[n].isdnormed = 1; /* Assume display type is normalised to 100 */
illum = icxIT_none; /* Displays are assumed to be self luminous */
/* ?? What if two files are different ?? */
}
- /* See if the CIE data has been normalised to Y = 100 */
- if ((ti = cgf->find_kword(cgf, 0, "NORMALIZED_TO_Y_100")) < 0
- || strcmp(cgf->t[0].kdata[ti],"NO") == 0) {
- cg[n].isdnormed = 0;
- } else {
- cg[n].isdnormed = 1;
+ if (cg[n].isdisp) {
+
+ if ((ti = cgf->find_kword(cgf, 0, "LUMINANCE_XYZ_CDM2")) >= 0) {
+ if (sscanf(cgf->t[0].kdata[ti], " %lf %lf %lf ",&cg[n].w[0], &cg[n].w[1], &cg[n].w[2]) != 3)
+ cg[n].w[0] = cg[n].w[1] = cg[n].w[2] = 0.0;
+ }
+
+ /* See if there is an explicit tag indicating data has been normalised to Y = 100 */
+ if ((ti = cgf->find_kword(cgf, 0, "NORMALIZED_TO_Y_100")) >= 0) {
+ if (strcmp(cgf->t[0].kdata[ti],"NO") == 0) {
+ cg[n].isdnormed = 0;
+ } else {
+ cg[n].isdnormed = 1;
+ }
+ }
}
}
@@ -410,6 +489,10 @@ int main(int argc, char *argv[])
&& cgf->t[0].ftype[sidx] != cs_t)
error("Sample ID/Name field isn't a quoted or non quoted character string");
+ if ((sldx = cgf->find_field(cgf, 0, "SAMPLE_LOC")) < 0
+ || cgf->t[0].ftype[sldx] != cs_t)
+ sldx = -1;
+
if (spec == 0) { /* Using instrument tristimulous value */
if (isLab) { /* Expect Lab */
@@ -443,24 +526,39 @@ int main(int argc, char *argv[])
for (i = 0; i < cg[n].npat; i++) {
strcpy(cg[n].pat[i].sid, (char *)cgf->t[0].fdata[i][sidx]);
- cg[n].pat[i].v[0] = *((double *)cgf->t[0].fdata[i][xix]);
- cg[n].pat[i].v[1] = *((double *)cgf->t[0].fdata[i][yix]);
- cg[n].pat[i].v[2] = *((double *)cgf->t[0].fdata[i][zix]);
-
- if (!isLab) { /* If XYZ */
-
- /* If normalised to 100, scale back to 1.0 */
- if (!cg[n].isdisp || !cg[n].isdnormed) {
- cg[n].pat[i].v[0] /= 100.0; /* scale back to 1.0 */
- cg[n].pat[i].v[1] /= 100.0;
- cg[n].pat[i].v[2] /= 100.0;
+ if (sldx >= 0)
+ strcpy(cg[n].pat[i].loc, (char *)cgf->t[0].fdata[i][sldx]);
+ else
+ cg[n].pat[i].loc[0] = '\000';
+ cg[n].pat[i].og = 0;
+ cg[n].pat[i].xyz[0] = *((double *)cgf->t[0].fdata[i][xix]);
+ cg[n].pat[i].xyz[1] = *((double *)cgf->t[0].fdata[i][yix]);
+ cg[n].pat[i].xyz[2] = *((double *)cgf->t[0].fdata[i][zix]);
+
+ if (isLab) { /* Convert to XYZ */
+ icmLab2XYZ(&icmD50, cg[n].pat[i].xyz, cg[n].pat[i].xyz);
+ }
+//printf("~1 file %d patch %d = XYZ %f %f %f\n", n,i,cg[n].pat[i].xyz[0],cg[n].pat[i].xyz[1],cg[n].pat[i].xyz[2]);
+
+ /* restore normalised display values to absolute */
+ if (cg[n].isdnormed) {
+ if (cg[n].w[1] > 0.0) {
+ cg[n].pat[i].xyz[0] *= cg[n].w[1]/100.0;
+ cg[n].pat[i].xyz[1] *= cg[n].w[1]/100.0;
+ cg[n].pat[i].xyz[2] *= cg[n].w[1]/100.0;
}
- } else { /* If Lab */
- icmLab2XYZ(&icmD50, cg[n].pat[i].v, cg[n].pat[i].v);
+
+ } else if (!cg[n].isdisp) {
+ /* If reflective or transmissive that are 0..100%, */
+ /* scale back to 0.. 1 */
+ cg[n].pat[i].xyz[0] /= 100.0; /* scale back to XYZ 1.0 */
+ cg[n].pat[i].xyz[1] /= 100.0;
+ cg[n].pat[i].xyz[2] /= 100.0;
}
+
/* Apply ccmx */
if (n == 1 && cmx != NULL) {
- cmx->xform(cmx, cg[n].pat[i].v, cg[n].pat[i].v);
+ cmx->xform(cmx, cg[n].pat[i].xyz, cg[n].pat[i].xyz);
}
}
@@ -563,6 +661,11 @@ int main(int argc, char *argv[])
for (i = 0; i < cg[0].npat; i++) {
strcpy(cg[n].pat[i].sid, (char *)cgf->t[0].fdata[i][sidx]);
+ if (sldx >= 0)
+ strcpy(cg[n].pat[i].loc, (char *)cgf->t[0].fdata[i][sldx]);
+ else
+ cg[n].pat[i].loc[0] = '\000';
+ cg[n].pat[i].og = 0;
/* Read the spectral values for this patch */
for (j = 0; j < sp.spec_n; j++) {
@@ -570,11 +673,21 @@ int main(int argc, char *argv[])
}
/* Convert it to XYZ space */
- sp2cie->convert(sp2cie, cg[n].pat[i].v, &sp);
+ sp2cie->convert(sp2cie, cg[n].pat[i].xyz, &sp);
+
+ /* restore normalised display values to absolute */
+ if (cg[n].isdnormed) {
+ if (cg[n].w[1] > 0.0) {
+ cg[n].pat[i].xyz[0] *= cg[n].w[1];
+ cg[n].pat[i].xyz[1] *= cg[n].w[1];
+ cg[n].pat[i].xyz[2] *= cg[n].w[1];
+ }
- /* Applu ccmx */
+ }
+
+ /* Apply ccmx */
if (n == 1 && cmx != NULL) {
- cmx->xform(cmx, cg[n].pat[i].v, cg[n].pat[i].v);
+ cmx->xform(cmx, cg[n].pat[i].xyz, cg[n].pat[i].xyz);
}
}
@@ -583,31 +696,68 @@ int main(int argc, char *argv[])
} /* End of reading in CGATs file */
- /* Normalise this file to white = 1.0 or D50 */
+ /* Locate the patch with maximum Y, a possible white patch */
if (norm) {
- double bxyz[3] = { 0.0, -100.0, 0.0 };
+ int ii;
- /* Locate patch with biggest Y */
- for (i = 0; i < cg[n].npat; i++) {
- double xyz[3];
- icmLab2XYZ(&icmD50, xyz, cg[n].pat[i].v);
- if (cg[n].pat[i].v[1] > bxyz[1]) {
- icmCpy3(bxyz, cg[n].pat[i].v);
+ if (cg[n].w[1] == 0.0) { /* No white patch */
+
+ /* Locate patch with biggest Y, assume it is white... */
+ for (i = 0; i < cg[n].npat; i++) {
+ if (cg[n].pat[i].xyz[1] > cg[n].w[1]) {
+ icmCpy3(cg[n].w, cg[n].pat[i].xyz);
+ ii = i;
+ }
}
+ if (verb) printf("File %d Chose patch %d as white, xyz %f %f %f\n",
+ n, ii+1,cg[n].w[0],cg[n].w[1],cg[n].w[2]);
+ } else {
+ if (verb) printf("File %d White is from display luminance ref. xyz %f %f %f\n",
+ n, cg[n].w[0],cg[n].w[1],cg[n].w[2]);
+ }
+ icmCpy3(cg[n].nw, cg[n].w);
+ }
+
+
+ /* Normalise this file to white = 1.0 or D50 */
+ if (norm) {
+ int ii;
+
+ double chmat[3][3]; /* Chromatic adapation matrix */
+
+ if (norm == 2) { /* Norm to white XYZ */
+ icmXYZNumber s_wp;
+ icmAry2XYZ(s_wp, cg[n].w);
+ icmChromAdaptMatrix(ICM_CAM_BRADFORD, icmD50, s_wp, chmat);
}
- /* Then normalize all the values */
for (i = 0; i < cg[n].npat; i++) {
if (norm == 1) {
- cg[n].pat[i].v[0] /= bxyz[1];
- cg[n].pat[i].v[1] /= bxyz[1];
- cg[n].pat[i].v[2] /= bxyz[1];
+ cg[n].pat[i].xyz[0] *= 100.0 / cg[n].w[1];
+ cg[n].pat[i].xyz[1] *= 100.0 / cg[n].w[1];
+ cg[n].pat[i].xyz[2] *= 100.0 / cg[n].w[1];
+ } else if (norm == 2) {
+ icmMulBy3x3(cg[n].pat[i].xyz, chmat, cg[n].pat[i].xyz);
} else {
- cg[n].pat[i].v[0] *= icmD50.X/bxyz[0];
- cg[n].pat[i].v[1] *= icmD50.Y/bxyz[1];
- cg[n].pat[i].v[2] *= icmD50.Z/bxyz[2];
+ cg[n].pat[i].xyz[0] *= 100.0 / (cg[n].w[0] + cg[n].w[1] + cg[n].w[2]);
+ cg[n].pat[i].xyz[1] *= 100.0 / (cg[n].w[0] + cg[n].w[1] + cg[n].w[2]);
+ cg[n].pat[i].xyz[2] *= 100.0 / (cg[n].w[0] + cg[n].w[1] + cg[n].w[2]);
}
+//printf("~1 file %d patch %d = norm XYZ %f %f %f\n", n,i,cg[n].pat[i].xyz[0],cg[n].pat[i].xyz[1],cg[n].pat[i].xyz[2]);
}
+ /* Compute normalised white too */
+ if (norm == 1) {
+ cg[n].nw[0] *= 100.0 / cg[n].w[1];
+ cg[n].nw[1] *= 100.0 / cg[n].w[1];
+ cg[n].nw[2] *= 100.0 / cg[n].w[1];
+ } else if (norm == 2) {
+ icmMulBy3x3(cg[n].nw, chmat, cg[n].w);
+ } else {
+ cg[n].nw[0] *= 100.0 / (cg[n].w[0] + cg[n].w[1] + cg[n].w[2]);
+ cg[n].nw[1] *= 100.0 / (cg[n].w[0] + cg[n].w[1] + cg[n].w[2]);
+ cg[n].nw[2] *= 100.0 / (cg[n].w[0] + cg[n].w[1] + cg[n].w[2]);
+ }
+//printf("~1 file %d norm white XYZ %f %f %f\n", n,cg[n].nw[0], cg[n].nw[1], cg[n].nw[2]);
}
cgf->del(cgf); /* Clean up */
}
@@ -634,19 +784,46 @@ int main(int argc, char *argv[])
}
}
- /* Adjust the reference white Y to be larger than the largest Y of the two files */
- if (!usestdd50) {
- double maxy = -1e6;
-
- for (n = 0; n < 2; n++) {
- for (i = 0; i < cg[n].npat; i++) {
- if (cg[n].pat[i].v[1] > maxy)
- maxy = cg[n].pat[i].v[1];
+ /* Figure out which patches to skip because they are out of gamut */
+ if (luo != NULL) {
+ double chmat[3][3]; /* Chromatic adapation matrix */
+ double out[MAX_CHAN], in[3], check[3];
+ icmXYZNumber s_wp;
+ int rv;
+
+ /* Convert sample PCS to relative */
+ icmAry2XYZ(s_wp, cg[0].nw);
+ icmChromAdaptMatrix(ICM_CAM_BRADFORD, icmD50, s_wp, chmat);
+
+ for (i = 0; i < cg[0].npat; i++) {
+ icmMulBy3x3(in, chmat, cg[0].pat[i].xyz);
+//printf("~1 %d: xyz %f %f %f, rel %f %f %f\n", i+1, cg[0].pat[i].xyz[0], cg[0].pat[i].xyz[1], cg[0].pat[i].xyz[2], in[0], in[1], in[2]);
+
+ if ((rv = luo->inv_lookup(luo, out, in)) > 0 || 1) {
+ double de;
+
+ luo->lookup(luo, check, out);
+ de = icmXYZLabDE(&icmD50,check, in);
+//printf("~1 %d: rv %d, de %f, check XYZ %f %f %f\n",i+1,rv, de, check[0],check[1],check[2]);
+
+ if (de >= 0.01) {
+ cg[0].pat[i].og = 1;
+//printf("~1 Patch %d is out of gamut by DE %f RGB %f %f %f\n",i+1,de,out[0],out[1],out[2]);
+ if (verb >= 3)
+ printf("Patch %d is out of gamut by DE %f\n",i+1,de);
+ cg[0].nig--;
+ }
}
}
- labw.X *= maxy/icmD50.Y; /* Scale white uniformly */
- labw.Y *= maxy/icmD50.Y; /* Scale white uniformly */
- labw.Z *= maxy/icmD50.Y;
+ if (verb)
+ fprintf(verbo,"No of test patches in gamut = %d/%d\n",cg[0].npat - cg[0].nig,cg[0].npat);
+ }
+
+ /* Adjust the Lab reference white to be the mean of the white of the two files */
+ if (norm != 0 && !usestdd50) {
+ labw.X = 0.5 * (cg[0].nw[0] + cg[1].nw[0]);
+ labw.Y = 0.5 * (cg[0].nw[1] + cg[1].nw[1]);
+ labw.Z = 0.5 * (cg[0].nw[2] + cg[1].nw[2]);
if (verb)
printf("L*a*b* white reference = XYZ %f %f %f\n",labw.X,labw.Y,labw.Z);
@@ -655,18 +832,30 @@ int main(int argc, char *argv[])
/* Convert XYZ to Lab */
for (n = 0; n < 2; n++) {
for (i = 0; i < cg[n].npat; i++) {
- icmXYZ2Lab(&labw, cg[n].pat[i].v, cg[n].pat[i].v);
+ icmXYZ2Lab(&labw, cg[n].pat[i].v, cg[n].pat[i].xyz);
}
}
/* Compute the delta E's */
for (i = 0; i < cg[0].npat; i++) {
+
+ if (cg[0].pat[i].og) /* Skip out of gamut patches */
+ continue;
+
+ cg[0].pat[i].ixde[0] = fabs(cg[0].pat[i].xyz[0] - cg[1].pat[match[i]].xyz[0]);
+ cg[0].pat[i].ixde[1] = fabs(cg[0].pat[i].xyz[1] - cg[1].pat[match[i]].xyz[1]);
+ cg[0].pat[i].ixde[2] = fabs(cg[0].pat[i].xyz[2] - cg[1].pat[match[i]].xyz[2]);
+
if (cie2k)
cg[0].pat[i].de = icmCIE2K(cg[0].pat[i].v, cg[1].pat[match[i]].v);
else if (cie94)
cg[0].pat[i].de = icmCIE94(cg[0].pat[i].v, cg[1].pat[match[i]].v);
else
cg[0].pat[i].de = icmLabDE(cg[0].pat[i].v, cg[1].pat[match[i]].v);
+
+ cg[0].pat[i].ide[0] = fabs(cg[0].pat[i].v[0] - cg[1].pat[match[i]].v[0]);
+ cg[0].pat[i].ide[1] = fabs(cg[0].pat[i].v[1] - cg[1].pat[match[i]].v[1]);
+ cg[0].pat[i].ide[2] = fabs(cg[0].pat[i].v[2] - cg[1].pat[match[i]].v[2]);
}
/* Create sorted list, from worst to best. */
@@ -688,6 +877,8 @@ int main(int argc, char *argv[])
int n10;
double merr10 = 0.0, aerr10 = 0.0;
double rad;
+ double aierr[3] = { 0.0, 0.0, 0.0 };
+ double aixerr[3] = { 0.0, 0.0, 0.0 };
if (dovrml) {
wrl = new_vrml(out_name, doaxes, 0);
@@ -700,6 +891,10 @@ int main(int argc, char *argv[])
/* Do overall results */
for (i = 0; i < cg[0].npat; i++) {
double de;
+
+ if (cg[0].pat[i].og) /* Skip out of gamut patches */
+ continue;
+
if (dosort)
j = sort[i];
else
@@ -708,12 +903,29 @@ int main(int argc, char *argv[])
de = cg[0].pat[j].de;
aerr += de;
- if (verb) {
- printf("%s: %f %f %f <=> %f %f %f de %f\n",
+ aierr[0] += cg[0].pat[j].ide[0];
+ aierr[1] += cg[0].pat[j].ide[1];
+ aierr[2] += cg[0].pat[j].ide[2];
+
+ aixerr[0] += cg[0].pat[j].ixde[0];
+ aixerr[1] += cg[0].pat[j].ixde[1];
+ aixerr[2] += cg[0].pat[j].ixde[2];
+
+ if (verb >= 2) {
+
+ printf("%s%s%s: %f %f %f <=> %f %f %f de %f\n",
cg[0].pat[j].sid,
+ cg[0].pat[j].loc[0] != '\000' ? " " : "",
+ cg[0].pat[j].loc,
cg[0].pat[j].v[0], cg[0].pat[j].v[1], cg[0].pat[j].v[2],
cg[1].pat[match[j]].v[0], cg[1].pat[match[j]].v[1], cg[1].pat[match[j]].v[2],
de);
+
+#ifdef NEVER /* Print XYZ as well */
+ printf(" %f %f %f <=> %f %f %f\n",
+ cg[0].pat[j].xyz[0], cg[0].pat[j].xyz[1], cg[0].pat[j].xyz[2],
+ cg[1].pat[match[j]].xyz[0], cg[1].pat[match[j]].xyz[1], cg[1].pat[match[j]].xyz[2]);
+#endif
}
if (de > merr)
@@ -731,8 +943,16 @@ int main(int argc, char *argv[])
}
}
- if (cg[0].npat > 0)
- aerr /= (double)cg[0].npat;
+ if (cg[0].nig > 0) {
+ aerr /= (double)cg[0].nig;
+ aierr[0] /= (double)cg[0].nig;
+ aierr[1] /= (double)cg[0].nig;
+ aierr[2] /= (double)cg[0].nig;
+
+ aixerr[0] /= (double)cg[0].nig;
+ aixerr[1] /= (double)cg[0].nig;
+ aixerr[2] /= (double)cg[0].nig;
+ }
if (dovrml) {
wrl->make_lines(wrl, 0, 2);
@@ -741,23 +961,33 @@ int main(int argc, char *argv[])
}
/* Do best 90% */
- n90 = (int)(cg[0].npat * 9.0/10.0 + 0.5);
- for (i = (cg[0].npat-n90); i < cg[0].npat; i++) {
+ n90 = (int)(cg[0].nig * 9.0/10.0 + 0.5);
+ for (i = j = 0; i < cg[0].npat; i++) {
double de = cg[0].pat[sort[i]].de;
- aerr90 += de;
- if (de > merr90)
- merr90 = de;
+ if (cg[0].pat[i].og) /* Skip out of gamut */
+ continue;
+ if (j >= (cg[0].nig-n90)) { /* If in top 90% of in gamut patches */
+ aerr90 += de;
+ if (de > merr90)
+ merr90 = de;
+ }
+ j++; /* Index of within gamut patches */
}
if (n90 > 0)
aerr90 /= (double)n90;
/* Do worst 10% */
- n10 = (int)(cg[0].npat * 1.0/10.0 + 0.5);
- for (i = 0; i < n10; i++) {
+ n10 = (int)(cg[0].nig * 1.0/10.0 + 0.5);
+ for (i = j = 0; i < cg[0].npat; i++) {
double de = cg[0].pat[sort[i]].de;
- aerr10 += de;
- if (de > merr10)
- merr10 = de;
+ if (cg[0].pat[i].og) /* Skip out of gamut */
+ continue;
+ if (j <= n10) { /* If in worst 10% of in gamut patches */
+ aerr10 += de;
+ if (de > merr10)
+ merr10 = de;
+ }
+ j++;
}
if (n10 > 0)
aerr10 /= (double)n10;
@@ -770,6 +1000,8 @@ int main(int argc, char *argv[])
printf(" Total errors%s: peak = %f, avg = %f\n", cie2k ? " (CIEDE2000)" : cie94 ? " (CIE94)" : "", merr, aerr);
printf(" Worst 10%% errors%s: peak = %f, avg = %f\n", cie2k ? " (CIEDE2000)" : cie94 ? " (CIE94)" : "", merr10, aerr10);
printf(" Best 90%% errors%s: peak = %f, avg = %f\n", cie2k ? " (CIEDE2000)" : cie94 ? " (CIE94)" : "", merr90, aerr90);
+ printf(" avg err X %f, Y %f, Z %f\n", aixerr[0], aixerr[1], aixerr[2]);
+ printf(" avg err L* %f, a* %f, b* %f\n", aierr[0], aierr[1], aierr[2]);
free(sort);
free(match);
@@ -777,6 +1009,15 @@ int main(int argc, char *argv[])
free(cg[1].pat);
}
+ if (luo != NULL)
+ luo->del(luo);
+ if (xicco != NULL)
+ xicco->del(xicco); /* Expansion wrapper */
+ if (icco != NULL)
+ icco->del(icco); /* Icc */
+ if (fp != NULL)
+ fp->del(fp);
+
return 0;
}
diff --git a/profile/prof.h b/profile/prof.h
index 074bb73..6013d99 100644
--- a/profile/prof.h
+++ b/profile/prof.h
@@ -49,6 +49,7 @@ void make_output_icc(
int gamdiag, /* Make gamut mapping diagnostic wrl plots */
int verify, /* nz to print verification */
int clipprims, /* Clip white, black and primaries */
+ double wpscale, /* >= 0.0 for media white point scale factor */
icxInk *ink, /* Ink limit/black generation setup */
char *in_name, /* input .ti3 file name */
char *file_name, /* output icc name */
@@ -62,6 +63,7 @@ void make_output_icc(
int fwacomp, /* FWA compensation requested */
double smooth, /* RSPL smoothing factor, -ve if raw */
double avgdev, /* reading Average Deviation as a proportion of the input range */
+ double demph, /* Emphasise dark region grid resolution in cLUT */
char *ipname, /* input icc profile - enables gamut map, NULL if none */
char *sgname, /* source image gamut - NULL if none */
char *absname[3], /* abstract profile name for each table */
diff --git a/profile/profcheck.c b/profile/profcheck.c
index ca9b0b2..1895713 100644
--- a/profile/profcheck.c
+++ b/profile/profcheck.c
@@ -507,7 +507,7 @@ int main(int argc, char *argv[])
/* Read in the CGATs fields */
{
int sidx; /* Sample ID index */
- int sloc; /* Sample location indexi (if any) */
+ int sloc; /* Sample location index (if any) */
int ti, ci, mi, yi, ki;
int Xi, Yi, Zi;
diff --git a/profile/profin.c b/profile/profin.c
index 2f74ec2..c703c42 100644
--- a/profile/profin.c
+++ b/profile/profin.c
@@ -825,6 +825,8 @@ make_input_icc(
flags |= ICX_SET_BLACK; /* Compute & use black */
flags |= ICX_SET_WHITE; /* Compute & use white */
+
+ /* ICX_SET_WHITE_C isn't applicable to matrix profiles */
if (autowpsc)
flags |= ICX_SET_WHITE_US; /* Compute & use white without scaling to L */
@@ -836,7 +838,7 @@ make_input_icc(
wr_xicc, icmFwd, icmDefaultIntent,
icmLuOrdNorm,
flags, /* Flags */
- npat, npat, tpat, NULL, 0.0, wpscale, smooth, avgdev,
+ npat, npat, tpat, NULL, 0.0, wpscale, smooth, avgdev, 1.0,
NULL, NULL, NULL, iquality)) == NULL)
error("%d, %s",wr_xicc->errc, wr_xicc->err);
@@ -1121,7 +1123,7 @@ make_input_icc(
ICX_2PASSSMTH |
#endif
flags, /* Flags */
- npat + nxpat, npat, tpat, NULL, 0.0, wpscale, smooth, avgdev,
+ npat + nxpat, npat, tpat, NULL, 0.0, wpscale, smooth, avgdev, 1.0,
NULL, NULL, NULL, iquality)) == NULL)
error ("%d, %s",wr_xicc->errc, wr_xicc->err);
@@ -1207,7 +1209,8 @@ make_input_icc(
NULL, NULL, /* Use default Lab' range */
in_b2a_clut, /* Lab' -> Device' transfer function */
NULL, NULL, /* Use default Device' range */
- in_b2a_output) != 0) /* Output transfer function, Device'->Device */
+ in_b2a_output, /* Output transfer function, Device'->Device */
+ NULL, NULL) != 0) /* Use default APXLS range */
error("Setting 16 bit PCS->Device Lut failed: %d, %s",wr_icco->errc,wr_icco->err);
if (cx.verb) {
printf("\n");
diff --git a/profile/profout.c b/profile/profout.c
index d89ae4e..8c6fa0d 100644
--- a/profile/profout.c
+++ b/profile/profout.c
@@ -65,6 +65,7 @@
#undef IMP_MONO /* [Undef] Turn on development code */
+#define EMPH_DISP_BLACKPOINT /* [Define] Increase weight near diplay black point */
#define NO_B2A_PCS_CURVES /* [Define] PCS curves seem to make B2A less accurate. Why ? */
#define USE_CAM_CLIP_OPT /* [Define] Clip out of gamut in CAM space rather than PCS */
#define USE_LEASTSQUARES_APROX /* [Define] Use least squares fitting approximation in B2A */
@@ -73,7 +74,7 @@
#undef DISABLE_GAMUT_TAG /* [Undef] To disable gamut tag */
#undef WARN_CLUT_CLIPPING /* [Undef] Print warning if setting clut clips */
#undef COMPARE_INV_CLUT /* [Undef] Compare result of inv_clut with clut to diag inv probs */
-#define FILTER_B2ACLIP /* [Define] Filter clip area of B2A */
+#undef FILTER_B2ACLIP /* [Undef] Filter clip area of B2A (Causes reversal problems) */
#define FILTER_THR_DE 3.0 /* [5.0] Filtering threshold DE */
#define FILTER_MAX_DE 5.0 /* [10.0] Filtering DE to gamut surface at whit MAX_RAD starts */
#define FILTER_MAX_RAD 0.1 /* [0.1] Filtering maximum radius in grid */
@@ -185,7 +186,7 @@ typedef struct {
double swxyz[3]; /* Source white point in XYZ */
gamut *gam; /* Output gamut object for setting gamut Lut */
- int wantLab; /* 0 if want is XYZ PCS, 1 want is Lab PCS */
+ int wantLab; /* 0 if is XYZ PCS, 1 if is Lab PCS */
} out_b2a_callback;
/* Utility to handle abstract profile application to PCS. */
@@ -642,6 +643,7 @@ make_output_icc(
int gamdiag, /* Make gamut mapping diagnostic wrl plots */
int verify, /* nz to print verification */
int clipprims, /* Clip white, black and primaries */
+ double wpscale, /* >= 0.0 for media white point scale factor */
icxInk *oink, /* Ink limit/black generation setup (NULL if n/a) */
char *in_name, /* input .ti3 file name */
char *file_name, /* output icc name */
@@ -655,6 +657,7 @@ make_output_icc(
int fwacomp, /* FWA compensation requested */
double smooth, /* RSPL smoothing factor, -ve if raw */
double avgdev, /* reading Average Deviation as a proportion of the input range */
+ double demph, /* Emphasise dark region grid resolution in cLUT */
char *ipname, /* input icc profile - enables gamut map, NULL if none */
char *sgname, /* source image gamut - NULL if none */
char *absname[3], /* abstract profile name for each table */
@@ -737,7 +740,7 @@ make_output_icc(
int ti;
if ((ti = icg->find_kword(icg, 0, "LUMINANCE_XYZ_CDM2")) >= 0) {
- if (sscanf(icg->t[0].kdata[ti], " %*lf %lf %*lf ",&dispLuminance) != 1)
+ if (sscanf(icg->t[0].kdata[ti], " %*f %lf %*f ",&dispLuminance) != 1)
dispLuminance = 0.0;
}
@@ -1215,6 +1218,17 @@ make_output_icc(
cc = 0.0;
else if (cc > 1.0)
cc = 1.0;
+
+ if (cal->tvenc) {
+ cc = (cc * (235.0-16.0) + 16.0)/255.0;
+
+ /* For video encoding the extra bits of precision are created by bit shifting */
+ /* rather than scaling, so we need to scale the fp value to account for this. */
+ /* We assume the precision is the vcgt table size = 16 */
+ /* ~~99 ideally we should tag the fact that this is video encoded, so that */
+ /* the vcgt loaded can adjust for a different bit precision ~~~~ */
+ cc = (cc * 255 * (1 << (16 - 8)))/((1 << 16) - 1.0);
+ }
((unsigned short*)wo->u.table.data)[ncal * j + i] = (int)(cc * 65535.0 + 0.5);
}
}
@@ -1389,12 +1403,12 @@ make_output_icc(
wog->allocate((icmBase *)wog);
wob->allocate((icmBase *)wob);
- wor->data[0].X = 1.0; wor->data[0].Y = 0.0; wor->data[0].Z = 0.0;
- wog->data[0].X = 0.0; wog->data[0].Y = 1.0; wog->data[0].Z = 0.0;
- wob->data[0].X = 0.0; wob->data[0].Y = 0.0; wob->data[0].Z = 1.0;
+// wor->data[0].X = 1.0; wor->data[0].Y = 0.0; wor->data[0].Z = 0.0;
+// wog->data[0].X = 0.0; wog->data[0].Y = 1.0; wog->data[0].Z = 0.0;
+// wob->data[0].X = 0.0; wob->data[0].Y = 0.0; wob->data[0].Z = 1.0;
/* Setup deliberately wrong dummy values (channels rotated). */
- /* icxMatrix may override override these later */
+ /* icxMatrix may override these later */
wor->data[0].X = 0.143066; wor->data[0].Y = 0.060608; wor->data[0].Z = 0.714096;
wog->data[0].X = 0.436066; wog->data[0].Y = 0.222488; wog->data[0].Z = 0.013916;
wob->data[0].X = 0.385147; wob->data[0].Y = 0.716873; wob->data[0].Z = 0.097076;
@@ -1834,6 +1848,8 @@ make_output_icc(
}
+ isLab = wantLab; /* We now have what we want */
+
/* Normalize display values to Y = 1.0 if needed */
/* (re-norm spec derived, since observer may be different) */
if (isdisp && (isdnormed == 0 || spec != 0)) {
@@ -1878,6 +1894,51 @@ make_output_icc(
}
} /* End of reading in CGATs file */
+
+#ifdef EMPH_DISP_BLACKPOINT
+ /* Add extra weighting to sample points near black for additive display. */
+ /* Not sure what the justification is, apart from making the black */
+ /* point more accurately modelled. Does this reflect an underlying */
+ /* problem with rspl in perceptual space ? Or is it a reflection */
+ /* of the possible "scaled" viewing mode of additive display */
+ /* usage ? What about print and scan ?? */
+ if (isdisp && (imask == ICX_W || imask == ICX_RGB)) {
+ double minL = 1e6;;
+
+ /* Locate the lowest L* value */
+ for (i = 0; i < npat; i++) {
+ if (wantLab) {
+ if (tpat[i].v[0] < minL)
+ minL = tpat[i].v[0];
+ } else {
+ double lab[2];
+ icmXYZ2Lab(&icmD50, lab, tpat[i].v);
+ if (lab[0] < minL)
+ minL = lab[0];
+ }
+ }
+
+ /* Compute weighting factor */
+ /* (Hard to guess what numbers to put in here.. */
+ for (i = 0; i < npat; i++) {
+ double lab[3], L;
+ if (wantLab) {
+ L = tpat[i].v[0];
+ } else {
+ icmXYZ2Lab(&icmD50, lab, tpat[i].v);
+ L = lab[0];
+ }
+ L -= minL;
+ L /= 20.0; /* Just weight over 20 L* range */
+ if (L > 1.0)
+ continue;
+ L = 1.0 + 19.0 * pow(1.0 - L, 3.0);
+ tpat[i].w *= L;
+//printf("~1 pat %d %f %f %f weight %f\n", i,tpat[i].p[0], tpat[i].p[1], tpat[i].p[2], tpat[i].w);
+ }
+ }
+#endif /* EMPH_DISP_BLACKPOINT */
+
if (isLut) {
xicc *wr_xicc; /* extention object */
icxLuBase *AtoB; /* AtoB ixcLu */
@@ -1920,7 +1981,7 @@ make_output_icc(
ICX_2PASSSMTH |
#endif
flags,
- npat, npat, tpat, NULL, dispLuminance, -1.0, smooth, avgdev,
+ npat, npat, tpat, NULL, dispLuminance, wpscale, smooth, avgdev, demph,
NULL, oink, cal, iquality)) == NULL)
error("%d, %s",wr_xicc->errc, wr_xicc->err);
@@ -2016,18 +2077,20 @@ make_output_icc(
vc->Lv = v->Lv;
if (v->Yf >= 0.0)
vc->Yf = v->Yf;
- if (v->Fxyz[0] >= 0.0 && v->Fxyz[1] > 0.0 && v->Fxyz[2] >= 0.0) {
+ if (v->Yg >= 0.0)
+ vc->Yg = v->Yg;
+ if (v->Gxyz[0] >= 0.0 && v->Gxyz[1] > 0.0 && v->Gxyz[2] >= 0.0) {
/* Normalise XYZ to current media white */
- vc->Fxyz[0] = v->Fxyz[0]/v->Fxyz[1] * vc->Fxyz[1];
- vc->Fxyz[2] = v->Fxyz[2]/v->Fxyz[1] * vc->Fxyz[1];
+ vc->Gxyz[0] = v->Gxyz[0]/v->Gxyz[1] * vc->Gxyz[1];
+ vc->Gxyz[2] = v->Gxyz[2]/v->Gxyz[1] * vc->Gxyz[1];
}
- if (v->Fxyz[0] >= 0.0 && v->Fxyz[1] >= 0.0 && v->Fxyz[2] < 0.0) {
+ if (v->Gxyz[0] >= 0.0 && v->Gxyz[1] >= 0.0 && v->Gxyz[2] < 0.0) {
/* Convert Yxy to XYZ */
- double x = v->Fxyz[0];
- double y = v->Fxyz[1]; /* If Y == 1.0, then X+Y+Z = 1/y */
+ double x = v->Gxyz[0];
+ double y = v->Gxyz[1]; /* If Y == 1.0, then X+Y+Z = 1/y */
double z = 1.0 - x - y;
- vc->Fxyz[0] = x/y * vc->Fxyz[1];
- vc->Fxyz[2] = z/y * vc->Fxyz[1];
+ vc->Gxyz[0] = x/y * vc->Gxyz[1];
+ vc->Gxyz[2] = z/y * vc->Gxyz[1];
}
}
@@ -2182,31 +2245,40 @@ make_output_icc(
/* cx.ix and cx.ox for each intent, but that would be expensive!. */
if (sepsat && (pgmi->usecas & 0xff) != (sgmi->usecas & 0xff))
error("Can't handle percept and sat table intents with different CAM spaces");
- /* Default perceptual input gamut mapping space is absolute perceptual */
- intentp = noptop ? icAbsoluteColorimetric : icmAbsolutePerceptual;
- /* But override this for apperance space gamut mapping */
- if ((pgmi->usecas & 0xff) != 0x0) {
+ /* If apperance space perceptual table gamut mapping */
+ if ((pgmi->usecas & 0xff) >= 0x2) {
intentp = noptop ? icxAppearance : icxPerceptualAppearance;
+ } else {
+ if ((pgmi->usecas & 0xff) == 0x0)
+ intentp = noptop ? icRelativeColorimetric : icPerceptual;
+ else /* pgmi->usecas & 0xff == 0x1 */
+ intentp = noptop ? icAbsoluteColorimetric : icmAbsolutePerceptual;
}
+
if (sepsat) {
- /* Default saturation gamut mapping space is absolute saturation */
- intents = nostos ? icAbsoluteColorimetric : icmAbsoluteSaturation;
- /* But override this for apperance space gamut mapping */
- if ((sgmi->usecas & 0xff) != 0x0) {
+ /* If apperance space saturation table gamut mapping */
+ if ((sgmi->usecas & 0xff) >= 0x2) {
intents = nostos ? icxAppearance : icxSaturationAppearance;
+ } else {
+ if ((sgmi->usecas & 0xff) == 0x0)
+ intents = nostos ? icRelativeColorimetric : icSaturation;
+ else
+ intents = nostos ? icAbsoluteColorimetric : icmAbsoluteSaturation;
}
}
- /* Default output gamut mapping space is absolute colorimetric */
- intento = icAbsoluteColorimetric;
- /* But override this for apperance space gamut mapping */
- if ((pgmi->usecas & 0xff) != 0x0) {
+ if ((pgmi->usecas & 0xff) >= 0x2) {
intento = icxAppearance;
+ } else {
+ if ((pgmi->usecas & 0xff) == 0x0)
+ intento = icRelativeColorimetric;
+ else /* pgmi->usecas & 0xff == 0x1 */
+ intento = icAbsoluteColorimetric;
}
- if ((pgmi->usecas & 0xff) == 0x2) {
+ if ((pgmi->usecas & 0xff) == 0x3) { /* Abs. appearance */
double mxw;
intentp = intents = intento = icxAbsAppearance;
@@ -2274,7 +2346,7 @@ make_output_icc(
if (sgname != NULL) { /* Optional source gamut - ie. from an images */
int isJab = 0;
- if ((pgmi->usecas & 0xff) != 0)
+ if ((pgmi->usecas & 0xff) >= 0x2)
isJab = 1;
if (verb)
@@ -2628,14 +2700,16 @@ make_output_icc(
ICM_CLUT_SET_FILTER |
#endif
0,
- &cx, /* Context */
- cx.pcsspace, /* Input color space */
- devspace, /* Output color space */
- out_b2a_input, /* Input transform PCS->PCS' */
- NULL, NULL, /* Use default PCS range */
- out_b2a_clut, /* Lab' -> Device' transfer function */
- NULL, NULL, /* Use default Device' range */
- out_b2a_output) != 0) /* Output transfer function, Device'->Device */
+ &cx, /* Context */
+ cx.pcsspace, /* Input color space */
+ devspace, /* Output color space */
+ out_b2a_input, /* Input transform PCS->PCS' */
+ NULL, NULL, /* Use default PCS range */
+ out_b2a_clut, /* Lab' -> Device' transfer function */
+ NULL, NULL, /* Use default Device' range */
+ out_b2a_output, /* Output transfer function, Device'->Device */
+ NULL, NULL /* Use default APXLS range */
+ ) != 0)
error("Setting 16 bit PCS->Device Lut failed: %d, %s",wr_icco->errc,wr_icco->err);
if (cx.verb) {
printf("\n");
@@ -2769,7 +2843,9 @@ make_output_icc(
NULL, NULL, /* Use default Lab' range */
PCSp_bdist, /* Lab' -> Boundary distance */
NULL, NULL, /* Use default Device' range */
- gamut_output) != 0) /* Boundary distance to out of gamut value */
+ gamut_output, /* Boundary distance to out of gamut value */
+ NULL, NULL
+ ) != 0)
error("Setting 16 bit PCS->Device Gamut Lut failed: %d, %s",wr_icco->errc,wr_icco->err);
#endif /* !DEBUG_ONE */
if (cx.verb) {
@@ -2823,7 +2899,7 @@ make_output_icc(
wr_xicc, icmFwd, isdisp ? icmDefaultIntent : icRelativeColorimetric,
icmLuOrdRev,
flags, /* Compute white & black */
- npat, npat, tpat, NULL, dispLuminance, -1.0, smooth, avgdev,
+ npat, npat, tpat, NULL, dispLuminance, wpscale, smooth, avgdev, demph,
NULL, oink, cal, iquality)) == NULL)
error("%d, %s",wr_xicc->errc, wr_xicc->err);
diff --git a/profile/txt2ti3.c b/profile/txt2ti3.c
index 9b425f3..62807f3 100644
--- a/profile/txt2ti3.c
+++ b/profile/txt2ti3.c
@@ -28,7 +28,7 @@
*/
-#undef DEBUG
+#define DEBUG
#include <stdio.h>
#include <stdlib.h>
@@ -50,7 +50,7 @@ usage(char *mes) {
fprintf(stderr,"Author: Graeme W. Gill, licensed under the AGPL Version 3\n");
if (mes != NULL)
fprintf(stderr,"error: %s\n",mes);
- fprintf(stderr,"usage: txt2ti3 [-v] [-l limit] [devfile] infile [specfile] outfile\n");
+ fprintf(stderr,"usage: txt2ti3 [-v] [-l limit] [devfile] infile [specfile] outbase\n");
/* fprintf(stderr," -v Verbose mode\n"); */
fprintf(stderr," -2 Create dummy .ti2 file as well\n");
fprintf(stderr," -l limit set ink limit, 0 - 400%% (default max in file)\n");
@@ -200,7 +200,7 @@ int main(int argc, char *argv[])
cmy->add_other(cmy, "ECI2002"); /* Gretag/Logo Target file */
cmy->add_other(cmy, ""); /* Wildcard */
if (cmy->read_name(cmy, devname))
- error ("Read: Can't read dev file '%s'. Unknown format or corrupted file ?",devname);
+ error ("Read: Can't read dev file '%s'. Unknown format or corrupted file ? (%s)",devname,cmy->err);
if (cmy->ntables != 1)
warning("Input file '%s' doesn't contain exactly one table",devname);