Bug Summary

File:IccProfLib/IccMpeSpectral.cpp
Warning:line 1428, column 8
Value stored to 'bUseAbsolute' during its initialization 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 IccMpeSpectral.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/IccProfLib -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 -D IccProfLib2_EXPORTS -I /Users/xss/DemoIccMAX-hoyt-master/build/Cmake/../../IccProfLib -I /Developer/Headers/FlatCarbon -F/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.0.sdk/System/Library/Frameworks -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/IccProfLib -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/IccProfLib/IccMpeSpectral.cpp
1/** @file
2 File: IccMpeSpectral.cpp
3
4 Contains: Implementation of Basic Multi Processing Elements
5
6 Version: V1
7
8 Copyright: � see ICC Software License
9*/
10
11/*
12 * The ICC Software License, Version 0.2
13 *
14 *
15 * Copyright (c) 2003-2014 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 1-30-2006
68//
69//////////////////////////////////////////////////////////////////////
70
71#ifdef WIN32
72#pragma warning( disable: 4786) //disable warning in <list.h>
73#endif
74
75#include <stdio.h>
76#include <math.h>
77#include <string.h>
78#include <stdlib.h>
79#include "IccMpeBasic.h"
80#include "IccMpeSpectral.h"
81#include "IccIO.h"
82#include <map>
83#include "IccMatrixMath.h"
84#include "IccUtil.h"
85#include "IccCAM.h"
86
87#ifdef USEREFICCMAXNAMESPACE
88namespace refIccMAX {
89#endif
90
91/**
92 ******************************************************************************
93 * Name: CIccMpeSpectralMatrix::CIccMpeSpectralMatrix
94 *
95 * Purpose:
96 *
97 * Args:
98 *
99 * Return:
100 ******************************************************************************/
101CIccMpeSpectralMatrix::CIccMpeSpectralMatrix()
102{
103 m_nReserved = 0;
104 m_nReserved2 = 0;
105 m_nInputChannels = m_nOutputChannels = 0;
106 m_size = 0;
107 m_pMatrix = NULL__null;
108 m_pOffset = NULL__null;
109 m_pWhite = NULL__null;
110
111 m_Range.start=0;
112 m_Range.end=0;
113 m_Range.steps=0;
114
115 m_pApplyMtx = NULL__null;
116}
117
118
119/**
120 ******************************************************************************
121 * Name: CIccMpeSpectralMatrix::CIccMpeSpectralMatrix
122 *
123 * Purpose:
124 *
125 * Args:
126 *
127 * Return:
128 ******************************************************************************/
129CIccMpeSpectralMatrix::CIccMpeSpectralMatrix(const CIccMpeSpectralMatrix &matrix)
130{
131 m_nReserved = matrix.m_nReserved;
132 m_nReserved2 = matrix.m_nReserved2;
133
134 m_nInputChannels = matrix.m_nInputChannels;
135 m_nOutputChannels = matrix.m_nOutputChannels;
136
137 m_Range = matrix.m_Range;
138
139 m_size = matrix.m_size;
140 if(matrix.m_pMatrix) {
141 int num = m_size * sizeof(icFloatNumber);
142 m_pMatrix = (icFloatNumber*)malloc(num);
143 memcpy(m_pMatrix, matrix.m_pMatrix, num);
144 }
145 else
146 m_pMatrix = NULL__null;
147
148 if (matrix.m_pOffset) {
149 int num = m_Range.steps * sizeof(icFloatNumber);
150 m_pOffset = (icFloatNumber*)malloc(num);
151 memcpy(m_pOffset, matrix.m_pOffset, num);
152 }
153 else
154 m_pOffset = NULL__null;
155
156 if (matrix.m_pWhite) {
157 int num = m_Range.steps * sizeof(icFloatNumber);
158 m_pWhite = (icFloatNumber*)malloc(num);
159 memcpy(m_pWhite, matrix.m_pWhite, num);
160 }
161 else
162 m_pWhite = NULL__null;
163
164 m_pApplyMtx = NULL__null;
165}
166
167/**
168 ******************************************************************************
169 * Name: &CIccMpeSpectralMatrix::operator=
170 *
171 * Purpose:
172 *
173 * Args:
174 *
175 * Return:
176 ******************************************************************************/
177void CIccMpeSpectralMatrix::copyData(const CIccMpeSpectralMatrix &matrix)
178{
179 m_nReserved = matrix.m_nReserved;
180 m_nReserved2 = matrix.m_nReserved2;
181
182 m_nInputChannels = matrix.m_nInputChannels;
183 m_nOutputChannels = matrix.m_nOutputChannels;
184
185 m_Range = m_Range;
186
187 if (m_pMatrix)
188 free(m_pMatrix);
189
190 m_size = matrix.m_size;
191 if (matrix.m_pMatrix) {
192 int num = m_size * sizeof(icFloatNumber);
193 m_pMatrix = (icFloatNumber*)malloc(num);
194 memcpy(m_pMatrix, matrix.m_pMatrix, num);
195 }
196 else
197 m_pMatrix = NULL__null;
198
199 if (m_pOffset)
200 free(m_pOffset);
201
202 if (matrix.m_pOffset) {
203 int num = m_Range.steps * sizeof(icFloatNumber);
204 m_pOffset = (icFloatNumber*)malloc(num);
205 memcpy(m_pOffset, matrix.m_pOffset, num);
206 }
207 else
208 m_pOffset = NULL__null;
209
210 if (m_pWhite)
211 free(m_pWhite);
212
213 if (matrix.m_pWhite) {
214 int num = m_Range.steps * sizeof(icFloatNumber);
215 m_pWhite = (icFloatNumber*)malloc(num);
216 memcpy(m_pWhite, matrix.m_pWhite, num);
217 }
218 else
219 m_pWhite = NULL__null;
220
221 m_pApplyMtx = NULL__null;
222}
223
224/**
225 ******************************************************************************
226 * Name: CIccMpeSpectralMatrix::~CIccMpeSpectralMatrix
227 *
228 * Purpose:
229 *
230 * Args:
231 *
232 * Return:
233 ******************************************************************************/
234CIccMpeSpectralMatrix::~CIccMpeSpectralMatrix()
235{
236 if (m_pMatrix)
237 free(m_pMatrix);
238
239 if (m_pOffset)
240 free(m_pOffset);
241
242 if (m_pWhite)
243 free(m_pWhite);
244
245 if (m_pApplyMtx)
246 delete m_pApplyMtx;
247}
248
249
250/**
251 ******************************************************************************
252 * Name: CIccMpeSpectralMatrix::SetSize
253 *
254 * Purpose:
255 *
256 * Args:
257 *
258 * Return:
259 ******************************************************************************/
260bool CIccMpeSpectralMatrix::SetSize(icUInt16Number nInputChannels, icUInt16Number nOutputChannels, const icSpectralRange &range)
261{
262 if (m_pMatrix) {
263 free(m_pMatrix);
264 m_pMatrix = NULL__null;
265 }
266
267 if (m_pWhite) {
268 free(m_pWhite);
269 m_pWhite = NULL__null;
270 }
271
272 if (m_pOffset) {
273 free(m_pOffset);
274 m_pOffset = NULL__null;
275 }
276
277 if (m_pApplyMtx) {
278 delete m_pApplyMtx;
279 m_pApplyMtx = NULL__null;
280 }
281
282 m_nInputChannels = nInputChannels;
283 m_nOutputChannels = nOutputChannels;
284 m_Range = range;
285
286 m_size = (icUInt32Number)numVectors() * range.steps;
287
288 m_pMatrix = (icFloatNumber*)calloc(m_size, sizeof(icFloatNumber));
289 m_pOffset = (icFloatNumber*)calloc(range.steps, sizeof(icFloatNumber));
290 m_pWhite = (icFloatNumber*)calloc(range.steps, sizeof(icFloatNumber));
291
292 if (!m_pMatrix || !m_pOffset || !m_pWhite) {
293 m_size = 0;
294 return false;
295 }
296
297 return true;
298}
299
300/**
301 ******************************************************************************
302 * Name: CIccMpeSpectralMatrix::Describe
303 *
304 * Purpose:
305 *
306 * Args:
307 *
308 * Return:
309 ******************************************************************************/
310void CIccMpeSpectralMatrix::Describe(std::string &sDescription)
311{
312 icChar buf[81];
313 int i, j;
314 icFloatNumber *data = m_pMatrix;
315
316 sprintf(buf, "BEGIN_%s %d %d \r\n", GetDescribeName(), m_nInputChannels, m_nOutputChannels);
317 sDescription += buf;
318
319 sprintf(buf, "RANGE %f %f %d\r\n", icF16toF(m_Range.start), icF16toF(m_Range.end), m_Range.steps);
320 sDescription += buf;
321
322 sDescription += "White\r\n";
323 for (j=0; j<(int)m_Range.steps; j++) {
324 if (j)
325 sDescription += " ";
326 sprintf(buf, "%12.8lf", m_pWhite[j]);
327 sDescription += buf;
328 }
329 sDescription += "\r\n";
330
331 sDescription += "BLACK_OFFSET\r\n";
332 for (j=0; j<(int)m_Range.steps; j++) {
333 if (j)
334 sDescription += " ";
335 sprintf(buf, "%12.8lf", m_pOffset[j]);
336 sDescription += buf;
337 }
338 sDescription += "\r\n";
339
340 if (data) {
341 sDescription += "CHANNEL_DATA\r\n";
342 for (j=0; j<m_nOutputChannels; j++) {
343 for (i=0; i<(int)m_Range.steps; i++) {
344 if (i)
345 sDescription += " ";
346 sprintf(buf, "%12.8lf", data[i]);
347 sDescription += buf;
348 }
349 sDescription += "\r\n";
350 data += m_nInputChannels;
351 }
352 }
353
354 sprintf(buf, "END_%s\r\n", GetDescribeName());
355 sDescription += buf;
356}
357
358/**
359 ******************************************************************************
360 * Name: CIccMpeSpectralMatrix::Read
361 *
362 * Purpose:
363 *
364 * Args:
365 *
366 * Return:
367 ******************************************************************************/
368bool CIccMpeSpectralMatrix::Read(icUInt32Number size, CIccIO *pIO)
369{
370 icElemTypeSignature sig;
371
372 icUInt32Number headerSize = sizeof(icElemTypeSignature) +
373 sizeof(icUInt32Number) +
374 sizeof(icUInt16Number) +
375 sizeof(icUInt16Number) +
376 sizeof(icUInt16Number) +
377 sizeof(icUInt16Number) +
378 sizeof(icUInt16Number) +
379 sizeof(icUInt16Number);
380
381 if (headerSize > size)
382 return false;
383
384 if (!pIO) {
385 return false;
386 }
387
388 icUInt16Number nInputChannels, nOutputChannels;
389 icSpectralRange range;
390
391 if (!pIO->Read32(&sig))
392 return false;
393
394 if (!pIO->Read32(&m_nReserved))
395 return false;
396
397 if (!pIO->Read16(&nInputChannels))
398 return false;
399
400 if (!pIO->Read16(&nOutputChannels))
401 return false;
402
403 if (!pIO->Read16(&range.start))
404 return false;
405
406 if (!pIO->Read16(&range.end))
407 return false;
408
409 if (!pIO->Read16(&range.steps))
410 return false;
411
412 if (!pIO->Read16(&m_nReserved2))
413 return false;
414
415 SetSize(nInputChannels, nOutputChannels, range);
416 if (!m_pWhite || !m_pMatrix || !m_pOffset)
417 return false;
418
419 if (size<headerSize + (int)range.steps*sizeof(icFloatNumber))
420 return false;
421
422 //Read White data
423 if (pIO->ReadFloat32Float(m_pWhite, range.steps)!=range.steps)
424 return false;
425
426 if (size<headerSize + (int)range.steps*sizeof(icFloatNumber) + m_size * sizeof(icFloatNumber))
427 return false;
428
429 //Read Matrix data
430 if (pIO->ReadFloat32Float(m_pMatrix, m_size)!=(icInt32Number)m_size)
431 return false;
432
433 if (size>=headerSize + 2*(int)range.steps*sizeof(icFloatNumber) + m_size * sizeof(icFloatNumber)) {
434 if (pIO->ReadFloat32Float(m_pOffset, range.steps)!=range.steps)
435 return false;
436 }
437 else {
438 memset(m_pOffset, 0, (int)range.steps*sizeof(icFloatNumber));
439 }
440
441 return true;
442}
443
444/**
445 ******************************************************************************
446 * Name: CIccMpeSpectralMatrix::Write
447 *
448 * Purpose:
449 *
450 * Args:
451 *
452 * Return:
453 ******************************************************************************/
454bool CIccMpeSpectralMatrix::Write(CIccIO *pIO)
455{
456 icElemTypeSignature sig = GetType();
457
458 if (!pIO)
459 return false;
460
461 if (!pIO->Write32(&sig))
462 return false;
463
464 if (!pIO->Write32(&m_nReserved))
465 return false;
466
467 if (!pIO->Write16(&m_nInputChannels))
468 return false;
469
470 if (!pIO->Write16(&m_nOutputChannels))
471 return false;
472
473 if (!pIO->Write16(&m_Range.start))
474 return false;
475
476 if (!pIO->Write16(&m_Range.end))
477 return false;
478
479 if (!pIO->Write16(&m_Range.steps))
480 return false;
481
482 if (!pIO->Write16(&m_nReserved2))
483 return false;
484
485 if (m_pWhite) {
486 if (pIO->WriteFloat32Float(m_pWhite, m_Range.steps)!=m_Range.steps)
487 return false;
488 }
489 else if (m_Range.steps) {
490 return false;
491 }
492
493 if (m_pMatrix) {
494 if (pIO->WriteFloat32Float(m_pMatrix, m_size)!=(icInt32Number)m_size)
495 return false;
496 }
497
498 //Write Constant data
499 if (m_pOffset) {
500 if (pIO->WriteFloat32Float(m_pOffset, m_Range.steps)!=m_Range.steps)
501 return false;
502 }
503
504 return true;
505}
506
507/**
508 ******************************************************************************
509 * Name: CIccMpeSpectralMatrix::Validate
510 *
511 * Purpose:
512 *
513 * Args:
514 *
515 * Return:
516 ******************************************************************************/
517icValidateStatus CIccMpeSpectralMatrix::Validate(std::string sigPath, std::string &sReport, const CIccTagMultiProcessElement* pMPE/*=NULL*/) const
518{
519 std::string mpeSigPath = sigPath + icGetSigPath(GetType());
520 icValidateStatus rv = CIccMultiProcessElement::Validate(sigPath, sReport, pMPE);
521
522 if (!m_Range.steps) {
523 CIccInfo Info;
524 std::string sSigPathName = Info.GetSigPathName(mpeSigPath);
525
526 sReport += icMsgValidateCriticalError;
527 sReport += sSigPathName;
528 sReport += " - Cannot have zero spectral range steps!\r\n";
529 rv = icMaxStatus(rv, icValidateCriticalError);
530 }
531
532 if (m_nOutputChannels != 3) {
533 CIccInfo Info;
534 std::string sSigPathName = Info.GetSigPathName(mpeSigPath);
535
536 sReport += icMsgValidateCriticalError;
537 sReport += sSigPathName;
538 sReport += " - Output Channels must be 3!\r\n";
539 rv = icMaxStatus(rv, icValidateCriticalError);
540 }
541
542 if (!m_pWhite) {
543 CIccInfo Info;
544 std::string sSigPathName = Info.GetSigPathName(mpeSigPath);
545
546 sReport += icMsgValidateCriticalError;
547 sReport += sSigPathName;
548 sReport += " - Has Empty White data!\r\n";
549 rv = icMaxStatus(rv, icValidateCriticalError);
550 }
551
552 if (!m_pMatrix) {
553 CIccInfo Info;
554 std::string sSigPathName = Info.GetSigPathName(mpeSigPath);
555
556 sReport += icMsgValidateCriticalError;
557 sReport += sSigPathName;
558 sReport += " - Has Empty Matrix data!\r\n";
559 rv = icMaxStatus(rv, icValidateCriticalError);
560 }
561
562 if (!m_pOffset) {
563 CIccInfo Info;
564 std::string sSigPathName = Info.GetSigPathName(mpeSigPath);
565
566 sReport += icMsgValidateCriticalError;
567 sReport += sSigPathName;
568 sReport += " - Has Empty Matrix Constant data!\r\n";
569 rv = icMaxStatus(rv, icValidateCriticalError);
570 }
571
572 if (m_Range.start>= m_Range.end || !m_Range.steps) {
573 CIccInfo Info;
574 std::string sSigPathName = Info.GetSigPathName(mpeSigPath);
575
576 sReport += icMsgValidateCriticalError;
577 sReport += sSigPathName;
578 sReport += " - Has an invalid spectral range!\r\n";
579 rv = icMaxStatus(rv, icValidateCriticalError);
580 }
581
582 return rv;
583}
584
585/**
586 ******************************************************************************
587 * Name: CIccMpeEmissionMatrix::Begin
588 *
589 * Purpose:
590 *
591 * Args:
592 *
593 * Return:
594 ******************************************************************************/
595bool CIccMpeEmissionMatrix::Begin(icElemInterp nInterp, CIccTagMultiProcessElement *pMPE)
596{
597 if (!m_pOffset ||!pMPE || !m_pMatrix || m_nOutputChannels != 3)
598 return false;
599
600 IIccProfileConnectionConditions *pAppliedPCC = pMPE->GetAppliedPCC();
601 if (!pAppliedPCC)
602 return false;
603
604 const CIccTagSpectralViewingConditions *pSVC = pAppliedPCC->getPccViewingConditions();
605 if (!pSVC)
606 return false;
607
608 CIccMatrixMath observer(3, m_Range.steps);
609 icFloat32Number *pSrc, *pMtx;
610
611 if (!pAppliedPCC->getEmissiveObserver(m_Range, m_pWhite, observer.entry(0)))
612 return false;
613
614 //convert m_Matrix emission values to a matrix of XYZ column vectors
615 m_pApplyMtx = new CIccMatrixMath(3,m_nInputChannels);
616
617 if (!m_pApplyMtx)
618 return false;
619
620 icFloatNumber xyz[3];
621 int i;
622
623 pSrc = m_pMatrix;
624 pMtx = m_pApplyMtx->entry(0);
625 for (i=0; i<m_nInputChannels; i++) {
626 observer.VectorMult(xyz, pSrc);
627 pSrc += m_Range.steps;
628
629 pMtx[0] = xyz[0];
630 pMtx[m_nInputChannels] = xyz[1];
631 pMtx[2*m_nInputChannels] = xyz[2];
632 pMtx++;
633 }
634
635 //Now convert offset emission to XYZ offset
636 observer.VectorMult(m_xyzOffset, m_pOffset);
637
638 return true;
639}
640
641/**
642 ******************************************************************************
643 * Name: CIccMpeEmissionMatrix::Apply
644 *
645 * Purpose:
646 *
647 * Args:
648 *
649 * Return:
650 ******************************************************************************/
651void CIccMpeEmissionMatrix::Apply(CIccApplyMpe *pApply, icFloatNumber *dstPixel, const icFloatNumber *srcPixel) const
652{
653 if (m_pApplyMtx) {
654 m_pApplyMtx->VectorMult(dstPixel, srcPixel);
655 dstPixel[0] += m_xyzOffset[0];
656 dstPixel[1] += m_xyzOffset[1];
657 dstPixel[2] += m_xyzOffset[2];
658 }
659 else {
660 dstPixel[0] = 0;
661 dstPixel[1] = 0;
662 dstPixel[2] = 0;
663 }
664}
665
666
667/**
668 ******************************************************************************
669 * Name: CIccMpeInvEmissionMatrix::Begin
670 *
671 * Purpose:
672 *
673 * Args:
674 *
675 * Return:
676 ******************************************************************************/
677bool CIccMpeInvEmissionMatrix::Begin(icElemInterp nInterp, CIccTagMultiProcessElement *pMPE)
678{
679 if (!m_pOffset ||!pMPE || !m_pMatrix || m_nInputChannels != 3 || m_nOutputChannels != 3)
680 return false;
681
682 IIccProfileConnectionConditions *pAppliedPCC = pMPE->GetAppliedPCC();
683 if (!pAppliedPCC)
684 return false;
685
686 const CIccTagSpectralViewingConditions *pSVC = pAppliedPCC->getPccViewingConditions();
687 if (!pSVC)
688 return false;
689
690 CIccMatrixMath observer(3, m_Range.steps);
691 icFloat32Number *pSrc, *pMtx;
692
693 if (!pAppliedPCC->getEmissiveObserver(m_Range, m_pWhite, observer.entry(0)))
694 return false;
695
696 observer.VectorMult(m_xyzOffset, m_pOffset);
697
698 //convert m_Matrix emission values to a matrix of XYZ column vectors
699 m_pApplyMtx = new CIccMatrixMath(3,m_nInputChannels);
700
701 if (!m_pApplyMtx)
702 return false;
703
704 icFloatNumber xyz[3];
705 int i;
706
707 pSrc = m_pMatrix;
708 pMtx = m_pApplyMtx->entry(0);
709 for (i=0; i<m_nInputChannels; i++) {
710 observer.VectorMult(xyz, pSrc);
711 pSrc += m_Range.steps;
712
713 pMtx[0] = xyz[0];
714 pMtx[m_nInputChannels] = xyz[1];
715 pMtx[2*m_nInputChannels] = xyz[2];
716 pMtx++;
717 }
718
719 m_pApplyMtx->Invert();
720
721 return true;
722}
723
724/**
725 ******************************************************************************
726 * Name: CIccMpeInvEmissionMatrix::Apply
727 *
728 * Purpose:
729 *
730 * Args:
731 *
732 * Return:
733 ******************************************************************************/
734void CIccMpeInvEmissionMatrix::Apply(CIccApplyMpe *pApply, icFloatNumber *dstPixel, const icFloatNumber *srcPixel) const
735{
736 if (m_pApplyMtx) {
737 icFloatNumber xyz[3];
738 xyz[0] = srcPixel[0] - m_xyzOffset[0];
739 xyz[1] = srcPixel[1] - m_xyzOffset[1];
740 xyz[2] = srcPixel[2] - m_xyzOffset[2];
741 m_pApplyMtx->VectorMult(dstPixel, xyz);
742 }
743 else {
744 dstPixel[0] = 0;
745 dstPixel[1] = 0;
746 dstPixel[2] = 0;
747 }
748}
749
750/**
751 ******************************************************************************
752 * Name: CIccMpeInvEmissionMatrix::Validate
753 *
754 * Purpose:
755 *
756 * Args:
757 *
758 * Return:
759 ******************************************************************************/
760icValidateStatus CIccMpeInvEmissionMatrix::Validate(std::string sigPath, std::string &sReport, const CIccTagMultiProcessElement* pMPE/*=NULL*/) const
761{
762 std::string mpeSigPath = sigPath + icGetSigPath(GetType());
763 icValidateStatus rv = CIccMpeSpectralMatrix::Validate(sigPath, sReport, pMPE);
764
765 if (m_nInputChannels != 3) {
766 CIccInfo Info;
767 std::string sSigPathName = Info.GetSigPathName(mpeSigPath);
768
769 sReport += icMsgValidateCriticalError;
770 sReport += sSigPathName;
771 sReport += " - Input Channels must be 3!\r\n";
772 rv = icMaxStatus(rv, icValidateCriticalError);
773 }
774
775 return rv;
776}
777
778static icFloatNumber NoClip(icFloatNumber v)
779{
780 return v;
781}
782
783
784
785/**
786 ******************************************************************************
787 * Name: CIccMpeSpectralCLUT::CIccMpeSpectralCLUT
788 *
789 * Purpose:
790 *
791 * Args:
792 *
793 * Return:
794 ******************************************************************************/
795CIccMpeSpectralCLUT::CIccMpeSpectralCLUT()
796{
797 m_nInputChannels = 0;
798 m_nOutputChannels = 0;
799
800 m_nReserved = 0;
801
802 m_Range.start = 0;
803 m_Range.end = 0;
804 m_Range.steps = 0;
805
806 m_nStorageType = icValueTypeFloat32;
807 m_flags = 0;
808
809 m_pCLUT = NULL__null;
810 m_pApplyCLUT = NULL__null;
811 m_pWhite = NULL__null;
812}
813
814/**
815 ******************************************************************************
816 * Name: CIccMpeSpectralCLUT::CIccMpeSpectralCLUT
817 *
818 * Purpose:
819 *
820 * Args:
821 *
822 * Return:
823 ******************************************************************************/
824CIccMpeSpectralCLUT::CIccMpeSpectralCLUT(const CIccMpeSpectralCLUT &clut)
825{
826 if (clut.m_pCLUT)
827 m_pCLUT = new CIccCLUT(*clut.m_pCLUT);
828 else
829 m_pCLUT = NULL__null;
830
831 if (clut.m_pApplyCLUT)
832 m_pApplyCLUT = new CIccCLUT(*clut.m_pApplyCLUT);
833 else
834 m_pApplyCLUT = NULL__null;
835
836 if (clut.m_pWhite) {
837 m_pWhite = (icFloatNumber *)malloc((int)clut.m_Range.steps*sizeof(icFloatNumber));
838 memcpy(m_pWhite, clut.m_pWhite, clut.m_Range.steps*sizeof(icFloatNumber));
839 }
840 else
841 m_pWhite = NULL__null;
842
843 m_nReserved = clut.m_nReserved;
844 m_nInputChannels = clut.m_nInputChannels;
845 m_nOutputChannels = clut.m_nOutputChannels;
846
847 m_Range = clut.m_Range;
848 m_nStorageType = clut.m_nStorageType;
849 m_flags = clut.m_flags;
850}
851
852/**
853 ******************************************************************************
854 * Name: &CIccMpeSpectralCLUT::operator=
855 *
856 * Purpose:
857 *
858 * Args:
859 *
860 * Return:
861 ******************************************************************************/
862void CIccMpeSpectralCLUT::copyData(const CIccMpeSpectralCLUT &clut)
863{
864 if (m_pCLUT)
865 delete m_pCLUT;
866
867 if (m_pApplyCLUT)
868 delete m_pApplyCLUT;
869
870 if (m_pWhite)
871 free(m_pWhite);
872
873 if (clut.m_pCLUT)
874 m_pCLUT = new CIccCLUT(*clut.m_pCLUT);
875 else
876 m_pCLUT = NULL__null;
877
878 if (clut.m_pApplyCLUT)
879 m_pApplyCLUT = new CIccCLUT(*clut.m_pApplyCLUT);
880 else
881 m_pApplyCLUT = NULL__null;
882
883 if (clut.m_pWhite) {
884 m_pWhite = (icFloatNumber *)malloc((int)clut.m_Range.steps*sizeof(icFloatNumber));
885 memcpy(m_pWhite, clut.m_pWhite, clut.m_Range.steps*sizeof(icFloatNumber));
886 }
887 else
888 m_pWhite = NULL__null;
889
890 m_nReserved = clut.m_nReserved;
891 m_nInputChannels = clut.m_nInputChannels;
892 m_nOutputChannels = clut.m_nOutputChannels;
893
894 m_Range = clut.m_Range;
895 m_nStorageType = clut.m_nStorageType;
896 m_flags = clut.m_flags;
897}
898
899/**
900 ******************************************************************************
901 * Name: CIccMpeSpectralCLUT::~CIccMpeSpectralCLUT
902 *
903 * Purpose:
904 *
905 * Args:
906 *
907 * Return:
908 ******************************************************************************/
909CIccMpeSpectralCLUT::~CIccMpeSpectralCLUT()
910{
911 if (m_pCLUT)
912 delete m_pCLUT;
913
914 if (m_pApplyCLUT)
915 delete m_pApplyCLUT;
916
917 if (m_pWhite)
918 free(m_pWhite);
919
920}
921
922/**
923 ******************************************************************************
924 * Name: CIccMpeSpectralCLUT::SetCLUT
925 *
926 * Purpose:
927 *
928 * Args:
929 *
930 * Return:
931 ******************************************************************************/
932void CIccMpeSpectralCLUT::SetData(CIccCLUT *pCLUT, icUInt16Number nStorageType,
933 const icSpectralRange &range, icFloatNumber *pWhite,
934 icUInt16Number nOutputChannels)
935{
936 if (m_pCLUT)
937 delete m_pCLUT;
938
939 m_pCLUT = pCLUT;
940 if (pCLUT) {
941 pCLUT->SetClipFunc(NoClip);
942 m_nInputChannels = pCLUT->GetInputDim();
943 m_nOutputChannels = nOutputChannels;
944 }
945
946 m_nStorageType = nStorageType;
947
948 if (m_pApplyCLUT) {
949 delete m_pApplyCLUT;
950 m_pApplyCLUT = NULL__null;
951 }
952
953 m_Range = range;
954
955 if (m_pWhite)
956 free(m_pWhite);
957
958 m_pWhite = pWhite;
959}
960
961/**
962 ******************************************************************************
963 * Name: CIccMpeSpectralCLUT::Describe
964 *
965 * Purpose:
966 *
967 * Args:
968 *
969 * Return:
970 ******************************************************************************/
971void CIccMpeSpectralCLUT::Describe(std::string &sDescription)
972{
973 if (m_pCLUT) {
974 m_pCLUT->DumpLut(sDescription, GetDescribeName(), icSigUnknownData((icColorSpaceSignature) 0x3f3f3f3f), icSigUnknownData((icColorSpaceSignature) 0x3f3f3f3f));
975 }
976}
977
978
979/**
980******************************************************************************
981* Name: CIccMpeSpectralCLUT::Read
982*
983* Purpose:
984*
985* Args:
986*
987* Return:
988******************************************************************************/
989bool CIccMpeSpectralCLUT::Read(icUInt32Number size, CIccIO *pIO)
990{
991 icTagTypeSignature sig;
992
993 icUInt32Number headerSize = sizeof(icTagTypeSignature) +
994 sizeof(icUInt32Number) +
995 sizeof(icUInt32Number) +
996 sizeof(icUInt16Number) +
997 sizeof(icUInt16Number) +
998 sizeof(icUInt16Number) +
999 sizeof(icUInt16Number) +
1000 sizeof(icUInt16Number) +
1001 sizeof(icUInt16Number) +
1002 16 * sizeof(icUInt8Number);
1003
1004 if (headerSize > size)
1005 return false;
1006
1007 if (!pIO) {
1008 return false;
1009 }
1010
1011 if (!pIO->Read32(&sig))
1012 return false;
1013
1014 if (!pIO->Read32(&m_nReserved))
1015 return false;
1016
1017 if (!pIO->Read16(&m_nInputChannels))
1018 return false;
1019
1020 if (!pIO->Read16(&m_nOutputChannels))
1021 return false;
1022
1023 if (!pIO->Read32(&m_flags))
1024 return false;
1025
1026 if (!pIO->Read16(&m_Range.start))
1027 return false;
1028
1029 if (!pIO->Read16(&m_Range.end))
1030 return false;
1031
1032 if (!pIO->Read16(&m_Range.steps))
1033 return false;
1034
1035 if (!pIO->Read16(&m_nStorageType))
1036 return false;
1037
1038 icUInt8Number gridPoints[16];
1039
1040 if (pIO->Read8(gridPoints, 16)!=16) {
1041 return false;
1042 }
1043
1044 m_pCLUT = new CIccCLUT((icUInt8Number)m_nInputChannels, (icUInt16Number)m_Range.steps, 4);
1045
1046 if (!m_pCLUT)
1047 return false;
1048
1049 m_pCLUT->SetClipFunc(NoClip);
1050 icUInt32Number nBytesPerPoint = icGetStorageTypeBytes(m_nStorageType) * m_Range.steps;
1051
1052 if (!nBytesPerPoint)
1053 return false;
1054
1055 m_pCLUT->Init(gridPoints, size - headerSize, (icUInt8Number)nBytesPerPoint);
1056
1057 icFloatNumber *pData = m_pCLUT->GetData(0);
1058
1059 if (!pData)
1060 return false;
1061
1062 icInt32Number nPoints = m_pCLUT->NumPoints()*(int)m_Range.steps;
1063
1064 switch(m_nStorageType) {
1065 case icValueTypeUInt8:
1066 if (pIO->ReadUInt8Float(pData,nPoints)!= nPoints)
1067 return false;
1068 break;
1069
1070 case icValueTypeUInt16:
1071 if (pIO->ReadUInt16Float(pData,nPoints)!= nPoints)
1072 return false;
1073 break;
1074
1075 case icValueTypeFloat16:
1076 if (pIO->ReadFloat16Float(pData,nPoints)!= nPoints)
1077 return false;
1078 break;
1079
1080 case icValueTypeFloat32:
1081 if (pIO->ReadFloat32Float(pData,nPoints)!= nPoints)
1082 return false;
1083 break;
1084
1085 default:
1086 return false;
1087 }
1088
1089 if (m_Range.steps *nBytesPerPoint > size - headerSize - nPoints*nBytesPerPoint)
1090 return false;
1091
1092 m_pWhite = (icFloatNumber *)malloc((int)m_Range.steps*sizeof(icFloatNumber));
1093 if (!m_pWhite)
1094 return false;
1095
1096 switch(m_nStorageType) {
1097 case icValueTypeUInt8:
1098 if (pIO->ReadUInt8Float(m_pWhite,m_Range.steps)!= m_Range.steps)
1099 return false;
1100 break;
1101
1102 case icValueTypeUInt16:
1103 if (pIO->ReadUInt16Float(m_pWhite,m_Range.steps)!= m_Range.steps)
1104 return false;
1105 break;
1106
1107 case icValueTypeFloat16:
1108 if (pIO->ReadFloat16Float(m_pWhite,m_Range.steps)!= m_Range.steps)
1109 return false;
1110 break;
1111
1112 case icValueTypeFloat32:
1113 if (pIO->ReadFloat32Float(m_pWhite,m_Range.steps)!= m_Range.steps)
1114 return false;
1115 break;
1116
1117 default:
1118 return false;
1119 }
1120
1121
1122 return true;
1123}
1124
1125/**
1126******************************************************************************
1127* Name: CIccMpeSpectralCLUT::Write
1128*
1129* Purpose:
1130*
1131* Args:
1132*
1133* Return:
1134******************************************************************************/
1135bool CIccMpeSpectralCLUT::Write(CIccIO *pIO)
1136{
1137 icElemTypeSignature sig = GetType();
1138
1139 if (!pIO)
1140 return false;
1141
1142 if (!pIO->Write32(&sig))
1143 return false;
1144
1145 if (!pIO->Write32(&m_nReserved))
1146 return false;
1147
1148 if (!pIO->Write16(&m_nInputChannels))
1149 return false;
1150
1151 if (!pIO->Write16(&m_nOutputChannels))
1152 return false;
1153
1154 if (!pIO->Write32(&m_flags))
1155 return false;
1156
1157 if (!pIO->Write16(&m_Range.start))
1158 return false;
1159
1160 if (!pIO->Write16(&m_Range.end))
1161 return false;
1162
1163 if (!pIO->Write16(&m_Range.steps))
1164 return false;
1165
1166 if (!pIO->Write16(&m_nStorageType))
1167 return false;
1168
1169 if (m_pCLUT) {
1170 icUInt8Number gridPoints[16];
1171 int i;
1172
1173 for (i=0; i<16; i++)
1174 gridPoints[i] = m_pCLUT->GridPoint(i);
1175
1176 if (pIO->Write8(gridPoints, 16)!=16)
1177 return false;
1178
1179 icFloatNumber *pData = m_pCLUT->GetData(0);
1180 icInt32Number nPoints = m_pCLUT->NumPoints()*(int)m_Range.steps;
1181
1182 switch(m_nStorageType) {
1183 case icValueTypeUInt8:
1184 if (pIO->WriteUInt8Float(pData,nPoints)!= nPoints)
1185 return false;
1186 break;
1187
1188 case icValueTypeUInt16:
1189 if (pIO->WriteUInt16Float(pData,nPoints)!= nPoints)
1190 return false;
1191 break;
1192
1193 case icValueTypeFloat16:
1194 if (pIO->WriteFloat16Float(pData,nPoints)!= nPoints)
1195 return false;
1196 break;
1197
1198 case icValueTypeFloat32:
1199 if (pIO->WriteFloat32Float(pData,nPoints)!= nPoints)
1200 return false;
1201 break;
1202
1203 default:
1204 return false;
1205 }
1206 }
1207
1208 if (m_pWhite) {
1209 switch(m_nStorageType) {
1210 case icValueTypeUInt8:
1211 if (pIO->WriteUInt8Float(m_pWhite, m_Range.steps)!= m_Range.steps)
1212 return false;
1213 break;
1214
1215 case icValueTypeUInt16:
1216 if (pIO->WriteUInt16Float(m_pWhite, m_Range.steps)!= m_Range.steps)
1217 return false;
1218 break;
1219
1220 case icValueTypeFloat16:
1221 if (pIO->WriteFloat16Float(m_pWhite, m_Range.steps)!= m_Range.steps)
1222 return false;
1223 break;
1224
1225 case icValueTypeFloat32:
1226 if (pIO->WriteFloat32Float(m_pWhite, m_Range.steps)!= m_Range.steps)
1227 return false;
1228 break;
1229
1230 default:
1231 return false;
1232 }
1233 }
1234 else if (m_Range.steps) {
1235 return false;
1236 }
1237
1238 return true;
1239}
1240
1241/**
1242 ******************************************************************************
1243 * Name: CIccMpeEmissionCLUT::Apply
1244 *
1245 * Purpose:
1246 *
1247 * Args:
1248 *
1249 * Return:
1250 ******************************************************************************/
1251void CIccMpeSpectralCLUT::Apply(CIccApplyMpe *pApply, icFloatNumber *dstPixel, const icFloatNumber *srcPixel) const
1252{
1253 const CIccCLUT *pCLUT = m_pApplyCLUT;
1254
1255 switch(m_interpType) {
1256 case ic1dInterp:
1257 pCLUT->Interp1d(dstPixel, srcPixel);
1258 break;
1259 case ic2dInterp:
1260 pCLUT->Interp2d(dstPixel, srcPixel);
1261 break;
1262 case ic3dInterpTetra:
1263 pCLUT->Interp3dTetra(dstPixel, srcPixel);
1264 break;
1265 case ic3dInterp:
1266 pCLUT->Interp3d(dstPixel, srcPixel);
1267 break;
1268 case ic4dInterp:
1269 pCLUT->Interp4d(dstPixel, srcPixel);
1270 break;
1271 case ic5dInterp:
1272 pCLUT->Interp5d(dstPixel, srcPixel);
1273 break;
1274 case ic6dInterp:
1275 pCLUT->Interp6d(dstPixel, srcPixel);
1276 break;
1277 case icNdInterp:
1278 pCLUT->InterpND(dstPixel, srcPixel);
1279 break;
1280 }
1281}
1282
1283
1284/**
1285 ******************************************************************************
1286 * Name: CIccMpeSpectralCLUT::Validate
1287 *
1288 * Purpose:
1289 *
1290 * Args:
1291 *
1292 * Return:
1293 ******************************************************************************/
1294icValidateStatus CIccMpeSpectralCLUT::Validate(std::string sigPath, std::string &sReport, const CIccTagMultiProcessElement* pMPE/*=NULL*/) const
1295{
1296 std::string mpeSigPath = sigPath + icGetSigPath(GetType());
1297 icValidateStatus rv = CIccMultiProcessElement::Validate(sigPath, sReport, pMPE);
1298
1299 if (m_nStorageType>icMaxValueTypeicValueTypeUInt8) {
1300 CIccInfo Info;
1301 std::string sSigPathName = Info.GetSigPathName(mpeSigPath);
1302
1303 sReport += icMsgValidateCriticalError;
1304 sReport += sSigPathName;
1305 sReport += " - Invalid storageType value!\r\n";
1306 return icMaxStatus(rv, icValidateCriticalError);
1307 }
1308
1309 if (!m_pCLUT) {
1310 CIccInfo Info;
1311 std::string sSigPathName = Info.GetSigPathName(mpeSigPath);
1312
1313 sReport += icMsgValidateCriticalError;
1314 sReport += sSigPathName;
1315 sReport += " - Has No CLUT!\r\n";
1316 rv = icMaxStatus(rv, icValidateCriticalError);
1317 }
1318
1319 if (!m_pWhite) {
1320 CIccInfo Info;
1321 std::string sSigPathName = Info.GetSigPathName(mpeSigPath);
1322
1323 sReport += icMsgValidateCriticalError;
1324 sReport += sSigPathName;
1325 sReport += " - Has Empty White data!\r\n";
1326 rv = icMaxStatus(rv, icValidateCriticalError);
1327 }
1328
1329 if (!m_Range.steps) {
1330 CIccInfo Info;
1331 std::string sSigPathName = Info.GetSigPathName(mpeSigPath);
1332
1333 sReport += icMsgValidateCriticalError;
1334 sReport += sSigPathName;
1335 sReport += " - Cannot have zero spectral range steps!\r\n";
1336 rv = icMaxStatus(rv, icValidateCriticalError);
1337 }
1338
1339 if (m_Range.start>= m_Range.end || !m_Range.steps) {
1340 CIccInfo Info;
1341 std::string sSigPathName = Info.GetSigPathName(mpeSigPath);
1342
1343 sReport += icMsgValidateCriticalError;
1344 sReport += sSigPathName;
1345 sReport += " - Has an invalid spectral range!\r\n";
1346 rv = icMaxStatus(rv, icValidateCriticalError);
1347 }
1348
1349 return rv;
1350}
1351
1352
1353/**
1354 ******************************************************************************
1355 * Name: CIccMpeEmissionCLUT::Begin
1356 *
1357 * Purpose:
1358 *
1359 * Args:
1360 *
1361 * Return:
1362 ******************************************************************************/
1363bool CIccMpeEmissionCLUT::Begin(icElemInterp nInterp, CIccTagMultiProcessElement *pMPE)
1364{
1365 if (!m_pCLUT || !m_pWhite || m_pCLUT->GetOutputChannels()!=m_Range.steps || m_nOutputChannels!=3)
1366 return false;
1367
1368 switch (m_nInputChannels) {
1369 case 1:
1370 m_interpType = ic1dInterp;
1371 break;
1372 case 2:
1373 m_interpType = ic2dInterp;
1374 break;
1375 case 3:
1376 if (nInterp==icElemInterpTetra)
1377 m_interpType = ic3dInterpTetra;
1378 else
1379 m_interpType = ic3dInterp;
1380 break;
1381 case 4:
1382 m_interpType = ic4dInterp;
1383 break;
1384 case 5:
1385 m_interpType = ic5dInterp;
1386 break;
1387 case 6:
1388 m_interpType = ic6dInterp;
1389 break;
1390 default:
1391 m_interpType = icNdInterp;
1392 break;
1393 }
1394
1395 IIccProfileConnectionConditions *pAppliedPCC = pMPE->GetAppliedPCC();
1396 if (!pAppliedPCC)
1397 return false;
1398
1399 const CIccTagSpectralViewingConditions *pSVC = pAppliedPCC->getPccViewingConditions();
1400 if (!pSVC)
1401 return false;
1402
1403 CIccMatrixMath observer(3, m_Range.steps);
1404
1405 if (!pAppliedPCC->getEmissiveObserver(m_Range, m_pWhite, observer.entry(0)))
1406 return false;
1407
1408 if (m_pApplyCLUT)
1409 delete m_pApplyCLUT;
1410
1411 m_pApplyCLUT = new CIccCLUT((icUInt8Number)m_nInputChannels, (icUInt16Number)m_nOutputChannels, 4);
1412
1413 if (!m_pApplyCLUT) {
1414 return false;
1415 }
1416
1417 m_pApplyCLUT->SetClipFunc(NoClip);
1418 m_pApplyCLUT->Init(m_pCLUT->GridPointArray());
1419
1420 icFloatNumber *pSrc = m_pCLUT->GetData(0);
1421 icFloatNumber *pDst = m_pApplyCLUT->GetData(0);
1422
1423 icFloatNumber xyzW[3];
1424 icUInt32Number i;
1425
1426 observer.VectorMult(xyzW, m_pWhite);
1427
1428 bool bUseAbsolute = (m_flags & icRelativeSpectralData0x00000000)!=0;
Value stored to 'bUseAbsolute' during its initialization is never read
1429 bool bLab = (m_flags & icLabSpectralData0x00000002) != 0;
1430
1431 for (i=0; i<m_pCLUT->NumPoints(); i++) {
1432 observer.VectorMult(pDst, pSrc);
1433 if (bLab) {
1434 icXYZtoLab(pDst, pDst, xyzW);
1435// icLabToPcs(pDst);
1436 }
1437 else {
1438// icXyzToPcs(pDst);
1439 }
1440 pSrc += m_Range.steps;
1441 pDst += m_nOutputChannels;
1442 }
1443
1444 m_pApplyCLUT->Begin();
1445
1446 return true;
1447}
1448
1449
1450/**
1451 ******************************************************************************
1452 * Name: CIccMpeReflectanceCLUT::Begin
1453 *
1454 * Purpose:
1455 *
1456 * Args:
1457 *
1458 * Return:
1459 ******************************************************************************/
1460bool CIccMpeReflectanceCLUT::Begin(icElemInterp nInterp, CIccTagMultiProcessElement *pMPE)
1461{
1462 if (!m_pCLUT || !m_pWhite || m_pCLUT->GetOutputChannels()!=m_Range.steps || m_nOutputChannels!=3)
1463 return false;
1464
1465 switch (m_nInputChannels) {
1466 case 1:
1467 m_interpType = ic1dInterp;
1468 break;
1469 case 2:
1470 m_interpType = ic2dInterp;
1471 break;
1472 case 3:
1473 if (nInterp==icElemInterpTetra)
1474 m_interpType = ic3dInterpTetra;
1475 else
1476 m_interpType = ic3dInterp;
1477 break;
1478 case 4:
1479 m_interpType = ic4dInterp;
1480 break;
1481 case 5:
1482 m_interpType = ic5dInterp;
1483 break;
1484 case 6:
1485 m_interpType = ic6dInterp;
1486 break;
1487 default:
1488 m_interpType = icNdInterp;
1489 break;
1490 }
1491
1492 IIccProfileConnectionConditions *pAppliedPCC = pMPE->GetAppliedPCC();
1493 if (!pAppliedPCC)
1494 return false;
1495
1496 const CIccTagSpectralViewingConditions *pSVC = pAppliedPCC->getPccViewingConditions();
1497 if (!pSVC)
1498 return false;
1499
1500 CIccMatrixMath observer(3, m_Range.steps);
1501 icSpectralRange illumRange;
1502 const icFloatNumber *illum = pSVC->getIlluminant(illumRange);
1503
1504 if (!pAppliedPCC->getEmissiveObserver(illumRange, illum, observer.entry(0)))
1505 return false;
1506
1507 //
1508 icFloatNumber xyzi[3];
1509
1510 //apply illuminant to observer and calculate XYZ of illuminant
1511 icFloatNumber *pObs = observer.entry(0);
1512 int i, j;
1513 for (i=0; i<3; i++) {
1514 xyzi[i] = 0.0;
1515 for (j=0; j<illumRange.steps; j++) {
1516 *pObs *= illum[j];
1517 xyzi[i] += *pObs;
1518 pObs++;
1519 }
1520 }
1521
1522 //concatenate reflectance range mapping to observer+illuminant
1523 CIccMatrixMath *rangeRef = CIccMatrixMath::rangeMap(m_Range, illumRange);
1524 CIccMatrixMath *pApplyMtx;
1525 if (!rangeRef)
1526 pApplyMtx = &observer;
1527 else
1528 pApplyMtx = rangeRef->Mult(&observer);
1529
1530 if (m_pApplyCLUT)
1531 delete m_pApplyCLUT;
1532
1533 m_pApplyCLUT = new CIccCLUT((icUInt8Number)m_nInputChannels, (icUInt16Number)m_nOutputChannels, 4);
1534
1535 if (!m_pApplyCLUT) {
1536 if (pApplyMtx!=&observer)
1537 delete pApplyMtx;
1538 return false;
1539 }
1540
1541 m_pApplyCLUT->SetClipFunc(NoClip);
1542 m_pApplyCLUT->Init(m_pCLUT->GridPointArray());
1543
1544 icFloatNumber *pSrc = m_pCLUT->GetData(0);
1545 icFloatNumber *pDst = m_pApplyCLUT->GetData(0);
1546
1547 icFloatNumber xyzW[3];
1548
1549 pApplyMtx->VectorMult(xyzW, m_pWhite);
1550
1551 bool bUseAbsolute = (m_flags & icRelativeSpectralData0x00000000)!=0;
1552 bool bLab = (m_flags & icLabSpectralData0x00000002) != 0;
1553
1554 icFloatNumber xyzscale[3];
1555 if (!bUseAbsolute) {
1556 xyzscale[0] = xyzi[0] / xyzW[0];
1557 xyzscale[1] = xyzi[1] / xyzW[1];
1558 xyzscale[2] = xyzi[2] / xyzW[2];
1559 }
1560
1561 for (i=0; i<(int)m_pCLUT->NumPoints(); i++) {
1562 pApplyMtx->VectorMult(pDst, pSrc);
1563
1564 if (!bUseAbsolute) {
1565 pDst[0] *= xyzscale[0];
1566 pDst[1] *= xyzscale[1];
1567 pDst[2] *= xyzscale[2];
1568 }
1569
1570 if (bLab) {
1571 icXYZtoLab(pDst, pDst, xyzi);
1572 // icLabToPcs(pDst);
1573 }
1574 else {
1575 // icXyzToPcs(pDst);
1576 }
1577 pSrc += m_Range.steps;
1578 pDst += m_nOutputChannels;
1579 }
1580
1581 if (pApplyMtx!=&observer)
1582 delete pApplyMtx;
1583
1584 m_pApplyCLUT->Begin();
1585
1586 return true;
1587}
1588
1589
1590/**
1591 ******************************************************************************
1592 * Name: CIccMpeSpectralObserver::CIccMpeSpectralObserver
1593 *
1594 * Purpose:
1595 *
1596 * Args:
1597 *
1598 * Return:
1599 ******************************************************************************/
1600CIccMpeSpectralObserver::CIccMpeSpectralObserver()
1601{
1602 m_nReserved = 0;
1603 m_nInputChannels = m_nOutputChannels = 0;
1604 m_pWhite = NULL__null;
1605
1606 m_Range.start=0;
1607 m_Range.end=0;
1608 m_Range.steps=0;
1609
1610 m_pApplyMtx = NULL__null;
1611}
1612
1613
1614/**
1615 ******************************************************************************
1616 * Name: CIccMpeSpectralObserver::CIccMpeSpectralObserver
1617 *
1618 * Purpose:
1619 *
1620 * Args:
1621 *
1622 * Return:
1623 ******************************************************************************/
1624CIccMpeSpectralObserver::CIccMpeSpectralObserver(const CIccMpeSpectralObserver &matrix)
1625{
1626 m_nReserved = matrix.m_nReserved;
1627
1628 m_nInputChannels = matrix.m_nInputChannels;
1629 m_nOutputChannels = matrix.m_nOutputChannels;
1630
1631 m_Range = matrix.m_Range;
1632
1633 if (matrix.m_pWhite) {
1634 int num = m_Range.steps*sizeof(icFloatNumber);
1635 m_pWhite = (icFloatNumber*)malloc(num);
1636 memcpy(m_pWhite, matrix.m_pWhite, num);
1637 }
1638 else
1639 m_pWhite = NULL__null;
1640
1641 m_pApplyMtx = NULL__null;
1642}
1643
1644/**
1645 ******************************************************************************
1646 * Name: &CIccMpeSpectralObserver::operator=
1647 *
1648 * Purpose:
1649 *
1650 * Args:
1651 *
1652 * Return:
1653 ******************************************************************************/
1654void CIccMpeSpectralObserver::copyData(const CIccMpeSpectralObserver &matrix)
1655{
1656 m_nReserved = matrix.m_nReserved;
1657
1658 m_nInputChannels = matrix.m_nInputChannels;
1659 m_nOutputChannels = matrix.m_nOutputChannels;
1660
1661 m_Range = m_Range;
1662
1663 if (m_pWhite)
1664 free(m_pWhite);
1665
1666 if (matrix.m_pWhite) {
1667 int num = m_Range.steps*sizeof(icFloatNumber);
1668 m_pWhite = (icFloatNumber*)malloc(num);
1669 memcpy(m_pWhite, matrix.m_pWhite, num);
1670 }
1671 else
1672 m_pWhite = NULL__null;
1673
1674 m_pApplyMtx = NULL__null;
1675}
1676
1677/**
1678 ******************************************************************************
1679 * Name: CIccMpeSpectralObserver::~CIccMpeSpectralObserver
1680 *
1681 * Purpose:
1682 *
1683 * Args:
1684 *
1685 * Return:
1686 ******************************************************************************/
1687CIccMpeSpectralObserver::~CIccMpeSpectralObserver()
1688{
1689 if (m_pWhite)
1690 free(m_pWhite);
1691
1692 if (m_pApplyMtx)
1693 delete m_pApplyMtx;
1694}
1695
1696
1697/**
1698 ******************************************************************************
1699 * Name: CIccMpeSpectralObserver::SetSize
1700 *
1701 * Purpose:
1702 *
1703 * Args:
1704 *
1705 * Return:
1706 ******************************************************************************/
1707bool CIccMpeSpectralObserver::SetSize(icUInt16Number nInputChannels, icUInt16Number nOutputChannels, const icSpectralRange &range)
1708{
1709 if (m_pWhite) {
1710 free(m_pWhite);
1711 m_pWhite = NULL__null;
1712 }
1713
1714 if (m_pApplyMtx) {
1715 delete m_pApplyMtx;
1716 m_pApplyMtx = NULL__null;
1717 }
1718
1719 m_nInputChannels = nInputChannels;
1720 m_nOutputChannels = nOutputChannels;
1721 m_Range = range;
1722
1723 m_pWhite = (icFloatNumber*)calloc(range.steps, sizeof(icFloatNumber));
1724
1725 if (!m_pWhite)
1726 return false;
1727
1728 return true;
1729}
1730
1731/**
1732 ******************************************************************************
1733 * Name: CIccMpeSpectralObserver::Describe
1734 *
1735 * Purpose:
1736 *
1737 * Args:
1738 *
1739 * Return:
1740 ******************************************************************************/
1741void CIccMpeSpectralObserver::Describe(std::string &sDescription)
1742{
1743 icChar buf[81];
1744 int j;
1745
1746 sprintf(buf, "BEGIN_%s %d %d \r\n", GetDescribeName(), m_nInputChannels, m_nOutputChannels);
1747 sDescription += buf;
1748
1749 sprintf(buf, "RANGE %f %f %d\r\n", icF16toF(m_Range.start), icF16toF(m_Range.end), m_Range.steps);
1750 sDescription += buf;
1751
1752 sDescription += "White\r\n";
1753 for (j=0; j<(int)m_Range.steps; j++) {
1754 if (j)
1755 sDescription += " ";
1756 sprintf(buf, "%12.8lf", m_pWhite[j]);
1757 sDescription += buf;
1758 }
1759 sDescription += "\r\n";
1760
1761 sprintf(buf, "END_%s\r\n", GetDescribeName());
1762 sDescription += buf;
1763}
1764
1765/**
1766 ******************************************************************************
1767 * Name: CIccMpeSpectralObserver::Read
1768 *
1769 * Purpose:
1770 *
1771 * Args:
1772 *
1773 * Return:
1774 ******************************************************************************/
1775bool CIccMpeSpectralObserver::Read(icUInt32Number size, CIccIO *pIO)
1776{
1777 icElemTypeSignature sig;
1778
1779 icUInt32Number headerSize = sizeof(icElemTypeSignature) +
1780 sizeof(icUInt32Number) +
1781 sizeof(icUInt16Number) +
1782 sizeof(icUInt16Number) +
1783 sizeof(icUInt16Number) +
1784 sizeof(icUInt16Number) +
1785 sizeof(icUInt16Number) +
1786 sizeof(icUInt16Number);
1787
1788 if (headerSize > size)
1789 return false;
1790
1791 if (!pIO) {
1792 return false;
1793 }
1794
1795 icUInt16Number nInputChannels, nOutputChannels;
1796 icSpectralRange range;
1797
1798 if (!pIO->Read32(&sig))
1799 return false;
1800
1801 if (!pIO->Read32(&m_nReserved))
1802 return false;
1803
1804 if (!pIO->Read16(&nInputChannels))
1805 return false;
1806
1807 if (!pIO->Read16(&nOutputChannels))
1808 return false;
1809
1810 if (!pIO->Read16(&range.start))
1811 return false;
1812
1813 if (!pIO->Read16(&range.end))
1814 return false;
1815
1816 if (!pIO->Read16(&range.steps))
1817 return false;
1818
1819 if (!pIO->Read16(&m_flags))
1820 return false;
1821
1822 if (!SetSize(nInputChannels, nOutputChannels, range))
1823 return false;
1824
1825 if (!m_pWhite )
1826 return false;
1827
1828 if (size<headerSize + (int)range.steps*sizeof(icFloatNumber))
1829 return false;
1830
1831 //Read White data
1832 if (pIO->ReadFloat32Float(m_pWhite, range.steps)!=range.steps)
1833 return false;
1834
1835 return true;
1836}
1837
1838/**
1839 ******************************************************************************
1840 * Name: CIccMpeSpectralObserver::Write
1841 *
1842 * Purpose:
1843 *
1844 * Args:
1845 *
1846 * Return:
1847 ******************************************************************************/
1848bool CIccMpeSpectralObserver::Write(CIccIO *pIO)
1849{
1850 icElemTypeSignature sig = GetType();
1851
1852 if (!pIO)
1853 return false;
1854
1855 if (!pIO->Write32(&sig))
1856 return false;
1857
1858 if (!pIO->Write32(&m_nReserved))
1859 return false;
1860
1861 if (!pIO->Write16(&m_nInputChannels))
1862 return false;
1863
1864 if (!pIO->Write16(&m_nOutputChannels))
1865 return false;
1866
1867 if (!pIO->Write16(&m_Range.start))
1868 return false;
1869
1870 if (!pIO->Write16(&m_Range.end))
1871 return false;
1872
1873 if (!pIO->Write16(&m_Range.steps))
1874 return false;
1875
1876 if (!pIO->Write16(&m_flags))
1877 return false;
1878
1879 if (m_pWhite) {
1880 if (pIO->WriteFloat32Float(m_pWhite, m_Range.steps)!=m_Range.steps)
1881 return false;
1882 }
1883 else if (m_Range.steps) {
1884 return false;
1885 }
1886
1887 return true;
1888}
1889
1890void CIccMpeSpectralObserver::Apply(CIccApplyMpe *pApply, icFloatNumber *dstPixel, const icFloatNumber *srcPixel) const
1891{
1892 if (m_pApplyMtx) {
1893 icFloatNumber xyz[3];
1894 m_pApplyMtx->VectorMult(xyz, srcPixel);
1895
1896 bool bUseAbsolute = (m_flags & icRelativeSpectralData0x00000000)!=0;
1897 bool bLab = (m_flags & icLabSpectralData0x00000002) != 0;
1898
1899 if (!bUseAbsolute) {
1900 xyz[0] *= m_xyzscale[0];
1901 xyz[1] *= m_xyzscale[1];
1902 xyz[2] *= m_xyzscale[2];
1903 }
1904
1905 if (bLab) {
1906 icXYZtoLab(dstPixel, xyz, m_xyzw);
1907 // icLabToPcs(dstPixel);
1908 }
1909 else {
1910 memcpy(dstPixel, xyz, 3*sizeof(icFloatNumber));
1911 // icXyzToPcs(dstPixel);
1912 }
1913 }
1914}
1915
1916/**
1917 ******************************************************************************
1918 * Name: CIccMpeSpectralObserver::Validate
1919 *
1920 * Purpose:
1921 *
1922 * Args:
1923 *
1924 * Return:
1925 ******************************************************************************/
1926icValidateStatus CIccMpeSpectralObserver::Validate(std::string sigPath, std::string &sReport, const CIccTagMultiProcessElement* pMPE/*=NULL*/) const
1927{
1928 std::string mpeSigPath = sigPath + icGetSigPath(GetType());
1929 icValidateStatus rv = CIccMultiProcessElement::Validate(sigPath, sReport, pMPE);
1930
1931 if (!m_Range.steps) {
1932 CIccInfo Info;
1933 std::string sSigPathName = Info.GetSigPathName(mpeSigPath);
1934
1935 sReport += icMsgValidateCriticalError;
1936 sReport += sSigPathName;
1937 sReport += " - Cannot have zero spectral range steps!\r\n";
1938 rv = icMaxStatus(rv, icValidateCriticalError);
1939 }
1940
1941 if (m_nOutputChannels != 3) {
1942 CIccInfo Info;
1943 std::string sSigPathName = Info.GetSigPathName(mpeSigPath);
1944
1945 sReport += icMsgValidateCriticalError;
1946 sReport += sSigPathName;
1947 sReport += " - Output Channels must be 3!\r\n";
1948 rv = icMaxStatus(rv, icValidateCriticalError);
1949 }
1950
1951 if (!m_pWhite) {
1952 CIccInfo Info;
1953 std::string sSigPathName = Info.GetSigPathName(mpeSigPath);
1954
1955 sReport += icMsgValidateCriticalError;
1956 sReport += sSigPathName;
1957 sReport += " - Has Empty White data!\r\n";
1958 rv = icMaxStatus(rv, icValidateCriticalError);
1959 }
1960
1961
1962 if (m_Range.start>= m_Range.end || !m_Range.steps) {
1963 CIccInfo Info;
1964 std::string sSigPathName = Info.GetSigPathName(mpeSigPath);
1965
1966 sReport += icMsgValidateCriticalError;
1967 sReport += sSigPathName;
1968 sReport += " - Has an invalid spectral range!\r\n";
1969 rv = icMaxStatus(rv, icValidateCriticalError);
1970 }
1971
1972 return rv;
1973}
1974
1975
1976/**
1977 ******************************************************************************
1978 * Name: CIccMpeEmissionObserver::Begin
1979 *
1980 * Purpose:
1981 *
1982 * Args:
1983 *
1984 * Return:
1985 ******************************************************************************/
1986bool CIccMpeEmissionObserver::Begin(icElemInterp nInterp, CIccTagMultiProcessElement *pMPE)
1987{
1988 if (!m_pWhite || m_nInputChannels!=m_Range.steps || m_nOutputChannels!=3)
1989 return false;
1990
1991 IIccProfileConnectionConditions *pAppliedPCC = pMPE->GetAppliedPCC();
1992 if (!pAppliedPCC)
1993 return false;
1994
1995 const CIccTagSpectralViewingConditions *pSVC = pAppliedPCC->getPccViewingConditions();
1996 if (!pSVC)
1997 return false;
1998
1999 m_pApplyMtx = new CIccMatrixMath(3, m_Range.steps);
2000
2001 if (!m_pApplyMtx)
2002 return false;
2003
2004 if (!pAppliedPCC->getEmissiveObserver(m_Range, m_pWhite, m_pApplyMtx->entry(0)))
2005 return false;
2006
2007 m_pApplyMtx->VectorMult(m_xyzw, m_pWhite);
2008
2009 m_xyzscale[0] = 1.0;
2010 m_xyzscale[0] = 1.0;
2011 m_xyzscale[0] = 1.0;
2012
2013 return true;
2014}
2015
2016
2017/**
2018 ******************************************************************************
2019 * Name: CIccMpeReflectanceObserver::Begin
2020 *
2021 * Purpose:
2022 *
2023 * Args:
2024 *
2025 * Return:
2026 ******************************************************************************/
2027bool CIccMpeReflectanceObserver::Begin(icElemInterp nInterp, CIccTagMultiProcessElement *pMPE)
2028{
2029 if (!m_pWhite || m_nInputChannels!=m_Range.steps || m_nOutputChannels!=3)
2030 return false;
2031
2032 IIccProfileConnectionConditions *pAppliedPCC = pMPE->GetAppliedPCC();
2033 if (!pAppliedPCC)
2034 return false;
2035
2036 const CIccTagSpectralViewingConditions *pSVC = pAppliedPCC->getPccViewingConditions();
2037 if (!pSVC)
2038 return false;
2039
2040 CIccMatrixMath observer(3, m_Range.steps);
2041 icSpectralRange illumRange;
2042 const icFloatNumber *illum = pSVC->getIlluminant(illumRange);
2043
2044 if (!pAppliedPCC->getEmissiveObserver(illumRange, illum, observer.entry(0)))
2045 return false;
2046
2047 //
2048 //apply illuminant to observer and calculate XYZ of illuminant
2049 icFloatNumber *pObs = observer.entry(0);
2050 int i, j;
2051 for (i=0; i<3; i++) {
2052 m_xyzw[i] = 0.0;
2053 for (j=0; j<illumRange.steps; j++) {
2054 *pObs *= illum[j];
2055 m_xyzw[i] += *pObs;
2056 pObs++;
2057 }
2058 }
2059
2060 //concatenate reflectance range mapping to observer+illuminant
2061 CIccMatrixMath *rangeRef = CIccMatrixMath::rangeMap(m_Range, illumRange);
2062 if (!rangeRef)
2063 m_pApplyMtx = new CIccMatrixMath(observer);
2064 else
2065 m_pApplyMtx = rangeRef->Mult(&observer);
2066
2067 icFloatNumber xyzm[3];
2068
2069 m_pApplyMtx->VectorMult(xyzm, m_pWhite);
2070
2071 bool bUseAbsolute = (m_flags & icRelativeSpectralData0x00000000)!=0;
2072 bool bLab = (m_flags & icLabSpectralData0x00000002) != 0;
2073
2074 if (!bUseAbsolute) {
2075 m_xyzscale[0] = m_xyzw[0] / xyzm[0];
2076 m_xyzscale[1] = m_xyzw[1] / xyzm[1];
2077 m_xyzscale[2] = m_xyzw[2] / xyzm[2];
2078 }
2079
2080 return true;
2081}
2082
2083#ifdef USEREFICCMAXNAMESPACE
2084} //namespace refIccMAX
2085#endif