update dev300-m58
[ooovba.git] / icc / source / create_sRGB_profile / create_sRGB_profile.cpp
bloba75c67638ac027602d608cda629d142f4d89f746
1 /*************************************************************************
3 * OpenOffice.org - a multi-platform office productivity suite
5 * $RCSfile: create_sRGB_profile.cpp,v $
7 * $Revision: 1.6 $
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
22 * reserved.
24 * Redistribution and use in source and binary forms, with or without
25 * modification, are permitted provided that the following conditions
26 * are met:
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
34 * distribution.
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
61 * SUCH DAMAGE.
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/>.
78 #include <math.h>
79 #include <iostream>
80 #include <fstream>
81 using namespace std;
83 #include "IccUtil.h"
84 #include "IccProfile.h"
86 #include "Vetters.h"
87 #include "CAT.h"
88 #include "CLUT.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 "/*************************************************************************",
111 " *",
112 " * OpenOffice.org - a multi-platform office productivity suite",
113 " *",
114 " * sRGB-IEC61966-2.1.hxx",
115 " *",
116 " * creator: create_sRGB_profile",
117 NULL
120 const char * const TheHeader2[] =
122 " *",
123 " * This file is part of OpenOffice.org.",
124 " *",
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.",
128 " *",
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).",
134 " *",
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.",
139 " *",
140 " ************************************************************************/",
142 "#ifndef INCLUDED_ICC_SRGB_IEC61966_2_1_H",
143 "#define INCLUDED_ICC_SRGB_IEC61966_2_1_H",
145 "/***********************************************************************",
146 " * NOTE:",
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 */",
159 NULL
162 icFloatNumber computeIEC_RGBtoXYZ( icFloatNumber indata )
164 double retval = 0.0;
165 if(indata < 0.04045)
166 retval = indata/12.92;
167 else // apply the other conversion
168 retval = pow( (indata + 0.055)/1.055 , 2.4);
170 return retval;
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;
182 return retval;
185 void dumpTag(FILE *outfile, CIccProfile *pIcc, icTagSignature sig)
187 CIccTag *pTag = pIcc->FindTag(sig);
188 char buf[64];
189 CIccInfo Fmt;
191 std::string contents;
193 if (pTag)
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);
204 else
205 fprintf(outfile, "Tag (%s) not found in profile\n", icGetSig(buf, sig));
208 void dumpProfile(FILE *outfile, const char * profileName)
210 CIccProfile *pIcc;
211 std::string sReport;
212 icValidateStatus nStatus;
214 pIcc = OpenIccProfile(profileName);
216 if (!pIcc)
217 printf("Unable to open '%s'\n", profileName);
218 else
220 icHeader *pHdr = &pIcc->m_Header;
221 CIccInfo Fmt;
222 char buf[64];
224 fprintf(outfile,"Profile: '%s'\n", profileName);
225 if(Fmt.IsProfileIDCalculated(&pHdr->profileID))
226 fprintf(outfile,"Profile ID: %s\n", Fmt.GetProfileID(&pHdr->profileID));
227 else
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", "----", "------", "----");
257 int 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);
270 delete pIcc;
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;
281 CIccProfile profile;
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:
306 // copyrightTag
307 // profileDescriptionTag
308 // redMatrixColumnTag
309 // greenMatrixColumnTag
310 // blueMatrixColumnTag
311 // redTRCTag
312 // greenTRCTag
313 // blueTRCTag
314 // mediaWhitePointTag
316 // the other tags:
318 // technologyTag
319 // deviceModelTag
320 // deviceMfgDescTag
321 // mediaBlackPointTag
322 // viewingCondDescTag
323 // viewingConditionsTag
324 // luminanceTag
325 // measurementTag
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
333 // copyrightTag
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 );
382 //device model tag
383 CIccTagTextDescription* deviceModelTag = new CIccTagTextDescription;
384 deviceModelTag->SetText("IEC 61966-2.1 Default RGB colour space - sRGB");
385 profile.AttachTag( icSigDeviceModelDescTag, deviceModelTag);
387 // deviceMfgDescTag
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 );
417 // luminanceTag
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);
424 // measurementTag
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);
451 //Verify things
452 string validationReport;
453 icValidateStatus validationStatus = profile.Validate(validationReport);
455 switch (validationStatus)
457 case icValidateOK:
458 break;
460 case icValidateWarning:
461 clog << "Profile validation warning" << endl
462 << validationReport;
463 break;
465 case icValidateNonCompliant:
466 clog << "Profile non compliancy" << endl
467 << validationReport;
468 break;
470 case icValidateCriticalError:
471 default:
472 clog << "Profile Error" << endl
473 << validationReport;
476 // Out it goes
477 CIccFileIO out;
478 out.Open(out_file_pathname, "wb+");
479 profile.Write(&out);
480 out.Close();
482 FILE *headerfile = fopen(hxx_file_name,"w");
484 //print OpenOffice standard file header
485 const char *the_string;
487 int idx = 0;
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 );
497 idx = 0;
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)
504 FILE *infile;
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);
519 if(achar == EOF)
520 break;
521 fprintf(headerfile,"0x%02x",achar);
522 if(number % 12 == 0)
523 fprintf(headerfile,",\n ");
524 else
525 fprintf(headerfile,", ");
526 number++;
527 } while(achar != EOF );
528 fprintf(headerfile,"\n};\n\n");
530 fclose(infile);
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
543 idx = 0;
544 while((the_string = TheTail[idx++]) != NULL )
545 fprintf(headerfile,"%s\n",the_string);
547 fclose(headerfile);
549 return EXIT_SUCCESS;
551 catch (const std::exception& e)
553 cout << myName << ": error: " << e.what() << endl;
554 return EXIT_FAILURE;