Bug Summary

File:Tools/CmdLine/IccApplyProfiles/iccApplyProfiles.cpp
Warning:line 207, column 7
Value stored to 'destEncoding' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-apple-macosx14.0.0 -Wundef-prefix=TARGET_OS_ -Werror=undef-prefix -Wdeprecated-objc-isa-usage -Werror=deprecated-objc-isa-usage -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name iccApplyProfiles.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=osx -analyzer-checker=security.insecureAPI.decodeValueOfObjCType -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -ffp-contract=on -fno-rounding-math -funwind-tables=2 -target-sdk-version=14.0 -fcompatibility-qualified-id-block-type-checking -fvisibility-inlines-hidden-static-local-var -target-cpu penryn -tune-cpu generic -debugger-tuning=lldb -target-linker-version 1015.7 -fprofile-instrument=clang -fcoverage-mapping -fcoverage-compilation-dir=/Users/xss/DemoIccMAX-hoyt-master/build/Tools/IccApplyProfiles -resource-dir /usr/local/Cellar/llvm/17.0.3/lib/clang/17 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.0.sdk -I /Users/xss/DemoIccMAX-hoyt-master/build/Cmake/../../IccProfLib -I /Library/Developer/CommandLineTools/SDKs/MacOSX12.sdk/usr/include/libxml2 -I /Users/xss/DemoIccMAX-hoyt-master/build/Cmake/../../IccXML/IccLibXML -I /usr/local/include -I /Users/xss/DemoIccMAX-hoyt-master/build/Cmake/Tools/IccApplyProfiles/../../../../Tools/CmdLine/IccApplyProfiles -internal-isystem /usr/local/Cellar/llvm/17.0.3/bin/../include/c++/v1 -internal-isystem /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.0.sdk/usr/local/include -internal-isystem /usr/local/Cellar/llvm/17.0.3/lib/clang/17/include -internal-externc-isystem /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.0.sdk/usr/include -std=gnu++17 -fdeprecated-macro -fdebug-compilation-dir=/Users/xss/DemoIccMAX-hoyt-master/build/Tools/IccApplyProfiles -ferror-limit 19 -fsanitize=address -fsanitize-system-ignorelist=/usr/local/Cellar/llvm/17.0.3/lib/clang/17/share/asan_ignorelist.txt -fno-sanitize-memory-param-retval -fsanitize-address-use-after-scope -fsanitize-address-globals-dead-stripping -fno-assume-sane-operator-new -stack-protector 1 -fblocks -fencode-extended-block-signature -fregister-global-dtors-with-atexit -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -fmax-type-align=16 -analyzer-output=html -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /var/folders/l9/sd9kj1px4yq2wc5_lkwhlt6w0000gn/T/scan-build-2023-10-28-102616-57860-1 -x c++ /Users/xss/DemoIccMAX-hoyt-master/Tools/CmdLine/IccApplyProfiles/iccApplyProfiles.cpp
1/*
2 File: CmdApplyProfiles.cpp
3
4 Contains: Console app that applies profiles
5
6 Version: V1
7
8 Copyright: (c) see below
9*/
10
11/*
12 * The ICC Software License, Version 0.2
13 *
14 *
15 * Copyright (c) 2003-2016 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 5-15-2003
68// -Modification to support iccMAX by Max Derhak in 2014
69//
70//////////////////////////////////////////////////////////////////////
71
72
73#include <stdio.h>
74#include "IccCmm.h"
75#include "IccUtil.h"
76#include "IccDefs.h"
77#include "IccApplyBPC.h"
78#include "IccEnvVar.h"
79#include "TiffImg.h"
80
81static icFloatNumber UnitClip(icFloatNumber v)
82{
83 if (v<0.0)
84 return 0.0;
85 if (v>1.0)
86 return 1.0;
87 return v;
88}
89
90
91typedef std::list<CIccProfile*> IccProfilePtrList;
92
93void Usage()
94{
95 printf("Usage: iccApplyProfiles src_tiff_file dst_tiff_file dst_sample_encoding interpolation dst_compression dst_planar dst_embed_icc {{-ENV:sig value} profile_file_path rendering_intent {-PCC connection_conditions_path}}\n\n");
96 printf(" For dst_sample_encoding:\n");
97 printf(" 0 - Same as src\n");
98 printf(" 1 - icEncode8Bit\n");
99 printf(" 2 - icEncode16Bit\n");
100 printf(" 4 - icEncodeFloat\n\n");
101
102 printf(" For interpolation:\n");
103 printf(" 0 - Linear\n");
104 printf(" 1 - Tetrahedral\n\n");
105
106 printf(" For dst_compression:\n");
107 printf(" 0 - No compression\n");
108 printf(" 1 - LZW compression\n\n");
109
110 printf(" For dst_planar:\n");
111 printf(" 0 - Contig\n");
112 printf(" 1 - Separation\n\n");
113
114 printf(" For dst_embed_icc:\n");
115 printf(" 0 - Do not Embed\n");
116 printf(" 1 - Embed Last ICC\n\n");
117
118 printf(" For rendering_intent:\n");
119 printf(" 0 - Perceptual\n");
120 printf(" 1 - Relative\n");
121 printf(" 2 - Saturation\n");
122 printf(" 3 - Absolute\n");
123 printf(" 10 - Perceptual without D2Bx/B2Dx\n");
124 printf(" 11 - Relative without D2Bx/B2Dx\n");
125 printf(" 12 - Saturation without D2Bx/B2Dx\n");
126 printf(" 13 - Absolute without D2Bx/B2Dx\n");
127 printf(" 20 - Preview Perceptual\n");
128 printf(" 21 - Preview Relative\n");
129 printf(" 22 - Preview Saturation\n");
130 printf(" 23 - Preview Absolute\n");
131 printf(" 30 - Gamut\n");
132 printf(" 33 - Gamut Absolute\n");
133 printf(" 40 - Perceptual with BPC\n");
134 printf(" 41 - Relative Colorimetric with BPC\n");
135 printf(" 42 - Saturation with BPC\n");
136 printf(" 50 - BDRF Parameters\n");
137 printf(" 60 - BDRF Direct\n");
138 printf(" 70 - BDRF MCS Parameters\n");
139 printf(" 80 - MCS connection\n");
140 printf(" +100 - Use Luminance based PCS adjustment\n");
141 printf(" +1000 - Use V5 sub-profile if present\n");
142}
143
144//===================================================
145
146int main(int argc, icChar* argv[])
147{
148 int minargs = 8; // minimum number of arguments
149 if(argc<minargs) {
150 Usage();
151 return -1;
152 }
153
154 int nNumProfiles, temp;
155 temp = argc - minargs;
156
157 //remaining arguments must be in pairs
158 if(temp%2 != 0) {
159 printf("\nMissing arguments!\n");
160 Usage();
161 return -1;
162 }
163
164 nNumProfiles = temp/2;
165
166 unsigned long i, j, k, sn, sphoto, photo, bps, dbps;
167 CTiffImg SrcImg, DstImg;
168 unsigned char *sptr, *dptr;
169 bool bSuccess = true;
170 bool bConvert = false;
171 char *last_path = NULL__null;
172
173 //Open source image file and get information from it
174 if (!SrcImg.Open(argv[1])) {
175 printf("\nFile [%s] cannot be opened.\n", argv[1]);
176 return false;
177 }
178 sn = SrcImg.GetSamples();
179 sphoto = SrcImg.GetPhoto();
180 bps = SrcImg.GetBitsPerSample();
181
182 //Setup source encoding based on bits per sample (bps) in source image
183 icFloatColorEncoding srcEncoding, destEncoding;
184 switch(bps) {
185 case 8:
186 srcEncoding = icEncode8Bit;
187 break;
188 case 16:
189 srcEncoding = icEncode16Bit;
190 break;
191 case 32:
192 srcEncoding = icEncodeFloat;
193 break;
194 default:
195 printf("Source bit depth / color data encoding not supported.\n");
196 return false;
197 }
198
199 //Setup destination encoding based on command line argument
200 destEncoding = (icFloatColorEncoding)atoi(argv[3]);
201 switch(destEncoding) {
202 case 0:
203 destEncoding = srcEncoding;
204 dbps = bps;
205 break;
206 case 1:
207 destEncoding = icEncode8Bit;
Value stored to 'destEncoding' is never read
208 dbps = 8;
209 break;
210 case 2:
211 destEncoding = icEncode16Bit;
212 dbps = 16;
213 break;
214 case 4:
215 destEncoding = icEncodeFloat;
216 dbps = 32;
217 break;
218 default:
219 printf("Source color data encoding not recognized.\n");
220 return false;
221 }
222
223 //Retrieve command line arguments
224 icXformInterp nInterp = (icXformInterp)atoi(argv[4]);
225 bool bCompress = atoi(argv[5])!=0;
226 bool bSeparation = atoi(argv[6])!=0;
227 bool bEmbed = atoi(argv[7])!=0;
228
229 int nIntent, nType, nLuminance;
230
231 //Allocate a CIccCmm to use to apply profiles.
232 //Let profiles determine starting and ending color spaces.
233 //Third argument indicates that Input transform from first profile should be used.
234 CIccCmm theCmm(icSigUnknownData((icColorSpaceSignature) 0x3f3f3f3f), icSigUnknownData((icColorSpaceSignature) 0x3f3f3f3f), true);
235
236 //PCC profiles need to stay around until the CMM has been completely initialized to apply transforms.
237 //TheCmm doesn't own them so keep a list so they can be released when they aren't needed any more.
238 IccProfilePtrList pccList;
239
240 int nCount;
241 bool bUseD2BxB2DxTags;
242 icStatusCMM stat; //status variable for CMM operations
243 icCmmEnvSigMap sigMap; //Keep track of CMM Environment for each profile
244 bool bUseSubProfile;
245
246 //Remaining arguments define a sequence of profiles to be applied.
247 //Add them to theCmm one at a time providing CMM environment variables and PCC overrides as provided.
248 for(i = 0, nCount=minargs; i<nNumProfiles; i++, nCount+=2) {
249#if defined(_WIN32) || defined(_WIN64)
250 if (!strnicmpstrncasecmp(argv[nCount], "-ENV:", 5)) { //check for -ENV: to allow for CMM Environment variables to be defined for next transform
251#else
252 if (!strncasecmp(argv[nCount], "-ENV:", 5)) {
253#endif
254 icSignature sig = icGetSigVal(argv[nCount]+5);
255 icFloatNumber val = (icFloatNumber)atof(argv[nCount+1]);
256
257 sigMap[sig]=val;
258 }
259 else if (stricmpstrcasecmp(argv[nCount], "-PCC")) { //Attach profile while ignoring -PCC (this are handled below as profiles are attached)
260 bUseD2BxB2DxTags = true;
261 nIntent = atoi(argv[nCount+1]);
262 bUseSubProfile = (nIntent / 1000) > 0;
263 nIntent = nIntent % 1000;
264 nLuminance = nIntent / 100;
265 nIntent = nIntent % 100;
266 nType = abs(nIntent) / 10;
267 nIntent = nIntent % 10;
268 CIccProfile *pPccProfile = NULL__null;
269
270 //Adjust type and hint information based on rendering intent
271 CIccCreateXformHintManager Hint;
272 switch(nType) {
273 case 1:
274 nType = 0;
275 bUseD2BxB2DxTags = false;
276 break;
277 case 4:
278 nType = 0;
279 Hint.AddHint(new CIccApplyBPCHint());
280 break;
281 }
282
283 if (nLuminance) {
284 Hint.AddHint(new CIccLuminanceMatchingHint());
285 }
286
287 // Use of following -PCC arg allows for profile connection conditions to be defined
288 if (i+1<nNumProfiles && !stricmpstrcasecmp(argv[nCount+2], "-PCC")) {
289 pPccProfile = OpenIccProfile(argv[nCount+3]);
290 if (!pPccProfile) {
291 printf("Unable to open Profile Connections Conditions from '%s'\n", argv[nCount+3]);
292 return -1;
293 }
294 //Keep track of pPccProfile for until after cmm.Begin is called
295 pccList.push_back(pPccProfile);
296 }
297
298 if (!i && !stricmpstrcasecmp(argv[nCount], "-embedded")) {
299 unsigned int len=0;
300 icUInt8Number *pProfile=NULL__null;
301
302 if (!SrcImg.GetIccProfile(pProfile, len)) {
303 printf("Image [%s] does not have an embedded profile\n", argv[nCount]);
304 return -1;
305 }
306
307 //Read and validate profile from memory
308 CIccProfile *pImgProfile = OpenIccProfile(pProfile, len, bUseSubProfile);
309 if (!pImgProfile) {
310 printf("Invalid Embedded profile in image [%s]\n", argv[nCount]);
311 return -1;
312 }
313
314 //CMM Environment variables are passed in as a Hint to the Xform associated with the profile
315 if (sigMap.size()>0) {
316 Hint.AddHint(new CIccCmmEnvVarHint(sigMap));
317 }
318
319 //Add embedded profile to theCmm (transferring ownership)
320 stat = theCmm.AddXform(pImgProfile, nIntent<0 ? icUnknownIntent((icRenderingIntent) 0x3f3f3f3f) : (icRenderingIntent)nIntent, nInterp, pPccProfile,
321 (icXformLutType)nType, bUseD2BxB2DxTags, &Hint);
322 if (stat) {
323 printf("Invalid Embedded profile in image [%s]\n", argv[nCount]);
324 return -1;
325 }
326 sigMap.clear();
327 }
328 else { //Non embedded profile case
329 //CMM Environment variables are passed in as a Hint to the Xform associated with the profile
330 if (sigMap.size()>0) {
331 Hint.AddHint(new CIccCmmEnvVarHint(sigMap));
332 }
333
334 //Remember last profile path so it can be embedded
335 last_path = &argv[nCount][0];
336
337 //Read profile from path and add it to theCmm
338 stat = theCmm.AddXform(argv[nCount], nIntent<0 ? icUnknownIntent((icRenderingIntent) 0x3f3f3f3f) : (icRenderingIntent)nIntent, nInterp, pPccProfile,
339 (icXformLutType)nType, bUseD2BxB2DxTags, &Hint, bUseSubProfile);
340 if (stat) {
341 printf("Invalid Profile(%d): %s\n", stat, argv[nCount]);
342 return -1;
343 }
344 sigMap.clear();
345 }
346 }
347 }
348
349 //All profiles have been added to CMM. Tell CMM that we are ready to begin applying colors/pixels
350 if((stat=theCmm.Begin())) {
351 printf("Error %d - Unable to begin profile application - Possibly invalid or incompatible profiles\n", stat);
352 return -1;
353 }
354
355 //Now we can release the pccProfile nodes.
356 IccProfilePtrList::iterator pcc;
357 for (pcc=pccList.begin(); pcc!=pccList.end(); pcc++) {
358 CIccProfile *pPccProfile = *pcc;
359 delete pPccProfile;
360 }
361 pccList.clear();
362
363 //Get and validate the source color space from theCmm.
364 icColorSpaceSignature SrcspaceSig = theCmm.GetSourceSpace();
365 int nSrcSamples = icGetSpaceSamples(SrcspaceSig);
366
367 if (nSrcSamples != sn) {
368 printf("Number of samples in image[%s] doesn't match device samples in first profile\n", argv[1]);
369 return -1;
370 }
371
372 //Get and validate the destination color space from theCmm.
373 icColorSpaceSignature DestspaceSig = theCmm.GetDestSpace();
374 int nDestSamples = icGetSpaceSamples(DestspaceSig);
375
376 switch (DestspaceSig) {
377 case icSigRgbData:
378 photo = PHOTO_MINISBLACK0;
379 break;
380
381 case icSigCmyData:
382 case icSigCmykData:
383 case icSig4colorData:
384 case icSig5colorData:
385 case icSig6colorData:
386 case icSig7colorData:
387 case icSig8colorData:
388 photo = PHOTO_MINISWHITE1;
389 break;
390
391 case icSigXYZData:
392 bConvert = true;
393 //Fall through - No break here
394
395 case icSigLabData:
396 photo = PHOTO_CIELAB2;
397 break;
398
399 default:
400 photo = PHOTO_MINISBLACK0;
401 break;
402 }
403
404 unsigned long sbpp = (nSrcSamples * bps + 7) / 8;
405 unsigned long dbpp = (nDestSamples * dbps + 7)/ 8;
406
407 //Open up output image using information from SrcImg and theCmm
408 if (!DstImg.Create(argv[2], SrcImg.GetWidth(), SrcImg.GetHeight(), dbps, photo, nDestSamples, SrcImg.GetXRes(), SrcImg.GetYRes(), bCompress, bSeparation)) {
409 printf("Unable to create Tiff file - '%s'\n", argv[2]);
410 return false;
411 }
412
413 //Embed the last profile into output image as needed
414 if (bEmbed) {
415 unsigned long length = 0;
416 icUInt8Number *pDestProfile = NULL__null;
417
418 CIccFileIO io;
419 if (io.Open(last_path, "r")) {
420 length = io.GetLength();
421 pDestProfile = (icUInt8Number *)malloc(length);
422 if (pDestProfile) {
423 io.Read8(pDestProfile, length);
424 DstImg.SetIccProfile(pDestProfile, length);
425 free(pDestProfile);
426 }
427 io.Close();
428 }
429 }
430
431 //Allocate buffer for reading source image pixels
432 unsigned char *pSBuf = (unsigned char *)malloc(SrcImg.GetBytesPerLine());
433 if (!pSBuf) {
434 printf("Out of Memory!\n");
435 return false;
436 }
437
438 //Allocate buffer for putting color managed pixels into that will be sent to output tiff image
439 unsigned char *pDBuf = (unsigned char *)malloc(DstImg.GetBytesPerLine());
440 if (!pDBuf) {
441 printf("Out of Memory!\n");
442 free(pSBuf);
443 return false;
444 }
445
446 //Allocate pixel buffers for performing encoding transformations
447 CIccPixelBuf SrcPixel(nSrcSamples+16), DestPixel(nDestSamples+16), Pixel(icIntMax(nSrcSamples, nDestSamples)+16);
448 int lastPer = -1;
449 int curper;
450
451 //Read each line
452 for (i=0; i<SrcImg.GetHeight(); i++) {
453 if (!SrcImg.ReadLine(pSBuf)) {
454 bSuccess = false;
455 break;
456 }
457 for (sptr=pSBuf, dptr=pDBuf, j=0; j<SrcImg.GetWidth(); j++, sptr+=sbpp, dptr+=dbpp) {
458
459 //Special conversions need to be made to convert CIELAB and CIEXYZ to internal PCS encoding
460 switch(bps) {
461 case 8:
462 if (sphoto==PHOTO_CIELAB2) {
463 unsigned char *pSPixel = sptr;
464 icFloatNumber *pPixel = SrcPixel;
465 pPixel[0]=(icFloatNumber)pSPixel[0] / 255.0f;
466 pPixel[1]=(icFloatNumber)(pSPixel[1]-128) / 255.0f;
467 pPixel[2]=(icFloatNumber)(pSPixel[2]-128) / 255.0f;
468 }
469 else {
470 unsigned char *pSPixel = sptr;
471 icFloatNumber *pPixel = SrcPixel;
472 for (k=0; k<nSrcSamples; k++) {
473 pPixel[k] = (icFloatNumber)pSPixel[k] / 255.0f;
474 }
475 }
476 break;
477
478 case 16:
479 if (sphoto==PHOTO_CIELAB2) {
480 unsigned short *pSPixel = (unsigned short*)sptr;
481 icFloatNumber *pPixel = SrcPixel;
482 pPixel[0]=(icFloatNumber)pSPixel[0] / 65535.0f;
483 pPixel[1]=(icFloatNumber)(pSPixel[1]-0x8000) / 65535.0f;
484 pPixel[2]=(icFloatNumber)(pSPixel[2]-0x8000) / 65535.0f;
485 }
486 else {
487 unsigned short *pSPixel = (unsigned short*)sptr;
488 icFloatNumber *pPixel = SrcPixel;
489 for (k=0; k<nSrcSamples; k++) {
490 pPixel[k] = (icFloatNumber)pSPixel[k] / 65535.0f;
491 }
492 }
493 break;
494
495 case 32:
496 {
497 if (sizeof(icFloatNumber)==sizeof(icFloat32Number)) {
498 memcpy(SrcPixel.get(), sptr, sbpp);
499 }
500 else {
501 icFloat32Number *pSPixel = (icFloat32Number*)sptr;
502 icFloatNumber *pPixel = SrcPixel;
503 for (k=0; k<nSrcSamples; k++) {
504 pPixel[k] = (icFloatNumber)pSPixel[k];
505 }
506 }
507
508 if (sphoto==PHOTO_CIELAB2 || sphoto==PHOTO_ICCLAB3) {
509 icLabToPcs(SrcPixel);
510 }
511 }
512 break;
513
514 default:
515 printf("Invalid source bit depth\n");
516 return -1;
517 }
518 if (sphoto == PHOTO_CIELAB2 && SrcspaceSig==icSigXYZData) {
519 icLabFromPcs(SrcPixel);
520 icLabtoXYZ(SrcPixel);
521 icXyzToPcs(SrcPixel);
522 }
523
524 //Use CMM to convert SrcPixel to DestPixel
525 theCmm.Apply(DestPixel, SrcPixel);
526
527 //Special conversions need to be made to convert from internal PCS encoding CIELAB
528 if (photo==PHOTO_CIELAB2 && DestspaceSig==icSigXYZData) {
529 icXyzFromPcs(DestPixel);
530 icXYZtoLab(DestPixel);
531 icLabToPcs(DestPixel);
532 }
533 switch(dbps) {
534 case 8:
535 if (photo==PHOTO_CIELAB2) {
536 unsigned char *pDPixel = dptr;
537 icFloatNumber *pPixel = DestPixel;
538 pDPixel[0]=(icUInt8Number)(UnitClip(pPixel[0]) * 255.0f + 0.5f);
539 pDPixel[1]=(icUInt8Number)(UnitClip(pPixel[1]) * 255.0f + 0.5f)+128;
540 pDPixel[2]=(icUInt8Number)(UnitClip(pPixel[2]) * 255.0f + 0.5f)+128;
541 }
542 else {
543 icUInt8Number *pDPixel = dptr;
544 icFloatNumber *pPixel = DestPixel;
545 for (k=0; k<nDestSamples; k++) {
546 pDPixel[k] = (icUInt8Number)(UnitClip(pPixel[k]) * 255.0f + 0.5f);
547 }
548 }
549 break;
550
551 case 16:
552 if (photo==PHOTO_CIELAB2) {
553 unsigned short *pDPixel = (unsigned short*)dptr;
554 icFloatNumber *pPixel = DestPixel;
555 pDPixel[0]=(icUInt16Number)(UnitClip(pPixel[0]) * 65535.0f + 0.5f);
556 pDPixel[1]=(icUInt16Number)(UnitClip(pPixel[1]) * 65535.0f + 0.5f)+0x8000;
557 pDPixel[2]=(icUInt16Number)(UnitClip(pPixel[2]) * 65535.0f + 0.5f)+0x8000;
558 }
559 else {
560 icUInt16Number *pDPixel = (icUInt16Number*)dptr;
561 icFloatNumber *pPixel = DestPixel;
562 for (k=0; k<nDestSamples; k++) {
563 pDPixel[k] = (icUInt16Number)(UnitClip(pPixel[k]) * 65535.0f+0.5f);
564 }
565 }
566 break;
567
568 case 32:
569 {
570 if (photo==PHOTO_CIELAB2 || photo==PHOTO_ICCLAB3) {
571 icLabFromPcs(SrcPixel);
572 }
573
574 if (sizeof(icFloatNumber)==sizeof(icFloat32Number)) {
575 memcpy(dptr, DestPixel.get(), dbpp);
576 }
577 else {
578 icFloat32Number *pDPixel = (icFloat32Number*)dptr;
579 icFloatNumber *pPixel = DestPixel;
580 for (k=0; k<nDestSamples; k++) {
581 pDPixel[k] = (icFloat32Number)pPixel[k];
582 }
583 }
584 }
585 break;
586
587 default:
588 printf("Invalid source bit depth\n");
589 return -1;
590 }
591 }
592
593 //Output the converted pixels to the destination image
594 if (!DstImg.WriteLine(pDBuf)) {
595 bSuccess = false;
596 break;
597 }
598
599 //Display status of how much we have accomplished
600 curper = (int)((float)(i+1)*100.0f/(float)SrcImg.GetHeight());
601 if (curper !=lastPer) {
602 printf("\r%d%%", curper);
603 lastPer = curper;
604 }
605 }
606 printf("\n");
607
608 //Clean everything up by closeing files and freeing buffers
609 SrcImg.Close();
610
611 free(pSBuf);
612 free(pDBuf);
613
614 DstImg.Close();
615
616 return 0;
617}
618