1 /*
2 File: iccRoundTrip.cpp
3
4 Contains: Console app to parse and display profile round-trip statistics
5
6 Version: V1
7
8 Copyright: � see below
9 */
10
11 /*
12 * The ICC Software License, Version 0.2
13 *
14 *
15 * Copyright (c) 2003-2010 The International Color Consortium. All rights
16 * reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
20 * are met:
21 *
22 * 1. Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer.
24 *
25 * 2. Redistributions in binary form must reproduce the above copyright
26 * notice, this list of conditions and the following disclaimer in
27 * the documentation and/or other materials provided with the
28 * distribution.
29 *
30 * 3. In the absence of prior written permission, the names "ICC" and "The
31 * International Color Consortium" must not be used to imply that the
32 * ICC organization endorses or promotes products derived from this
33 * software.
34 *
35 *
36 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39 * DISCLAIMED. IN NO EVENT SHALL THE INTERNATIONAL COLOR CONSORTIUM OR
40 * ITS CONTRIBUTING MEMBERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47 * SUCH DAMAGE.
48 * ====================================================================
49 *
50 * This software consists of voluntary contributions made by many
51 * individuals on behalf of the The International Color Consortium.
52 *
53 *
54 * Membership in the ICC is encouraged when this software is used for
55 * commercial purposes.
56 *
57 *
58 * For more information on The International Color Consortium, please
59 * see <http://www.color.org/>.
60 *
61 *
62 */
63
64 //////////////////////////////////////////////////////////////////////
65 // HISTORY:
66 //
67 // -Initial implementation by Max Derhak 10-1-2007
68 //
69 //////////////////////////////////////////////////////////////////////
70
71
72 #include <stdio.h>
73 #include <math.h>
74 #include "IccUtil.h"
75 #include "IccEval.h"
76 #include "IccPrmg.h"
77
78 class CIccMinMaxEval : public CIccEvalCompare
79 {
80 public:
81 CIccMinMaxEval();
82
83 void Compare(icFloatNumber *pixel, icFloatNumber *deviceLab, icFloatNumber *lab1, icFloatNumber *lab2);
84
GetMean1()85 icFloatNumber GetMean1() { return sum1 / num1; }
GetMean2()86 icFloatNumber GetMean2() { return sum2 / num2; }
87
88 icFloatNumber minDE1, minDE2;
89 icFloatNumber maxDE1, maxDE2;
90
91 icFloatNumber maxLab1[3], maxLab2[3];
92
93 protected:
94
95 icFloatNumber sum1, sum2;
96 icFloatNumber num1, num2;
97 };
98
CIccMinMaxEval()99 CIccMinMaxEval::CIccMinMaxEval()
100 {
101 minDE1 = minDE2 = 10000;
102 maxDE1 = maxDE2 = -1;
103 sum1 = sum2 = 0;
104 num1 = num2 = 0;
105
106 memset(&maxLab1[0], 0, sizeof(maxLab1));
107 memset(&maxLab2[0], 0, sizeof(maxLab2));
108 }
109
Compare(icFloatNumber * pixel,icFloatNumber * deviceLab,icFloatNumber * lab1,icFloatNumber * lab2)110 void CIccMinMaxEval::Compare(icFloatNumber *pixel, icFloatNumber *deviceLab, icFloatNumber *lab1, icFloatNumber *lab2)
111 {
112 icFloatNumber DE1 = icDeltaE(deviceLab, lab1);
113 icFloatNumber DE2 = icDeltaE(lab1, lab2);
114
115 if (DE1<minDE1) {
116 minDE1 = DE1;
117 }
118
119 if (DE1>maxDE1) {
120 maxDE1 = DE1;
121 memcpy(&maxLab1[0], deviceLab, sizeof(maxLab1));
122 }
123
124 if (DE2<minDE2) {
125 minDE2 = DE2;
126 }
127
128 if (DE2>maxDE2) {
129 maxDE2 = DE2;
130 memcpy(&maxLab2[0], deviceLab, sizeof(maxLab2));
131 }
132
133 sum1 += DE1;
134 num1 += 1.0;
135
136 sum2 += DE2;
137 num2 += 1.0;
138 }
139
140
main(int argc,char * argv[])141 int main(int argc, char* argv[])
142 {
143 int nArg = 1;
144
145 if (argc<=1) {
146 printf("Usage: iccRoundTrip profile {rendering_intent=1 {use_mpe=0}}\n");
147 printf(" where rendering_intent is (0=perceptual, 1=relative, 2=saturation, 3=absolute)\n");
148 return -1;
149 }
150
151 icRenderingIntent nIntent = icRelativeColorimetric;
152 int nUseMPE = 0;
153
154 if (argc>2) {
155 nIntent = (icRenderingIntent)atoi(argv[2]);
156 if (argc>3) {
157 nUseMPE = atoi(argv[3]);
158 }
159 }
160
161 CIccMinMaxEval eval;
162
163 icStatusCMM stat = eval.EvaluateProfile(argv[1], 0, nIntent, icInterpLinear, (nUseMPE!=0));
164
165 if (stat!=icCmmStatOk) {
166 printf("Unable to perform round trip on '%s'\n", argv[1]);
167 return -1;
168 }
169
170 CIccPRMG prmg;
171
172 stat = prmg.EvaluateProfile(argv[1], nIntent, icInterpLinear, (nUseMPE!=0));
173
174 if (stat!=icCmmStatOk) {
175 printf("Unable to perform PRMG analysis on '%s'\n", argv[1]);
176 return -1;
177 }
178
179 CIccInfo info;
180
181 printf("Profile: '%s'\n", argv[1]);
182 printf("Rendering Intent: %s\n", info.GetRenderingIntentName(nIntent));
183 printf("Specified Gamut: %s\n", prmg.m_bPrmgImplied ? "Perceptual Reference Medium Gamut" : "Not Specified");
184
185 printf("\nRound Trip 1\n");
186 printf( "------------\n");
187 printf("Min DeltaE: %8.2" ICFLOATSFX "\n", eval.minDE1);
188 printf("Mean DeltaE: %8.2" ICFLOATSFX "\n", eval.GetMean1());
189 printf("Max DeltaE: %8.2" ICFLOATSFX "\n\n", eval.maxDE1);
190
191 printf("Max L, a, b: " ICFLOATFMT ", " ICFLOATFMT ", " ICFLOATFMT "\n", eval.maxLab1[0], eval.maxLab1[1], eval.maxLab1[2]);
192
193 printf("\nRound Trip 2\n");
194 printf( "------------\n");
195 printf("Min DeltaE: %8.2" ICFLOATSFX "\n", eval.minDE2);
196 printf("Mean DeltaE: %8.2" ICFLOATSFX "\n", eval.GetMean2());
197 printf("Max DeltaE: %8.2" ICFLOATSFX "\n\n", eval.maxDE2);
198
199 printf("Max L, a, b: " ICFLOATFMT ", " ICFLOATFMT ", " ICFLOATFMT "\n", eval.maxLab2[0], eval.maxLab2[1], eval.maxLab2[2]);
200
201 if (prmg.m_nTotal) {
202 printf("\nPRMG Interoperability - Round Trip Results\n");
203 printf( "------------------------------------------------------\n");
204
205 printf("DE <= 1.0 (%8u): %5.1f%%\n", prmg.m_nDE1, (float)prmg.m_nDE1/(float)prmg.m_nTotal*100.0);
206 printf("DE <= 2.0 (%8u): %5.1f%%\n", prmg.m_nDE2, (float)prmg.m_nDE2/(float)prmg.m_nTotal*100.0);
207 printf("DE <= 3.0 (%8u): %5.1f%%\n", prmg.m_nDE3, (float)prmg.m_nDE3/(float)prmg.m_nTotal*100.0);
208 printf("DE <= 5.0 (%8u): %5.1f%%\n", prmg.m_nDE5, (float)prmg.m_nDE5/(float)prmg.m_nTotal*100.0);
209 printf("DE <=10.0 (%8u): %5.1f%%\n", prmg.m_nDE10, (float)prmg.m_nDE10/(float)prmg.m_nTotal*100.0);
210 printf("Total (%8u)\n", prmg.m_nTotal);
211 }
212 return 0;
213 }
214
215