1 /*************************************************************************
3 * OpenOffice.org - a multi-platform office productivity suite
5 * $RCSfile: create_sRGB_profile.cpp,v $
9 * last change: $Author: rt $ $Date: 2008-04-11 07:31:14 $
11 Derived by beppec56@openoffice.org from various examples
12 in SampleICC library, the original copyright retained.
14 Copyright: © see below
18 * The ICC Software License, Version 0.1
21 * Copyright (c) 2003-2006 The International Color Consortium. All rights
24 * Redistribution and use in source and binary forms, with or without
25 * modification, are permitted provided that the following conditions
28 * 1. Redistributions of source code must retain the above copyright
29 * notice, this list of conditions and the following disclaimer.
31 * 2. Redistributions in binary form must reproduce the above copyright
32 * notice, this list of conditions and the following disclaimer in
33 * the documentation and/or other materials provided with the
36 * 3. The end-user documentation included with the redistribution,
37 * if any, must include the following acknowledgment:
38 * "This product includes software developed by the
39 * The International Color Consortium (www.color.org)"
40 * Alternately, this acknowledgment may appear in the software itself,
41 * if and wherever such third-party acknowledgments normally appear.
43 * 4. The names "ICC" and "The International Color Consortium" must
44 * not be used to imply that the ICC organization endorses or
45 * promotes products derived from this software without prior
46 * written permission. For written permission, please see
47 * <http://www.color.org/>.
50 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
51 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
52 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
53 * DISCLAIMED. IN NO EVENT SHALL THE INTERNATIONAL COLOR CONSORTIUM OR
54 * ITS CONTRIBUTING MEMBERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
56 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
57 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
58 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
59 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
60 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 * ====================================================================
64 * This software consists of voluntary contributions made by many
65 * individuals on behalf of the The International Color Consortium.
68 * Membership in the ICC is encouraged when this software is used for
69 * commercial purposes.
72 * For more information on The International Color Consortium, please
73 * see <http://www.color.org/>.
84 #include "IccProfile.h"
90 const char * const icc_file_name
= "sRGB-IEC61966-2.1.icc";
91 const char * const hxx_file_name
= "sRGB-IEC61966-2.1.hxx";
92 const char * const this_file_name_and_location
=" * icc/source/create_sRGB_profile/create_sRGB_profile.cpp";
94 const char* const description
= "sRGB IEC61966-2.1";
95 //const char* const devicemanufact = "IEC http://www.iec.ch"; not used, device manufactured by OOo seems funny...
96 const char* const devicemodel
= "IEC 61966-2.1 Default RGB colour space - sRGB";
97 const char* const copyright
= "The Contents of this file are made available subject to the terms of GNU Lesser General Public License version 3";
99 // the creation date is fixed, corresponds to the last time this file has been changed
100 // NOTE: change this date values whenever the data inside the profile are changed.
101 const int data_last_changed_year
= 2007;
102 const int data_last_changed_month
= 12;
103 const int data_last_day
= 12;
104 const int data_last_changed_hour
= 18;
105 const int data_last_changed_minute
= 32;
107 // the following string array it's the standard OOo header format
108 const char * const TheHeader1
[] =
110 "/*************************************************************************",
112 " * OpenOffice.org - a multi-platform office productivity suite",
114 " * sRGB-IEC61966-2.1.hxx",
116 " * creator: create_sRGB_profile",
120 const char * const TheHeader2
[] =
123 " * This file is part of OpenOffice.org.",
125 " * OpenOffice.org is free software: you can redistribute it and/or modify",
126 " * it under the terms of the GNU Lesser General Public License version 3",
127 " * only, as published by the Free Software Foundation.",
129 " * OpenOffice.org is distributed in the hope that it will be useful,",
130 " * but WITHOUT ANY WARRANTY; without even the implied warranty of",
131 " * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the",
132 " * GNU Lesser General Public License version 3 for more details",
133 " * (a copy is included in the LICENSE file that accompanied this code).",
135 " * You should have received a copy of the GNU Lesser General Public License",
136 " * version 3 along with OpenOffice.org. If not, see",
137 " * <http://www.openoffice.org/license.html>",
138 " * for a copy of the LGPLv3 License.",
140 " ************************************************************************/",
142 "#ifndef INCLUDED_ICC_SRGB_IEC61966_2_1_H",
143 "#define INCLUDED_ICC_SRGB_IEC61966_2_1_H",
145 "/***********************************************************************",
147 " * this file is automatically generated by running the program",
148 " * obtained building:",
149 this_file_name_and_location
,
150 " * contained in module icc",
151 " * modify that program if you need to change something.",
152 " ***********************************************************************/",
153 NULL
// last string, a null
156 const char * const TheTail
[] =
158 "#endif /* INCLUDED_ICC_SRGB_IEC61966_2_1_H */",
162 icFloatNumber
computeIEC_RGBtoXYZ( icFloatNumber indata
)
166 retval
= indata
/12.92;
167 else // apply the other conversion
168 retval
= pow( (indata
+ 0.055)/1.055 , 2.4);
173 icFloatNumber
computeIEC_XYZtoRGB( icFloatNumber indata
)
175 icFloatNumber retval
= 0.0;
176 if(indata
< 0.0031308)
177 retval
= indata
*12.92;
178 else // apply the other conversion
179 retval
= 1.055*pow( indata
, icFloatNumber(1.0/2.4)) - 0.055;
181 // cout << retval << endl;
185 void dumpTag(FILE *outfile
, CIccProfile
*pIcc
, icTagSignature sig
)
187 CIccTag
*pTag
= pIcc
->FindTag(sig
);
191 std::string contents
;
195 fprintf(outfile
, "\nContents of %s tag (%s)\n", Fmt
.GetTagSigName(sig
), icGetSig(buf
, sig
));
196 fprintf(outfile
,"Type: ");
198 if (pTag
->IsArrayType()) fprintf(outfile
, "Array of ");
200 fprintf(outfile
, "%s\n", Fmt
.GetTagTypeSigName(pTag
->GetType()));
201 pTag
->Describe(contents
);
202 fwrite(contents
.c_str(), contents
.length(), 1, outfile
);
205 fprintf(outfile
, "Tag (%s) not found in profile\n", icGetSig(buf
, sig
));
208 void dumpProfile(FILE *outfile
, const char * profileName
)
212 icValidateStatus nStatus
;
214 pIcc
= OpenIccProfile(profileName
);
217 printf("Unable to open '%s'\n", profileName
);
220 icHeader
*pHdr
= &pIcc
->m_Header
;
224 fprintf(outfile
,"Profile: '%s'\n", profileName
);
225 if(Fmt
.IsProfileIDCalculated(&pHdr
->profileID
))
226 fprintf(outfile
,"Profile ID: %s\n", Fmt
.GetProfileID(&pHdr
->profileID
));
228 fprintf(outfile
,"Profile ID: Profile ID not calculated.\n");
229 fprintf(outfile
,"Size: %ld(0x%lx) bytes\n", pHdr
->size
, pHdr
->size
);
231 fprintf(outfile
,"\nHeader\n");
232 fprintf(outfile
,"------\n");
233 fprintf(outfile
,"Attributes: %s\n", Fmt
.GetDeviceAttrName(pHdr
->attributes
));
234 fprintf(outfile
,"Cmm: %s\n", Fmt
.GetCmmSigName((icCmmSignature
)(pHdr
->cmmId
)));
235 fprintf(outfile
,"Creation Date: %d/%d/%d %02u:%02u:%02u\n",
236 pHdr
->date
.month
, pHdr
->date
.day
, pHdr
->date
.year
,
237 pHdr
->date
.hours
, pHdr
->date
.minutes
, pHdr
->date
.seconds
);
238 fprintf(outfile
,"Creator: %s\n", icGetSig(buf
, pHdr
->creator
));
239 fprintf(outfile
,"Data Color Space: %s\n", Fmt
.GetColorSpaceSigName(pHdr
->colorSpace
));
240 fprintf(outfile
,"Flags %s\n", Fmt
.GetProfileFlagsName(pHdr
->flags
));
241 fprintf(outfile
,"PCS Color Space: %s\n", Fmt
.GetColorSpaceSigName(pHdr
->pcs
));
242 fprintf(outfile
,"Platform: %s\n", Fmt
.GetPlatformSigName(pHdr
->platform
));
243 fprintf(outfile
,"Rendering Intent: %s\n", Fmt
.GetRenderingIntentName((icRenderingIntent
)(pHdr
->renderingIntent
)));
244 fprintf(outfile
,"Type: %s\n", Fmt
.GetProfileClassSigName(pHdr
->deviceClass
));
245 fprintf(outfile
,"Version: %s\n", Fmt
.GetVersionName(pHdr
->version
));
246 fprintf(outfile
,"Illuminant: X=%.4lf, Y=%.4lf, Z=%.4lf\n",
247 icFtoD(pHdr
->illuminant
.X
),
248 icFtoD(pHdr
->illuminant
.Y
),
249 icFtoD(pHdr
->illuminant
.Z
));
251 fprintf(outfile
,"\nProfile Tags\n");
252 fprintf(outfile
,"------------\n");
254 fprintf(outfile
,"%25s ID %8s\t%8s\n", "Tag", "Offset", "Size");
255 fprintf(outfile
,"%25s ------ %8s\t%8s\n", "----", "------", "----");
258 TagEntryList::iterator i
;
260 for (n
=0, i
=pIcc
->m_Tags
->begin(); i
!=pIcc
->m_Tags
->end(); i
++, n
++)
262 fprintf(outfile
,"%25s %s %8ld\t%8ld\n", Fmt
.GetTagSigName(i
->TagInfo
.sig
),
263 icGetSig(buf
, i
->TagInfo
.sig
, false),
264 i
->TagInfo
.offset
, i
->TagInfo
.size
);
267 for (n
=0, i
=pIcc
->m_Tags
->begin(); i
!=pIcc
->m_Tags
->end(); i
++, n
++)
268 dumpTag(outfile
, pIcc
, i
->TagInfo
.sig
);
273 int main(int argc
, char* argv
[])
275 const char* myName
= path_tail(argv
[0]);
279 const char* const out_file_pathname
= icc_file_name
;
282 profile
.InitHeader();
284 profile
.m_Header
.date
.year
= data_last_changed_year
;
285 profile
.m_Header
.date
.month
= data_last_changed_month
;
286 profile
.m_Header
.date
.day
= data_last_day
;
287 profile
.m_Header
.date
.hours
= data_last_changed_hour
;
288 profile
.m_Header
.date
.minutes
= data_last_changed_minute
;
289 profile
.m_Header
.date
.seconds
= 0;
291 profile
.m_Header
.deviceClass
= icSigDisplayClass
;
292 profile
.m_Header
.colorSpace
= icSigRgbData
;
293 profile
.m_Header
.pcs
= icSigXYZData
;
294 profile
.m_Header
.platform
= icSigUnkownPlatform
;
295 profile
.m_Header
.attributes
= static_cast<icUInt64Number
>(icReflective
);
296 profile
.m_Header
.renderingIntent
= icPerceptual
;
298 profile
.m_Header
.cmmId
= 0x6E6F6E65; /* 'none' */
299 profile
.m_Header
.model
= 0x73524742;//sRGB
301 profile
.m_Header
.version
=icVersionNumberV2_1
;
303 // Required tags for a three-component matrix-based display profile, as laid
304 // out by specification ICC.1:1998-09 (clause 6.3) are:
307 // profileDescriptionTag
308 // redMatrixColumnTag
309 // greenMatrixColumnTag
310 // blueMatrixColumnTag
314 // mediaWhitePointTag
321 // mediaBlackPointTag
322 // viewingCondDescTag
323 // viewingConditionsTag
327 // are optionals, added for completeness
329 // the element below are sorted in the same order as
330 // the list above, but the LUT table,
331 // embedded at the end of the profile
334 CIccTagText
* copyrightTag
= new CIccTagText
;
335 copyrightTag
->SetText(copyright
);
336 profile
.AttachTag(icSigCopyrightTag
, copyrightTag
);
338 // profileDescriptionTag
339 CIccTagTextDescription
* descriptionTag
= new CIccTagTextDescription
;
340 descriptionTag
->SetText(description
);
341 profile
.AttachTag(icSigProfileDescriptionTag
, descriptionTag
);
343 CIccTagXYZ
* redMatrixColumnTag
= new CIccTagXYZ
;
344 //values from raccomandation of ICC for sRGB, D50 referenced characterisation data
345 //should be: 0.4361, 0.2225, 0.0139 according to application notes,
346 // the 'X' value below is the one commonly in use on a very
347 // diffused sRGB profile
348 (*redMatrixColumnTag
)[0].X
= icDtoF(0.4361);
349 (*redMatrixColumnTag
)[0].Y
= icDtoF(0.2225);
350 (*redMatrixColumnTag
)[0].Z
= icDtoF(0.0139);
351 profile
.AttachTag(icSigRedMatrixColumnTag
, redMatrixColumnTag
);
353 CIccTagXYZ
* greenMatrixColumnTag
= new CIccTagXYZ
;
354 //values from raccomandation of ICC for sRGB, D50 referenced characterisation data
355 (*greenMatrixColumnTag
)[0].X
= icDtoF(0.3851);
356 (*greenMatrixColumnTag
)[0].Y
= icDtoF(0.7169);
357 (*greenMatrixColumnTag
)[0].Z
= icDtoF(0.0971);
358 profile
.AttachTag(icSigGreenMatrixColumnTag
, greenMatrixColumnTag
);
360 CIccTagXYZ
* blueMatrixColumnTag
= new CIccTagXYZ
;
361 //values from raccomandation of ICC for sRGB, D50 referenced characterisation data
362 //should be: 0.1431, 0.0606, 0.7139 according to application notes,
363 // the 'Z' value below is the one commonly in use on a very
364 // diffused sRGB profile
365 (*blueMatrixColumnTag
)[0].X
= icDtoF(0.1431);
366 (*blueMatrixColumnTag
)[0].Y
= icDtoF(0.0606);
367 (*blueMatrixColumnTag
)[0].Z
= icDtoF(0.7141);
368 profile
.AttachTag(icSigBlueMatrixColumnTag
, blueMatrixColumnTag
);
370 // mediaWhitePointTag
371 CIccTagXYZ
* whitePointTag
= new CIccTagXYZ
;
372 (*whitePointTag
)[0].X
= icDtoF(0.9505);
373 (*whitePointTag
)[0].Y
= icDtoF(1.0);
374 (*whitePointTag
)[0].Z
= icDtoF(1.0891);
375 profile
.AttachTag(icSigMediaWhitePointTag
, whitePointTag
);
377 //device signature (technologytag)
378 CIccTagSignature
* deviceSign
= new CIccTagSignature
;
379 deviceSign
->SetValue( icSigCRTDisplay
);
380 profile
.AttachTag( icSigTechnologyTag
, deviceSign
);
383 CIccTagTextDescription
* deviceModelTag
= new CIccTagTextDescription
;
384 deviceModelTag
->SetText("IEC 61966-2.1 Default RGB colour space - sRGB");
385 profile
.AttachTag( icSigDeviceModelDescTag
, deviceModelTag
);
388 CIccTagTextDescription
* deviceMfgTag
= new CIccTagTextDescription
;
389 deviceMfgTag
->SetText("IEC http://www.iec.ch");
390 profile
.AttachTag( icSigDeviceMfgDescTag
, deviceMfgTag
);
392 // mediaBlackPointTag
393 CIccTagXYZ
* blackPointTag
= new CIccTagXYZ
;
394 (*blackPointTag
)[0].X
=
395 (*blackPointTag
)[0].Y
=
396 (*blackPointTag
)[0].Z
= icDtoF(0.0);
397 profile
.AttachTag(icSigMediaBlackPointTag
, blackPointTag
);
399 // viewingCondDescTag
400 CIccTagTextDescription
* viewingCondDescTag
= new CIccTagTextDescription
;
401 viewingCondDescTag
->SetText("Reference viewing condition according to IEC 61966-2.1");
402 profile
.AttachTag( icSigViewingCondDescTag
, viewingCondDescTag
);
404 // viewingConditionsTag
405 CIccTagViewingConditions
* viewingConditionsTag
= new CIccTagViewingConditions
;
406 // Illuminant tristimulus value
407 (*viewingConditionsTag
).m_XYZIllum
.X
= icDtoF(19.6445);
408 (*viewingConditionsTag
).m_XYZIllum
.Y
= icDtoF(20.3718);
409 (*viewingConditionsTag
).m_XYZIllum
.Z
= icDtoF(16.8089);
410 // surround tristimulus value
411 (*viewingConditionsTag
).m_XYZSurround
.X
= icDtoF(3.9289);
412 (*viewingConditionsTag
).m_XYZSurround
.Y
= icDtoF(4.0744);
413 (*viewingConditionsTag
).m_XYZSurround
.Z
= icDtoF(3.3618);
414 (*viewingConditionsTag
).m_illumType
= icIlluminantD50
;
415 profile
.AttachTag( icSigViewingConditionsType
, viewingConditionsTag
);
418 CIccTagXYZ
* luminanceTag
= new CIccTagXYZ
;
419 (*luminanceTag
)[0].X
= icDtoF(76.0365);
420 (*luminanceTag
)[0].Y
= icDtoF(80.0);
421 (*luminanceTag
)[0].Z
= icDtoF(87.1246);
422 profile
.AttachTag(icSigLuminanceTag
, luminanceTag
);
425 CIccTagMeasurement
* measurementTag
= new CIccTagMeasurement
;
426 (*measurementTag
).m_Data
.stdObserver
= icStdObs1931TwoDegrees
;
427 (*measurementTag
).m_Data
.backing
.X
=
428 (*measurementTag
).m_Data
.backing
.Y
=
429 (*measurementTag
).m_Data
.backing
.Z
= icDtoF(0.0);
430 (*measurementTag
).m_Data
.geometry
= icGeometryUnknown
;
431 // the flare is 1%, but the library doesn't seem all right with this
432 // see specification ICC.1:1998-09, clause 6.5.8, table 55 fot the right
433 // format of the data value
434 (*measurementTag
).m_Data
.flare
= static_cast< icMeasurementFlare
> ( icDtoUF( 0.01 ) );//means 1%
435 (*measurementTag
).m_Data
.illuminant
= icIlluminantD65
;
436 profile
.AttachTag(icSigMeasurementTag
, measurementTag
);
438 // compute the LUT curves, they are equal for all three colors
439 // so only one LUT is computed and stored
440 int N
= 1024; // number of points in LUTs
441 CIccTagCurve
* colorTRCTag
= new CIccTagCurve(N
);
442 // apply conversion from RGB to XYZ, stepping the RGB value linearly from 0 to 100%
443 // 1024 steps are computed
444 for (int i
= 0; i
< N
; ++i
)
445 (*colorTRCTag
)[i
] = computeIEC_RGBtoXYZ( (icFloatNumber
)i
/(N
-1));
447 profile
.AttachTag(icSigRedTRCTag
, colorTRCTag
);
448 profile
.AttachTag(icSigGreenTRCTag
, colorTRCTag
);
449 profile
.AttachTag(icSigBlueTRCTag
, colorTRCTag
);
452 string validationReport
;
453 icValidateStatus validationStatus
= profile
.Validate(validationReport
);
455 switch (validationStatus
)
460 case icValidateWarning
:
461 clog
<< "Profile validation warning" << endl
465 case icValidateNonCompliant
:
466 clog
<< "Profile non compliancy" << endl
470 case icValidateCriticalError
:
472 clog
<< "Profile Error" << endl
478 out
.Open(out_file_pathname
, "wb+");
482 FILE *headerfile
= fopen(hxx_file_name
,"w");
484 //print OpenOffice standard file header
485 const char *the_string
;
489 while((the_string
= TheHeader1
[idx
++]) != NULL
)
490 fprintf(headerfile
,"%s\n",the_string
);
491 // print the creation date (today)
492 // print the date of sRGB ICC profile data
493 fprintf(headerfile
," * the date of last change to sRGB ICC profile data is:\n * %4d/%02d/%02d - %02d:%02d\n",
494 data_last_changed_year
, data_last_changed_month
,
495 data_last_day
, data_last_changed_hour
,data_last_changed_minute
);
499 while((the_string
= TheHeader2
[idx
++]) != NULL
)
500 fprintf(headerfile
,"%s\n",the_string
);
503 // spit out the data structure (an array of unsigned char)
506 int achar
, number
= 1;
508 infile
= fopen(out_file_pathname
,"rb");
510 fseek(infile
,0,SEEK_END
);
511 long int thesize
= ftell(infile
);
512 fseek(infile
,0,SEEK_SET
);
514 fprintf(headerfile
,"\nsal_uInt8 nsRGB_ICC_profile[%d]=\n{\n ",thesize
);
518 achar
= fgetc(infile
);
521 fprintf(headerfile
,"0x%02x",achar
);
523 fprintf(headerfile
,",\n ");
525 fprintf(headerfile
,", ");
527 } while(achar
!= EOF
);
528 fprintf(headerfile
,"\n};\n\n");
532 // append the file contents, in human readable form, as comment in the header
533 // get the functions from iccDump
535 fprintf(headerfile
,"/*****************\n\n");
537 fprintf(headerfile
,"This ICC profile contains the following data:\n\n");
539 dumpProfile(headerfile
, out_file_pathname
);
541 fprintf(headerfile
,"\n*****************/\n");
542 //now append the tail
544 while((the_string
= TheTail
[idx
++]) != NULL
)
545 fprintf(headerfile
,"%s\n",the_string
);
551 catch (const std::exception
& e
)
553 cout
<< myName
<< ": error: " << e
.what() << endl
;