1 //---------------------------------------------------------------------------------
\r
3 // Little Color Management System
\r
4 // Copyright (c) 1998-2010 Marti Maria Saguer
\r
6 // Permission is hereby granted, free of charge, to any person obtaining
\r
7 // a copy of this software and associated documentation files (the "Software"),
\r
8 // to deal in the Software without restriction, including without limitation
\r
9 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
\r
10 // and/or sell copies of the Software, and to permit persons to whom the Software
\r
11 // is furnished to do so, subject to the following conditions:
\r
13 // The above copyright notice and this permission notice shall be included in
\r
14 // all copies or substantial portions of the Software.
\r
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
\r
17 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
\r
18 // THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
\r
19 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
\r
20 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
\r
21 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
\r
22 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
24 //---------------------------------------------------------------------------------
\r
32 static char ProgramName[256] = "";
\r
34 void FatalError(const char *frm, ...)
\r
38 va_start(args, frm);
\r
39 fprintf(stderr, "[%s fatal error]: ", ProgramName);
\r
40 vfprintf(stderr, frm, args);
\r
41 fprintf(stderr, "\n");
\r
47 // Show errors to the end user (unless quiet option)
\r
49 void MyErrorLogHandler(cmsContext ContextID, cmsUInt32Number ErrorCode, const char *Text)
\r
52 fprintf(stderr, "[%s]: %s\n", ProgramName, Text);
\r
54 UTILS_UNUSED_PARAMETER(ErrorCode);
\r
55 UTILS_UNUSED_PARAMETER(ContextID);
\r
59 void InitUtils(const char* PName)
\r
61 strncpy(ProgramName, PName, sizeof(ProgramName));
\r
62 ProgramName[sizeof(ProgramName)-1] = 0;
\r
64 cmsSetLogErrorHandler(MyErrorLogHandler);
\r
68 // Virtual profiles are handled here.
\r
69 cmsHPROFILE OpenStockProfile(cmsContext ContextID, const char* File)
\r
72 return cmsCreate_sRGBProfileTHR(ContextID);
\r
74 if (cmsstrcasecmp(File, "*Lab2") == 0)
\r
75 return cmsCreateLab2ProfileTHR(ContextID, NULL);
\r
77 if (cmsstrcasecmp(File, "*Lab4") == 0)
\r
78 return cmsCreateLab4ProfileTHR(ContextID, NULL);
\r
80 if (cmsstrcasecmp(File, "*Lab") == 0)
\r
81 return cmsCreateLab4ProfileTHR(ContextID, NULL);
\r
83 if (cmsstrcasecmp(File, "*LabD65") == 0) {
\r
87 cmsWhitePointFromTemp( &D65xyY, 6504);
\r
88 return cmsCreateLab4ProfileTHR(ContextID, &D65xyY);
\r
91 if (cmsstrcasecmp(File, "*XYZ") == 0)
\r
92 return cmsCreateXYZProfileTHR(ContextID);
\r
94 if (cmsstrcasecmp(File, "*Gray22") == 0) {
\r
96 cmsToneCurve* Curve = cmsBuildGamma(ContextID, 2.2);
\r
97 cmsHPROFILE hProfile = cmsCreateGrayProfileTHR(ContextID, cmsD50_xyY(), Curve);
\r
98 cmsFreeToneCurve(Curve);
\r
102 if (cmsstrcasecmp(File, "*Gray30") == 0) {
\r
104 cmsToneCurve* Curve = cmsBuildGamma(ContextID, 3.0);
\r
105 cmsHPROFILE hProfile = cmsCreateGrayProfileTHR(ContextID, cmsD50_xyY(), Curve);
\r
106 cmsFreeToneCurve(Curve);
\r
110 if (cmsstrcasecmp(File, "*srgb") == 0)
\r
111 return cmsCreate_sRGBProfileTHR(ContextID);
\r
113 if (cmsstrcasecmp(File, "*null") == 0)
\r
114 return cmsCreateNULLProfileTHR(ContextID);
\r
117 if (cmsstrcasecmp(File, "*Lin2222") == 0) {
\r
119 cmsToneCurve* Gamma = cmsBuildGamma(0, 2.2);
\r
120 cmsToneCurve* Gamma4[4];
\r
121 cmsHPROFILE hProfile;
\r
123 Gamma4[0] = Gamma4[1] = Gamma4[2] = Gamma4[3] = Gamma;
\r
124 hProfile = cmsCreateLinearizationDeviceLink(cmsSigCmykData, Gamma4);
\r
125 cmsFreeToneCurve(Gamma);
\r
130 return cmsOpenProfileFromFileTHR(ContextID, File, "r");
\r
133 // Help on available built-ins
\r
134 void PrintBuiltins(void)
\r
136 fprintf(stderr, "\nBuilt-in profiles:\n\n");
\r
137 fprintf(stderr, "\t*Lab2 -- D50-based v2 CIEL*a*b\n"
\r
138 "\t*Lab4 -- D50-based v4 CIEL*a*b\n"
\r
139 "\t*Lab -- D50-based v4 CIEL*a*b\n"
\r
140 "\t*XYZ -- CIE XYZ (PCS)\n"
\r
141 "\t*sRGB -- sRGB color space\n"
\r
142 "\t*Gray22 - Monochrome of Gamma 2.2\n"
\r
143 "\t*Gray30 - Monochrome of Gamma 3.0\n"
\r
144 "\t*null - Monochrome black for all input\n"
\r
145 "\t*Lin2222- CMYK linearization of gamma 2.2 on each channel\n");
\r
149 // Auxiliar for printing information on profile
\r
151 void PrintInfo(cmsHPROFILE h, cmsInfoType Info)
\r
156 len = cmsGetProfileInfoASCII(h, Info, "en", "US", NULL, 0);
\r
157 if (len == 0) return;
\r
159 text = malloc(len * sizeof(char));
\r
160 if (text == NULL) return;
\r
162 cmsGetProfileInfoASCII(h, Info, "en", "US", text, len);
\r
164 if (strlen(text) > 0)
\r
165 printf("%s\n", text);
\r
172 // Displays the colorant table
\r
174 void PrintColorantTable(cmsHPROFILE hInput, cmsTagSignature Sig, const char* Title)
\r
176 cmsNAMEDCOLORLIST* list;
\r
179 if (cmsIsTag(hInput, Sig)) {
\r
181 printf("%s:\n", Title);
\r
183 list = cmsReadTag(hInput, Sig);
\r
184 if (list == NULL) {
\r
185 printf("(Unavailable)\n");
\r
189 n = cmsNamedColorCount(list);
\r
190 for (i=0; i < n; i++) {
\r
192 char Name[cmsMAX_PATH];
\r
194 cmsNamedColorInfo(list, i, Name, NULL, NULL, NULL, NULL);
\r
195 printf("\t%s\n", Name);
\r
204 void PrintProfileInformation(cmsHPROFILE hInput)
\r
206 PrintInfo(hInput, cmsInfoDescription);
\r
207 PrintInfo(hInput, cmsInfoManufacturer);
\r
208 PrintInfo(hInput, cmsInfoModel);
\r
209 PrintInfo(hInput, cmsInfoCopyright);
\r
213 PrintColorantTable(hInput, cmsSigColorantTableTag, "Input colorant table");
\r
214 PrintColorantTable(hInput, cmsSigColorantTableOutTag, "Input colorant out table");
\r
220 // -----------------------------------------------------------------------------
\r
223 void PrintRenderingIntents(void)
\r
225 cmsUInt32Number Codes[200];
\r
226 char* Descriptions[200];
\r
227 cmsUInt32Number n, i;
\r
229 fprintf(stderr, "%ct<n> rendering intent:\n\n", SW);
\r
231 n = cmsGetSupportedIntents(200, Codes, Descriptions);
\r
233 for (i=0; i < n; i++) {
\r
234 fprintf(stderr, "\t%d - %s\n", Codes[i], Descriptions[i]);
\r
236 fprintf(stderr, "\n");
\r
241 // ------------------------------------------------------------------------------
\r
243 cmsBool SaveMemoryBlock(const cmsUInt8Number* Buffer, cmsUInt32Number dwLen, const char* Filename)
\r
245 FILE* out = fopen(Filename, "wb");
\r
247 FatalError("Cannot create '%s'", Filename);
\r
251 if (fwrite(Buffer, 1, dwLen, out) != dwLen) {
\r
252 FatalError("Cannot write %ld bytes to %s", dwLen, Filename);
\r
256 if (fclose(out) != 0) {
\r
257 FatalError("Error flushing file '%s'", Filename);
\r
264 // ------------------------------------------------------------------------------
\r
266 // Return a pixel type on depending on the number of channels
\r
267 int PixelTypeFromChanCount(int ColorChannels)
\r
269 switch (ColorChannels) {
\r
271 case 1: return PT_GRAY;
\r
272 case 2: return PT_MCH2;
\r
273 case 3: return PT_MCH3;
\r
274 case 4: return PT_CMYK;
\r
275 case 5: return PT_MCH5;
\r
276 case 6: return PT_MCH6;
\r
277 case 7: return PT_MCH7;
\r
278 case 8: return PT_MCH8;
\r
279 case 9: return PT_MCH9;
\r
280 case 10: return PT_MCH10;
\r
281 case 11: return PT_MCH11;
\r
282 case 12: return PT_MCH12;
\r
283 case 13: return PT_MCH13;
\r
284 case 14: return PT_MCH14;
\r
285 case 15: return PT_MCH15;
\r
289 FatalError("What a weird separation of %d channels?!?!", ColorChannels);
\r
295 // ------------------------------------------------------------------------------
\r
297 // Return number of channels of pixel type
\r
298 int ChanCountFromPixelType(int ColorChannels)
\r
300 switch (ColorChannels) {
\r
302 case PT_GRAY: return 1;
\r
308 case PT_YCbCr: return 3;
\r
310 case PT_CMYK: return 4 ;
\r
311 case PT_MCH2: return 2 ;
\r
312 case PT_MCH3: return 3 ;
\r
313 case PT_MCH4: return 4 ;
\r
314 case PT_MCH5: return 5 ;
\r
315 case PT_MCH6: return 6 ;
\r
316 case PT_MCH7: return 7 ;
\r
317 case PT_MCH8: return 8 ;
\r
318 case PT_MCH9: return 9 ;
\r
319 case PT_MCH10: return 10;
\r
320 case PT_MCH11: return 11;
\r
321 case PT_MCH12: return 12;
\r
322 case PT_MCH13: return 12;
\r
323 case PT_MCH14: return 14;
\r
324 case PT_MCH15: return 15;
\r
328 FatalError("Unsupported color space of %d channels", ColorChannels);
\r