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