Bug Summary

File:IccProfLib/IccMpeBasic.cpp
Warning:line 2787, column 18
Value stored to 'startPos' 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 IccMpeBasic.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/IccMpeBasic.cpp
1/** @file
2 File: IccMpeBasic.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-2012 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 "IccIO.h"
81#include <map>
82#include "IccUtil.h"
83#include "IccCAM.h"
84
85#ifdef USEREFICCMAXNAMESPACE
86namespace refIccMAX {
87#endif
88
89/**
90 ******************************************************************************
91 * Name: CIccFormulaCurveSegment::CIccFormulaCurveSegment
92 *
93 * Purpose:
94 *
95 * Args:
96 *
97 * Return:
98 ******************************************************************************/
99CIccFormulaCurveSegment::CIccFormulaCurveSegment(icFloatNumber start, icFloatNumber end)
100{
101 m_nReserved = 0;
102 m_nReserved2 = 0;
103 m_startPoint = start;
104 m_endPoint = end;
105
106 m_nFunctionType = 0;
107 m_nShortcutType = 0;
108 m_nParameters = 0;
109 m_params = NULL__null;
110}
111
112/**
113 ******************************************************************************
114 * Name: CIccFormulaCurveSegment::CIccFormulaCurveSegment
115 *
116 * Purpose:
117 *
118 * Args:
119 *
120 * Return:
121 ******************************************************************************/
122CIccFormulaCurveSegment::CIccFormulaCurveSegment(const CIccFormulaCurveSegment &seg)
123{
124 m_nReserved = seg.m_nReserved;
125 m_nReserved2 = seg.m_nReserved2;
126 m_startPoint = seg.m_startPoint;
127 m_endPoint = seg.m_endPoint;
128
129 m_nFunctionType = seg.m_nFunctionType;
130 m_nShortcutType = seg.m_nShortcutType;
131 m_nParameters = seg.m_nParameters;
132
133 if (seg.m_params) {
134 m_params = (icFloatNumber*)malloc(m_nParameters*sizeof(icFloatNumber));
135 memcpy(m_params, seg.m_params, m_nParameters*sizeof(icFloatNumber));
136 }
137 else
138 m_params = NULL__null;
139}
140
141/**
142 ******************************************************************************
143 * Name: &CIccFormulaCurveSegment::operator=
144 *
145 * Purpose:
146 *
147 * Args:
148 *
149 * Return:
150 ******************************************************************************/
151CIccFormulaCurveSegment &CIccFormulaCurveSegment::operator=(const CIccFormulaCurveSegment &seg)
152{
153 if (m_params)
154 free(m_params);
155
156 m_nReserved = seg.m_nReserved;
157 m_nReserved2 = seg.m_nReserved2;
158 m_startPoint = seg.m_startPoint;
159 m_endPoint = seg.m_endPoint;
160
161 m_nFunctionType = seg.m_nFunctionType;
162 m_nShortcutType = seg.m_nShortcutType;
163 m_nParameters = seg.m_nParameters;
164 if (seg.m_params) {
165 m_params = (icFloatNumber*)malloc(m_nParameters*sizeof(icFloatNumber));
166 memcpy(m_params, seg.m_params, m_nParameters*sizeof(icFloatNumber));
167 }
168 else
169 m_params = NULL__null;
170
171 return (*this);
172}
173
174/**
175 ******************************************************************************
176 * Name: CIccFormulaCurveSegment::~CIccFormulaCurveSegment
177 *
178 * Purpose:
179 *
180 * Args:
181 *
182 * Return:
183 ******************************************************************************/
184CIccFormulaCurveSegment::~CIccFormulaCurveSegment()
185{
186 if (m_params) {
187 free(m_params);
188 }
189}
190
191/**
192 ******************************************************************************
193 * Name: CIccFormulaCurveSegment::Describe
194 *
195 * Purpose:
196 *
197 * Args:
198 *
199 * Return:
200 ******************************************************************************/
201void CIccFormulaCurveSegment::Describe(std::string &sDescription)
202{
203 icChar buf[128];
204
205 sDescription += "Segment [";
206 if (m_startPoint==icMinFloat32Number-3.402823466e+38F)
207 sDescription += "-Infinity, ";
208 else {
209 sprintf(buf, "%.8f, ", m_startPoint);
210 sDescription += buf;
211 }
212 if (m_endPoint==icMaxFloat32Number3.402823466e+38F)
213 sDescription += "+Infinity";
214 else {
215 sprintf(buf, "%.8f", m_endPoint);
216 sDescription += buf;
217 }
218 sprintf(buf, "]\r\nFunctionType: %04Xh\r\n", m_nFunctionType);
219 sDescription += buf;
220
221 switch(m_nFunctionType) {
222 case 0x0000:
223 if (m_params[1]==0.0 && m_params[2]==0.0)
224 sprintf(buf, "Y = %.8f\r\n\r\n", m_params[3]);
225 else if (m_params[0]==1.0 && m_params[1]==1.0 && m_params[2]==0.0 && m_params[3]==0.0)
226 sprintf(buf, "Y = X\r\n\r\n");
227 else if (m_params[0]==1.0 && m_params[2]==0.0)
228 sprintf(buf, "Y = %.8f * X + %.8f\r\n\r\n",
229 m_params[1], m_params[3]);
230 else
231 sprintf(buf, "Y = (%.8f * X + %.8f)^%.4f + %.8f\r\n\r\n",
232 m_params[1], m_params[2], m_params[0], m_params[3]);
233 sDescription += buf;
234 return;
235
236 case 0x0001:
237 sprintf(buf, "Y = %.8f * log (%.8f * (X ^ %.8f) + %.8f) + %.8f\r\n\r\n",
238 m_params[1], m_params[2], m_params[0], m_params[3], m_params[4]);
239 sDescription += buf;
240 return;
241
242 case 0x0002:
243 sprintf(buf, "Y = %.8f * (%.8f ^ (%.8f * X + %.8f)) + %.8f\r\n\r\n",
244 m_params[0], m_params[1], m_params[2], m_params[3], m_params[4]);
245 sDescription += buf;
246 return;
247
248 case 0x0003:
249 if (m_params[1]==0.0 && m_params[2]==0.0)
250 sprintf(buf, "Y = %.8f\r\n\r\n", m_params[3]);
251 else if (m_params[0]==1.0 && m_params[1]==1.0 && m_params[2]==1.0 && m_params[3]==0.0 && m_params[4]==0.0)
252 sprintf(buf, "Y = X\r\n\r\n");
253 else if (m_params[0]==1.0 && m_params[1]==1.0 && m_params[3]==0.0)
254 sprintf(buf, "Y = %.8f * X + %.8f\r\n\r\n",
255 m_params[2], m_params[3]);
256 else if (m_params[0]==1.0 && m_params[2]==1.0 && m_params[3]==0.0)
257 sprintf(buf, "Y = %.8f * X + %.8f\r\n\r\n",
258 m_params[1], m_params[3]);
259 else
260 sprintf(buf, "Y = %8f * (%.8f * X + %.8f)^%.4f + %.8f\r\n\r\n",
261 m_params[1], m_params[2], m_params[3], m_params[0], m_params[4]);
262 sDescription += buf;
263 return;
264
265 default:
266 int i;
267 sprintf(buf, "Unknown Function with %d parameters:\r\n\r\n", m_nParameters);
268 sDescription += buf;
269
270 for (i=0; i<m_nParameters; i++) {
271 sprintf(buf, "Param[%d] = %.8lf\r\n\r\n", i, m_params[i]);
272 sDescription += buf;
273 }
274 }
275}
276
277
278/**
279 ******************************************************************************
280 * Name: CIccFormulaCurveSegment::SetFunction
281 *
282 * Purpose:
283 *
284 * Args:
285 *
286 * Return:
287 ******************************************************************************/
288void CIccFormulaCurveSegment::SetFunction(icUInt16Number functionType, icUInt8Number num_parameters, icFloatNumber *parameters)
289{
290 if (m_params)
291 free(m_params);
292
293 if (num_parameters) {
294 m_params = (icFloatNumber*)malloc(num_parameters * sizeof(icFloatNumber));
295 memcpy(m_params, parameters, num_parameters * sizeof(icFloatNumber));
296 }
297 else
298 m_params = NULL__null;
299
300 m_nFunctionType = functionType;
301 m_nParameters = num_parameters;
302}
303
304/**
305 ******************************************************************************
306 * Name: CIccFormulaCurveSegment::Read
307 *
308 * Purpose:
309 *
310 * Args:
311 *
312 * Return:
313 ******************************************************************************/
314bool CIccFormulaCurveSegment::Read(icUInt32Number size, CIccIO *pIO)
315{
316 icCurveSegSignature sig;
317
318 icUInt32Number headerSize = sizeof(icTagTypeSignature) +
319 sizeof(icUInt32Number) +
320 sizeof(icUInt16Number) +
321 sizeof(icUInt16Number);
322
323 if (headerSize > size)
324 return false;
325
326 if (!pIO) {
327 return false;
328 }
329
330 if (!pIO->Read32(&sig))
331 return false;
332
333 if (!pIO->Read32(&m_nReserved))
334 return false;
335
336 if (!pIO->Read16(&m_nFunctionType))
337 return false;
338
339 if (!pIO->Read16(&m_nReserved2))
340 return false;
341
342 if (m_params) {
343 free(m_params);
344 }
345
346 switch(m_nFunctionType) {
347 case 0x0000:
348 m_nParameters = 4;
349 break;
350
351 case 0x0001:
352 case 0x0002:
353 case 0x0003:
354 m_nParameters = 5;
355 break;
356
357 default:
358 return false;
359 }
360
361 if (m_nParameters) {
362
363 m_params = (icFloatNumber*)malloc(m_nParameters * sizeof(icFloatNumber));
364 if (!m_params)
365 return false;
366
367 if (pIO->ReadFloat32Float(m_params, m_nParameters)!= m_nParameters) {
368 return false;
369 }
370 }
371 else
372 m_params = NULL__null;
373
374 return true;
375}
376
377/**
378 ******************************************************************************
379 * Name: CIccFormulaCurveSegment::Write
380 *
381 * Purpose:
382 *
383 * Args:
384 *
385 * Return:
386 ******************************************************************************/
387bool CIccFormulaCurveSegment::Write(CIccIO *pIO)
388{
389 icCurveSegSignature sig = GetType();
390
391 if (!pIO)
392 return false;
393
394 if (!pIO->Write32(&sig))
395 return false;
396
397 if (!pIO->Write32(&m_nReserved))
398 return false;
399
400 if (!pIO->Write16(&m_nFunctionType))
401 return false;
402
403 if (!pIO->Write16(&m_nReserved2))
404 return false;
405
406 switch(m_nFunctionType) {
407 case 0x0000:
408 if (m_nParameters!=4)
409 return false;
410 break;
411
412 case 0x0001:
413 case 0x0002:
414 case 0x0003:
415 if (m_nParameters!=5)
416 return false;
417 break;
418 }
419
420 if (m_nParameters) {
421 if (pIO->WriteFloat32Float(m_params, m_nParameters)!=m_nParameters)
422 return false;
423 }
424
425 return true;
426}
427
428/**
429 ******************************************************************************
430 * Name: CIccFormulaCurveSegment::Begin
431 *
432 * Purpose:
433 *
434 * Args:
435 *
436 * Return:
437 ******************************************************************************/
438bool CIccFormulaCurveSegment::Begin(CIccCurveSegment *pPrevSeg = NULL__null)
439{
440 switch (m_nFunctionType) {
441 case 0x0000:
442 if (!m_params || m_nParameters<4)
443 return false;
444
445 if (m_params[0] == (icFloatNumber)1.0) { //don't apply gamma
446 if (m_params[2] == (icFloatNumber)0.0 && m_params[3] == (icFloatNumber)0.0)
447 m_nShortcutType = 1;
448 else if (m_params[2] == 0.0)
449 m_nShortcutType = 2;
450 else if (m_params[3] == 0.0)
451 m_nShortcutType = 3;
452 else
453 m_nShortcutType = 4;
454 }
455 else {
456 m_nShortcutType = 0;
457 }
458
459 return true;
460
461 case 0x0001:
462 if (!m_params || m_nParameters<5)
463 return false;
464
465 return true;
466
467 case 0x0002:
468 case 0x0003:
469 if (!m_params || m_nParameters<5)
470 return false;
471
472 return true;
473
474 default:
475 return false;
476 }
477
478 return true;
479}
480
481/**
482 ******************************************************************************
483 * Name: CIccFormulaCurveSegment::Apply
484 *
485 * Purpose:
486 *
487 * Args:
488 *
489 * Return:
490 ******************************************************************************/
491icFloatNumber CIccFormulaCurveSegment::Apply(icFloatNumber v) const
492{
493 switch (m_nFunctionType) {
494 case 0x0000:
495 //Y = (a * X + b) ^ g + c : g a b c
496 switch (m_nShortcutType) {
497 case 0:
498 default:
499 return (icFloatNumber)(pow(m_params[1] * v + m_params[2], m_params[0]) + m_params[3]);
500 case 1:
501 return (m_params[1] * v);
502 case 2:
503 return (m_params[1] * v + m_params[3]);
504 case 3:
505 return (m_params[1] * v + m_params[2]);
506 case 4:
507 return (m_params[1] * v + m_params[2] + m_params[3]);
508 }
509
510 case 0x0001:
511 // Y = a * log (b * X^g + c) + d : g a b c d
512 return (icFloatNumber)(m_params[1] * log10(m_params[2] * pow(v, m_params[0]) + m_params[3]) + m_params[4]);
513
514 case 0x0002:
515 //Y = a * b^(c*X+d) + e : a b c d e
516 return (icFloatNumber)(m_params[0] * pow(m_params[1], m_params[2] * v + m_params[3]) + m_params[4]);
517
518 case 0x0003:
519 //Y = a * (b * X + c) ^ g + d : g a b c d
520 return (icFloatNumber)(m_params[1] * pow(m_params[2] * v + m_params[3], m_params[0]) + m_params[4]);
521 }
522
523 //Shouldn't get here!
524 return v;
525}
526
527/**
528 ******************************************************************************
529 * Name: CIccFormulaCurveSegment::Validate
530 *
531 * Purpose:
532 *
533 * Args:
534 *
535 * Return:
536 ******************************************************************************/
537icValidateStatus CIccFormulaCurveSegment::Validate(std::string sigPath, std::string &sReport, const CIccTagMultiProcessElement* pMPE/*=NULL*/) const
538{
539 CIccInfo Info;
540 std::string sSigPathName = Info.GetSigPathName(sigPath);
541
542 icValidateStatus rv = icValidateOK;
543 if (m_nReserved || m_nReserved2) {
544 sReport += icMsgValidateWarning;
545 sReport += sSigPathName;
546 sReport += " formula curve has non zero reserved data.\r\n";
547 rv = icMaxStatus(rv, icValidateWarning);
548 }
549
550 switch (m_nFunctionType) {
551 case 0x0000:
552 if (!m_params || m_nParameters<4) {
553 sReport += icMsgValidateCriticalError;
554 sReport += sSigPathName;
555 sReport += " formula curve has Invalid formulaCurveSegment parameters.\r\n";
556 rv = icMaxStatus(rv, icValidateCriticalError);
557 }
558 else if (m_nParameters > 4) {
559 sReport += icMsgValidateWarning;
560 sReport += sSigPathName;
561 sReport += " formula curve has too many formulaCurveSegment parameters.\r\n";
562 rv = icMaxStatus(rv, icValidateWarning);
563 }
564 break;
565
566 case 0x0001:
567 if (!m_params || m_nParameters<5) {
568 sReport += icMsgValidateCriticalError;
569 sReport += sSigPathName;
570 sReport += " formula curve has Invalid formulaCurveSegment parameters.\r\n";
571 rv = icMaxStatus(rv, icValidateCriticalError);
572 }
573 else if (m_nParameters > 5) {
574 sReport += icMsgValidateWarning;
575 sReport += sSigPathName;
576 sReport += " formula curve has too many formulaCurveSegment parameters.\r\n";
577 rv = icMaxStatus(rv, icValidateWarning);
578 }
579 break;
580
581 case 0x0002:
582 if (!m_params || m_nParameters<5) {
583 sReport += icMsgValidateCriticalError;
584 sReport += sSigPathName;
585 sReport += " formula curve has Invalid formulaCurveSegment parameters.\r\n";
586 rv = icMaxStatus(rv, icValidateCriticalError);
587 }
588 else if (m_nParameters > 5) {
589 sReport += icMsgValidateWarning;
590 sReport += sSigPathName;
591 sReport += " formula curve has too many formulaCurveSegment parameters.\r\n";
592 rv = icMaxStatus(rv, icValidateWarning);
593 }
594 break;
595
596 case 0x0003:
597 if (!m_params || m_nParameters<5) {
598 sReport += icMsgValidateCriticalError;
599 sReport += sSigPathName;
600 sReport += " formula curve has Invalid formulaCurveSegment parameters.\r\n";
601 rv = icMaxStatus(rv, icValidateCriticalError);
602 }
603 else if (m_nParameters > 5) {
604 sReport += icMsgValidateWarning;
605 sReport += sSigPathName;
606 sReport += " formula curve has too many formulaCurveSegment parameters.\r\n";
607 rv = icMaxStatus(rv, icValidateWarning);
608 }
609 break;
610
611 default:
612 {
613 icChar buf[128];
614 sReport += icMsgValidateCriticalError;
615 sReport += sSigPathName;
616 sprintf(buf, " formula curve uses unknown formulaCurveSegment function type %d\r\n", m_nFunctionType);
617 sReport += buf;
618 rv = icMaxStatus(rv, icValidateCriticalError);
619 }
620 }
621
622 return rv;
623}
624
625/**
626 ******************************************************************************
627 * Name: CIccSampledCurveSegment::CIccSampledCurveSegment
628 *
629 * Purpose:
630 *
631 * Args:
632 *
633 * Return:
634 ******************************************************************************/
635CIccSampledCurveSegment::CIccSampledCurveSegment(icFloatNumber start, icFloatNumber end)
636{
637 m_nReserved = 0;
638 m_startPoint = start;
639 m_endPoint = end;
640 m_nCount = 0;
641 m_pSamples = 0;
642}
643
644/**
645 ******************************************************************************
646 * Name: CIccSampledCurveSegment::CIccSampledCurveSegment
647 *
648 * Purpose:
649 *
650 * Args:
651 *
652 * Return:
653 ******************************************************************************/
654CIccSampledCurveSegment::CIccSampledCurveSegment(const CIccSampledCurveSegment &curve)
655{
656 m_nReserved = curve.m_nReserved;
657 m_startPoint = curve.m_startPoint;
658 m_endPoint = curve.m_endPoint;
659 m_nCount = curve.m_nCount;
660
661 if (m_nCount) {
662 m_pSamples = (icFloatNumber*)malloc(m_nCount * sizeof(icFloatNumber));
663 if (m_pSamples)
664 memcpy(m_pSamples, curve.m_pSamples, m_nCount * sizeof(icFloatNumber));
665 else
666 m_nCount = 0;
667 }
668 else{
669 m_pSamples = NULL__null;
670 }
671}
672
673/**
674 ******************************************************************************
675 * Name: &CIccSampledCurveSegment::operator=
676 *
677 * Purpose:
678 *
679 * Args:
680 *
681 * Return:
682 ******************************************************************************/
683CIccSampledCurveSegment &CIccSampledCurveSegment::operator=(const CIccSampledCurveSegment &curve)
684{
685 if (m_pSamples)
686 free(m_pSamples);
687
688 m_nReserved = curve.m_nReserved;
689 m_startPoint = curve.m_startPoint;
690 m_endPoint = curve.m_endPoint;
691 m_nCount = curve.m_nCount;
692
693 if (m_nCount) {
694 m_pSamples = (icFloatNumber*)malloc(m_nCount * sizeof(icFloatNumber));
695 if (m_pSamples)
696 memcpy(m_pSamples, curve.m_pSamples, m_nCount * sizeof(icFloatNumber));
697 else
698 m_nCount = 0;
699 }
700 else {
701 m_pSamples = NULL__null;
702 }
703 return (*this);
704}
705
706/**
707 ******************************************************************************
708 * Name: CIccSampledCurveSegment::~CIccSampledCurveSegment
709 *
710 * Purpose:
711 *
712 * Args:
713 *
714 * Return:
715 ******************************************************************************/
716CIccSampledCurveSegment::~CIccSampledCurveSegment()
717{
718 if (m_pSamples)
719 free(m_pSamples);
720}
721
722/**
723 ******************************************************************************
724 * Name: CIccSampledCurveSegment::SetSize
725 *
726 * Purpose:
727 * Sets size of sampled lookup table. Previous data (if exists) is lost.
728 *
729 * Args:
730 * nCount = number of elements in lut (must be >= 2). Note: the m_pSample[0] is
731 * initialized from the the previous segment. It is not saved as part
732 * of Write(), or loaded as part of Read(). It will be initialized during
733 * the call to Begin(), The actual count of elements written to the file
734 * will be nCount-1
735 * bZeroAlloc = flag to decide if memory should be set to zero.
736 *
737 * Return:
738 * true if allocation successful.
739 ******************************************************************************/
740bool CIccSampledCurveSegment::SetSize(icUInt32Number nCount, bool bZeroAlloc/*=true*/)
741{
742 if (!nCount) {
743 if (m_pSamples)
744 free(m_pSamples);
745 m_pSamples = NULL__null;
746 m_nCount = nCount;
747 return true;
748 }
749
750 if (m_pSamples) {
751 free(m_pSamples);
752 }
753
754 if (bZeroAlloc)
755 m_pSamples = (icFloatNumber*)calloc(nCount, sizeof(icFloatNumber));
756 else
757 m_pSamples = (icFloatNumber*)malloc(nCount * sizeof(icFloatNumber));
758
759 if (m_pSamples)
760 m_nCount = nCount;
761 else
762 m_nCount = 0;
763
764 return (m_pSamples != NULL__null);
765}
766
767/**
768 ******************************************************************************
769 * Name: CIccSampledCurveSegment::Describe
770 *
771 * Purpose:
772 *
773 * Args:
774 *
775 * Return:
776 ******************************************************************************/
777void CIccSampledCurveSegment::Describe(std::string &sDescription)
778{
779 icChar buf[128];
780
781 if (m_nCount<2) {
782 sDescription += "Empty Segment [";
783 if (m_startPoint==icMinFloat32Number-3.402823466e+38F)
784 sDescription += "-Infinity, ";
785 else {
786 sprintf(buf, "%.8f, ", m_startPoint);
787 sDescription += buf;
788 }
789 if (m_endPoint==icMaxFloat32Number3.402823466e+38F)
790 sDescription += "+Infinity";
791 else {
792 sprintf(buf, "%.8f", m_endPoint);
793 sDescription += buf;
794 }
795
796 sprintf(buf, "]\r\n");
797 sDescription += buf;
798 }
799 else {
800 sDescription += "Sampled Segment [";
801 if (m_startPoint==icMinFloat32Number-3.402823466e+38F)
802 sDescription += "-Infinity, ";
803 else {
804 sprintf(buf, "%.8f, ", m_startPoint);
805 sDescription += buf;
806 }
807 if (m_endPoint==icMaxFloat32Number3.402823466e+38F)
808 sDescription += "+Infinity";
809 else {
810 sprintf(buf, "%.8f", m_endPoint);
811 sDescription += buf;
812 }
813 sprintf(buf, "]\r\n");
814 sDescription += buf;
815 sDescription += "IN OUT\r\n";
816
817 icUInt32Number i;
818
819 icFloatNumber range = m_endPoint - m_startPoint;
820 icFloatNumber last = (icFloatNumber)(m_nCount-1);
821
822 for (i=1; i<m_nCount; i++) {
823 sprintf(buf, "%.8f %.8f\r\n", m_startPoint + (icFloatNumber)i*range/last, m_pSamples[i]);
824 sDescription += buf;
825 }
826 }
827 sDescription += "\r\n";
828}
829
830/**
831 ******************************************************************************
832 * Name: CIccSampledCurveSegment::Read
833 *
834 * Purpose:
835 *
836 * Args:
837 *
838 * Return:
839 ******************************************************************************/
840bool CIccSampledCurveSegment::Read(icUInt32Number size, CIccIO *pIO)
841{
842 icCurveSegSignature sig;
843
844 icUInt32Number headerSize = sizeof(icTagTypeSignature) +
845 sizeof(icUInt32Number) +
846 sizeof(icUInt32Number);
847
848 if (headerSize > size)
849 return false;
850
851 if (!pIO) {
852 return false;
853 }
854
855 if (!pIO->Read32(&sig))
856 return false;
857
858 if (!pIO->Read32(&m_nReserved))
859 return false;
860
861 if (!pIO->Read32(&m_nCount))
862 return false;
863
864 if (m_nCount > size - headerSize || m_nCount * sizeof(icFloat32Number) > size - headerSize)
865 return false;
866
867 //Reserve room for first point who's value comes from previous segment
868 m_nCount++;
869
870 if (!SetSize(m_nCount, false))
871 return false;
872
873 if (m_nCount) {
874 if (pIO->ReadFloat32Float(m_pSamples+1, m_nCount-1)!=(icInt32Number)(m_nCount-1))
875 return false;
876 }
877
878 //Initialize first point with zero. Properly initialized during Begin()
879 m_pSamples[0] = 0;
880
881 return true;
882}
883
884/**
885 ******************************************************************************
886 * Name: CIccSampledCurveSegment::Write
887 *
888 * Purpose:
889 *
890 * Args:
891 *
892 * Return:
893 ******************************************************************************/
894bool CIccSampledCurveSegment::Write(CIccIO *pIO)
895{
896 icCurveSegSignature sig = GetType();
897
898 if (!pIO)
899 return false;
900
901 if (!pIO->Write32(&sig))
902 return false;
903
904 if (!pIO->Write32(&m_nReserved))
905 return false;
906
907 icUInt32Number nCount;
908
909 if (m_nCount)
910 nCount = m_nCount -1;
911 else
912 nCount = 0;
913
914 if (!pIO->Write32(&nCount))
915 return false;
916
917 //First point in samples is ONLY for interpolation (not saved)
918 if (nCount) {
919 if (pIO->WriteFloat32Float(m_pSamples+1, nCount)!=(icInt32Number)nCount)
920 return false;
921 }
922
923 return true;
924}
925
926/**
927 ******************************************************************************
928 * Name: CIccSampledCurveSegment::Begin
929 *
930 * Purpose:
931 *
932 * Args:
933 *
934 * Return:
935 ******************************************************************************/
936bool CIccSampledCurveSegment::Begin(CIccCurveSegment *pPrevSeg = NULL__null)
937{
938 if (m_nCount<2)
939 return false;
940
941 m_range = m_endPoint - m_startPoint;
942 m_last = (icFloatNumber)(m_nCount - 1);
943
944 if (m_endPoint-m_startPoint == 0.0)
945 return false;
946
947 if (!pPrevSeg)
948 return false;
949
950 //Set up interpolation from Application of last segment
951 m_pSamples[0] = pPrevSeg->Apply(m_startPoint);
952
953 return true;
954}
955
956/**
957 ******************************************************************************
958 * Name: CIccSampledCurveSegment::Apply
959 *
960 * Purpose:
961 *
962 * Args:
963 *
964 * Return:
965 ******************************************************************************/
966icFloatNumber CIccSampledCurveSegment::Apply(icFloatNumber v) const
967{
968 if (v<m_startPoint)
969 v=m_startPoint;
970 else if (v>m_endPoint)
971 v=m_endPoint;
972
973 icFloatNumber pos = (v-m_startPoint)/m_range * m_last;
974 icUInt32Number index = (icUInt32Number) pos;
975 icFloatNumber remainder = pos - (icFloatNumber)index;
976
977 if (remainder==0.0)
978 return m_pSamples[index];
979
980 return (icFloatNumber)((1.0-remainder)*m_pSamples[index] + remainder*m_pSamples[index+1]);
981}
982
983/**
984 ******************************************************************************
985 * Name: CIccSampledCurveSegment::Validate
986 *
987 * Purpose:
988 *
989 * Args:
990 *
991 * Return:
992 ******************************************************************************/
993icValidateStatus CIccSampledCurveSegment::Validate(std::string sigPath, std::string &sReport, const CIccTagMultiProcessElement* pMPE/*=NULL*/) const
994{
995 CIccInfo Info;
996 std::string sSigPathName = Info.GetSigPathName(sigPath);
997
998 icValidateStatus rv = icValidateOK;
999 if (m_nReserved) {
1000 sReport += icMsgValidateWarning;
1001 sReport += sSigPathName;
1002 sReport += " sampled curve has non zero reserved data.\r\n";
1003 rv = icValidateWarning;
1004 }
1005
1006 if (m_nCount<1) {
1007 sReport += icMsgValidateCriticalError;
1008 sReport += sSigPathName;
1009 sReport += " sampled curve has too few sample points.\r\n";
1010 rv = icMaxStatus(rv, icValidateCriticalError);
1011 }
1012 else if (m_endPoint-m_startPoint == 0.0) {
1013 sReport += icMsgValidateWarning;
1014 sReport += sSigPathName;
1015 sReport += " sampled curve has a range of zero.\r\n";
1016 rv = icMaxStatus(rv, icValidateWarning);
1017 }
1018
1019 return rv;
1020}
1021
1022
1023
1024/**
1025******************************************************************************
1026* Name: CIccSingleSampledCurve::CIccSingleSampledCurve
1027*
1028* Purpose:
1029*
1030* Args:
1031*
1032* Return:
1033******************************************************************************/
1034CIccSingleSampledCurve::CIccSingleSampledCurve(icFloatNumber first, icFloatNumber last)
1035{
1036 m_nReserved = 0;
1037 m_nCount = 0;
1038 m_pSamples = 0;
1039
1040 m_storageType = icValueTypeFloat32;
1041 m_extensionType = icClipSingleSampledCurve;
1042
1043 if (first < last) {
1044 m_firstEntry = first;
1045 m_lastEntry = last;
1046 }
1047 else {
1048 m_firstEntry = last;
1049 m_lastEntry = first;
1050 }
1051
1052 m_loIntercept = 0;
1053 m_loSlope = 0;
1054 m_hiIntercept = 1.0;
1055 m_hiSlope = 0;
1056}
1057
1058/**
1059******************************************************************************
1060* Name: CIccSingleSampledCurve::CIccSingleSampledCurve
1061*
1062* Purpose:
1063*
1064* Args:
1065*
1066* Return:
1067******************************************************************************/
1068CIccSingleSampledCurve::CIccSingleSampledCurve(const CIccSingleSampledCurve &curve)
1069{
1070 m_nReserved = curve.m_nReserved;
1071 m_nCount = curve.m_nCount;
1072
1073 m_storageType = curve.m_storageType;
1074 m_extensionType = curve.m_extensionType;
1075
1076 if (m_nCount) {
1077 m_pSamples = (icFloatNumber*)malloc(m_nCount * sizeof(icFloatNumber));
1078 if (m_pSamples)
1079 memcpy(m_pSamples, curve.m_pSamples, m_nCount * sizeof(icFloatNumber));
1080 else
1081 m_nCount = 0;
1082 }
1083 else{
1084 m_pSamples = NULL__null;
1085 }
1086
1087 m_firstEntry = curve.m_firstEntry;
1088 m_lastEntry = curve.m_lastEntry;
1089
1090 m_loIntercept = curve.m_loIntercept;
1091 m_loSlope = curve.m_loSlope;
1092 m_hiIntercept = curve.m_hiIntercept;
1093 m_hiSlope = curve.m_hiSlope;
1094}
1095
1096/**
1097******************************************************************************
1098* Name: &CIccSingleSampledCurve::operator=
1099*
1100* Purpose:
1101*
1102* Args:
1103*
1104* Return:
1105******************************************************************************/
1106CIccSingleSampledCurve &CIccSingleSampledCurve::operator=(const CIccSingleSampledCurve &curve)
1107{
1108 if (m_pSamples)
1109 free(m_pSamples);
1110
1111 m_nReserved = curve.m_nReserved;
1112 m_nCount = curve.m_nCount;
1113
1114 m_storageType = curve.m_storageType;
1115 m_extensionType = curve.m_extensionType;
1116
1117 if (m_nCount) {
1118 m_pSamples = (icFloatNumber*)malloc(m_nCount * sizeof(icFloatNumber));
1119 if (m_pSamples)
1120 memcpy(m_pSamples, curve.m_pSamples, m_nCount * sizeof(icFloatNumber));
1121 else
1122 m_nCount = 0;
1123 }
1124 else {
1125 m_pSamples = NULL__null;
1126 }
1127
1128 m_firstEntry = curve.m_firstEntry;
1129 m_lastEntry = curve.m_lastEntry;
1130
1131 m_loIntercept = curve.m_loIntercept;
1132 m_loSlope = curve.m_loSlope;
1133 m_hiIntercept = curve.m_hiIntercept;
1134 m_hiSlope = curve.m_hiSlope;
1135 return (*this);
1136}
1137
1138/**
1139******************************************************************************
1140* Name: CIccSingleSampledCurve::~CIccSingleSampledCurve
1141*
1142* Purpose:
1143*
1144* Args:
1145*
1146* Return:
1147******************************************************************************/
1148CIccSingleSampledCurve::~CIccSingleSampledCurve()
1149{
1150 if (m_pSamples)
1151 free(m_pSamples);
1152}
1153
1154/**
1155******************************************************************************
1156* Name: CIccSingleSampledCurve::SetRange
1157*
1158* Purpose:
1159* Sets range of sampled lookup table.
1160*
1161* Args:
1162* first = first entry input position
1163* last = last entry input position
1164******************************************************************************/
1165void CIccSingleSampledCurve::SetRange(icFloatNumber first/* =0.0f */, icFloatNumber last/* =1.0f */)
1166{
1167 if (first < last) {
1168 m_firstEntry = first;
1169 m_lastEntry = last;
1170 }
1171 else {
1172 m_firstEntry = last;
1173 m_lastEntry = first;
1174 }
1175}
1176
1177
1178/**
1179******************************************************************************
1180* Name: CIccSingleSampledCurve::SetExtensionType
1181*
1182* Purpose:
1183* Sets extension type of the single sampled curve
1184*
1185* Args:
1186* nExtensionType is type of extension to use
1187*
1188* Return:
1189* true if valid extension type, false otherwise
1190******************************************************************************/
1191bool CIccSingleSampledCurve::SetExtensionType(icUInt16Number nExtensionType)
1192{
1193 m_extensionType = nExtensionType;
1194
1195 switch (nExtensionType) {
1196 case icClipSingleSampledCurve:
1197 case icExtendSingleSampledCurve:
1198 return true;
1199 }
1200 return false;
1201}
1202
1203/**
1204******************************************************************************
1205* Name: CIccSingleSampledCurve::SetStorageType
1206*
1207* Purpose:
1208* Sets storate type of the data stored in the single sampled curve
1209*
1210* Args:
1211* nStorageType is type of data to use
1212*
1213* Return:
1214* true if valid storage type, false otherwise
1215******************************************************************************/
1216bool CIccSingleSampledCurve::SetStorageType(icUInt16Number nStorateType)
1217{
1218 m_storageType = nStorateType;
1219
1220 switch (nStorateType) {
1221 case icValueTypeUInt8:
1222 case icValueTypeUInt16:
1223 case icValueTypeFloat16:
1224 case icValueTypeFloat32:
1225 return true;
1226 }
1227 return false;
1228}
1229
1230
1231/**
1232******************************************************************************
1233* Name: CIccSingleSampledCurve::SetSize
1234*
1235* Purpose:
1236* Sets size of sampled lookup table. Previous data (if exists) is lost.
1237*
1238* Args:
1239* nCount = number of elements in lut (must be >= 2).
1240* bZeroAlloc = flag to decide if memory should be set to zero.
1241*
1242* Return:
1243* true if allocation successful.
1244******************************************************************************/
1245bool CIccSingleSampledCurve::SetSize(icUInt32Number nCount, bool bZeroAlloc/*=true*/)
1246{
1247 if (!nCount) {
1248 if (m_pSamples)
1249 free(m_pSamples);
1250 m_pSamples = NULL__null;
1251 m_nCount = nCount;
1252 return true;
1253 }
1254
1255 if (m_pSamples) {
1256 free(m_pSamples);
1257 }
1258
1259 if (bZeroAlloc)
1260 m_pSamples = (icFloatNumber*)calloc(nCount, sizeof(icFloatNumber));
1261 else
1262 m_pSamples = (icFloatNumber*)malloc(nCount * sizeof(icFloatNumber));
1263
1264 if (m_pSamples)
1265 m_nCount = nCount;
1266 else
1267 m_nCount = 0;
1268
1269 return (m_pSamples != NULL__null);
1270}
1271
1272/**
1273******************************************************************************
1274* Name: CIccSingleSampledCurve::Describe
1275*
1276* Purpose:
1277*
1278* Args:
1279*
1280* Return:
1281******************************************************************************/
1282void CIccSingleSampledCurve::Describe(std::string &sDescription)
1283{
1284 icChar buf[128];
1285
1286 if (m_nCount<2) {
1287 sDescription += "Empty Single Sampled Curve [";
1288 sprintf(buf, "%.8f, ", m_firstEntry);
1289 sDescription += buf;
1290
1291 sprintf(buf, "%.8f", m_lastEntry);
1292 sDescription += buf;
1293
1294 sprintf(buf, "]\r\n");
1295 sDescription += buf;
1296 }
1297 else {
1298 sDescription += "Single Sampled Curve [";
1299
1300 sprintf(buf, "%.8f, ", m_firstEntry);
1301 sDescription += buf;
1302
1303 sprintf(buf, "%.8f", m_lastEntry);
1304 sDescription += buf;
1305
1306 sprintf(buf, "]\r\n");
1307 sDescription += buf;
1308
1309 switch(m_storageType) {
1310 case icValueTypeUInt8:
1311 sDescription +="UInt8Number Array\n";
1312 break;
1313 case icValueTypeUInt16:
1314 sDescription +="UInt16Number Array\n";
1315 break;
1316 case icValueTypeFloat16:
1317 sDescription +="Float16Number Array\n";
1318 break;
1319 case icValueTypeFloat32:
1320 sDescription +="Float32Number Array\n";
1321 break;
1322 default:
1323 sDescription +="Unknown Data Type\n";
1324 break;
1325 }
1326
1327 switch(m_extensionType) {
1328 case icClipSingleSampledCurve:
1329 sDescription += "Clip End Points\n";
1330 break;
1331 case icExtendSingleSampledCurve:
1332 sDescription += "Extend End Points\n";
1333 break;
1334 default:
1335 sDescription += "Unknown extension handling\n";
1336 break;
1337 }
1338 sDescription += "IN OUT\r\n";
1339
1340 icUInt32Number i;
1341
1342 icFloatNumber range = m_lastEntry - m_firstEntry;
1343 icFloatNumber last = (icFloatNumber)(m_nCount-1);
1344
1345 for (i=0; i<m_nCount; i++) {
1346 sprintf(buf, "%.8f %.8f\r\n", m_firstEntry + (icFloatNumber)i*range/last, m_pSamples[i]);
1347 sDescription += buf;
1348 }
1349 }
1350 sDescription += "\r\n";
1351}
1352
1353/**
1354******************************************************************************
1355* Name: CIccSingleSampledCurve::Read
1356*
1357* Purpose:
1358*
1359* Args:
1360*
1361* Return:
1362******************************************************************************/
1363bool CIccSingleSampledCurve::Read(icUInt32Number size, CIccIO *pIO)
1364{
1365 icCurveSegSignature sig;
1366
1367 icUInt32Number headerSize = sizeof(icTagTypeSignature) +
1368 sizeof(icUInt32Number) +
1369 sizeof(icUInt32Number) +
1370 sizeof(icFloat32Number) +
1371 sizeof(icFloat32Number) +
1372 sizeof(icUInt16Number) +
1373 sizeof(icUInt16Number);
1374
1375 if (headerSize > size)
1376 return false;
1377
1378 if (!pIO) {
1379 return false;
1380 }
1381
1382 if (!pIO->Read32(&sig) || sig!=GetType())
1383 return false;
1384
1385 if (!pIO->Read32(&m_nReserved))
1386 return false;
1387
1388 if (!pIO->Read32(&m_nCount))
1389 return false;
1390
1391 if (!pIO->ReadFloat32Float(&m_firstEntry))
1392 return false;
1393
1394 if (!pIO->ReadFloat32Float(&m_lastEntry))
1395 return false;
1396
1397 if (!pIO->Read16(&m_extensionType))
1398 return false;
1399
1400 if (!pIO->Read16(&m_storageType))
1401 return false;
1402
1403 if (!SetSize(m_nCount, false))
1404 return false;
1405
1406 if (m_nCount > size - headerSize)
1407 return false;
1408
1409 if (m_nCount) {
1410 switch(m_storageType) {
1411 case icValueTypeUInt8:
1412 if (m_nCount * sizeof(icUInt8Number) > size - headerSize)
1413 return false;
1414
1415 if (pIO->ReadUInt8Float(m_pSamples, m_nCount)!=(icInt32Number)(m_nCount))
1416 return false;
1417 break;
1418 case icValueTypeUInt16:
1419 if (m_nCount * 2 > size - headerSize)
1420 return false;
1421
1422 if (pIO->ReadUInt16Float(m_pSamples, m_nCount)!=(icInt32Number)(m_nCount))
1423 return false;
1424 break;
1425 case icValueTypeFloat16:
1426 if (m_nCount * 2 > size - headerSize)
1427 return false;
1428
1429 if (pIO->ReadFloat16Float(m_pSamples, m_nCount)!=(icInt32Number)(m_nCount))
1430 return false;
1431 break;
1432 case icValueTypeFloat32:
1433 if (m_nCount * sizeof(icFloat32Number) > size - headerSize)
1434 return false;
1435
1436 if (pIO->ReadFloat32Float(m_pSamples, m_nCount)!=(icInt32Number)(m_nCount))
1437 return false;
1438 break;
1439 default:
1440 return false;
1441 }
1442 }
1443
1444 return true;
1445}
1446
1447/**
1448******************************************************************************
1449* Name: CIccSingleSampledCurve::Write
1450*
1451* Purpose:
1452*
1453* Args:
1454*
1455* Return:
1456******************************************************************************/
1457bool CIccSingleSampledCurve::Write(CIccIO *pIO)
1458{
1459 icCurveElemSignature sig = GetType();
1460
1461 if (!pIO)
1462 return false;
1463
1464 if (!pIO->Write32(&sig))
1465 return false;
1466
1467 if (!pIO->Write32(&m_nReserved))
1468 return false;
1469
1470 if (!pIO->Write32(&m_nCount))
1471 return false;
1472
1473 if (!pIO->WriteFloat32Float(&m_firstEntry))
1474 return false;
1475
1476 if (!pIO->WriteFloat32Float(&m_lastEntry))
1477 return false;
1478
1479 if (!pIO->Write16(&m_extensionType))
1480 return false;
1481
1482 if (!pIO->Write16(&m_storageType))
1483 return false;
1484
1485 if (m_nCount) {
1486
1487 switch(m_storageType) {
1488 case icValueTypeUInt8:
1489 if (pIO->WriteUInt8Float(m_pSamples, m_nCount)!=(icInt32Number)(m_nCount))
1490 return false;
1491 break;
1492 case icValueTypeUInt16:
1493 if (pIO->WriteUInt16Float(m_pSamples, m_nCount)!=(icInt32Number)(m_nCount))
1494 return false;
1495 break;
1496 case icValueTypeFloat16:
1497 if (pIO->WriteFloat16Float(m_pSamples, m_nCount)!=(icInt32Number)(m_nCount))
1498 return false;
1499 break;
1500 case icValueTypeFloat32:
1501 if (pIO->WriteFloat32Float(m_pSamples, m_nCount)!=(icInt32Number)(m_nCount))
1502 return false;
1503 break;
1504 default:
1505 return false;
1506 }
1507 }
1508
1509 return true;
1510}
1511
1512/**
1513******************************************************************************
1514* Name: CIccSingleSampledCurve::Begin
1515*
1516* Purpose:
1517*
1518* Args:
1519*
1520* Return:
1521******************************************************************************/
1522bool CIccSingleSampledCurve::Begin()
1523{
1524 if (m_nCount<2)
1525 return false;
1526
1527 m_range = m_lastEntry - m_firstEntry;
1528 m_last = (icFloatNumber)(m_nCount - 1);
1529 icFloatNumber stepSize = m_range / m_last;
1530
1531 if (m_range == 0.0)
1532 return false;
1533
1534 switch(m_extensionType) {
1535 case icClipSingleSampledCurve:
1536 m_loSlope=0.0;
1537 m_loIntercept = m_pSamples[0];
1538
1539 m_hiSlope=0.0;
1540 m_hiIntercept = m_pSamples[m_nCount-1];
1541 break;
1542
1543 case icExtendSingleSampledCurve:
1544 m_loSlope = (m_pSamples[1]-m_pSamples[0])/stepSize;
1545 m_loIntercept = m_pSamples[0] - m_loSlope*m_firstEntry;
1546
1547 m_hiSlope = (m_pSamples[m_nCount-1] - m_pSamples[m_nCount-2])/stepSize;
1548 m_hiIntercept = m_pSamples[m_nCount-1] - m_hiSlope*m_lastEntry;
1549 break;
1550
1551 default:
1552 return false;
1553 }
1554
1555 return true;
1556}
1557
1558/**
1559******************************************************************************
1560* Name: CIccSingleSampledCurve::Apply
1561*
1562* Purpose:
1563*
1564* Args:
1565*
1566* Return:
1567******************************************************************************/
1568icFloatNumber CIccSingleSampledCurve::Apply(icFloatNumber v) const
1569{
1570 if (v<m_firstEntry) {
1571 return m_loSlope * v + m_loIntercept;;
1572 }
1573 else if (v>m_lastEntry) {
1574 return m_hiSlope * v + m_hiIntercept;
1575 }
1576
1577 icFloatNumber pos = (v-m_firstEntry)/m_range * m_last;
1578 icUInt32Number index = (icUInt32Number) pos;
1579 icFloatNumber remainder = pos - (icFloatNumber)index;
1580
1581 if (remainder==0.0)
1582 return m_pSamples[index];
1583
1584 return (icFloatNumber)((1.0-remainder)*m_pSamples[index] + remainder*m_pSamples[index+1]);
1585}
1586
1587/**
1588******************************************************************************
1589* Name: CIccSingleSampledCurve::Validate
1590*
1591* Purpose:
1592*
1593* Args:
1594*
1595* Return:
1596******************************************************************************/
1597icValidateStatus CIccSingleSampledCurve::Validate(std::string sigPath, std::string &sReport, const CIccTagMultiProcessElement* pMPE/*=NULL*/) const
1598{
1599 CIccInfo Info;
1600 std::string sSigPathName = Info.GetSigPathName(sigPath);
1601
1602 icValidateStatus rv = icValidateOK;
1603 if (m_nReserved) {
1604 sReport += icMsgValidateWarning;
1605 sReport += sSigPathName;
1606 sReport += " single sampled curve has non zero reserved data.\r\n";
1607 rv = icValidateWarning;
1608 }
1609
1610 if (m_extensionType > icMaxSingleSampledCurveTypeicExtendSingleSampledCurve) {
1611 sReport += icMsgValidateCriticalError;
1612 sReport += sSigPathName;
1613 sReport += " single sampled curve has unknown extension type\r\n";
1614 rv = icMaxStatus(rv, icValidateCriticalError);
1615 }
1616
1617 if (m_storageType > icMaxValueTypeicValueTypeUInt8) {
1618 sReport += icMsgValidateCriticalError;
1619 sReport += sSigPathName;
1620 sReport += " single sampled curve uses unknown value type\r\n";
1621 rv = icMaxStatus(rv, icValidateCriticalError);
1622 }
1623
1624 if (m_nCount<2) {
1625 sReport += icMsgValidateCriticalError;
1626 sReport += sSigPathName;
1627 sReport += " single sampled curve has too few sample points.\r\n";
1628 rv = icMaxStatus(rv, icValidateCriticalError);
1629 }
1630
1631 else if (m_lastEntry-m_firstEntry <= 0.0) {
1632 sReport += icMsgValidateWarning;
1633 sReport += sSigPathName;
1634 sReport += " single sampled curve has an invalid sample range.\r\n";
1635 rv = icMaxStatus(rv, icValidateWarning);
1636 }
1637
1638 return rv;
1639}
1640
1641/**
1642 ******************************************************************************
1643 * Name: CIccCurveSegment::Create
1644 *
1645 * Purpose:
1646 *
1647 * Args:
1648 *
1649 * Return:
1650 ******************************************************************************/
1651CIccCurveSegment* CIccCurveSegment::Create(icCurveSegSignature sig, icFloatNumber start, icFloatNumber end)
1652{
1653 switch(sig) {
1654 case icSigFormulaCurveSeg:
1655 return new CIccFormulaCurveSegment(start, end);
1656 case icSigSampledCurveSeg:
1657 return new CIccSampledCurveSegment(start, end);
1658 default:
1659 return NULL__null;
1660 }
1661
1662}
1663
1664/**
1665 ******************************************************************************
1666 * Name: CIccSegmentedCurve::CIccSegmentedCurve
1667 *
1668 * Purpose:
1669 *
1670 * Args:
1671 *
1672 * Return:
1673 ******************************************************************************/
1674CIccSegmentedCurve::CIccSegmentedCurve()
1675{
1676 m_list = new CIccCurveSegmentList();
1677 m_nReserved1 = 0;
1678 m_nReserved2 = 0;
1679
1680}
1681
1682
1683/**
1684 ******************************************************************************
1685 * Name: CIccSegmentedCurve::CIccSegmentedCurve
1686 *
1687 * Purpose:
1688 *
1689 * Args:
1690 *
1691 * Return:
1692 ******************************************************************************/
1693CIccSegmentedCurve::CIccSegmentedCurve(const CIccSegmentedCurve &curve)
1694{
1695 CIccCurveSegmentList::iterator i;
1696
1697 m_list = new CIccCurveSegmentList();
1698
1699 for (i=curve.m_list->begin(); i!=curve.m_list->end(); i++) {
1700 m_list->push_back((*i)->NewCopy());
1701 }
1702 m_nReserved1 = curve.m_nReserved1;
1703 m_nReserved2 = curve.m_nReserved2;
1704}
1705
1706
1707/**
1708 ******************************************************************************
1709 * Name: &CIccSegmentedCurve::operator=
1710 *
1711 * Purpose:
1712 *
1713 * Args:
1714 *
1715 * Return:
1716 ******************************************************************************/
1717CIccSegmentedCurve &CIccSegmentedCurve::operator=(const CIccSegmentedCurve &curve)
1718{
1719 Reset();
1720
1721 CIccCurveSegmentList::iterator i;
1722
1723 for (i=curve.m_list->begin(); i!=curve.m_list->end(); i++) {
1724 m_list->push_back((*i)->NewCopy());
1725 }
1726 m_nReserved1 = curve.m_nReserved1;
1727 m_nReserved2 = curve.m_nReserved2;
1728
1729 return (*this);
1730}
1731
1732
1733/**
1734 ******************************************************************************
1735 * Name: CIccSegmentedCurve::~CIccSegmentedCurve
1736 *
1737 * Purpose:
1738 *
1739 * Args:
1740 *
1741 * Return:
1742 ******************************************************************************/
1743CIccSegmentedCurve::~CIccSegmentedCurve()
1744{
1745 Reset();
1746 delete m_list;
1747}
1748
1749
1750/**
1751 ******************************************************************************
1752 * Name: CIccSegmentedCurve::Describe
1753 *
1754 * Purpose:
1755 *
1756 * Args:
1757 *
1758 * Return:
1759 ******************************************************************************/
1760void CIccSegmentedCurve::Describe(std::string &sDescription)
1761{
1762 CIccCurveSegmentList::iterator i;
1763
1764 sDescription += "BEGIN_CURVE\r\n";
1765 for (i=m_list->begin(); i!=m_list->end(); i++) {
1766 (*i)->Describe(sDescription);
1767 }
1768}
1769
1770
1771
1772/**
1773 ******************************************************************************
1774 * Name: CIccSegmentedCurve::Read
1775 *
1776 * Purpose:
1777 *
1778 * Args:
1779 *
1780 * Return:
1781 ******************************************************************************/
1782bool CIccSegmentedCurve::Read(icUInt32Number size, CIccIO *pIO)
1783{
1784 icCurveElemSignature sig;
1785
1786 icUInt32Number startPos = pIO->Tell();
1787
1788 icUInt32Number headerSize = sizeof(icCurveElemSignature) +
1789 sizeof(icUInt32Number) +
1790 sizeof(icUInt16Number) +
1791 sizeof(icUInt16Number);
1792
1793 if (headerSize > size)
1794 return false;
1795
1796 if (!pIO) {
1797 return false;
1798 }
1799
1800 if (!pIO->Read32(&sig))
1801 return false;
1802
1803 if (sig!=GetType())
1804 return false;
1805
1806 if (!pIO->Read32(&m_nReserved1))
1807 return false;
1808
1809 icUInt16Number nSegments;
1810
1811 if (!pIO->Read16(&nSegments))
1812 return false;
1813
1814 if (!pIO->Read16(&m_nReserved2))
1815 return false;
1816
1817 Reset();
1818
1819 icUInt32Number pos = pIO->Tell();
1820 icCurveSegSignature segSig;
1821 CIccCurveSegment *pSeg;
1822
1823 if (nSegments==1) {
1824 if (sizeof(segSig) > size - headerSize)
1825 return false;
1826
1827 if (!pIO->Read32(&segSig))
1828 return false;
1829 pSeg = CIccCurveSegment::Create(segSig, icMinFloat32Number-3.402823466e+38F, icMaxFloat32Number3.402823466e+38F);
1830 if (!pSeg)
1831 return false;
1832
1833 pIO->Seek(pos, icSeekSet);
1834
1835 if (!pSeg->Read(size-(pos-startPos), pIO)) {
1836 delete pSeg;
1837 return false;
1838 }
1839
1840 m_list->push_back(pSeg);
1841 }
1842 else if (nSegments) {
1843 if (nSegments > size - headerSize)
1844 return false;
1845
1846 icFloatNumber *breakpoints=(icFloatNumber*)calloc(nSegments-1, sizeof(icFloatNumber));
1847
1848 if (!breakpoints)
1849 return false;
1850
1851 if (pIO->ReadFloat32Float(breakpoints, nSegments-1)!=nSegments-1) {
1852 free(breakpoints);
1853 return false;
1854 }
1855
1856 int i;
1857 for (i=0; i<nSegments; i++) {
1858 pos = pIO->Tell();
1859 if (!pIO->Read32(&segSig)) {
1860 free(breakpoints);
1861 return false;
1862 }
1863 if (pIO->Seek(pos, icSeekSet)!=(icInt32Number)pos)
1864 return false;;
1865
1866 if (!i)
1867 pSeg = CIccCurveSegment::Create(segSig, icMinFloat32Number-3.402823466e+38F, breakpoints[i]);
1868 else if (i==nSegments-1)
1869 pSeg = CIccCurveSegment::Create(segSig, breakpoints[i-1], icMaxFloat32Number3.402823466e+38F);
1870 else
1871 pSeg = CIccCurveSegment::Create(segSig, breakpoints[i-1], breakpoints[i]);
1872
1873 if (!pSeg) {
1874 free(breakpoints);
1875 return false;
1876 }
1877
1878 if (!pSeg->Read(size-(pos-startPos), pIO)) {
1879 delete pSeg;
1880 free(breakpoints);
1881 return false;
1882 }
1883
1884 m_list->push_back(pSeg);
1885 }
1886
1887 free(breakpoints);
1888 }
1889
1890 return true;
1891}
1892
1893
1894/**
1895 ******************************************************************************
1896 * Name: CIccSegmentedCurve::Write
1897 *
1898 * Purpose:
1899 *
1900 * Args:
1901 *
1902 * Return:
1903 ******************************************************************************/
1904bool CIccSegmentedCurve::Write(CIccIO *pIO)
1905{
1906 icCurveElemSignature sig = GetType();
1907
1908 if (!pIO)
1909 return false;
1910
1911 if (!pIO->Write32(&sig))
1912 return false;
1913
1914 if (!pIO->Write32(&m_nReserved1))
1915 return false;
1916
1917 icUInt16Number nSegments = (icUInt16Number)m_list->size();
1918
1919 if (!pIO->Write16(&nSegments))
1920 return false;
1921
1922 if (!pIO->Write16(&m_nReserved2))
1923 return false;
1924
1925 CIccCurveSegmentList::iterator i;
1926 if (nSegments>1) {
1927 icFloatNumber breakpoint;
1928
1929 i=m_list->begin();
1930 for (i++; i!=m_list->end(); i++) {
1931 breakpoint = (*i)->StartPoint();
1932 if (!pIO->WriteFloat32Float(&breakpoint))
1933 return false;
1934 }
1935 }
1936 for (i=m_list->begin(); i!=m_list->end(); i++) {
1937 if (!(*i)->Write(pIO))
1938 return false;
1939 }
1940
1941 return true;
1942}
1943
1944
1945/**
1946 ******************************************************************************
1947 * Name: CIccSegmentedCurve::Reset
1948 *
1949 * Purpose:
1950 *
1951 * Args:
1952 *
1953 * Return:
1954 ******************************************************************************/
1955void CIccSegmentedCurve::Reset()
1956{
1957 CIccCurveSegmentList::iterator i;
1958
1959 for (i=m_list->begin(); i!=m_list->end(); i++) {
1960 delete (*i);
1961 }
1962 m_list->clear();
1963}
1964
1965
1966/**
1967 ******************************************************************************
1968 * Name: CIccSegmentedCurve::Insert
1969 *
1970 * Purpose:
1971 *
1972 * Args:
1973 *
1974 * Return:
1975 ******************************************************************************/
1976bool CIccSegmentedCurve::Insert(CIccCurveSegment *pCurveSegment)
1977{
1978 CIccCurveSegmentList::reverse_iterator last = m_list->rbegin();
1979
1980 if (last!=m_list->rend()) {
1981 if (pCurveSegment->StartPoint() == (*last)->EndPoint()) {
1982 m_list->push_back(pCurveSegment);
1983 return true;
1984 }
1985 }
1986 else {
1987 m_list->push_back(pCurveSegment);
1988 return true;
1989 }
1990
1991 return false;
1992}
1993
1994
1995/**
1996 ******************************************************************************
1997 * Name: CIccSegmentedCurve::Begin
1998 *
1999 * Purpose:
2000 *
2001 * Args:
2002 *
2003 * Return:
2004 ******************************************************************************/
2005bool CIccSegmentedCurve::Begin()
2006{
2007 if (m_list->size()==0)
2008 return false;
2009
2010 CIccCurveSegmentList::iterator i;
2011 CIccCurveSegment *pLast = NULL__null;
2012
2013 for (i=m_list->begin(); i!=m_list->end(); i++) {
2014 if (!(*i)->Begin(pLast))
2015 return false;
2016 pLast = *i;
2017 }
2018
2019 return true;
2020}
2021
2022
2023/**
2024 ******************************************************************************
2025 * Name: CIccSegmentedCurve::Apply
2026 *
2027 * Purpose:
2028 *
2029 * Args:
2030 *
2031 * Return:
2032 ******************************************************************************/
2033icFloatNumber CIccSegmentedCurve::Apply(icFloatNumber v) const
2034{
2035 CIccCurveSegmentList::iterator i;
2036
2037 for (i=m_list->begin(); i!=m_list->end(); i++) {
2038 if (v <= (*i)->EndPoint())
2039 return (*i)->Apply(v);
2040 }
2041 return v;
2042}
2043
2044/**
2045 ******************************************************************************
2046 * Name: CIccSegmentedCurve::Validate
2047 *
2048 * Purpose:
2049 *
2050 * Args:
2051 *
2052 * Return:
2053 ******************************************************************************/
2054icValidateStatus CIccSegmentedCurve::Validate(std::string sigPath, std::string &sReport, const CIccTagMultiProcessElement* pMPE/*=NULL*/) const
2055{
2056 CIccInfo Info;
2057 std::string sSigPathName = Info.GetSigPathName(sigPath);
2058
2059 icValidateStatus rv = icValidateOK;
2060 if (m_nReserved1 || m_nReserved2) {
2061 sReport += icMsgValidateWarning;
2062 sReport += sSigPathName;
2063 sReport += " Segmented curve has non zero reserved data.\r\n";
2064 rv = icValidateWarning;
2065 }
2066
2067 if (m_list->size()==0) {
2068 sReport += icMsgValidateCriticalError;
2069 sReport += sSigPathName;
2070 sReport += " Has Empty CurveSegment!\r\n";
2071 return icMaxStatus(rv, icValidateCriticalError);
2072 }
2073
2074 CIccCurveSegmentList::iterator i;
2075
2076 for (i=m_list->begin(); i!=m_list->end(); i++) {
2077 rv = icMaxStatus(rv, (*i)->Validate(sigPath+icGetSigPath(GetType()), sReport, pMPE));
2078 }
2079
2080 return rv;
2081}
2082
2083
2084/**
2085 ******************************************************************************
2086 * Name: CIccCurveSetCurve::Create
2087 *
2088 * Purpose:
2089 *
2090 * Args:
2091 *
2092 * Return:
2093 ******************************************************************************/
2094CIccCurveSetCurve* CIccCurveSetCurve::Create(icCurveElemSignature sig)
2095{
2096 switch (sig) {
2097 case icSigSegmentedCurve:
2098 return new CIccSegmentedCurve();
2099 case icSigSingleSampledCurve:
2100 return new CIccSingleSampledCurve();
2101 default:
2102 return NULL__null;
2103 }
2104}
2105
2106/**
2107 ******************************************************************************
2108 * Name: CIccMpeCurveSet::CIccMpeCurveSet
2109 *
2110 * Purpose:
2111 *
2112 * Args:
2113 *
2114 * Return:
2115 ******************************************************************************/
2116CIccMpeCurveSet::CIccMpeCurveSet(int nSize/*=0*/)
2117{
2118 m_nReserved = 0;
2119 if (nSize) {
2120 m_nInputChannels = m_nOutputChannels = nSize;
2121 m_curve = (icCurveSetCurvePtr*)calloc(nSize, sizeof(icCurveSetCurvePtr));
2122 m_position = (icPositionNumber*)calloc(nSize, sizeof(icPositionNumber));
2123 }
2124 else {
2125 m_nInputChannels = m_nOutputChannels = 0;
2126 m_curve = NULL__null;
2127 m_position = NULL__null;
2128 }
2129}
2130
2131typedef std::map<icCurveSetCurvePtr, icCurveSetCurvePtr> icCurveMap;
2132
2133/**
2134 ******************************************************************************
2135 * Name: CIccMpeCurveSet::CIccMpeCurveSet
2136 *
2137 * Purpose:
2138 *
2139 * Args:
2140 *
2141 * Return:
2142 ******************************************************************************/
2143CIccMpeCurveSet::CIccMpeCurveSet(const CIccMpeCurveSet &curveSet)
2144{
2145 m_nReserved = curveSet.m_nReserved;
2146
2147 if (curveSet.m_nInputChannels) {
2148 int i;
2149
2150 m_nInputChannels = m_nOutputChannels = curveSet.m_nInputChannels;
2151 m_curve = (icCurveSetCurvePtr*)calloc(m_nInputChannels, sizeof(icCurveSetCurvePtr));
2152 m_position = (icPositionNumber*)calloc(m_nInputChannels, sizeof(icPositionNumber));
2153
2154 icCurveMap map;
2155 for (i=0; i<m_nInputChannels; i++) {
2156 CIccCurveSetCurve *ptr = curveSet.m_curve[i];
2157 if (ptr) {
2158 if (!map[ptr]) {
2159 m_curve[i] = ptr->NewCopy();
2160 map[ptr] = m_curve[i];
2161 }
2162 else
2163 m_curve[i] = map[ptr];
2164 }
2165 }
2166 }
2167 else {
2168 m_nInputChannels = m_nOutputChannels = 0;
2169 m_curve = NULL__null;
2170 }
2171}
2172
2173/**
2174 ******************************************************************************
2175 * Name: &CIccMpeCurveSet::operator=
2176 *
2177 * Purpose:
2178 *
2179 * Args:
2180 *
2181 * Return:
2182 ******************************************************************************/
2183CIccMpeCurveSet &CIccMpeCurveSet::operator=(const CIccMpeCurveSet &curveSet)
2184{
2185 m_nReserved = m_nReserved;
2186
2187 if (m_curve) {
2188 free(m_curve);
2189 }
2190
2191 if (curveSet.m_nInputChannels) {
2192 int i;
2193
2194 m_nInputChannels = m_nOutputChannels = curveSet.m_nInputChannels;
2195 m_curve = (icCurveSetCurvePtr*)calloc(m_nInputChannels, sizeof(icCurveSetCurvePtr));
2196 m_position = (icPositionNumber*)calloc(m_nInputChannels, sizeof(icPositionNumber));
2197
2198 icCurveMap map;
2199 for (i=0; i<m_nInputChannels; i++) {
2200 CIccCurveSetCurve *ptr = curveSet.m_curve[i];
2201 if (ptr) {
2202 if (!map[ptr]) {
2203 m_curve[i] = ptr->NewCopy();
2204 map[ptr] = m_curve[i];
2205 }
2206 else
2207 m_curve[i] = map[ptr];
2208 }
2209 }
2210 }
2211 else {
2212 m_nInputChannels = m_nOutputChannels = 0;
2213 m_curve = NULL__null;
2214 }
2215
2216 return *this;
2217}
2218
2219/**
2220 ******************************************************************************
2221 * Name: CIccMpeCurveSet::~CIccMpeCurveSet
2222 *
2223 * Purpose:
2224 *
2225 * Args:
2226 *
2227 * Return:
2228 ******************************************************************************/
2229CIccMpeCurveSet::~CIccMpeCurveSet()
2230{
2231 SetSize(0);
2232}
2233
2234/**
2235 ******************************************************************************
2236 * Name: CIccMpeCurveSet::SetSize
2237 *
2238 * Purpose:
2239 *
2240 * Args:
2241 *
2242 * Return:
2243 ******************************************************************************/
2244bool CIccMpeCurveSet::SetSize(int nNewSize)
2245{
2246 if (m_curve) {
2247 icCurveMap map;
2248 int i;
2249
2250 for (i=0; i<m_nInputChannels; i++) {
2251 if (!map[m_curve[i]]) {
2252 map[m_curve[i]] = (CIccCurveSetCurve*)1;
2253 delete m_curve[i];
2254 }
2255 }
2256 free(m_curve);
2257 }
2258 if (m_position) {
2259 free(m_position);
2260 }
2261
2262 if (nNewSize) {
2263 m_curve = (icCurveSetCurvePtr*)calloc(nNewSize, sizeof(icCurveSetCurvePtr));
2264
2265 if (!m_curve) {
2266 m_position = NULL__null;
2267 m_nInputChannels = m_nOutputChannels = 0;
2268 return false;
2269 }
2270
2271 m_position = (icPositionNumber*)calloc(nNewSize, sizeof(icPositionNumber));
2272
2273 if (!m_position) {
2274 free(m_curve);
2275 m_curve = NULL__null;
2276
2277 m_nInputChannels = m_nOutputChannels = 0;
2278 return false;
2279 }
2280 m_nInputChannels = m_nOutputChannels = nNewSize;
2281 }
2282 else {
2283 m_curve = NULL__null;
2284 m_nInputChannels = m_nOutputChannels = 0;
2285 }
2286
2287 return true;
2288}
2289
2290/**
2291 ******************************************************************************
2292 * Name: CIccMpeCurveSet::SetCurve
2293 *
2294 * Purpose:
2295 *
2296 * Args:
2297 *
2298 * Return:
2299 ******************************************************************************/
2300bool CIccMpeCurveSet::SetCurve(int nIndex, icCurveSetCurvePtr newCurve)
2301{
2302 if (nIndex<0 || nIndex>m_nInputChannels)
2303 return false;
2304
2305 if (m_curve) {
2306 int i;
2307
2308 for (i=0; i<m_nInputChannels; i++)
2309 if (i!=nIndex && m_curve[i]==m_curve[nIndex])
2310 break;
2311
2312 if (i==m_nInputChannels && m_curve[nIndex]) {
2313 delete m_curve[nIndex];
2314 }
2315 }
2316 m_curve[nIndex] = newCurve;
2317
2318 return true;
2319}
2320
2321
2322/**
2323 ******************************************************************************
2324 * Name: CIccMpeCurveSet::Describe
2325 *
2326 * Purpose:
2327 *
2328 * Args:
2329 *
2330 * Return:
2331 ******************************************************************************/
2332void CIccMpeCurveSet::Describe(std::string &sDescription)
2333{
2334 if (m_curve) {
2335 icChar buf[81];
2336 int i;
2337
2338 sprintf(buf, "BEGIN_CURVE_SET %d\r\n", m_nInputChannels);
2339 sDescription += buf;
2340
2341 for (i=0; i<m_nInputChannels; i++) {
2342 sprintf(buf, "Curve %d of %d\r\n", i+1, m_nInputChannels);
2343 sDescription += buf;
2344 if (m_curve[i]) {
2345 m_curve[i]->Describe(sDescription);
2346 }
2347 }
2348 sDescription += "END_CURVE_SET\r\n";
2349 }
2350}
2351
2352typedef std::map<icUInt32Number, CIccCurveSetCurve*> icCurveOffsetMap;
2353typedef std::map<CIccCurveSetCurve*, icPositionNumber> icCurvePtrMap;
2354
2355/**
2356 ******************************************************************************
2357 * Name: CIccMpeCurveSet::Read
2358 *
2359 * Purpose:
2360 *
2361 * Args:
2362 *
2363 * Return:
2364 ******************************************************************************/
2365bool CIccMpeCurveSet::Read(icUInt32Number size, CIccIO *pIO)
2366{
2367 icElemTypeSignature sig;
2368
2369 icUInt32Number startPos = pIO->Tell();
2370
2371 icUInt32Number headerSize = sizeof(icTagTypeSignature) +
2372 sizeof(icUInt32Number) +
2373 sizeof(icUInt16Number) +
2374 sizeof(icUInt16Number);
2375
2376 if (headerSize > size)
2377 return false;
2378
2379 if (!pIO) {
2380 return false;
2381 }
2382
2383 icUInt16Number nInputChannels, nOutputChannels;
2384
2385 if (!pIO->Read32(&sig))
2386 return false;
2387
2388 if (!pIO->Read32(&m_nReserved))
2389 return false;
2390
2391 if (!pIO->Read16(&nInputChannels))
2392 return false;
2393
2394 if (!pIO->Read16(&nOutputChannels))
2395 return false;
2396
2397 if (nInputChannels != nOutputChannels)
2398 return false;
2399
2400 if (nInputChannels > size - headerSize || nInputChannels * 2*sizeof(icUInt32Number) > size - headerSize)
2401 return false;
2402
2403 if (!SetSize(nInputChannels))
2404 return false;
2405
2406 if (m_curve) {
2407 int i;
2408
2409 if (headerSize + m_nInputChannels*2*sizeof(icUInt32Number) > size)
2410 return false;
2411
2412 for (i=0; i<m_nInputChannels; i++) {
2413 if (!pIO->Read32(&m_position[i].offset)) {
2414 return false;
2415 }
2416 if (!pIO->Read32(&m_position[i].size)) {
2417 return false;
2418 }
2419 }
2420
2421 icCurveOffsetMap map;
2422 icCurveElemSignature curveSig;
2423 for (i=0; i<m_nInputChannels; i++) {
2424 if (!map[m_position[i].offset]) {
2425 icUInt32Number pos;
2426 if (!m_position[i].offset || !m_position[i].size) {
2427 return false;
2428 }
2429
2430 pos = startPos + m_position[i].offset;
2431 if (pIO->Seek(pos, icSeekSet)!=(icInt32Number)pos) {
2432 return false;
2433 }
2434
2435 if (!pIO->Read32(&curveSig)) {
2436 return false;
2437 }
2438 m_curve[i] = CIccCurveSetCurve::Create(curveSig);
2439
2440 if (!m_curve[i]) {
2441 return false;
2442 }
2443
2444 if (pIO->Seek(pos, icSeekSet)!=(icInt32Number)pos) {
2445 return false;
2446 }
2447
2448 if (!m_curve[i]->Read(m_position[i].size, pIO)) {
2449 return false;
2450 }
2451
2452 map[m_position[i].offset] = m_curve[i];
2453 }
2454 else {
2455 m_curve[i] = map[m_position[i].offset];
2456 }
2457 }
2458 }
2459
2460 return true;
2461}
2462
2463/**
2464 ******************************************************************************
2465 * Name: CIccMpeCurveSet::Write
2466 *
2467 * Purpose:
2468 *
2469 * Args:
2470 *
2471 * Return:
2472 ******************************************************************************/
2473bool CIccMpeCurveSet::Write(CIccIO *pIO)
2474{
2475 icElemTypeSignature sig = GetType();
2476
2477 if (!pIO)
2478 return false;
2479
2480 icUInt32Number elemStart = pIO->Tell();
2481
2482 if (!pIO->Write32(&sig))
2483 return false;
2484
2485 if (!pIO->Write32(&m_nReserved))
2486 return false;
2487
2488 if (!pIO->Write16(&m_nInputChannels))
2489 return false;
2490
2491 if (!pIO->Write16(&m_nInputChannels))
2492 return false;
2493
2494 if (m_curve && m_nInputChannels) {
2495 int i;
2496 icCurvePtrMap map;
2497 icUInt32Number start, end;
2498 icUInt32Number zeros[2] = { 0, 0};
2499 icPositionNumber position;
2500
2501 icUInt32Number startTable = pIO->Tell();
2502
2503 //First write empty position table
2504 for (i=0; i<m_nInputChannels; i++) {
2505 if (pIO->Write32(&zeros[0], 2)!=2)
2506 return false;
2507 }
2508
2509 //Now Write curves
2510 for (i=0; i<m_nInputChannels; i++) {
2511 if (m_curve[i]) {
2512 if (map.find(m_curve[i])==map.end()) {
2513 start = pIO->Tell();
2514 m_curve[i]->Write(pIO);
2515 end = pIO->Tell();
2516 pIO->Align32();
2517 position.offset = start - elemStart;
2518 position.size = end - start;
2519 map[m_curve[i]] = position;
2520 }
2521 m_position[i] = map[m_curve[i]];
2522 }
2523 }
2524 end = pIO->Tell();
2525
2526 //Back fill position table
2527 pIO->Seek(startTable, icSeekSet);
2528 for (i=0; i<m_nInputChannels; i++) {
2529 if (!pIO->Write32(&m_position[i].offset))
2530 return false;
2531 if (!pIO->Write32(&m_position[i].size))
2532 return false;
2533 }
2534
2535 pIO->Seek(end, icSeekSet);
2536 }
2537
2538 return true;
2539}
2540
2541/**
2542 ******************************************************************************
2543 * Name: CIccMpeCurveSet::Begin
2544 *
2545 * Purpose:
2546 *
2547 * Args:
2548 *
2549 * Return:
2550 ******************************************************************************/
2551bool CIccMpeCurveSet::Begin(icElemInterp nInterp, CIccTagMultiProcessElement *pMPE)
2552{
2553 if (!m_curve)
2554 return false;
2555
2556 int i;
2557 for (i=0; i<m_nInputChannels; i++) {
2558 if (!m_curve[i] || !m_curve[i]->Begin())
2559 return false;
2560 }
2561
2562 return true;
2563}
2564
2565/**
2566 ******************************************************************************
2567 * Name: CIccMpeCurveSet::Apply
2568 *
2569 * Purpose:
2570 *
2571 * Args:
2572 *
2573 * Return:
2574 ******************************************************************************/
2575void CIccMpeCurveSet::Apply(CIccApplyMpe *pApply, icFloatNumber *pDestPixel, const icFloatNumber *pSrcPixel) const
2576{
2577 int i;
2578 for (i=0; i<m_nInputChannels; i++) {
2579 *pDestPixel++ = m_curve[i]->Apply(*pSrcPixel++);
2580 }
2581}
2582
2583/**
2584 ******************************************************************************
2585 * Name: CIccMpeCurveSet::Validate
2586 *
2587 * Purpose:
2588 *
2589 * Args:
2590 *
2591 * Return:
2592 ******************************************************************************/
2593icValidateStatus CIccMpeCurveSet::Validate(std::string sigPath, std::string &sReport, const CIccTagMultiProcessElement* pMPE/*=NULL*/) const
2594{
2595 std::string mpeSigPath = sigPath + icGetSigPath(GetType());
2596 icValidateStatus rv = CIccMultiProcessElement::Validate(sigPath, sReport, pMPE);
2597
2598 bool empty=false;
2599 if (m_curve) {
2600 int i;
2601 for (i=0; !empty && i<m_nInputChannels; i++) {
2602 if (!m_curve[i]) {
2603 empty = true;
2604 }
2605 else {
2606 rv = icMaxStatus(rv, m_curve[i]->Validate(mpeSigPath, sReport, pMPE));
2607 }
2608 }
2609 }
2610 else
2611 empty = true;
2612
2613 if (empty) {
2614 CIccInfo Info;
2615 std::string sSigPathName = Info.GetSigPathName(mpeSigPath);
2616
2617 sReport += icMsgValidateCriticalError;
2618 sReport += sSigPathName;
2619 sReport += " - Has Empty Curve Element(s)!\r\n";
2620 return icValidateCriticalError;
2621 }
2622
2623 return rv;
2624}
2625
2626/**
2627 ******************************************************************************
2628 * Name: CIccMpeTintArray::CIccMpeTintArray
2629 *
2630 * Purpose:
2631 *
2632 * Args:
2633 *
2634 * Return:
2635 ******************************************************************************/
2636CIccMpeTintArray::CIccMpeTintArray(int nVectorSize/*=0*/)
2637{
2638 m_nReserved = 0;
2639 m_nInputChannels = 1;
2640 m_nOutputChannels = nVectorSize;
2641 m_Array = NULL__null;
2642}
2643
2644typedef std::map<icCurveSetCurvePtr, icCurveSetCurvePtr> icCurveMap;
2645
2646/**
2647 ******************************************************************************
2648 * Name: CIccMpeTintArray::CIccMpeTintArray
2649 *
2650 * Purpose:
2651 *
2652 * Args:
2653 *
2654 * Return:
2655 ******************************************************************************/
2656CIccMpeTintArray::CIccMpeTintArray(const CIccMpeTintArray &tintArray)
2657{
2658 m_nReserved = tintArray.m_nReserved;
2659
2660 m_nInputChannels = tintArray.m_nInputChannels;
2661 m_nOutputChannels = tintArray.m_nOutputChannels;
2662
2663 if (tintArray.m_Array)
2664 m_Array = (CIccTagNumArray*)tintArray.m_Array->NewCopy();
2665
2666}
2667
2668/**
2669 ******************************************************************************
2670 * Name: &CIccMpeTintArray::operator=
2671 *
2672 * Purpose:
2673 *
2674 * Args:
2675 *
2676 * Return:
2677 ******************************************************************************/
2678CIccMpeTintArray &CIccMpeTintArray::operator=(const CIccMpeTintArray &tintArray)
2679{
2680 m_nReserved = m_nReserved;
2681
2682 if (m_Array) {
2683 delete m_Array;
2684 }
2685
2686 m_nInputChannels = tintArray.m_nInputChannels;
2687 m_nOutputChannels = tintArray.m_nOutputChannels;
2688
2689 if (tintArray.m_Array)
2690 m_Array = (CIccTagNumArray*)tintArray.m_Array->NewCopy();
2691
2692 return *this;
2693}
2694
2695/**
2696 ******************************************************************************
2697 * Name: CIccMpeTintArray::~CIccMpeTintArray
2698 *
2699 * Purpose:
2700 *
2701 * Args:
2702 *
2703 * Return:
2704 ******************************************************************************/
2705CIccMpeTintArray::~CIccMpeTintArray()
2706{
2707 if (m_Array)
2708 delete m_Array;
2709}
2710
2711/**
2712 ******************************************************************************
2713 * Name: CIccMpeTintArray::SetVectorSize
2714 *
2715 * Purpose:
2716 *
2717 * Args:
2718 *
2719 * Return:
2720 ******************************************************************************/
2721void CIccMpeTintArray::SetVectorSize(int nVectorSize)
2722{
2723 m_nOutputChannels = nVectorSize;
2724}
2725
2726/**
2727 ******************************************************************************
2728 * Name: CIccMpeTintArray::SetCurve
2729 *
2730 * Purpose:
2731 *
2732 * Args:
2733 *
2734 * Return:
2735 ******************************************************************************/
2736void CIccMpeTintArray::SetArray(CIccTagNumArray *pArray)
2737{
2738 if (m_Array)
2739 delete m_Array;
2740
2741 m_Array = pArray;
2742}
2743
2744
2745/**
2746 ******************************************************************************
2747 * Name: CIccMpeTintArray::Describe
2748 *
2749 * Purpose:
2750 *
2751 * Args:
2752 *
2753 * Return:
2754 ******************************************************************************/
2755void CIccMpeTintArray::Describe(std::string &sDescription)
2756{
2757 if (m_Array) {
2758 icChar buf[81];
2759
2760 sprintf(buf, "BEGIN_TINT_ARRAY %d\r\n", m_nOutputChannels);
2761 sDescription += buf;
2762
2763 m_Array->Describe(sDescription);
2764
2765 sDescription += "END_TINT_ARRAY\r\n";
2766 }
2767}
2768
2769/**
2770 ******************************************************************************
2771 * Name: CIccMpeTintArray::Read
2772 *
2773 * Purpose:
2774 *
2775 * Args:
2776 *
2777 * Return:
2778 ******************************************************************************/
2779bool CIccMpeTintArray::Read(icUInt32Number size, CIccIO *pIO)
2780{
2781 if (m_Array)
2782 delete m_Array;
2783 m_Array = NULL__null;
2784
2785 icElemTypeSignature sig;
2786
2787 icUInt32Number startPos = pIO->Tell();
Value stored to 'startPos' during its initialization is never read
2788
2789 icUInt32Number headerSize = sizeof(icElemTypeSignature) +
2790 sizeof(icUInt32Number) +
2791 sizeof(icUInt16Number) +
2792 sizeof(icUInt16Number);
2793
2794 if (headerSize +sizeof(icTagTypeSignature) > size)
2795 return false;
2796
2797 if (!pIO) {
2798 return false;
2799 }
2800
2801 icUInt16Number nInputChannels, nOutputChannels;
2802
2803 if (!pIO->Read32(&sig))
2804 return false;
2805
2806 if (!pIO->Read32(&m_nReserved))
2807 return false;
2808
2809 if (!pIO->Read16(&nInputChannels))
2810 return false;
2811
2812 if (!pIO->Read16(&nOutputChannels))
2813 return false;
2814
2815 if (nInputChannels != 1 || !nOutputChannels)
2816 return false;
2817
2818 m_nInputChannels = nInputChannels;
2819 m_nOutputChannels = nOutputChannels;
2820
2821 icUInt32Number arrayPos = pIO->Tell();
2822
2823 icTagTypeSignature tagType;
2824 if (!pIO->Read32(&tagType))
2825 return false;
2826
2827 CIccTag *pTag = CIccTag::Create(tagType);
2828 if (!pTag)
2829 return false;
2830
2831 if (!pTag->IsNumArrayType()) {
2832 delete pTag;
2833 }
2834
2835 m_Array = (CIccTagNumArray*)pTag;
2836 pIO->Seek(arrayPos, icSeekSet);
2837 if (!m_Array->Read(size-headerSize, pIO)) {
2838 return false;
2839 }
2840
2841 icUInt32Number nVals = m_Array->GetNumValues();
2842 if (nVals/m_nOutputChannels <2 || (nVals%m_nOutputChannels) != 0) {
2843 return false;
2844 }
2845
2846 return true;
2847}
2848
2849/**
2850 ******************************************************************************
2851 * Name: CIccMpeTintArray::Write
2852 *
2853 * Purpose:
2854 *
2855 * Args:
2856 *
2857 * Return:
2858 ******************************************************************************/
2859bool CIccMpeTintArray::Write(CIccIO *pIO)
2860{
2861 if (!m_Array)
2862 return false;
2863
2864 icElemTypeSignature sig = GetType();
2865
2866 if (!pIO)
2867 return false;
2868
2869 if (!pIO->Write32(&sig))
2870 return false;
2871
2872 if (!pIO->Write32(&m_nReserved))
2873 return false;
2874
2875 if (!pIO->Write16(&m_nInputChannels))
2876 return false;
2877
2878 if (!pIO->Write16(&m_nOutputChannels))
2879 return false;
2880
2881 return m_Array->Write(pIO);
2882}
2883
2884/**
2885 ******************************************************************************
2886 * Name: CIccMpeTintArray::Begin
2887 *
2888 * Purpose:
2889 *
2890 * Args:
2891 *
2892 * Return:
2893 ******************************************************************************/
2894bool CIccMpeTintArray::Begin(icElemInterp nInterp, CIccTagMultiProcessElement *pMPE)
2895{
2896 if (!m_Array)
2897 return false;
2898
2899 icUInt32Number nVals = m_Array->GetNumValues();
2900
2901 if (nVals/m_nOutputChannels<2 || nVals % m_nOutputChannels != 0)
2902 return false;
2903
2904 return true;
2905}
2906
2907/**
2908 ******************************************************************************
2909 * Name: CIccMpeTintArray::Apply
2910 *
2911 * Purpose:
2912 *
2913 * Args:
2914 *
2915 * Return:
2916 ******************************************************************************/
2917void CIccMpeTintArray::Apply(CIccApplyMpe *pApply, icFloatNumber *pDestPixel, const icFloatNumber *pSrcPixel) const
2918{
2919 if (m_Array) {
2920 m_Array->Interpolate(pDestPixel, *pSrcPixel, m_nOutputChannels);
2921 }
2922 else
2923 memset(pDestPixel, 0, m_nOutputChannels*sizeof(icFloatNumber));
2924}
2925
2926/**
2927 ******************************************************************************
2928 * Name: CIccMpeTintArray::Validate
2929 *
2930 * Purpose:
2931 *
2932 * Args:
2933 *
2934 * Return:
2935 ******************************************************************************/
2936icValidateStatus CIccMpeTintArray::Validate(std::string sigPath, std::string &sReport, const CIccTagMultiProcessElement* pMPE/*=NULL*/) const
2937{
2938 std::string mpeSigPath = sigPath + icGetSigPath(GetType());
2939 icValidateStatus rv = CIccMultiProcessElement::Validate(sigPath, sReport, pMPE);
2940
2941 if (m_nInputChannels!=1) {
2942 CIccInfo Info;
2943 std::string sSigPathName = Info.GetSigPathName(mpeSigPath);
2944
2945 sReport += icMsgValidateCriticalError;
2946 sReport += sSigPathName;
2947 sReport += " - Bad number of input channels!\r\n";
2948 return icValidateCriticalError;
2949 }
2950
2951 if (!m_nOutputChannels) {
2952 CIccInfo Info;
2953 std::string sSigPathName = Info.GetSigPathName(mpeSigPath);
2954
2955 sReport += icMsgValidateCriticalError;
2956 sReport += sSigPathName;
2957 sReport += " - Bad number of output channels!\r\n";
2958 return icValidateCriticalError;
2959 }
2960
2961 if (!m_Array) {
2962 CIccInfo Info;
2963 std::string sSigPathName = Info.GetSigPathName(mpeSigPath);
2964
2965 sReport += icMsgValidateCriticalError;
2966 sReport += sSigPathName;
2967 sReport += " - Has no tint values(s)!\r\n";
2968 return icValidateCriticalError;
2969 }
2970 else {
2971 icUInt32Number nVals = m_Array->GetNumValues();
2972 bool bBad = false;
2973
2974 /*
2975 * NOTE: nVals is unsigned as is m_nOutputChannels
2976 * so the result will never be < 0
2977 */
2978 /*
2979 if (nVals/m_nOutputChannels<0) {
2980 CIccInfo Info;
2981 std::string sSigPathName = Info.GetSigPathName(mpeSigPath);
2982
2983 sReport += icMsgValidateCriticalError;
2984 sReport += sSigPathName;
2985 sReport += " - Needs two or more tint steps!\r\n";
2986 bBad = true;
2987 }
2988 */
2989 if ((nVals % m_nOutputChannels)!=0) {
2990 CIccInfo Info;
2991 std::string sSigPathName = Info.GetSigPathName(mpeSigPath);
2992
2993 sReport += icMsgValidateCriticalError;
2994 sReport += sSigPathName;
2995 sReport += " - Array size must be multiple of output channels!\r\n";
2996 bBad = true;
2997 }
2998
2999 if (bBad) {
3000 return icValidateCriticalError;
3001 }
3002 }
3003
3004 return rv;
3005}
3006
3007/**
3008 ******************************************************************************
3009 * Name: CIccMpeMatrix::CIccMpeMatrix
3010 *
3011 * Purpose:
3012 *
3013 * Args:
3014 *
3015 * Return:
3016 ******************************************************************************/
3017CIccMpeMatrix::CIccMpeMatrix()
3018{
3019 m_nReserved = 0;
3020 m_nInputChannels = m_nOutputChannels = 0;
3021 m_size = 0;
3022 m_pMatrix = NULL__null;
3023 m_pConstants = NULL__null;
3024}
3025
3026
3027/**
3028 ******************************************************************************
3029 * Name: CIccMpeMatrix::CIccMpeMatrix
3030 *
3031 * Purpose:
3032 *
3033 * Args:
3034 *
3035 * Return:
3036 ******************************************************************************/
3037CIccMpeMatrix::CIccMpeMatrix(const CIccMpeMatrix &matrix)
3038{
3039 m_nReserved = matrix.m_nReserved;
3040
3041 m_nInputChannels = matrix.m_nInputChannels;
3042 m_nOutputChannels = matrix.m_nOutputChannels;
3043
3044 m_size = matrix.m_size;
3045 if(matrix.m_pMatrix) {
3046 int num = m_size * sizeof(icFloatNumber);
3047 m_pMatrix = (icFloatNumber*)malloc(num);
3048 memcpy(m_pMatrix, matrix.m_pMatrix, num);
3049 }
3050 else
3051 m_pMatrix = NULL__null;
3052
3053 if (matrix.m_pConstants) {
3054 int num = m_nOutputChannels*sizeof(icFloatNumber);
3055 m_pConstants = (icFloatNumber*)malloc(num);
3056 memcpy(m_pConstants, matrix.m_pConstants, num);
3057 }
3058 else
3059 m_pConstants = NULL__null;
3060
3061 m_bApplyConstants = true;
3062}
3063
3064/**
3065 ******************************************************************************
3066 * Name: &CIccMpeMatrix::operator=
3067 *
3068 * Purpose:
3069 *
3070 * Args:
3071 *
3072 * Return:
3073 ******************************************************************************/
3074CIccMpeMatrix &CIccMpeMatrix::operator=(const CIccMpeMatrix &matrix)
3075{
3076 m_nReserved = matrix.m_nReserved;
3077
3078 m_nInputChannels = matrix.m_nInputChannels;
3079 m_nOutputChannels = matrix.m_nOutputChannels;
3080
3081 if (m_pMatrix)
3082 free(m_pMatrix);
3083
3084 m_size = matrix.m_size;
3085 if (matrix.m_pMatrix) {
3086 int num = m_size * sizeof(icFloatNumber);
3087 m_pMatrix = (icFloatNumber*)malloc(num);
3088 memcpy(m_pMatrix, matrix.m_pMatrix, num);
3089 }
3090 else
3091 m_pMatrix = NULL__null;
3092
3093 if (m_pConstants)
3094 free(m_pConstants);
3095
3096 if (matrix.m_pConstants) {
3097 int num = m_nOutputChannels*sizeof(icFloatNumber);
3098 m_pConstants = (icFloatNumber*)malloc(num);
3099 memcpy(m_pConstants, matrix.m_pConstants, num);
3100 }
3101 else
3102 m_pConstants = NULL__null;
3103
3104 m_bApplyConstants = matrix.m_bApplyConstants;
3105
3106 return *this;
3107}
3108
3109/**
3110 ******************************************************************************
3111 * Name: CIccMpeMatrix::~CIccMpeMatrix
3112 *
3113 * Purpose:
3114 *
3115 * Args:
3116 *
3117 * Return:
3118 ******************************************************************************/
3119CIccMpeMatrix::~CIccMpeMatrix()
3120{
3121 if (m_pMatrix)
3122 free(m_pMatrix);
3123
3124 if (m_pConstants)
3125 free(m_pConstants);
3126}
3127
3128/**
3129 ******************************************************************************
3130 * Name: CIccMpeMatrix::SetSize
3131 *
3132 * Purpose:
3133 *
3134 * Args:
3135 *
3136 * Return:
3137 ******************************************************************************/
3138bool CIccMpeMatrix::SetSize(icUInt16Number nInputChannels, icUInt16Number nOutputChannels, bool bUseConstants)
3139{
3140 if (m_pMatrix) {
3141 free(m_pMatrix);
3142 m_pMatrix = NULL__null;
3143 }
3144 if (m_pConstants) {
3145 free(m_pConstants);
3146 m_pConstants = NULL__null;
3147 }
3148
3149 m_size = (icUInt32Number)nInputChannels * nOutputChannels;
3150
3151 if (m_size) {
3152 m_pMatrix = (icFloatNumber*)calloc(m_size, sizeof(icFloatNumber));
3153 if (!m_pMatrix)
3154 return false;
3155 }
3156
3157 if (bUseConstants) {
3158 m_pConstants = (icFloatNumber*)calloc(nOutputChannels, sizeof(icFloatNumber));
3159
3160 if (!m_pConstants)
3161 return false;
3162 }
3163
3164 m_nInputChannels = nInputChannels;
3165 m_nOutputChannels = nOutputChannels;
3166
3167 return true;
3168}
3169
3170/**
3171 ******************************************************************************
3172 * Name: CIccMpeMatrix::Describe
3173 *
3174 * Purpose:
3175 *
3176 * Args:
3177 *
3178 * Return:
3179 ******************************************************************************/
3180void CIccMpeMatrix::Describe(std::string &sDescription)
3181{
3182 icChar buf[81];
3183 int i, j;
3184 icFloatNumber *data = m_pMatrix;
3185
3186 sprintf(buf, "BEGIN_ELEM_MATRIX %d %d\r\n", m_nInputChannels, m_nOutputChannels);
3187 sDescription += buf;
3188
3189 for (j=0; j<m_nOutputChannels; j++) {
3190 if (data) {
3191 for (i=0; i<m_nInputChannels; i++) {
3192 if (i)
3193 sDescription += " ";
3194 sprintf(buf, "%12.8lf", data[i]);
3195 sDescription += buf;
3196 }
3197 if (m_pConstants) {
3198 sprintf(buf, " + %12.8lf\r\n", m_pConstants[j]);
3199 sDescription += buf;
3200 }
3201 data += i;
3202 }
3203 else {
3204 sprintf(buf, "ZeroRow + %12.8lf\r\n", m_pConstants[j]);
3205 sDescription += buf;
3206 }
3207 }
3208 sDescription += "END_ELEM_MATRIX\r\n";
3209}
3210
3211/**
3212 ******************************************************************************
3213 * Name: CIccMpeMatrix::Read
3214 *
3215 * Purpose:
3216 *
3217 * Args:
3218 *
3219 * Return:
3220 ******************************************************************************/
3221bool CIccMpeMatrix::Read(icUInt32Number size, CIccIO *pIO)
3222{
3223 icElemTypeSignature sig;
3224
3225 icUInt32Number headerSize = sizeof(icElemTypeSignature) +
3226 sizeof(icUInt32Number) +
3227 sizeof(icUInt16Number) +
3228 sizeof(icUInt16Number);
3229
3230 if (headerSize > size)
3231 return false;
3232
3233 icUInt32Number dataSize = size - headerSize;
3234
3235 if (!pIO) {
3236 return false;
3237 }
3238
3239 icUInt16Number nInputChannels, nOutputChannels;
3240
3241 if (!pIO->Read32(&sig))
3242 return false;
3243
3244 if (!pIO->Read32(&m_nReserved))
3245 return false;
3246
3247 if (!pIO->Read16(&nInputChannels))
3248 return false;
3249
3250 if (!pIO->Read16(&nOutputChannels))
3251 return false;
3252
3253 if (dataSize >= (icUInt32Number)nInputChannels * nOutputChannels * sizeof(icFloatNumber) &&
3254 dataSize < ((icUInt32Number)nInputChannels+1) * nOutputChannels * sizeof(icFloatNumber)) {
3255 //Matrix with no constants
3256 if (!SetSize(nInputChannels, nOutputChannels, false))
3257 return false;
3258
3259 if (!m_pMatrix)
3260 return false;
3261
3262 //Read Matrix data
3263 if (pIO->ReadFloat32Float(m_pMatrix, m_size) != (icInt32Number)m_size)
3264 return false;
3265 }
3266 else if (dataSize < (icUInt32Number)nInputChannels * nOutputChannels *sizeof(icFloatNumber) &&
3267 dataSize >= (icUInt32Number)nOutputChannels * sizeof(icFloatNumber)) {
3268 //Constants with no matrix
3269 if (!SetSize(0, nOutputChannels))
3270 return false;
3271
3272 m_nInputChannels = nInputChannels;
3273
3274 //Read Constant data
3275 if (pIO->ReadFloat32Float(m_pConstants, m_nOutputChannels)!=m_nOutputChannels)
3276 return false;
3277 }
3278 else {
3279 if ((icUInt32Number)nInputChannels*nOutputChannels > dataSize ||
3280 ((icUInt32Number)nInputChannels*nOutputChannels + nOutputChannels) > dataSize ||
3281 ((icUInt32Number)nInputChannels*nOutputChannels + nOutputChannels) * sizeof(icFloat32Number) > dataSize)
3282 return false;
3283
3284 //Matrix with constants
3285 if (!SetSize(nInputChannels, nOutputChannels))
3286 return false;
3287
3288 if (!m_pMatrix)
3289 return false;
3290
3291 if ((m_size + nOutputChannels)*sizeof(icFloat32Number) > dataSize)
3292 return false;
3293
3294 //Read Matrix data
3295 if (pIO->ReadFloat32Float(m_pMatrix, m_size)!=(icInt32Number)m_size)
3296 return false;
3297
3298 //Read Constant data
3299 if (pIO->ReadFloat32Float(m_pConstants, m_nOutputChannels)!=m_nOutputChannels)
3300 return false;
3301 }
3302
3303 return true;
3304}
3305
3306/**
3307 ******************************************************************************
3308 * Name: CIccMpeMatrix::Write
3309 *
3310 * Purpose:
3311 *
3312 * Args:
3313 *
3314 * Return:
3315 ******************************************************************************/
3316bool CIccMpeMatrix::Write(CIccIO *pIO)
3317{
3318 icElemTypeSignature sig = GetType();
3319
3320 if (!pIO)
3321 return false;
3322
3323 if (!pIO->Write32(&sig))
3324 return false;
3325
3326 if (!pIO->Write32(&m_nReserved))
3327 return false;
3328
3329 if (!pIO->Write16(&m_nInputChannels))
3330 return false;
3331
3332 if (!pIO->Write16(&m_nOutputChannels))
3333 return false;
3334
3335 if (m_pMatrix) {
3336 if (pIO->WriteFloat32Float(m_pMatrix, m_size)!=(icInt32Number)m_size)
3337 return false;
3338 }
3339
3340 //Write Constant data
3341 if (m_pConstants) {
3342 if (pIO->WriteFloat32Float(m_pConstants, m_nOutputChannels)!=m_nOutputChannels)
3343 return false;
3344 }
3345 else {
3346 //Write zero constants because spec says it they have to be there
3347 icFloat32Number zero = 0;
3348 int i;
3349 for (i = 0; i < m_nOutputChannels; i++) {
3350 if (!pIO->WriteFloat32Float(&zero, 1))
3351 return false;
3352 }
3353 }
3354
3355 return true;
3356}
3357
3358/**
3359 ******************************************************************************
3360 * Name: CIccMpeMatrix::Begin
3361 *
3362 * Purpose:
3363 *
3364 * Args:
3365 *
3366 * Return:
3367 ******************************************************************************/
3368bool CIccMpeMatrix::Begin(icElemInterp nInterp, CIccTagMultiProcessElement *pMPE)
3369{
3370 m_bApplyConstants = false;
3371 if (m_pConstants) {
3372 int i;
3373 for (i = 0; i < m_nOutputChannels; i++) {
3374 if (icNotZero(m_pConstants[i])((m_pConstants[i])>1.0e-8 || (m_pConstants[i])<-1.0e-8)) {
3375 m_bApplyConstants = true;
3376 break;
3377 }
3378 }
3379 }
3380
3381 if (m_nInputChannels==3 && m_nOutputChannels==3)
3382 m_type = ic3x3Matrix;
3383 else if (m_nInputChannels==3 && m_nOutputChannels==4)
3384 m_type = ic3x4Matrix;
3385 else if (m_nInputChannels==4 && m_nOutputChannels==3)
3386 m_type = ic4x3Matrix;
3387 else if (m_nInputChannels==4 && m_nOutputChannels==4)
3388 m_type = ic4x4Matrix;
3389 else
3390 m_type = icOtherMatrix;
3391
3392 return true;
3393}
3394
3395/**
3396 ******************************************************************************
3397 * Name: CIccMpeMatrix::Apply
3398 *
3399 * Purpose:
3400 *
3401 * Args:
3402 *
3403 * Return:
3404 ******************************************************************************/
3405void CIccMpeMatrix::Apply(CIccApplyMpe *pApply, icFloatNumber *dstPixel, const icFloatNumber *srcPixel) const
3406{
3407 icFloatNumber *data = m_pMatrix;
3408 if (data) {
3409 if (m_bApplyConstants) {
3410 switch (m_type) {
3411 case ic3x3Matrix:
3412 *dstPixel++ = data[ 0]*srcPixel[0] + data[ 1]*srcPixel[1] + data[ 2]*srcPixel[2] + m_pConstants[0];
3413 *dstPixel++ = data[ 3]*srcPixel[0] + data[ 4]*srcPixel[1] + data[ 5]*srcPixel[2] + m_pConstants[1];
3414 *dstPixel = data[ 6]*srcPixel[0] + data[ 7]*srcPixel[1] + data[ 8]*srcPixel[2] + m_pConstants[2];
3415 break;
3416
3417 case ic3x4Matrix:
3418 *dstPixel++ = data[ 0]*srcPixel[0] + data[ 1]*srcPixel[1] + data[ 2]*srcPixel[2] + m_pConstants[0];
3419 *dstPixel++ = data[ 3]*srcPixel[0] + data[ 4]*srcPixel[1] + data[ 5]*srcPixel[2] + m_pConstants[1];
3420 *dstPixel++ = data[ 6]*srcPixel[0] + data[ 7]*srcPixel[1] + data[ 8]*srcPixel[2] + m_pConstants[2];
3421 *dstPixel = data[ 9]*srcPixel[0] + data[10]*srcPixel[1] + data[11]*srcPixel[2] + m_pConstants[3];
3422 break;
3423
3424 case ic4x3Matrix:
3425 *dstPixel++ = data[ 0]*srcPixel[0] + data[ 1]*srcPixel[1] + data[ 2]*srcPixel[2] + data[ 3]*srcPixel[3] + m_pConstants[0];
3426 *dstPixel++ = data[ 4]*srcPixel[0] + data[ 5]*srcPixel[1] + data[ 6]*srcPixel[2] + data[ 7]*srcPixel[3] + m_pConstants[1];
3427 *dstPixel = data[ 8]*srcPixel[0] + data[ 9]*srcPixel[1] + data[10]*srcPixel[2] + data[11]*srcPixel[3] + m_pConstants[2];
3428 break;
3429
3430 case ic4x4Matrix:
3431 *dstPixel++ = data[ 0]*srcPixel[0] + data[ 1]*srcPixel[1] + data[ 2]*srcPixel[2] + data[ 3]*srcPixel[3] + m_pConstants[0];
3432 *dstPixel++ = data[ 4]*srcPixel[0] + data[ 5]*srcPixel[1] + data[ 6]*srcPixel[2] + data[ 7]*srcPixel[3] + m_pConstants[1];
3433 *dstPixel++ = data[ 8]*srcPixel[0] + data[ 9]*srcPixel[1] + data[10]*srcPixel[2] + data[11]*srcPixel[3] + m_pConstants[2];
3434 *dstPixel = data[12]*srcPixel[0] + data[13]*srcPixel[1] + data[14]*srcPixel[2] + data[15]*srcPixel[3] + m_pConstants[3];
3435 break;
3436
3437 case icOtherMatrix:
3438 default:
3439 {
3440 int i, j;
3441
3442 for (j=0; j<m_nOutputChannels; j++) {
3443 *dstPixel = m_pConstants[j];
3444
3445 for (i=0; i<m_nInputChannels; i++) {
3446 *dstPixel += data[i]*srcPixel[i];
3447 }
3448
3449 data += i;
3450 dstPixel++;
3451 }
3452 }
3453 break;
3454 }
3455 }
3456 else {
3457 switch (m_type) {
3458 case ic3x3Matrix:
3459 *dstPixel++ = data[0] * srcPixel[0] + data[1] * srcPixel[1] + data[2] * srcPixel[2];
3460 *dstPixel++ = data[3] * srcPixel[0] + data[4] * srcPixel[1] + data[5] * srcPixel[2];
3461 *dstPixel = data[6] * srcPixel[0] + data[7] * srcPixel[1] + data[8] * srcPixel[2];
3462 break;
3463
3464 case ic3x4Matrix:
3465 *dstPixel++ = data[0] * srcPixel[0] + data[1] * srcPixel[1] + data[2] * srcPixel[2];
3466 *dstPixel++ = data[3] * srcPixel[0] + data[4] * srcPixel[1] + data[5] * srcPixel[2];
3467 *dstPixel++ = data[6] * srcPixel[0] + data[7] * srcPixel[1] + data[8] * srcPixel[2];
3468 *dstPixel = data[9] * srcPixel[0] + data[10] * srcPixel[1] + data[11] * srcPixel[2];
3469 break;
3470
3471 case ic4x3Matrix:
3472 *dstPixel++ = data[0] * srcPixel[0] + data[1] * srcPixel[1] + data[2] * srcPixel[2] + data[3] * srcPixel[3];
3473 *dstPixel++ = data[4] * srcPixel[0] + data[5] * srcPixel[1] + data[6] * srcPixel[2] + data[7] * srcPixel[3];
3474 *dstPixel = data[8] * srcPixel[0] + data[9] * srcPixel[1] + data[10] * srcPixel[2] + data[11] * srcPixel[3];
3475 break;
3476
3477 case ic4x4Matrix:
3478 *dstPixel++ = data[0] * srcPixel[0] + data[1] * srcPixel[1] + data[2] * srcPixel[2] + data[3] * srcPixel[3];
3479 *dstPixel++ = data[4] * srcPixel[0] + data[5] * srcPixel[1] + data[6] * srcPixel[2] + data[7] * srcPixel[3];
3480 *dstPixel++ = data[8] * srcPixel[0] + data[9] * srcPixel[1] + data[10] * srcPixel[2] + data[11] * srcPixel[3];
3481 *dstPixel = data[12] * srcPixel[0] + data[13] * srcPixel[1] + data[14] * srcPixel[2] + data[15] * srcPixel[3];
3482 break;
3483
3484 case icOtherMatrix:
3485 default:
3486 {
3487 int i, j;
3488
3489 for (j = 0; j < m_nOutputChannels; j++) {
3490 *dstPixel = 0.0f;
3491
3492 for (i = 0; i < m_nInputChannels; i++) {
3493 *dstPixel += data[i] * srcPixel[i];
3494 }
3495
3496 data += i;
3497 dstPixel++;
3498 }
3499 }
3500 break;
3501 }
3502 }
3503 }
3504 else if (m_bApplyConstants) {
3505 memcpy(dstPixel, m_pConstants, m_nOutputChannels*sizeof(icFloatNumber));
3506 }
3507 else {
3508 memset(dstPixel, 0, m_nOutputChannels * sizeof(icFloatNumber));
3509 }
3510}
3511
3512/**
3513 ******************************************************************************
3514 * Name: CIccMpeMatrix::Validate
3515 *
3516 * Purpose:
3517 *
3518 * Args:
3519 *
3520 * Return:
3521 ******************************************************************************/
3522icValidateStatus CIccMpeMatrix::Validate(std::string sigPath, std::string &sReport, const CIccTagMultiProcessElement* pMPE/*=NULL*/) const
3523{
3524 std::string mpeSigPath = sigPath + icGetSigPath(GetType());
3525 icValidateStatus rv = CIccMultiProcessElement::Validate(sigPath, sReport, pMPE);
3526
3527 if (!m_pConstants) {
3528 CIccInfo Info;
3529 std::string sSigPathName = Info.GetSigPathName(mpeSigPath);
3530
3531 sReport += icMsgValidateCriticalError;
3532 sReport += sSigPathName;
3533 sReport += " - Has Empty Matrix Constant data!\r\n";
3534 return icValidateCriticalError;
3535 }
3536
3537 return rv;
3538}
3539
3540
3541static icFloatNumber NoClip(icFloatNumber v)
3542{
3543 return v;
3544}
3545
3546/**
3547 ******************************************************************************
3548 * Name: CIccMpeCLUT::CIccMpeCLUT
3549 *
3550 * Purpose:
3551 *
3552 * Args:
3553 *
3554 * Return:
3555 ******************************************************************************/
3556CIccMpeCLUT::CIccMpeCLUT()
3557{
3558 m_pCLUT = NULL__null;
3559 m_nInputChannels = 0;
3560 m_nOutputChannels = 0;
3561
3562 m_nReserved = 0;
3563}
3564
3565/**
3566 ******************************************************************************
3567 * Name: CIccMpeCLUT::CIccMpeCLUT
3568 *
3569 * Purpose:
3570 *
3571 * Args:
3572 *
3573 * Return:
3574 ******************************************************************************/
3575CIccMpeCLUT::CIccMpeCLUT(const CIccMpeCLUT &clut)
3576{
3577 if (clut.m_pCLUT)
3578 m_pCLUT = new CIccCLUT(*clut.m_pCLUT);
3579 else
3580 m_pCLUT = NULL__null;
3581
3582 m_nReserved = clut.m_nReserved;
3583 m_nInputChannels = clut.m_nInputChannels;
3584 m_nOutputChannels = clut.m_nOutputChannels;
3585}
3586
3587/**
3588 ******************************************************************************
3589 * Name: &CIccMpeCLUT::operator=
3590 *
3591 * Purpose:
3592 *
3593 * Args:
3594 *
3595 * Return:
3596 ******************************************************************************/
3597CIccMpeCLUT &CIccMpeCLUT::operator=(const CIccMpeCLUT &clut)
3598{
3599 if (m_pCLUT)
3600 delete m_pCLUT;
3601
3602 if (clut.m_pCLUT)
3603 m_pCLUT = new CIccCLUT(*clut.m_pCLUT);
3604 else
3605 m_pCLUT = NULL__null;
3606
3607 m_nReserved = clut.m_nReserved;
3608 m_nInputChannels = clut.m_nInputChannels;
3609 m_nOutputChannels = clut.m_nOutputChannels;
3610
3611 return *this;
3612}
3613
3614/**
3615 ******************************************************************************
3616 * Name: CIccMpeCLUT::~CIccMpeCLUT
3617 *
3618 * Purpose:
3619 *
3620 * Args:
3621 *
3622 * Return:
3623 ******************************************************************************/
3624CIccMpeCLUT::~CIccMpeCLUT()
3625{
3626 if (m_pCLUT)
3627 delete m_pCLUT;
3628}
3629
3630/**
3631 ******************************************************************************
3632 * Name: CIccMpeCLUT::SetCLUT
3633 *
3634 * Purpose:
3635 *
3636 * Args:
3637 *
3638 * Return:
3639 ******************************************************************************/
3640void CIccMpeCLUT::SetCLUT(CIccCLUT *pCLUT)
3641{
3642 if (m_pCLUT)
3643 delete m_pCLUT;
3644
3645 m_pCLUT = pCLUT;
3646 if (pCLUT) {
3647 pCLUT->SetClipFunc(NoClip);
3648 m_nInputChannels = pCLUT->GetInputDim();
3649 m_nOutputChannels = pCLUT->GetOutputChannels();
3650 }
3651}
3652
3653/**
3654 ******************************************************************************
3655 * Name: CIccMpeCLUT::Describe
3656 *
3657 * Purpose:
3658 *
3659 * Args:
3660 *
3661 * Return:
3662 ******************************************************************************/
3663void CIccMpeCLUT::Describe(std::string &sDescription)
3664{
3665 if (m_pCLUT) {
3666 m_pCLUT->DumpLut(sDescription, "ELEM_CLUT", icSigUnknownData((icColorSpaceSignature) 0x3f3f3f3f), icSigUnknownData((icColorSpaceSignature) 0x3f3f3f3f));
3667 }
3668}
3669
3670/**
3671 ******************************************************************************
3672 * Name: CIccMpeCLUT::Read
3673 *
3674 * Purpose:
3675 *
3676 * Args:
3677 *
3678 * Return:
3679 ******************************************************************************/
3680bool CIccMpeCLUT::Read(icUInt32Number size, CIccIO *pIO)
3681{
3682 icTagTypeSignature sig;
3683
3684 icUInt32Number headerSize = sizeof(icTagTypeSignature) +
3685 sizeof(icUInt32Number) +
3686 sizeof(icUInt16Number) +
3687 sizeof(icUInt16Number) +
3688 16 * sizeof(icUInt8Number);
3689
3690 if (headerSize > size)
3691 return false;
3692
3693 icUInt32Number dataSize = size - headerSize;
3694
3695 if (!pIO) {
3696 return false;
3697 }
3698
3699 if (!pIO->Read32(&sig))
3700 return false;
3701
3702 if (!pIO->Read32(&m_nReserved))
3703 return false;
3704
3705 if (!pIO->Read16(&m_nInputChannels))
3706 return false;
3707
3708 if (!pIO->Read16(&m_nOutputChannels))
3709 return false;
3710
3711 icUInt8Number gridPoints[16];
3712
3713 if (pIO->Read8(gridPoints, 16)!=16) {
3714 return false;
3715 }
3716
3717 icUInt32Number nPoints = (icUInt32Number)m_nInputChannels * m_nOutputChannels;
3718
3719 if (m_nInputChannels > 16 || nPoints > dataSize || nPoints * sizeof (icFloat32Number) > dataSize)
3720 return false;
3721
3722 m_pCLUT = new CIccCLUT((icUInt8Number)m_nInputChannels, (icUInt16Number)m_nOutputChannels, 4);
3723
3724 if (!m_pCLUT)
3725 return false;
3726
3727 m_pCLUT->SetClipFunc(NoClip);
3728
3729 m_pCLUT->Init(gridPoints);
3730
3731 icFloatNumber *pData = m_pCLUT->GetData(0);
3732
3733 if (!pData)
3734 return false;
3735
3736 nPoints = m_pCLUT->NumPoints()*m_nOutputChannels;
3737
3738 if (pIO->ReadFloat32Float(pData,nPoints)!= nPoints)
3739 return false;
3740
3741 return true;
3742}
3743
3744/**
3745 ******************************************************************************
3746 * Name: CIccMpeCLUT::Write
3747 *
3748 * Purpose:
3749 *
3750 * Args:
3751 *
3752 * Return:
3753 ******************************************************************************/
3754bool CIccMpeCLUT::Write(CIccIO *pIO)
3755{
3756 icElemTypeSignature sig = GetType();
3757
3758 if (!pIO)
3759 return false;
3760
3761 if (!pIO->Write32(&sig))
3762 return false;
3763
3764 if (!pIO->Write32(&m_nReserved))
3765 return false;
3766
3767 if (!pIO->Write16(&m_nInputChannels))
3768 return false;
3769
3770 if (!pIO->Write16(&m_nOutputChannels))
3771 return false;
3772
3773 if (m_pCLUT) {
3774 icUInt8Number gridPoints[16];
3775 int i;
3776
3777 for (i=0; i<16; i++)
3778 gridPoints[i] = m_pCLUT->GridPoint(i);
3779
3780 if (pIO->Write8(gridPoints, 16)!=16)
3781 return false;
3782
3783 icFloatNumber *pData = m_pCLUT->GetData(0);
3784 icInt32Number nPoints = m_pCLUT->NumPoints()*m_nOutputChannels;
3785
3786 if (pIO->WriteFloat32Float(pData, nPoints) != nPoints)
3787 return false;
3788 }
3789
3790 return true;
3791}
3792
3793/**
3794 ******************************************************************************
3795 * Name: CIccMpeCLUT::Begin
3796 *
3797 * Purpose:
3798 *
3799 * Args:
3800 *
3801 * Return:
3802 ******************************************************************************/
3803bool CIccMpeCLUT::Begin(icElemInterp nInterp, CIccTagMultiProcessElement *pMPE)
3804{
3805 if (!m_pCLUT)
3806 return false;
3807
3808 m_pCLUT->Begin();
3809
3810 switch (m_nInputChannels) {
3811 case 1:
3812 m_interpType = ic1dInterp;
3813 break;
3814 case 2:
3815 m_interpType = ic2dInterp;
3816 break;
3817 case 3:
3818 if (nInterp==icElemInterpTetra)
3819 m_interpType = ic3dInterpTetra;
3820 else
3821 m_interpType = ic3dInterp;
3822 break;
3823 case 4:
3824 m_interpType = ic4dInterp;
3825 break;
3826 case 5:
3827 m_interpType = ic5dInterp;
3828 break;
3829 case 6:
3830 m_interpType = ic6dInterp;
3831 break;
3832 default:
3833 m_interpType = icNdInterp;
3834 break;
3835 }
3836 return true;
3837}
3838
3839/**
3840 ******************************************************************************
3841 * Name: CIccMpeCLUT::Apply
3842 *
3843 * Purpose:
3844 *
3845 * Args:
3846 *
3847 * Return:
3848 ******************************************************************************/
3849void CIccMpeCLUT::Apply(CIccApplyMpe *pApply, icFloatNumber *dstPixel, const icFloatNumber *srcPixel) const
3850{
3851 const CIccCLUT *pCLUT = m_pCLUT;
3852
3853 switch(m_interpType) {
3854 case ic1dInterp:
3855 pCLUT->Interp1d(dstPixel, srcPixel);
3856 break;
3857 case ic2dInterp:
3858 pCLUT->Interp2d(dstPixel, srcPixel);
3859 break;
3860 case ic3dInterpTetra:
3861 pCLUT->Interp3dTetra(dstPixel, srcPixel);
3862 break;
3863 case ic3dInterp:
3864 pCLUT->Interp3d(dstPixel, srcPixel);
3865 break;
3866 case ic4dInterp:
3867 pCLUT->Interp4d(dstPixel, srcPixel);
3868 break;
3869 case ic5dInterp:
3870 pCLUT->Interp5d(dstPixel, srcPixel);
3871 break;
3872 case ic6dInterp:
3873 pCLUT->Interp6d(dstPixel, srcPixel);
3874 break;
3875 case icNdInterp:
3876 pCLUT->InterpND(dstPixel, srcPixel);
3877 break;
3878 }
3879}
3880
3881/**
3882 ******************************************************************************
3883 * Name: CIccMpeCLUT::Validate
3884 *
3885 * Purpose:
3886 *
3887 * Args:
3888 *
3889 * Return:
3890 ******************************************************************************/
3891icValidateStatus CIccMpeCLUT::Validate(std::string sigPath, std::string &sReport, const CIccTagMultiProcessElement* pMPE/*=NULL*/) const
3892{
3893 std::string mpeSigPath = sigPath + icGetSigPath(GetType());
3894 icValidateStatus rv = CIccMultiProcessElement::Validate(sigPath, sReport, pMPE);
3895
3896 if (!m_pCLUT) {
3897 CIccInfo Info;
3898 std::string sSigPathName = Info.GetSigPathName(mpeSigPath);
3899
3900 sReport += icMsgValidateCriticalError;
3901 sReport += sSigPathName;
3902 sReport += " - Has No CLUT!\r\n";
3903 return icValidateCriticalError;
3904 }
3905
3906 return rv;
3907}
3908
3909/**
3910******************************************************************************
3911* Name: CIccMpeExtCLUT::CIccMpeExtCLUT
3912*
3913* Purpose:
3914*
3915* Args:
3916*
3917* Return:
3918******************************************************************************/
3919CIccMpeExtCLUT::CIccMpeExtCLUT()
3920{
3921 m_pCLUT = NULL__null;
3922 m_nInputChannels = 0;
3923 m_nOutputChannels = 0;
3924
3925 m_nReserved = 0;
3926 m_nReserved2 = 0;
3927
3928 m_storageType = icValueTypeFloat32;
3929}
3930
3931/**
3932******************************************************************************
3933* Name: CIccMpeExtCLUT::CIccMpeExtCLUT
3934*
3935* Purpose:
3936*
3937* Args:
3938*
3939* Return:
3940******************************************************************************/
3941CIccMpeExtCLUT::CIccMpeExtCLUT(const CIccMpeExtCLUT &clut) : CIccMpeCLUT(clut)
3942{
3943 m_nReserved2 = clut.m_nReserved2;
3944 m_storageType = clut.m_storageType;
3945}
3946
3947/**
3948******************************************************************************
3949* Name: &CIccMpeExtCLUT::operator=
3950*
3951* Purpose:
3952*
3953* Args:
3954*
3955* Return:
3956******************************************************************************/
3957CIccMpeExtCLUT &CIccMpeExtCLUT::operator=(const CIccMpeExtCLUT &clut)
3958{
3959 CIccMpeCLUT::operator=(clut);
3960
3961 m_nReserved2 = clut.m_nReserved2;
3962 m_storageType = clut.m_storageType;
3963
3964 return *this;
3965}
3966
3967/**
3968******************************************************************************
3969* Name: CIccMpeExtCLUT::Describe
3970*
3971* Purpose:
3972*
3973* Args:
3974*
3975* Return:
3976******************************************************************************/
3977void CIccMpeExtCLUT::Describe(std::string &sDescription)
3978{
3979 if (m_pCLUT) {
3980 char desc[256];
3981 sprintf(desc, "EXT_ELEM_CLUT(%d)", m_storageType);
3982
3983 m_pCLUT->DumpLut(sDescription, desc, icSigUnknownData((icColorSpaceSignature) 0x3f3f3f3f), icSigUnknownData((icColorSpaceSignature) 0x3f3f3f3f));
3984 }
3985}
3986
3987/**
3988******************************************************************************
3989* Name: CIccMpeExtCLUT::SetStorageType
3990*
3991* Purpose:
3992* Sets storage type of the data stored in the CLUT
3993*
3994* Args:
3995* nStorageType is type of data to use
3996*
3997* Return:
3998* true if valid storage type, false otherwise
3999******************************************************************************/
4000bool CIccMpeExtCLUT::SetStorageType(icUInt16Number nStorateType)
4001{
4002 m_storageType = nStorateType;
4003
4004 switch (nStorateType) {
4005 case icValueTypeUInt8:
4006 case icValueTypeUInt16:
4007 case icValueTypeFloat16:
4008 case icValueTypeFloat32:
4009 return true;
4010 }
4011 return false;
4012}
4013
4014
4015/**
4016******************************************************************************
4017* Name: CIccMpeExtCLUT::Read
4018*
4019* Purpose:
4020*
4021* Args:
4022*
4023* Return:
4024******************************************************************************/
4025bool CIccMpeExtCLUT::Read(icUInt32Number size, CIccIO *pIO)
4026{
4027 icTagTypeSignature sig;
4028
4029 icUInt32Number headerSize = sizeof(icTagTypeSignature) +
4030 sizeof(icUInt32Number) +
4031 sizeof(icUInt16Number) +
4032 sizeof(icUInt16Number) +
4033 sizeof(icUInt16Number) +
4034 sizeof(icUInt16Number) +
4035 16 * sizeof(icUInt8Number);
4036
4037 if (headerSize > size)
4038 return false;
4039
4040 icUInt32Number dataSize = size - headerSize;
4041
4042 if (!pIO) {
4043 return false;
4044 }
4045
4046 if (!pIO->Read32(&sig))
4047 return false;
4048
4049 if (!pIO->Read32(&m_nReserved))
4050 return false;
4051
4052 if (!pIO->Read16(&m_nInputChannels))
4053 return false;
4054
4055 if (!pIO->Read16(&m_nOutputChannels))
4056 return false;
4057
4058 if (!pIO->Read16(&m_storageType))
4059 return false;
4060
4061 if (!pIO->Read16(&m_nReserved2))
4062 return false;
4063
4064 icUInt8Number gridPoints[16];
4065
4066 if (pIO->Read8(gridPoints, 16)!=16) {
4067 return false;
4068 }
4069
4070 icUInt32Number nPoints = (icUInt32Number)m_nInputChannels * m_nOutputChannels;
4071
4072 if (m_nInputChannels > 16 || nPoints > dataSize)
4073 return false;
4074
4075 m_pCLUT = new CIccCLUT((icUInt8Number)m_nInputChannels, (icUInt16Number)m_nOutputChannels, 4);
4076
4077 if (!m_pCLUT)
4078 return false;
4079
4080 m_pCLUT->SetClipFunc(NoClip);
4081
4082 if (!m_pCLUT->Init(gridPoints, dataSize, icGetStorageTypeBytes(m_storageType)))
4083 return false;
4084
4085 icFloatNumber *pData = m_pCLUT->GetData(0);
4086
4087 if (!pData)
4088 return false;
4089
4090 nPoints = m_pCLUT->NumPoints()*m_nOutputChannels;
4091
4092 if (nPoints > dataSize)
4093 return false;
4094
4095 switch(m_storageType) {
4096 case icValueTypeUInt8:
4097 if (pIO->ReadUInt8Float(pData,nPoints)!= nPoints)
4098 return false;
4099 break;
4100
4101 case icValueTypeUInt16:
4102 if (nPoints * 2 > dataSize)
4103 return false;
4104
4105 if (pIO->ReadUInt16Float(pData,nPoints)!= nPoints)
4106 return false;
4107 break;
4108
4109 case icValueTypeFloat16:
4110 if (nPoints * 2 > dataSize)
4111 return false;
4112
4113 if (pIO->ReadFloat16Float(pData,nPoints)!= nPoints)
4114 return false;
4115 break;
4116
4117 case icValueTypeFloat32:
4118 if (pIO->ReadFloat32Float(pData,nPoints)!= nPoints)
4119 return false;
4120 break;
4121
4122 default:
4123 return false;
4124 }
4125 return true;
4126}
4127
4128/**
4129******************************************************************************
4130* Name: CIccMpeExtCLUT::Write
4131*
4132* Purpose:
4133*
4134* Args:
4135*
4136* Return:
4137******************************************************************************/
4138bool CIccMpeExtCLUT::Write(CIccIO *pIO)
4139{
4140 icElemTypeSignature sig = GetType();
4141
4142 if (!pIO)
4143 return false;
4144
4145 if (!pIO->Write32(&sig))
4146 return false;
4147
4148 if (!pIO->Write32(&m_nReserved))
4149 return false;
4150
4151 if (!pIO->Write16(&m_nInputChannels))
4152 return false;
4153
4154 if (!pIO->Write16(&m_nOutputChannels))
4155 return false;
4156
4157 if (!pIO->Write16(&m_storageType))
4158 return false;
4159
4160 if (!pIO->Write16(&m_nReserved2))
4161 return false;
4162
4163 if (m_pCLUT) {
4164 icUInt8Number gridPoints[16];
4165 int i;
4166
4167 for (i=0; i<16; i++)
4168 gridPoints[i] = m_pCLUT->GridPoint(i);
4169
4170 if (pIO->Write8(gridPoints, 16)!=16)
4171 return false;
4172
4173 icFloatNumber *pData = m_pCLUT->GetData(0);
4174 icInt32Number nPoints = m_pCLUT->NumPoints()*m_nOutputChannels;
4175
4176 switch(m_storageType) {
4177 case icValueTypeUInt8:
4178 if (pIO->WriteUInt8Float(pData,nPoints)!= nPoints)
4179 return false;
4180 break;
4181
4182 case icValueTypeUInt16:
4183 if (pIO->WriteUInt16Float(pData,nPoints)!= nPoints)
4184 return false;
4185 break;
4186
4187 case icValueTypeFloat16:
4188 if (pIO->WriteFloat16Float(pData,nPoints)!= nPoints)
4189 return false;
4190 break;
4191
4192 case icValueTypeFloat32:
4193 if (pIO->WriteFloat32Float(pData,nPoints)!= nPoints)
4194 return false;
4195 break;
4196
4197 default:
4198 return false;
4199 }
4200 }
4201
4202 return true;
4203}
4204
4205
4206/**
4207******************************************************************************
4208* Name: CIccMpeExtCLUT::Validate
4209*
4210* Purpose:
4211*
4212* Args:
4213*
4214* Return:
4215******************************************************************************/
4216icValidateStatus CIccMpeExtCLUT::Validate(std::string sigPath, std::string &sReport, const CIccTagMultiProcessElement* pMPE/*=NULL*/) const
4217{
4218 std::string mpeSigPath = sigPath + icGetSigPath(GetType());
4219 icValidateStatus rv = CIccMpeCLUT::Validate(sigPath, sReport, pMPE);
4220
4221 if (m_storageType>icMaxValueTypeicValueTypeUInt8) {
4222 CIccInfo Info;
4223 std::string sSigPathName = Info.GetSigPathName(mpeSigPath);
4224
4225 sReport += icMsgValidateCriticalError;
4226 sReport += sSigPathName;
4227 sReport += " - Invalid value type!\r\n";
4228 return icValidateCriticalError;
4229 }
4230
4231 return rv;
4232}
4233
4234
4235CIccMpeCAM::CIccMpeCAM()
4236{
4237 m_pCAM = NULL__null;
4238 m_nInputChannels = 3;
4239 m_nOutputChannels = 3;
4240 m_nReserved = 0;
4241}
4242
4243CIccMpeCAM::~CIccMpeCAM()
4244{
4245 if (m_pCAM)
4246 delete m_pCAM;
4247}
4248
4249bool CIccMpeCAM::Read(icUInt32Number size, CIccIO *pIO)
4250{
4251 icTagTypeSignature sig;
4252
4253 icUInt32Number headerSize = sizeof(icTagTypeSignature) +
4254 sizeof(icUInt32Number) +
4255 sizeof(icUInt16Number)*2 +
4256 8 * sizeof(icFloat32Number);
4257
4258 if (headerSize > size)
4259 return false;
4260
4261 if (!pIO) {
4262 return false;
4263 }
4264
4265 if (!pIO->Read32(&sig))
4266 return false;
4267
4268 if (sig!=GetType())
4269 return false;
4270
4271 if (!pIO->Read32(&m_nReserved))
4272 return false;
4273
4274 if (!pIO->Read16(&m_nInputChannels))
4275 return false;
4276
4277 if (!pIO->Read16(&m_nOutputChannels))
4278 return false;
4279
4280 icFloatNumber param[8];
4281
4282 if (pIO->ReadFloat32Float(param, 8)!=8)
4283 return false;
4284
4285 if (m_pCAM)
4286 delete m_pCAM;
4287
4288 m_pCAM = new CIccCamConverter;
4289
4290 m_pCAM->SetParameter_WhitePoint(&param[0]);
4291 m_pCAM->SetParameter_La(param[3]);
4292 m_pCAM->SetParameter_Yb(param[4]);
4293 m_pCAM->SetParameter_C(param[5]);
4294 m_pCAM->SetParameter_Nc(param[6]);
4295 m_pCAM->SetParameter_F(param[7]);
4296
4297 return true;
4298}
4299
4300bool CIccMpeCAM::Write(CIccIO *pIO)
4301{
4302 if (!m_pCAM)
4303 return false;
4304
4305 icElemTypeSignature sig = GetType();
4306
4307 if (!pIO)
4308 return false;
4309
4310 if (!pIO->Write32(&sig))
4311 return false;
4312
4313 if (!pIO->Write32(&m_nReserved))
4314 return false;
4315
4316 if (!pIO->Write16(&m_nInputChannels))
4317 return false;
4318
4319 if (!pIO->Write16(&m_nOutputChannels))
4320 return false;
4321
4322
4323 icFloatNumber param[8];
4324
4325 m_pCAM->GetParameter_WhitePoint(&param[0]); //sets param[0], param[1], and param[2]
4326 param[3] = m_pCAM->GetParameter_La();
4327 param[4] = m_pCAM->GetParameter_Yb();
4328 param[5] = m_pCAM->GetParameter_C();
4329 param[6] = m_pCAM->GetParameter_Nc();
4330 param[7] = m_pCAM->GetParameter_F();
4331
4332 if (pIO->WriteFloat32Float(&param, 8)!=8)
4333 return false;
4334
4335 return true;
4336}
4337
4338bool CIccMpeCAM::Begin(icElemInterp nInterp, CIccTagMultiProcessElement *pMPE)
4339{
4340 if (m_pCAM) {
4341 return true;
4342 }
4343 return false;
4344}
4345
4346void CIccMpeCAM::SetCAM(CIccCamConverter *pCAM)
4347{
4348 if (m_pCAM)
4349 delete m_pCAM;
4350 m_pCAM = pCAM;
4351}
4352
4353void CIccMpeCAM::Describe(std::string &sDescription)
4354{
4355 sDescription += "Begin ";
4356 sDescription += GetXformName();
4357 sDescription += "\n";
4358
4359 if (m_pCAM) {
4360 char line[256];
4361
4362 icFloatNumber xyz[3];
4363 m_pCAM->GetParameter_WhitePoint(xyz);
4364 sprintf(line, "WhitePoint (X=%f, Y=%f, Z=%f)\n", xyz[0], xyz[1], xyz[2]);
4365 sDescription += line;
4366
4367 sprintf(line, "Luminance(La)=%f cd/m^2\n", m_pCAM->GetParameter_La());
4368 sDescription += line;
4369
4370 sprintf(line, "Background Luminance(Yb)=%f cd/m^2\n", m_pCAM->GetParameter_Yb());
4371 sDescription += line;
4372
4373 sprintf(line, "Impact Surround(C)=%f\n", m_pCAM->GetParameter_C());
4374 sDescription += line;
4375
4376 sprintf(line, "Chromatic Induction Factor(Nc)=%f\n", m_pCAM->GetParameter_Nc());
4377 sDescription += line;
4378
4379 sprintf(line, "Adaptation Factor(F)=%f\n", m_pCAM->GetParameter_F());
4380 sDescription += line;
4381
4382 }
4383 sDescription += "End";
4384 sDescription += GetXformName();
4385 sDescription += "\n";
4386}
4387
4388
4389icValidateStatus CIccMpeCAM::Validate(std::string sigPath, std::string &sReport, const CIccTagMultiProcessElement* pMPE/*=NULL*/) const
4390{
4391 icValidateStatus rv = icValidateOK;
4392
4393 if (m_nInputChannels!=3) {
4394 sReport += icMsgValidateCriticalError;
4395 sReport += "CAM Element Must have 3 input channels\n";
4396 rv = icMaxStatus(icValidateCriticalError, rv);
4397 }
4398 if (m_nOutputChannels!=3) {
4399 sReport += icMsgValidateCriticalError;
4400 sReport += "CAM Element Must have 3 output channels";
4401 return icMaxStatus(icValidateCriticalError, rv);
4402 }
4403 if (!m_pCAM) {
4404 sReport += icMsgValidateCriticalError;
4405 sReport += "Invalid CAM";
4406 return icMaxStatus(icValidateCriticalError, rv);
4407 }
4408
4409 return rv;
4410}
4411
4412CIccMpeJabToXYZ::CIccMpeJabToXYZ() : CIccMpeCAM()
4413{
4414}
4415
4416CIccMpeJabToXYZ::CIccMpeJabToXYZ(const CIccMpeJabToXYZ &cam)
4417{
4418 if (cam.m_pCAM) {
4419 m_pCAM = new CIccCamConverter();
4420 icFloatNumber xyz[3];
4421 cam.m_pCAM->GetParameter_WhitePoint(xyz);
4422 m_pCAM->SetParameter_WhitePoint(xyz);
4423 m_pCAM->SetParameter_La(cam.m_pCAM->GetParameter_La());
4424 m_pCAM->SetParameter_Yb(cam.m_pCAM->GetParameter_Yb());
4425 m_pCAM->SetParameter_C(cam.m_pCAM->GetParameter_C());
4426 m_pCAM->SetParameter_Nc(cam.m_pCAM->GetParameter_Nc());
4427 m_pCAM->SetParameter_F(cam.m_pCAM->GetParameter_F());
4428 }
4429 else
4430 m_pCAM = NULL__null;
4431}
4432
4433CIccMpeJabToXYZ &CIccMpeJabToXYZ::operator=(const CIccMpeJabToXYZ &cam)
4434{
4435 if (cam.m_pCAM) {
4436 if (m_pCAM)
4437 delete m_pCAM;
4438
4439 m_pCAM = new CIccCamConverter();
4440 icFloatNumber xyz[3];
4441
4442 cam.m_pCAM->GetParameter_WhitePoint(xyz);
4443 m_pCAM->SetParameter_WhitePoint(xyz);
4444 m_pCAM->SetParameter_La(cam.m_pCAM->GetParameter_La());
4445 m_pCAM->SetParameter_Yb(cam.m_pCAM->GetParameter_Yb());
4446 m_pCAM->SetParameter_C(cam.m_pCAM->GetParameter_C());
4447 m_pCAM->SetParameter_Nc(cam.m_pCAM->GetParameter_Nc());
4448 m_pCAM->SetParameter_F(cam.m_pCAM->GetParameter_F());
4449 }
4450 else
4451 m_pCAM = NULL__null;
4452
4453 return *this;
4454}
4455
4456CIccMpeJabToXYZ::~CIccMpeJabToXYZ()
4457{
4458}
4459
4460void CIccMpeJabToXYZ::Apply(CIccApplyMpe *pApply, icFloatNumber *dstPixel, const icFloatNumber *srcPixel) const
4461{
4462 if (m_pCAM)
4463 m_pCAM->JabToXYZ(srcPixel, dstPixel, 1);
4464}
4465
4466CIccMpeXYZToJab::CIccMpeXYZToJab() : CIccMpeCAM()
4467{
4468}
4469
4470CIccMpeXYZToJab::CIccMpeXYZToJab(const CIccMpeXYZToJab &cam)
4471{
4472 if (cam.m_pCAM) {
4473 m_pCAM = new CIccCamConverter();
4474 icFloatNumber xyz[3];
4475
4476 cam.m_pCAM->GetParameter_WhitePoint(xyz);
4477 m_pCAM->SetParameter_WhitePoint(xyz);
4478 m_pCAM->SetParameter_La(cam.m_pCAM->GetParameter_La());
4479 m_pCAM->SetParameter_Yb(cam.m_pCAM->GetParameter_Yb());
4480 m_pCAM->SetParameter_C(cam.m_pCAM->GetParameter_C());
4481 m_pCAM->SetParameter_Nc(cam.m_pCAM->GetParameter_Nc());
4482 m_pCAM->SetParameter_F(cam.m_pCAM->GetParameter_F());
4483 }
4484 else
4485 m_pCAM = NULL__null;
4486}
4487
4488CIccMpeXYZToJab &CIccMpeXYZToJab::operator=(const CIccMpeXYZToJab &cam)
4489{
4490 if (cam.m_pCAM) {
4491 if (m_pCAM)
4492 delete m_pCAM;
4493
4494 m_pCAM = new CIccCamConverter();
4495 icFloatNumber xyz[3];
4496
4497 cam.m_pCAM->GetParameter_WhitePoint(xyz);
4498 m_pCAM->SetParameter_WhitePoint(xyz);
4499 m_pCAM->SetParameter_La(cam.m_pCAM->GetParameter_La());
4500 m_pCAM->SetParameter_Yb(cam.m_pCAM->GetParameter_Yb());
4501 m_pCAM->SetParameter_C(cam.m_pCAM->GetParameter_C());
4502 m_pCAM->SetParameter_Nc(cam.m_pCAM->GetParameter_Nc());
4503 m_pCAM->SetParameter_F(cam.m_pCAM->GetParameter_F());
4504 }
4505 else
4506 m_pCAM = NULL__null;
4507
4508 return *this;
4509}
4510
4511CIccMpeXYZToJab::~CIccMpeXYZToJab()
4512{
4513}
4514
4515void CIccMpeXYZToJab::Apply(CIccApplyMpe *pApply, icFloatNumber *dstPixel, const icFloatNumber *srcPixel) const
4516{
4517 if (m_pCAM)
4518 m_pCAM->XYZToJab(srcPixel, dstPixel, 1);
4519}
4520
4521
4522#ifdef USEREFICCMAXNAMESPACE
4523} //namespace refIccMAX
4524#endif