Hoyt's FORK of DemoIccMAX 2.1.17.hoyt
Documentation for Hoyt's FORK of DemoIccMAX
Loading...
Searching...
No Matches
IccMpeBasic.cpp
Go to the documentation of this file.
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#include "IccMpeCalc.h"
85
86#ifdef USEREFICCMAXNAMESPACE
87namespace refIccMAX {
88#endif
89
90/**
91 ******************************************************************************
92 * Name: CIccFormulaCurveSegment::CIccFormulaCurveSegment
93 *
94 * Purpose:
95 *
96 * Args:
97 *
98 * Return:
99 ******************************************************************************/
101{
102 m_nReserved = 0;
103 m_nReserved2 = 0;
104 m_startPoint = start;
105 m_endPoint = end;
106
107 m_nFunctionType = 0;
108 m_nShortcutType = 0;
109 m_nParameters = 0;
110 m_params = NULL;
111}
112
113/**
114 ******************************************************************************
115 * Name: CIccFormulaCurveSegment::CIccFormulaCurveSegment
116 *
117 * Purpose:
118 *
119 * Args:
120 *
121 * Return:
122 ******************************************************************************/
124{
125 m_nReserved = seg.m_nReserved;
126 m_nReserved2 = seg.m_nReserved2;
127 m_startPoint = seg.m_startPoint;
128 m_endPoint = seg.m_endPoint;
129
130 m_nFunctionType = seg.m_nFunctionType;
131 m_nShortcutType = seg.m_nShortcutType;
132 m_nParameters = seg.m_nParameters;
133
134 if (seg.m_params) {
135 m_params = (icFloatNumber*)malloc(m_nParameters*sizeof(icFloatNumber));
136 if (m_params)
137 memcpy(m_params, seg.m_params, m_nParameters*sizeof(icFloatNumber));
138 }
139 else
140 m_params = NULL;
141}
142
143/**
144 ******************************************************************************
145 * Name: &CIccFormulaCurveSegment::operator=
146 *
147 * Purpose:
148 *
149 * Args:
150 *
151 * Return:
152 ******************************************************************************/
154{
155 if (m_params)
156 free(m_params);
157
158 m_nReserved = seg.m_nReserved;
159 m_nReserved2 = seg.m_nReserved2;
160 m_startPoint = seg.m_startPoint;
161 m_endPoint = seg.m_endPoint;
162
163 m_nFunctionType = seg.m_nFunctionType;
164 m_nShortcutType = seg.m_nShortcutType;
165 m_nParameters = seg.m_nParameters;
166 if (seg.m_params) {
167 m_params = (icFloatNumber*)malloc(m_nParameters*sizeof(icFloatNumber));
168 if (m_params)
169 memcpy(m_params, seg.m_params, m_nParameters*sizeof(icFloatNumber));
170 }
171 else
172 m_params = NULL;
173
174 return (*this);
175}
176
177/**
178 ******************************************************************************
179 * Name: CIccFormulaCurveSegment::~CIccFormulaCurveSegment
180 *
181 * Purpose:
182 *
183 * Args:
184 *
185 * Return:
186 ******************************************************************************/
188{
189 if (m_params) {
190 free(m_params);
191 }
192}
193
194/**
195 ******************************************************************************
196 * Name: CIccFormulaCurveSegment::Describe
197 *
198 * Purpose:
199 *
200 * Args:
201 *
202 * Return:
203 ******************************************************************************/
204void CIccFormulaCurveSegment::Describe(std::string &sDescription, int nVerboseness)
205{
206 icChar buf[256];
207
208 sDescription += "Segment [";
209 if (m_startPoint==icMinFloat32Number)
210 sDescription += "-Infinity, ";
211 else {
212 sprintf(buf, "%.8f, ", m_startPoint);
213 sDescription += buf;
214 }
215 if (m_endPoint==icMaxFloat32Number)
216 sDescription += "+Infinity";
217 else {
218 sprintf(buf, "%.8f", m_endPoint);
219 sDescription += buf;
220 }
221 sprintf(buf, "]\nFunctionType: %04Xh\n", m_nFunctionType);
222 sDescription += buf;
223
224 switch(m_nFunctionType) {
225 case 0x0000:
226 if (icIsNear(m_params[1], 0.0) && icIsNear(m_params[2], 0.0))
227 sprintf(buf, "Y = %.8f\n\n", m_params[3]);
228 else if (icIsNear(m_params[0], 1.0) && icIsNear(m_params[1], 1.0) &&
229 icIsNear(m_params[2], 0.0) && icIsNear(m_params[3], 0.0))
230 sprintf(buf, "Y = X\n\n");
231 else if (icIsNear(m_params[0], 1.0) && icIsNear(m_params[2], 0.0))
232 sprintf(buf, "Y = %.8f * X + %.8f\n\n",
233 m_params[1], m_params[3]);
234 else
235 sprintf(buf, "Y = (%.8f * X + %.8f)^%.4f + %.8f\n\n",
236 m_params[1], m_params[2], m_params[0], m_params[3]);
237 sDescription += buf;
238 return;
239
240 case 0x0001:
241 sprintf(buf, "Y = %.8f * log (%.8f * (X ^ %.8f) + %.8f) + %.8f\n\n",
242 m_params[1], m_params[2], m_params[0], m_params[3], m_params[4]);
243 sDescription += buf;
244 return;
245
246 case 0x0002:
247 sprintf(buf, "Y = %.8f * (%.8f ^ (%.8f * X + %.8f)) + %.8f\n\n",
248 m_params[0], m_params[1], m_params[2], m_params[3], m_params[4]);
249 sDescription += buf;
250 return;
251
252 case 0x0003:
253 if (icIsNear(m_params[1],0.0) && icIsNear(m_params[2], 0.0))
254 sprintf(buf, "Y = %.8f\n\n", m_params[3]);
255 else if (icIsNear(m_params[0], 1.0) && icIsNear(m_params[1], 1.0) &&
256 icIsNear(m_params[2], 1.0) && icIsNear(m_params[3], 0.0) &&
257 icIsNear(m_params[4], 0.0))
258 sprintf(buf, "Y = X\n\n");
259 else if (icIsNear(m_params[0], 1.0) && icIsNear(m_params[1], 1.0) &&
260 icIsNear(m_params[3], 0.0))
261 sprintf(buf, "Y = %.8f * X + %.8f\n\n",
262 m_params[2], m_params[3]);
263 else if (icIsNear(m_params[0], 1.0) && icIsNear(m_params[2], 1.0) &&
264 icIsNear(m_params[3], 0.0))
265 sprintf(buf, "Y = %.8f * X + %.8f\n\n",
266 m_params[1], m_params[3]);
267 else
268 sprintf(buf, "Y = %8f * (%.8f * X + %.8f)^%.4f + %.8f\n\n",
269 m_params[1], m_params[2], m_params[3], m_params[0], m_params[4]);
270 sDescription += buf;
271 return;
272
273 case 0x0004:
274 if (!icIsNear(m_params[0], 1.0))
275 sprintf(buf, "Y = %.8f * ln(%.8f * X^%8.f - %.8f) + %.8f\n\n",
276 m_params[1], m_params[4], m_params[0], m_params[2], m_params[3]);
277 else
278 sprintf(buf, "Y = %.8f * ln(%.8f * X - %.8f) + %.8f\n\n",
279 m_params[1], m_params[4], m_params[2], m_params[3]);
280
281 sDescription += buf;
282 return;
283
284 case 0x0005:
285 if (!icIsNear(m_params[0], 1.0))
286 sprintf(buf, "Y = %.8f * exp((%.8f * X^%.8f - %.8f) / %.8f) + %.8f\n\n",
287 m_params[5], m_params[4], m_params[0], m_params[3], m_params[1], m_params[2]);
288 else
289 sprintf(buf, "Y = %.8f * exp((%.8f * X - %.8f) / %.8f) + %.8f\n\n",
290 m_params[5], m_params[4], m_params[3], m_params[1], m_params[2]);
291
292 sDescription += buf;
293 return;
294
295 case 0x0006:
296 if (!icIsNear(m_params[1], 1.0))
297 sprintf(buf, "Y = %.8f * (max[(%.8f * X^%.8f - %.8f), 0] / (%.8f - %.8f * X^%.8f))^%.8f\n\n",
298 m_params[5], m_params[6], m_params[1], m_params[2], m_params[3], m_params[4], m_params[1], m_params[0]);
299 else
300 sprintf(buf, "Y = %.8f * (max[(%.8f * X - %.8f), 0] / (%.8f - %.8f * X))^%.8f\n\n",
301 m_params[5], m_params[6], m_params[2], m_params[3], m_params[4], m_params[0]);
302 sDescription += buf;
303 return;
304
305 case 0x0007:
306 if (!icIsNear(m_params[1], 1.0))
307 sprintf(buf, "Y = %.8f * ((%.8f + %.8f * X^%.8f) / (1 + %.8f * X^%.8f))^%.8f\n\n",
308 m_params[5], m_params[2], m_params[3], m_params[1], m_params[4], m_params[1], m_params[0]);
309 else
310 sprintf(buf, "Y = %.8f * ((%.8f + %.8f * X) / (1 + %.8f * X))^%.8f\n\n",
311 m_params[5], m_params[2], m_params[3], m_params[4], m_params[0]);
312 sDescription += buf;
313 return;
314
315 default:
316 int i;
317 sprintf(buf, "Unknown Function with %d parameters:\n\n", m_nParameters);
318 sDescription += buf;
319
320 for (i=0; i<m_nParameters; i++) {
321 sprintf(buf, "Param[%d] = %.8lf\n\n", i, m_params[i]);
322 sDescription += buf;
323 }
324 }
325}
326
327
328/**
329 ******************************************************************************
330 * Name: CIccFormulaCurveSegment::SetFunction
331 *
332 * Purpose:
333 *
334 * Args:
335 *
336 * Return:
337 ******************************************************************************/
339{
340 if (m_params)
341 free(m_params);
342
343 if (num_parameters) {
344 m_params = (icFloatNumber*)malloc(num_parameters * sizeof(icFloatNumber));
345 if (m_params)
346 memcpy(m_params, parameters, num_parameters * sizeof(icFloatNumber));
347 }
348 else
349 m_params = NULL;
350
351 m_nFunctionType = functionType;
352 m_nParameters = num_parameters;
353}
354
355/**
356 ******************************************************************************
357 * Name: CIccFormulaCurveSegment::Read
358 *
359 * Purpose:
360 *
361 * Args:
362 *
363 * Return:
364 ******************************************************************************/
366{
368
369 icUInt32Number headerSize = sizeof(icTagTypeSignature) +
370 sizeof(icUInt32Number) +
371 sizeof(icUInt16Number) +
372 sizeof(icUInt16Number);
373
374 if (headerSize > size)
375 return false;
376
377 if (!pIO) {
378 return false;
379 }
380
381 if (!pIO->Read32(&sig))
382 return false;
383
384 if (!pIO->Read32(&m_nReserved))
385 return false;
386
387 if (!pIO->Read16(&m_nFunctionType))
388 return false;
389
390 if (!pIO->Read16(&m_nReserved2))
391 return false;
392
393 if (m_params) {
394 free(m_params);
395 }
396
397 switch(m_nFunctionType) {
398 case 0x0000:
399 m_nParameters = 4;
400 break;
401
402 case 0x0001:
403 case 0x0002:
404 case 0x0003:
405 case 0x0004:
406 m_nParameters = 5;
407 break;
408
409 case 0x0005:
410 case 0x0007:
411 m_nParameters = 6;
412 break;
413
414 case 0x0006:
415 m_nParameters = 7;
416 break;
417
418 default:
419 return false;
420 }
421
422 if (m_nParameters) {
423
424 m_params = (icFloatNumber*)malloc(m_nParameters * sizeof(icFloatNumber));
425 if (!m_params)
426 return false;
427
428 if (pIO->ReadFloat32Float(m_params, m_nParameters)!= m_nParameters) {
429 return false;
430 }
431 }
432 else
433 m_params = NULL;
434
435 return true;
436}
437
438/**
439 ******************************************************************************
440 * Name: CIccFormulaCurveSegment::Write
441 *
442 * Purpose:
443 *
444 * Args:
445 *
446 * Return:
447 ******************************************************************************/
449{
450 icCurveSegSignature sig = GetType();
451
452 if (!pIO)
453 return false;
454
455 if (!pIO->Write32(&sig))
456 return false;
457
458 if (!pIO->Write32(&m_nReserved))
459 return false;
460
461 if (!pIO->Write16(&m_nFunctionType))
462 return false;
463
464 if (!pIO->Write16(&m_nReserved2))
465 return false;
466
467 switch(m_nFunctionType) {
468 case 0x0000:
469 if (m_nParameters!=4)
470 return false;
471 break;
472
473 case 0x0001:
474 case 0x0002:
475 case 0x0003:
476 case 0x0004:
477 if (m_nParameters!=5)
478 return false;
479 break;
480
481 case 0x0005:
482 case 0x0007:
483 if (m_nParameters != 6)
484 return false;
485 break;
486
487 case 0x0006:
488 if (m_nParameters != 7)
489 return false;
490 break;
491 }
492
493 if (m_nParameters) {
494 if (pIO->WriteFloat32Float(m_params, m_nParameters)!=m_nParameters)
495 return false;
496 }
497
498 return true;
499}
500
501/**
502 ******************************************************************************
503 * Name: CIccFormulaCurveSegment::Begin
504 *
505 * Purpose:
506 *
507 * Args:
508 *
509 * Return:
510 ******************************************************************************/
512{
513 switch (m_nFunctionType) {
514 case 0x0000:
515 if (!m_params || m_nParameters<4)
516 return false;
517
518 if (icIsNear(m_params[0], 1.0)) { //don't apply gamma
519 if (icIsNear(m_params[2], 0.0) && icIsNear(m_params[3], 0.0))
520 m_nShortcutType = 1;
521 else if (icIsNear(m_params[2], 0.0))
522 m_nShortcutType = 2;
523 else if (icIsNear(m_params[3], 0.0))
524 m_nShortcutType = 3;
525 else
526 m_nShortcutType = 4;
527 }
528 else {
529 m_nShortcutType = 0;
530 }
531
532 return true;
533
534 case 0x0001:
535 if (!m_params || m_nParameters<5)
536 return false;
537
538 return true;
539
540 case 0x0002:
541 case 0x0003:
542 if (!m_params || m_nParameters < 5)
543 return false;
544
545 case 0x0004:
546 if (!m_params || m_nParameters < 5)
547 return false;
548
549 if (icIsNear(m_params[0], 1.0)) { //don't apply gamma
550 m_nShortcutType = 1;
551 }
552 else {
553 m_nShortcutType = 0;
554 }
555 return true;
556
557 case 0x0005:
558 if (!m_params || m_nParameters < 6)
559 return false;
560
561 if (icIsNear(m_params[0], 1.0)) { //don't apply gamma
562 m_nShortcutType = 1;
563 }
564 else {
565 m_nShortcutType = 0;
566 }
567 return true;
568
569 case 0x0006:
570 if (!m_params || m_nParameters < 7)
571 return false;
572
573 if (icIsNear(m_params[1], 1.0)) { //don't apply gamma
574 m_nShortcutType = 1;
575 }
576 else {
577 m_nShortcutType = 0;
578 }
579 return true;
580
581 case 0x0007:
582 if (!m_params || m_nParameters < 6)
583 return false;
584
585 if (icIsNear(m_params[1], 1.0)) { //don't apply gamma
586 m_nShortcutType = 1;
587 }
588 else {
589 m_nShortcutType = 0;
590 }
591 return true;
592
593
594 default:
595 return false;
596 }
597
598 return true;
599}
600
601static icFloatNumber clipPow(double v, double g)
602{
603 if (v <= 0)
604 return 0;
605 return (icFloatNumber)pow(v, g);
606}
607
608/**
609 ******************************************************************************
610 * Name: CIccFormulaCurveSegment::Apply
611 *
612 * Purpose:
613 *
614 * Args:
615 *
616 * Return:
617 ******************************************************************************/
619{
620 switch (m_nFunctionType) {
621 case 0x0000:
622 //Y = (a * X + b) ^ g + c : g a b c
623 switch (m_nShortcutType) {
624 case 0:
625 default:
626 return (icFloatNumber)(pow(m_params[1] * v + m_params[2], m_params[0]) + m_params[3]);
627 case 1:
628 return (m_params[1] * v);
629 case 2:
630 return (m_params[1] * v + m_params[3]);
631 case 3:
632 return (m_params[1] * v + m_params[2]);
633 case 4:
634 return (m_params[1] * v + m_params[2] + m_params[3]);
635 }
636
637 case 0x0001:
638 // Y = a * log (b * X^g + c) + d : g a b c d
639 return (icFloatNumber)(m_params[1] * log10(m_params[2] * pow(v, m_params[0]) + m_params[3]) + m_params[4]);
640
641 case 0x0002:
642 //Y = a * b^(c*X+d) + e : a b c d e
643 return (icFloatNumber)(m_params[0] * pow(m_params[1], m_params[2] * v + m_params[3]) + m_params[4]);
644
645 case 0x0003:
646 //Y = a * (b * X + c) ^ g + d : g a b c d
647 return (icFloatNumber)(m_params[1] * clipPow(m_params[2] * v + m_params[3], m_params[0]) + m_params[4]);
648
649 case 0x0004:
650 //Y = a * ln(d * X^g - b) + c : g a b c d
651 if (m_nShortcutType != 1)
652 return (icFloatNumber)(m_params[1] * log(m_params[4] * pow(v, m_params[0]) - m_params[2]) + m_params[3]);
653 else
654 return (icFloatNumber)(m_params[1] * log(m_params[4] * v - m_params[2]) + m_params[3]);
655
656 case 0x0005:
657 //Y = e * exp((d * X^g - c) / a) + b : g a b c d e
658 if (m_nShortcutType != 1)
659 return (icFloatNumber)(m_params[5] * exp((m_params[4] * pow(v, m_params[0]) - m_params[3]) / m_params[1]) + m_params[2]);
660 else
661 return (icFloatNumber)(m_params[5] * exp((m_params[4] * v - m_params[3]) / m_params[1]) + m_params[2]);
662
663 case 0x0006:
664 //Y = d * (max(e * X^g - a, 0)/(b - c * X^g))^w : w g a b c d e
665 if (m_nShortcutType!=1) {
666 return (icFloatNumber)(m_params[5] * pow(icMax((icFloatNumber)(m_params[6] * pow(v, m_params[1]) - m_params[2]), 0.0f) /
667 (m_params[3] - m_params[4] * pow(v, m_params[1])), m_params[0]));
668 }
669 else { //m_nShortcutType == 1
670 return (icFloatNumber)(m_params[5] * pow(icMax((icFloatNumber)(m_params[6] * v - m_params[2]), 0.0f) /
671 (m_params[3] - m_params[4] * v), m_params[0]));
672 }
673
674 case 0x0007:
675 //Y = d * ((a + b * X^g)/(1 + c * X^g)) ^ w : w g a b c d
676 if (m_nShortcutType != 1) {
677 return (icFloatNumber)(m_params[5] * pow((m_params[2] + m_params[3] * pow(v, m_params[1])) /
678 (1.0 + m_params[4] * pow(v, m_params[1])), m_params[0]));
679 }
680 else { //m_nShortcutType == 1
681 return (icFloatNumber)(m_params[5] * pow((m_params[2] + m_params[3] * v) /
682 (1.0 + m_params[4] * v), m_params[0]));
683 }
684 }
685
686 //Shouldn't get here!
687 return v;
688}
689
690/**
691 ******************************************************************************
692 * Name: CIccFormulaCurveSegment::Validate
693 *
694 * Purpose:
695 *
696 * Args:
697 *
698 * Return:
699 ******************************************************************************/
700icValidateStatus CIccFormulaCurveSegment::Validate(std::string sigPath, std::string &sReport, const CIccTagMultiProcessElement* pMPE/*=NULL*/, const CIccProfile *pProfile/*=NULL*/) const
701{
702 CIccInfo Info;
703 std::string sSigPathName = Info.GetSigPathName(sigPath);
704
706 if (m_nReserved || m_nReserved2) {
707 sReport += icMsgValidateWarning;
708 sReport += sSigPathName;
709 sReport += " formula curve has non zero reserved data.\n";
711 }
712
713 switch (m_nFunctionType) {
714 case 0x0000:
715 if (!m_params || m_nParameters<4) {
717 sReport += sSigPathName;
718 sReport += " formula curve has Invalid formulaCurveSegment parameters.\n";
720 }
721 else if (m_nParameters > 4) {
722 sReport += icMsgValidateWarning;
723 sReport += sSigPathName;
724 sReport += " formula curve has too many formulaCurveSegment parameters.\n";
726 }
727 break;
728
729 case 0x0001:
730 if (!m_params || m_nParameters<5) {
732 sReport += sSigPathName;
733 sReport += " formula curve has Invalid formulaCurveSegment parameters.\n";
735 }
736 else if (m_nParameters > 5) {
737 sReport += icMsgValidateWarning;
738 sReport += sSigPathName;
739 sReport += " formula curve has too many formulaCurveSegment parameters.\n";
741 }
742 break;
743
744 case 0x0002:
745 if (!m_params || m_nParameters<5) {
747 sReport += sSigPathName;
748 sReport += " formula curve has Invalid formulaCurveSegment parameters.\n";
750 }
751 else if (m_nParameters > 5) {
752 sReport += icMsgValidateWarning;
753 sReport += sSigPathName;
754 sReport += " formula curve has too many formulaCurveSegment parameters.\n";
756 }
757 break;
758
759 case 0x0003:
760 if (!m_params || m_nParameters<5) {
762 sReport += sSigPathName;
763 sReport += " formula curve has Invalid formulaCurveSegment parameters.\n";
765 }
766 else if (m_nParameters > 5) {
767 sReport += icMsgValidateWarning;
768 sReport += sSigPathName;
769 sReport += " formula curve has too many formulaCurveSegment parameters.\n";
771 }
772 break;
773
774 case 0x0004:
775 if (!m_params || m_nParameters < 5) {
777 sReport += sSigPathName;
778 sReport += " formula curve has Invalid formulaCurveSegment parameters.\n";
780 }
781 else if (m_nParameters > 5) {
782 sReport += icMsgValidateWarning;
783 sReport += sSigPathName;
784 sReport += " formula curve has too many formulaCurveSegment parameters.\n";
786 }
787 break;
788
789 case 0x0005:
790 if (!m_params || m_nParameters < 6) {
792 sReport += sSigPathName;
793 sReport += " formula curve has Invalid formulaCurveSegment parameters.\n";
795 }
796 else if (m_nParameters > 6) {
797 sReport += icMsgValidateWarning;
798 sReport += sSigPathName;
799 sReport += " formula curve has too many formulaCurveSegment parameters.\n";
801 }
802 break;
803
804 case 0x0006:
805 if (!m_params || m_nParameters < 6) {
807 sReport += sSigPathName;
808 sReport += " formula curve has Invalid formulaCurveSegment parameters.\n";
810 }
811 else if (m_nParameters > 6) {
812 sReport += icMsgValidateWarning;
813 sReport += sSigPathName;
814 sReport += " formula curve has too many formulaCurveSegment parameters.\n";
816 }
817 break;
818
819 case 0x0007:
820 if (!m_params || m_nParameters < 6) {
822 sReport += sSigPathName;
823 sReport += " formula curve has Invalid formulaCurveSegment parameters.\n";
825 }
826 else if (m_nParameters > 6) {
827 sReport += icMsgValidateWarning;
828 sReport += sSigPathName;
829 sReport += " formula curve has too many formulaCurveSegment parameters.\n";
831 }
832 break;
833
834 default:
835 {
836 icChar buf[128];
838 sReport += sSigPathName;
839 sprintf(buf, " formula curve uses unknown formulaCurveSegment function type %d\n", m_nFunctionType);
840 sReport += buf;
842 }
843 }
844
845 return rv;
846}
847
848/**
849 ******************************************************************************
850 * Name: CIccSampledCurveSegment::CIccSampledCurveSegment
851 *
852 * Purpose:
853 *
854 * Args:
855 *
856 * Return:
857 ******************************************************************************/
859{
860 m_nReserved = 0;
861 m_startPoint = start;
862 m_endPoint = end;
863 m_range = end - start;
864 m_nCount = 0;
865 m_pSamples = 0;
866 m_last = 0;
867}
868
869/**
870 ******************************************************************************
871 * Name: CIccSampledCurveSegment::CIccSampledCurveSegment
872 *
873 * Purpose:
874 *
875 * Args:
876 *
877 * Return:
878 ******************************************************************************/
880{
881 m_nReserved = curve.m_nReserved;
882 m_startPoint = curve.m_startPoint;
883 m_endPoint = curve.m_endPoint;
884 m_range = m_endPoint - m_startPoint;
885 m_nCount = curve.m_nCount;
886 m_last = curve.m_last;
887
888 if (m_nCount) {
889 m_pSamples = (icFloatNumber*)malloc(m_nCount * sizeof(icFloatNumber));
890 if (m_pSamples)
891 memcpy(m_pSamples, curve.m_pSamples, m_nCount * sizeof(icFloatNumber));
892 else
893 m_nCount = 0;
894 }
895 else{
896 m_pSamples = NULL;
897 }
898}
899
900/**
901 ******************************************************************************
902 * Name: &CIccSampledCurveSegment::operator=
903 *
904 * Purpose:
905 *
906 * Args:
907 *
908 * Return:
909 ******************************************************************************/
911{
912 if (m_pSamples)
913 free(m_pSamples);
914
915 m_nReserved = curve.m_nReserved;
916 m_startPoint = curve.m_startPoint;
917 m_endPoint = curve.m_endPoint;
918 m_nCount = curve.m_nCount;
919
920 if (m_nCount) {
921 m_pSamples = (icFloatNumber*)malloc(m_nCount * sizeof(icFloatNumber));
922 if (m_pSamples)
923 memcpy(m_pSamples, curve.m_pSamples, m_nCount * sizeof(icFloatNumber));
924 else
925 m_nCount = 0;
926 }
927 else {
928 m_pSamples = NULL;
929 }
930 return (*this);
931}
932
933/**
934 ******************************************************************************
935 * Name: CIccSampledCurveSegment::~CIccSampledCurveSegment
936 *
937 * Purpose:
938 *
939 * Args:
940 *
941 * Return:
942 ******************************************************************************/
944{
945 if (m_pSamples)
946 free(m_pSamples);
947}
948
949/**
950 ******************************************************************************
951 * Name: CIccSampledCurveSegment::SetSize
952 *
953 * Purpose:
954 * Sets size of sampled lookup table. Previous data (if exists) is lost.
955 *
956 * Args:
957 * nCount = number of elements in lut (must be >= 2). Note: the m_pSample[0] is
958 * initialized from the the previous segment. It is not saved as part
959 * of Write(), or loaded as part of Read(). It will be initialized during
960 * the call to Begin(), The actual count of elements written to the file
961 * will be nCount-1
962 * bZeroAlloc = flag to decide if memory should be set to zero.
963 *
964 * Return:
965 * true if allocation successful.
966 ******************************************************************************/
967bool CIccSampledCurveSegment::SetSize(icUInt32Number nCount, bool bZeroAlloc/*=true*/)
968{
969 if (!nCount) {
970 if (m_pSamples)
971 free(m_pSamples);
972 m_pSamples = NULL;
973 m_nCount = nCount;
974 return true;
975 }
976
977 if (m_pSamples) {
978 free(m_pSamples);
979 }
980
981 if (bZeroAlloc)
982 m_pSamples = (icFloatNumber*)calloc(nCount, sizeof(icFloatNumber));
983 else
984 m_pSamples = (icFloatNumber*)malloc(nCount * sizeof(icFloatNumber));
985
986 if (m_pSamples)
987 m_nCount = nCount;
988 else
989 m_nCount = 0;
990
991 return (m_pSamples != NULL);
992}
993
994/**
995 ******************************************************************************
996 * Name: CIccSampledCurveSegment::Describe
997 *
998 * Purpose:
999 *
1000 * Args:
1001 *
1002 * Return:
1003 ******************************************************************************/
1004void CIccSampledCurveSegment::Describe(std::string &sDescription, int nVerboseness)
1005{
1006 icChar buf[128];
1007
1008 if (m_nCount<2) {
1009 sDescription += "Empty Segment [";
1010 if (m_startPoint==icMinFloat32Number)
1011 sDescription += "-Infinity, ";
1012 else {
1013 sprintf(buf, "%.8f, ", m_startPoint);
1014 sDescription += buf;
1015 }
1016 if (m_endPoint==icMaxFloat32Number)
1017 sDescription += "+Infinity";
1018 else {
1019 sprintf(buf, "%.8f", m_endPoint);
1020 sDescription += buf;
1021 }
1022
1023 sprintf(buf, "]\n");
1024 sDescription += buf;
1025 }
1026 else {
1027 sDescription += "Sampled Segment [";
1028 if (m_startPoint==icMinFloat32Number)
1029 sDescription += "-Infinity, ";
1030 else {
1031 sprintf(buf, "%.8f, ", m_startPoint);
1032 sDescription += buf;
1033 }
1034 if (m_endPoint==icMaxFloat32Number)
1035 sDescription += "+Infinity";
1036 else {
1037 sprintf(buf, "%.8f", m_endPoint);
1038 sDescription += buf;
1039 }
1040 sprintf(buf, "]\n");
1041 sDescription += buf;
1042 sDescription += "IN OUT\n";
1043
1045
1046 icFloatNumber range = m_endPoint - m_startPoint;
1047 icFloatNumber last = (icFloatNumber)(m_nCount-1);
1048
1049 for (i=1; i<m_nCount; i++) {
1050 sprintf(buf, "%.8f %.8f\n", m_startPoint + (icFloatNumber)i*range/last, m_pSamples[i]);
1051 sDescription += buf;
1052 }
1053 }
1054 sDescription += "\n";
1055}
1056
1057/**
1058 ******************************************************************************
1059 * Name: CIccSampledCurveSegment::Read
1060 *
1061 * Purpose:
1062 *
1063 * Args:
1064 *
1065 * Return:
1066 ******************************************************************************/
1068{
1070
1071 icUInt32Number headerSize = sizeof(icTagTypeSignature) +
1072 sizeof(icUInt32Number) +
1073 sizeof(icUInt32Number);
1074
1075 if (headerSize > size)
1076 return false;
1077
1078 if (!pIO) {
1079 return false;
1080 }
1081
1082 if (!pIO->Read32(&sig))
1083 return false;
1084
1085 if (!pIO->Read32(&m_nReserved))
1086 return false;
1087
1088 if (!pIO->Read32(&m_nCount))
1089 return false;
1090
1091 if (m_nCount > size - headerSize || m_nCount * sizeof(icFloat32Number) > size - headerSize)
1092 return false;
1093
1094 //Reserve room for first point who's value comes from previous segment
1095 m_nCount++;
1096
1097 if (!SetSize(m_nCount, false))
1098 return false;
1099
1100 if (m_nCount) {
1101 if (pIO->ReadFloat32Float(m_pSamples+1, m_nCount-1)!=(icInt32Number)(m_nCount-1))
1102 return false;
1103 }
1104
1105 //Initialize first point with zero. Properly initialized during Begin()
1106 m_pSamples[0] = 0;
1107
1108 return true;
1109}
1110
1111/**
1112 ******************************************************************************
1113 * Name: CIccSampledCurveSegment::Write
1114 *
1115 * Purpose:
1116 *
1117 * Args:
1118 *
1119 * Return:
1120 ******************************************************************************/
1122{
1123 icCurveSegSignature sig = GetType();
1124
1125 if (!pIO)
1126 return false;
1127
1128 if (!pIO->Write32(&sig))
1129 return false;
1130
1131 if (!pIO->Write32(&m_nReserved))
1132 return false;
1133
1134 icUInt32Number nCount;
1135
1136 if (m_nCount)
1137 nCount = m_nCount -1;
1138 else
1139 nCount = 0;
1140
1141 if (!pIO->Write32(&nCount))
1142 return false;
1143
1144 //First point in samples is ONLY for interpolation (not saved)
1145 if (nCount) {
1146 if (pIO->WriteFloat32Float(m_pSamples+1, nCount)!=(icInt32Number)nCount)
1147 return false;
1148 }
1149
1150 return true;
1151}
1152
1153/**
1154 ******************************************************************************
1155 * Name: CIccSampledCurveSegment::Begin
1156 *
1157 * Purpose:
1158 *
1159 * Args:
1160 *
1161 * Return:
1162 ******************************************************************************/
1164{
1165 if (m_nCount<2)
1166 return false;
1167
1168 m_range = m_endPoint - m_startPoint;
1169 m_last = (icFloatNumber)(m_nCount - 1);
1170
1171 if (m_endPoint-m_startPoint == 0.0)
1172 return false;
1173
1174 if (!pPrevSeg)
1175 return false;
1176
1177 //Set up interpolation from Application of last segment
1178 m_pSamples[0] = pPrevSeg->Apply(m_startPoint);
1179
1180 return true;
1181}
1182
1183/**
1184 ******************************************************************************
1185 * Name: CIccSampledCurveSegment::Apply
1186 *
1187 * Purpose:
1188 *
1189 * Args:
1190 *
1191 * Return:
1192 ******************************************************************************/
1194{
1195 if (v<m_startPoint)
1196 v=m_startPoint;
1197 else if (v>m_endPoint)
1198 v=m_endPoint;
1199
1200 icFloatNumber pos = (v-m_startPoint)/m_range * m_last;
1201 icUInt32Number index = (icUInt32Number) pos;
1202 icFloatNumber remainder = pos - (icFloatNumber)index;
1203
1204 if (remainder==0.0)
1205 return m_pSamples[index];
1206
1207 return (icFloatNumber)((1.0-remainder)*m_pSamples[index] + remainder*m_pSamples[index+1]);
1208}
1209
1210/**
1211 ******************************************************************************
1212 * Name: CIccSampledCurveSegment::Validate
1213 *
1214 * Purpose:
1215 *
1216 * Args:
1217 *
1218 * Return:
1219 ******************************************************************************/
1220icValidateStatus CIccSampledCurveSegment::Validate(std::string sigPath, std::string &sReport, const CIccTagMultiProcessElement* pMPE/*=NULL*/, const CIccProfile *pProfile/*=NULL*/) const
1221{
1222 CIccInfo Info;
1223 std::string sSigPathName = Info.GetSigPathName(sigPath);
1224
1226 if (m_nReserved) {
1227 sReport += icMsgValidateWarning;
1228 sReport += sSigPathName;
1229 sReport += " sampled curve has non zero reserved data.\n";
1230 rv = icValidateWarning;
1231 }
1232
1233 if (m_nCount<1) {
1234 sReport += icMsgValidateCriticalError;
1235 sReport += sSigPathName;
1236 sReport += " sampled curve has too few sample points.\n";
1238 }
1239 else if (m_endPoint-m_startPoint == 0.0) {
1240 sReport += icMsgValidateWarning;
1241 sReport += sSigPathName;
1242 sReport += " sampled curve has a range of zero.\n";
1244 }
1245
1246 return rv;
1247}
1248
1249
1250
1251/**
1252******************************************************************************
1253* Name: CIccSingleSampledCurve::CIccSingleSampledCurve
1254*
1255* Purpose:
1256*
1257* Args:
1258*
1259* Return:
1260******************************************************************************/
1262{
1263 m_nReserved = 0;
1264 m_nCount = 0;
1265 m_pSamples = 0;
1266 m_last = 0;
1267
1268 m_storageType = icValueTypeFloat32;
1269 m_extensionType = icClipSingleSampledCurve;
1270
1271 if (first < last) {
1272 m_firstEntry = first;
1273 m_lastEntry = last;
1274 }
1275 else {
1276 m_firstEntry = last;
1277 m_lastEntry = first;
1278 }
1279
1280 m_range = m_lastEntry - m_firstEntry;
1281 m_loIntercept = 0;
1282 m_loSlope = 0;
1283 m_hiIntercept = 1.0;
1284 m_hiSlope = 0;
1285}
1286
1287/**
1288******************************************************************************
1289* Name: CIccSingleSampledCurve::CIccSingleSampledCurve
1290*
1291* Purpose:
1292*
1293* Args:
1294*
1295* Return:
1296******************************************************************************/
1298{
1299 m_nReserved = curve.m_nReserved;
1300 m_nCount = curve.m_nCount;
1301
1302 m_storageType = curve.m_storageType;
1303 m_extensionType = curve.m_extensionType;
1304
1305 if (m_nCount) {
1306 m_pSamples = (icFloatNumber*)malloc(m_nCount * sizeof(icFloatNumber));
1307 if (m_pSamples)
1308 memcpy(m_pSamples, curve.m_pSamples, m_nCount * sizeof(icFloatNumber));
1309 else
1310 m_nCount = 0;
1311 }
1312 else{
1313 m_pSamples = NULL;
1314 }
1315
1316 m_firstEntry = curve.m_firstEntry;
1317 m_lastEntry = curve.m_lastEntry;
1318 m_range = m_lastEntry - m_firstEntry;
1319
1320 m_loIntercept = curve.m_loIntercept;
1321 m_loSlope = curve.m_loSlope;
1322 m_hiIntercept = curve.m_hiIntercept;
1323 m_hiSlope = curve.m_hiSlope;
1324}
1325
1326/**
1327******************************************************************************
1328* Name: &CIccSingleSampledCurve::operator=
1329*
1330* Purpose:
1331*
1332* Args:
1333*
1334* Return:
1335******************************************************************************/
1337{
1338 if (m_pSamples)
1339 free(m_pSamples);
1340
1341 m_nReserved = curve.m_nReserved;
1342 m_nCount = curve.m_nCount;
1343
1344 m_storageType = curve.m_storageType;
1345 m_extensionType = curve.m_extensionType;
1346
1347 if (m_nCount) {
1348 m_pSamples = (icFloatNumber*)malloc(m_nCount * sizeof(icFloatNumber));
1349 if (m_pSamples)
1350 memcpy(m_pSamples, curve.m_pSamples, m_nCount * sizeof(icFloatNumber));
1351 else
1352 m_nCount = 0;
1353 }
1354 else {
1355 m_pSamples = NULL;
1356 }
1357
1358 m_firstEntry = curve.m_firstEntry;
1359 m_lastEntry = curve.m_lastEntry;
1360
1361 m_loIntercept = curve.m_loIntercept;
1362 m_loSlope = curve.m_loSlope;
1363 m_hiIntercept = curve.m_hiIntercept;
1364 m_hiSlope = curve.m_hiSlope;
1365 return (*this);
1366}
1367
1368/**
1369******************************************************************************
1370* Name: CIccSingleSampledCurve::~CIccSingleSampledCurve
1371*
1372* Purpose:
1373*
1374* Args:
1375*
1376* Return:
1377******************************************************************************/
1379{
1380 if (m_pSamples)
1381 free(m_pSamples);
1382}
1383
1384/**
1385******************************************************************************
1386* Name: CIccSingleSampledCurve::SetRange
1387*
1388* Purpose:
1389* Sets range of sampled lookup table.
1390*
1391* Args:
1392* first = first entry input position
1393* last = last entry input position
1394******************************************************************************/
1395void CIccSingleSampledCurve::SetRange(icFloatNumber first/* =0.0f */, icFloatNumber last/* =1.0f */)
1396{
1397 if (first < last) {
1398 m_firstEntry = first;
1399 m_lastEntry = last;
1400 }
1401 else {
1402 m_firstEntry = last;
1403 m_lastEntry = first;
1404 }
1405}
1406
1407
1408/**
1409******************************************************************************
1410* Name: CIccSingleSampledCurve::SetExtensionType
1411*
1412* Purpose:
1413* Sets extension type of the single sampled curve
1414*
1415* Args:
1416* nExtensionType is type of extension to use
1417*
1418* Return:
1419* true if valid extension type, false otherwise
1420******************************************************************************/
1422{
1423 m_extensionType = nExtensionType;
1424
1425 switch (nExtensionType) {
1428 return true;
1429 }
1430 return false;
1431}
1432
1433/**
1434******************************************************************************
1435* Name: CIccSingleSampledCurve::SetStorageType
1436*
1437* Purpose:
1438* Sets storate type of the data stored in the single sampled curve
1439*
1440* Args:
1441* nStorageType is type of data to use
1442*
1443* Return:
1444* true if valid storage type, false otherwise
1445******************************************************************************/
1447{
1448 m_storageType = nStorateType;
1449
1450 switch (nStorateType) {
1451 case icValueTypeUInt8:
1452 case icValueTypeUInt16:
1453 case icValueTypeFloat16:
1454 case icValueTypeFloat32:
1455 return true;
1456 }
1457 return false;
1458}
1459
1460
1461/**
1462******************************************************************************
1463* Name: CIccSingleSampledCurve::SetSize
1464*
1465* Purpose:
1466* Sets size of sampled lookup table. Previous data (if exists) is lost.
1467*
1468* Args:
1469* nCount = number of elements in lut (must be >= 2).
1470* bZeroAlloc = flag to decide if memory should be set to zero.
1471*
1472* Return:
1473* true if allocation successful.
1474******************************************************************************/
1475bool CIccSingleSampledCurve::SetSize(icUInt32Number nCount, bool bZeroAlloc/*=true*/)
1476{
1477 if (!nCount) {
1478 if (m_pSamples)
1479 free(m_pSamples);
1480 m_pSamples = NULL;
1481 m_nCount = nCount;
1482 return true;
1483 }
1484
1485 if (m_pSamples) {
1486 free(m_pSamples);
1487 }
1488
1489 if (bZeroAlloc)
1490 m_pSamples = (icFloatNumber*)calloc(nCount, sizeof(icFloatNumber));
1491 else
1492 m_pSamples = (icFloatNumber*)malloc(nCount * sizeof(icFloatNumber));
1493
1494 if (m_pSamples)
1495 m_nCount = nCount;
1496 else
1497 m_nCount = 0;
1498
1499 return (m_pSamples != NULL);
1500}
1501
1502/**
1503******************************************************************************
1504* Name: CIccSingleSampledCurve::Describe
1505*
1506* Purpose:
1507*
1508* Args:
1509*
1510* Return:
1511******************************************************************************/
1512void CIccSingleSampledCurve::Describe(std::string &sDescription, int nVerboseness)
1513{
1514 icChar buf[128];
1515
1516 if (m_nCount<2) {
1517 sDescription += "Empty Single Sampled Curve [";
1518 sprintf(buf, "%.8f, ", m_firstEntry);
1519 sDescription += buf;
1520
1521 sprintf(buf, "%.8f", m_lastEntry);
1522 sDescription += buf;
1523
1524 sprintf(buf, "]\n");
1525 sDescription += buf;
1526 }
1527 else {
1528 sDescription += "Single Sampled Curve [";
1529
1530 sprintf(buf, "%.8f, ", m_firstEntry);
1531 sDescription += buf;
1532
1533 sprintf(buf, "%.8f", m_lastEntry);
1534 sDescription += buf;
1535
1536 sprintf(buf, "]\n");
1537 sDescription += buf;
1538
1539 switch(m_storageType) {
1540 case icValueTypeUInt8:
1541 sDescription +="UInt8Number Array\n";
1542 break;
1543 case icValueTypeUInt16:
1544 sDescription +="UInt16Number Array\n";
1545 break;
1546 case icValueTypeFloat16:
1547 sDescription +="Float16Number Array\n";
1548 break;
1549 case icValueTypeFloat32:
1550 sDescription +="Float32Number Array\n";
1551 break;
1552 default:
1553 sDescription +="Unknown Data Type\n";
1554 break;
1555 }
1556
1557 switch(m_extensionType) {
1559 sDescription += "Clip End Points\n";
1560 break;
1562 sDescription += "Extend End Points\n";
1563 break;
1564 default:
1565 sDescription += "Unknown extension handling\n";
1566 break;
1567 }
1568 sDescription += "IN OUT\n";
1569
1571
1572 icFloatNumber range = m_lastEntry - m_firstEntry;
1573 icFloatNumber last = (icFloatNumber)(m_nCount-1);
1574
1575 for (i=0; i<m_nCount; i++) {
1576 sprintf(buf, "%.8f %.8f\n", m_firstEntry + (icFloatNumber)i*range/last, m_pSamples[i]);
1577 sDescription += buf;
1578 }
1579 }
1580 sDescription += "\n";
1581}
1582
1583/**
1584******************************************************************************
1585* Name: CIccSingleSampledCurve::Read
1586*
1587* Purpose:
1588*
1589* Args:
1590*
1591* Return:
1592******************************************************************************/
1594{
1596
1597 icUInt32Number headerSize = sizeof(icTagTypeSignature) +
1598 sizeof(icUInt32Number) +
1599 sizeof(icUInt32Number) +
1600 sizeof(icFloat32Number) +
1601 sizeof(icFloat32Number) +
1602 sizeof(icUInt16Number) +
1603 sizeof(icUInt16Number);
1604
1605 if (headerSize > size)
1606 return false;
1607
1608 if (!pIO) {
1609 return false;
1610 }
1611
1612 if (!pIO->Read32(&sig) || sig!=GetType())
1613 return false;
1614
1615 if (!pIO->Read32(&m_nReserved))
1616 return false;
1617
1618 if (!pIO->Read32(&m_nCount))
1619 return false;
1620
1621 if (!pIO->ReadFloat32Float(&m_firstEntry))
1622 return false;
1623
1624 if (!pIO->ReadFloat32Float(&m_lastEntry))
1625 return false;
1626
1627 if (!pIO->Read16(&m_extensionType))
1628 return false;
1629
1630 if (!pIO->Read16(&m_storageType))
1631 return false;
1632
1633 if (!SetSize(m_nCount, false))
1634 return false;
1635
1636 if (m_nCount > size - headerSize)
1637 return false;
1638
1639 if (m_nCount) {
1640 switch(m_storageType) {
1641 case icValueTypeUInt8:
1642 if (m_nCount * sizeof(icUInt8Number) > size - headerSize)
1643 return false;
1644
1645 if (pIO->ReadUInt8Float(m_pSamples, m_nCount)!=(icInt32Number)(m_nCount))
1646 return false;
1647 break;
1648 case icValueTypeUInt16:
1649 if (m_nCount * 2 > size - headerSize)
1650 return false;
1651
1652 if (pIO->ReadUInt16Float(m_pSamples, m_nCount)!=(icInt32Number)(m_nCount))
1653 return false;
1654 break;
1655 case icValueTypeFloat16:
1656 if (m_nCount * 2 > size - headerSize)
1657 return false;
1658
1659 if (pIO->ReadFloat16Float(m_pSamples, m_nCount)!=(icInt32Number)(m_nCount))
1660 return false;
1661 break;
1662 case icValueTypeFloat32:
1663 if (m_nCount * sizeof(icFloat32Number) > size - headerSize)
1664 return false;
1665
1666 if (pIO->ReadFloat32Float(m_pSamples, m_nCount)!=(icInt32Number)(m_nCount))
1667 return false;
1668 break;
1669 default:
1670 return false;
1671 }
1672 }
1673
1674 return true;
1675}
1676
1677/**
1678******************************************************************************
1679* Name: CIccSingleSampledCurve::Write
1680*
1681* Purpose:
1682*
1683* Args:
1684*
1685* Return:
1686******************************************************************************/
1688{
1689 icCurveElemSignature sig = GetType();
1690
1691 if (!pIO)
1692 return false;
1693
1694 if (!pIO->Write32(&sig))
1695 return false;
1696
1697 if (!pIO->Write32(&m_nReserved))
1698 return false;
1699
1700 if (!pIO->Write32(&m_nCount))
1701 return false;
1702
1703 if (!pIO->WriteFloat32Float(&m_firstEntry))
1704 return false;
1705
1706 if (!pIO->WriteFloat32Float(&m_lastEntry))
1707 return false;
1708
1709 if (!pIO->Write16(&m_extensionType))
1710 return false;
1711
1712 if (!pIO->Write16(&m_storageType))
1713 return false;
1714
1715 if (m_nCount) {
1716
1717 switch(m_storageType) {
1718 case icValueTypeUInt8:
1719 if (pIO->WriteUInt8Float(m_pSamples, m_nCount)!=(icInt32Number)(m_nCount))
1720 return false;
1721 break;
1722 case icValueTypeUInt16:
1723 if (pIO->WriteUInt16Float(m_pSamples, m_nCount)!=(icInt32Number)(m_nCount))
1724 return false;
1725 break;
1726 case icValueTypeFloat16:
1727 if (pIO->WriteFloat16Float(m_pSamples, m_nCount)!=(icInt32Number)(m_nCount))
1728 return false;
1729 break;
1730 case icValueTypeFloat32:
1731 if (pIO->WriteFloat32Float(m_pSamples, m_nCount)!=(icInt32Number)(m_nCount))
1732 return false;
1733 break;
1734 default:
1735 return false;
1736 }
1737 }
1738
1739 return true;
1740}
1741
1742/**
1743******************************************************************************
1744* Name: CIccSingleSampledCurve::Begin
1745*
1746* Purpose:
1747*
1748* Args:
1749*
1750* Return:
1751******************************************************************************/
1753{
1754 if (m_nCount<2)
1755 return false;
1756
1757 m_range = m_lastEntry - m_firstEntry;
1758 m_last = (icFloatNumber)(m_nCount - 1);
1759 icFloatNumber stepSize = m_range / m_last;
1760
1761 if (m_range == 0.0)
1762 return false;
1763
1764 switch(m_extensionType) {
1766 m_loSlope=0.0;
1767 m_loIntercept = m_pSamples[0];
1768
1769 m_hiSlope=0.0;
1770 m_hiIntercept = m_pSamples[m_nCount-1];
1771 break;
1772
1774 m_loSlope = (m_pSamples[1]-m_pSamples[0])/stepSize;
1775 m_loIntercept = m_pSamples[0] - m_loSlope*m_firstEntry;
1776
1777 m_hiSlope = (m_pSamples[m_nCount-1] - m_pSamples[m_nCount-2])/stepSize;
1778 m_hiIntercept = m_pSamples[m_nCount-1] - m_hiSlope*m_lastEntry;
1779 break;
1780
1781 default:
1782 return false;
1783 }
1784
1785 return true;
1786}
1787
1788/**
1789******************************************************************************
1790* Name: CIccSingleSampledCurve::Apply
1791*
1792* Purpose:
1793*
1794* Args:
1795*
1796* Return:
1797******************************************************************************/
1799{
1800 if (v<m_firstEntry) {
1801 return m_loSlope * v + m_loIntercept;;
1802 }
1803 else if (v>m_lastEntry) {
1804 return m_hiSlope * v + m_hiIntercept;
1805 }
1806
1807 icFloatNumber pos = (v-m_firstEntry)/m_range * m_last;
1808 icUInt32Number index = (icUInt32Number) pos;
1809 icFloatNumber remainder = pos - (icFloatNumber)index;
1810
1811 if (remainder==0.0)
1812 return m_pSamples[index];
1813
1814 return (icFloatNumber)((1.0-remainder)*m_pSamples[index] + remainder*m_pSamples[index+1]);
1815}
1816
1817/**
1818******************************************************************************
1819* Name: CIccSingleSampledCurve::Validate
1820*
1821* Purpose:
1822*
1823* Args:
1824*
1825* Return:
1826******************************************************************************/
1827icValidateStatus CIccSingleSampledCurve::Validate(std::string sigPath, std::string &sReport, const CIccTagMultiProcessElement* pMPE/*=NULL*/, const CIccProfile *pProfile/*=NULL*/) const
1828{
1829 CIccInfo Info;
1830 std::string sSigPathName = Info.GetSigPathName(sigPath);
1831
1833 if (m_nReserved) {
1834 sReport += icMsgValidateWarning;
1835 sReport += sSigPathName;
1836 sReport += " single sampled curve has non zero reserved data.\n";
1837 rv = icValidateWarning;
1838 }
1839
1840 if (m_extensionType > icMaxSingleSampledCurveType) {
1841 sReport += icMsgValidateCriticalError;
1842 sReport += sSigPathName;
1843 sReport += " single sampled curve has unknown extension type\n";
1845 }
1846
1847 if (m_storageType > icMaxValueType) {
1848 sReport += icMsgValidateCriticalError;
1849 sReport += sSigPathName;
1850 sReport += " single sampled curve uses unknown value type\n";
1852 }
1853
1854 if (m_nCount<2) {
1855 sReport += icMsgValidateCriticalError;
1856 sReport += sSigPathName;
1857 sReport += " single sampled curve has too few sample points.\n";
1859 }
1860
1861 if (m_lastEntry-m_firstEntry <= 0.0) {
1862 sReport += icMsgValidateWarning;
1863 sReport += sSigPathName;
1864 sReport += " single sampled curve has an invalid sample range.\r\n";
1866 }
1867
1868 return rv;
1869}
1870
1871
1872/**
1873******************************************************************************
1874* Name: CIccSampledCalculatorCurve::CIccSampledCalculatorCurve
1875*
1876* Purpose:
1877*
1878* Args:
1879*
1880* Return:
1881******************************************************************************/
1883{
1884 m_nReserved = 0;
1885 m_nReserved2 = 0;
1886
1887 m_pCalc = 0;
1888
1889 m_nCount = 0;
1890 m_pSamples = 0;
1891
1892 m_extensionType = icClipSingleSampledCurve;
1893
1894 if (first < last) {
1895 m_firstEntry = first;
1896 m_lastEntry = last;
1897 }
1898 else {
1899 m_firstEntry = last;
1900 m_lastEntry = first;
1901 }
1902
1903 m_loIntercept = 0;
1904 m_loSlope = 0;
1905 m_hiIntercept = 1.0;
1906 m_hiSlope = 0;
1907}
1908
1909/**
1910******************************************************************************
1911* Name: CIccSampledCalculatorCurve::CIccSampledCalculatorCurve
1912*
1913* Purpose:
1914*
1915* Args:
1916*
1917* Return:
1918******************************************************************************/
1920{
1921 m_nReserved = curve.m_nReserved;
1922 m_nReserved2 = curve.m_nReserved2;
1923
1924 m_nCount = curve.m_nCount;
1925
1926 m_extensionType = curve.m_extensionType;
1927
1928 m_nDesiredSize = curve.m_nDesiredSize;
1929
1930 if (curve.m_pCalc)
1931 m_pCalc = curve.m_pCalc->NewCopy();
1932
1933 if (m_nCount) {
1934 m_pSamples = (icFloatNumber*)malloc(m_nCount * sizeof(icFloatNumber));
1935 if (m_pSamples)
1936 memcpy(m_pSamples, curve.m_pSamples, m_nCount * sizeof(icFloatNumber));
1937 else
1938 m_nCount = 0;
1939 }
1940 else {
1941 m_pSamples = NULL;
1942 }
1943
1944 m_firstEntry = curve.m_firstEntry;
1945 m_lastEntry = curve.m_lastEntry;
1946
1947 m_loIntercept = curve.m_loIntercept;
1948 m_loSlope = curve.m_loSlope;
1949 m_hiIntercept = curve.m_hiIntercept;
1950 m_hiSlope = curve.m_hiSlope;
1951}
1952
1953/**
1954******************************************************************************
1955* Name: &CIccSampledCalculatorCurve::operator=
1956*
1957* Purpose:
1958*
1959* Args:
1960*
1961* Return:
1962******************************************************************************/
1964{
1965 if (m_pCalc)
1966 delete m_pCalc;
1967
1968 if (m_pSamples)
1969 free(m_pSamples);
1970
1971 m_nReserved = curve.m_nReserved;
1972 m_nReserved2 = curve.m_nReserved2;
1973
1974 m_nCount = curve.m_nCount;
1975
1976 m_nDesiredSize = curve.m_nDesiredSize;
1977
1978 m_extensionType = curve.m_extensionType;
1979
1980 if (curve.m_pCalc)
1981 m_pCalc = curve.m_pCalc->NewCopy();
1982
1983 if (m_nCount) {
1984 m_pSamples = (icFloatNumber*)malloc(m_nCount * sizeof(icFloatNumber));
1985 if (m_pSamples)
1986 memcpy(m_pSamples, curve.m_pSamples, m_nCount * sizeof(icFloatNumber));
1987 else
1988 m_nCount = 0;
1989 }
1990 else {
1991 m_pSamples = NULL;
1992 }
1993
1994 m_firstEntry = curve.m_firstEntry;
1995 m_lastEntry = curve.m_lastEntry;
1996
1997 m_loIntercept = curve.m_loIntercept;
1998 m_loSlope = curve.m_loSlope;
1999 m_hiIntercept = curve.m_hiIntercept;
2000 m_hiSlope = curve.m_hiSlope;
2001 return (*this);
2002}
2003
2004/**
2005******************************************************************************
2006* Name: CIccSampledCalculatorCurve::~CIccSampledCalculatorCurve
2007*
2008* Purpose:
2009*
2010* Args:
2011*
2012* Return:
2013******************************************************************************/
2015{
2016 if (m_pSamples)
2017 free(m_pSamples);
2018
2019 if (m_pCalc)
2020 delete m_pCalc;
2021}
2022
2023/**
2024******************************************************************************
2025* Name: CIccSampledCalculatorCurve::SetRange
2026*
2027* Purpose:
2028* Sets range of sampled lookup table.
2029*
2030* Args:
2031* first = first entry input position
2032* last = last entry input position
2033******************************************************************************/
2035{
2036 if (first < last) {
2037 m_firstEntry = first;
2038 m_lastEntry = last;
2039 }
2040 else {
2041 m_firstEntry = last;
2042 m_lastEntry = first;
2043 }
2044}
2045
2046
2047/**
2048******************************************************************************
2049* Name: CIccSampledCalculatorCurve::SetExtensionType
2050*
2051* Purpose:
2052* Sets extension type of the single sampled curve
2053*
2054* Args:
2055* nExtensionType is type of extension to use
2056*
2057* Return:
2058* true if valid extension type, false otherwise
2059******************************************************************************/
2061{
2062 m_extensionType = nExtensionType;
2063
2064 switch (nExtensionType) {
2067 return true;
2068 }
2069 return false;
2070}
2071
2072
2073/**
2074******************************************************************************
2075* Name: CIccSampledCalculatorCurve::SetCalculator
2076* Purpose:
2077* Sets calculator associated with the curve
2078*
2079* Args:
2080* nSize = desired number of elements in lut (must be >= 2).
2081*
2082*
2083* Return:
2084* true if calculator element is valid for curve, false otherwise
2085******************************************************************************/
2087{
2088 if (m_pCalc)
2089 delete m_pCalc;
2090
2091 m_pCalc = pCalc;
2092
2093 return true;
2094}
2095
2096
2097/**
2098******************************************************************************
2099* Name: CIccSampledCalculatorCurve::SetRecommendedSize
2100*
2101* Purpose:
2102* Sets size of sampled lookup table. Previous data (if exists) is lost.
2103*
2104* Args:
2105* nSize = desired number of elements in lut (must be >= 2).
2106*
2107* Return:
2108* true if amount is valid.
2109******************************************************************************/
2111{
2112 if (nSize < 2) {
2113 return false;
2114 }
2115
2116 m_nDesiredSize = nSize;
2117
2118 return true;
2119}
2120
2121
2122/**
2123******************************************************************************
2124* Name: CIccSampledCalculatorCurve::SetSize
2125*
2126* Purpose:
2127* Sets size of sampled lookup table. Previous data (if exists) is lost.
2128*
2129* Args:
2130* nCount = number of elements in lut (must be >= 2).
2131* bZeroAlloc = flag to decide if memory should be set to zero.
2132*
2133* Return:
2134* true if allocation successful.
2135******************************************************************************/
2136bool CIccSampledCalculatorCurve::SetSize(icUInt32Number nCount, bool bZeroAlloc/*=true*/)
2137{
2138 if (nCount<2) {
2139 if (m_pSamples)
2140 free(m_pSamples);
2141 m_pSamples = NULL;
2142 m_nCount = nCount;
2143 return nCount == 0;
2144 }
2145
2146 if (m_pSamples) {
2147 free(m_pSamples);
2148 }
2149
2150 if (bZeroAlloc)
2151 m_pSamples = (icFloatNumber*)calloc(nCount, sizeof(icFloatNumber));
2152 else
2153 m_pSamples = (icFloatNumber*)malloc(nCount * sizeof(icFloatNumber));
2154
2155 if (m_pSamples)
2156 m_nCount = nCount;
2157 else
2158 m_nCount = 0;
2159
2160 return (m_pSamples != NULL);
2161}
2162
2163/**
2164******************************************************************************
2165* Name: CIccSampledCalculatorCurve::Describe
2166*
2167* Purpose:
2168*
2169* Args:
2170*
2171* Return:
2172******************************************************************************/
2173void CIccSampledCalculatorCurve::Describe(std::string &sDescription, int nVerboseness/*=*100*/)
2174{
2175 icChar buf[128];
2176
2177 if (!m_pCalc) {
2178 sDescription += "Empty Sampled Calculator Curve [";
2179 sprintf(buf, "%.8f, ", m_firstEntry);
2180 sDescription += buf;
2181
2182 sprintf(buf, "%.8f,", m_lastEntry);
2183 sDescription += buf;
2184
2185 sprintf(buf, "%d", m_nDesiredSize);
2186 sDescription += buf;
2187
2188 sprintf(buf, "]\r\n");
2189 sDescription += buf;
2190 }
2191 else {
2192 sDescription += "Sampled Calculator Curve [";
2193
2194 sprintf(buf, "%.8f, ", m_firstEntry);
2195 sDescription += buf;
2196
2197 sprintf(buf, "%.8f,", m_lastEntry);
2198 sDescription += buf;
2199
2200 sprintf(buf, "%d", m_nDesiredSize);
2201 sDescription += buf;
2202
2203 sprintf(buf, "]\r\n");
2204 sDescription += buf;
2205
2206 switch (m_extensionType) {
2208 sDescription += "Clip End Points\n";
2209 break;
2211 sDescription += "Extend End Points\n";
2212 break;
2213 default:
2214 sDescription += "Unknown extension handling\n";
2215 break;
2216 }
2217 m_pCalc->Describe(sDescription, nVerboseness);
2218 }
2219 sDescription += "\r\n";
2220}
2221
2222/**
2223******************************************************************************
2224* Name: CIccSampledCalculatorCurve::Read
2225*
2226* Purpose:
2227*
2228* Args:
2229*
2230* Return:
2231******************************************************************************/
2233{
2235
2236 icUInt32Number headerSize = sizeof(icTagTypeSignature) +
2237 sizeof(icUInt32Number) +
2238 sizeof(icUInt32Number) +
2239 sizeof(icFloat32Number) +
2240 sizeof(icFloat32Number) +
2241 sizeof(icUInt16Number) +
2242 sizeof(icUInt16Number);
2243
2244 if (headerSize >= size)
2245 return false;
2246
2247 if (!pIO) {
2248 return false;
2249 }
2250
2251 if (!pIO->Read32(&sig) || sig != GetType())
2252 return false;
2253
2254 if (!pIO->Read32(&m_nReserved))
2255 return false;
2256
2257 if (!pIO->Read32(&m_nDesiredSize))
2258 return false;
2259
2260 if (!pIO->ReadFloat32Float(&m_firstEntry))
2261 return false;
2262
2263 if (!pIO->ReadFloat32Float(&m_lastEntry))
2264 return false;
2265
2266 if (!pIO->Read16(&m_extensionType))
2267 return false;
2268
2269 if (!pIO->Read16(&m_nReserved2))
2270 return false;
2271
2273 return false;
2274
2275 if (!m_pCalc->Read(size - headerSize, pIO))
2276 return false;
2277
2278 return true;
2279}
2280
2281/**
2282******************************************************************************
2283* Name: CIccSampledCalculatorCurve::Write
2284*
2285* Purpose:
2286*
2287* Args:
2288*
2289* Return:
2290******************************************************************************/
2292{
2293 icCurveElemSignature sig = GetType();
2294
2295 if (!pIO)
2296 return false;
2297
2298 if (!pIO->Write32(&sig))
2299 return false;
2300
2301 if (!pIO->Write32(&m_nReserved))
2302 return false;
2303
2304 if (!pIO->Write32(&m_nDesiredSize))
2305 return false;
2306
2307 if (!pIO->WriteFloat32Float(&m_firstEntry))
2308 return false;
2309
2310 if (!pIO->WriteFloat32Float(&m_lastEntry))
2311 return false;
2312
2313 if (!pIO->Write16(&m_extensionType))
2314 return false;
2315
2316 if (!pIO->Write16(&m_nReserved2))
2317 return false;
2318
2319 if (m_pCalc && m_pCalc->Write(pIO)) {
2320 return true;
2321 }
2322
2323 return false;
2324}
2325
2326/**
2327******************************************************************************
2328* Name: CIccSampledCalculatorCurve::Begin
2329*
2330* Purpose:
2331*
2332* Args:
2333*
2334* Return:
2335******************************************************************************/
2337{
2338 if (m_nDesiredSize < 2 || !m_pCalc || !m_pCalc->Begin(nInterp, pMPE))
2339 return false;
2340
2341 icUInt32Number nSize = m_nDesiredSize;
2342 if (nSize < 2)
2343 nSize = 2;
2344 if (nSize > ICC_MAXCALCCURVESIZE)
2345 nSize = ICC_MAXCALCCURVESIZE;
2346
2347 SetSize(nSize);
2348
2349 m_range = m_lastEntry - m_firstEntry;
2350
2351 if (m_range == 0.0)
2352 return false;
2353
2354 m_last = (icFloatNumber)(m_nCount - 1);
2355 icFloatNumber stepSize = m_range / m_last;
2356
2357 //Use calculator element to populate lookup table
2358 CIccApplyMpe *pApply = m_pCalc->GetNewApply(NULL);
2359 for (icUInt32Number i = 0; i < m_nCount; i++) {
2360 icFloatNumber src, dst;
2361 src = (icFloatNumber)i / m_last * m_range + m_firstEntry;
2362
2363 m_pCalc->Apply(pApply, &dst, &src);
2364 m_pSamples[i] = dst;
2365 }
2366
2367 if (pApply)
2368 delete pApply;
2369
2370 switch (m_extensionType) {
2372 m_loSlope = 0.0;
2373 m_loIntercept = m_pSamples[0];
2374
2375 m_hiSlope = 0.0;
2376 m_hiIntercept = m_pSamples[m_nCount - 1];
2377 break;
2378
2380 m_loSlope = (m_pSamples[1] - m_pSamples[0]) / stepSize;
2381 m_loIntercept = m_pSamples[0] - m_loSlope*m_firstEntry;
2382
2383 m_hiSlope = (m_pSamples[m_nCount - 1] - m_pSamples[m_nCount - 2]) / stepSize;
2384 m_hiIntercept = m_pSamples[m_nCount - 1] - m_hiSlope*m_lastEntry;
2385 break;
2386
2387 default:
2388 return false;
2389 }
2390
2391 return true;
2392}
2393
2394/**
2395******************************************************************************
2396* Name: CIccSampledCalculatorCurve::Apply
2397*
2398* Purpose:
2399*
2400* Args:
2401*
2402* Return:
2403******************************************************************************/
2405{
2406 if (v < m_firstEntry) {
2407 return m_loSlope * v + m_loIntercept;;
2408 }
2409 else if (v > m_lastEntry) {
2410 return m_hiSlope * v + m_hiIntercept;
2411 }
2412
2413 icFloatNumber pos = (v - m_firstEntry) / m_range * m_last;
2414 icUInt32Number index = (icUInt32Number)pos;
2415 icFloatNumber remainder = pos - (icFloatNumber)index;
2416
2417 if (remainder == 0.0)
2418 return m_pSamples[index];
2419
2420 return (icFloatNumber)((1.0 - remainder)*m_pSamples[index] + remainder*m_pSamples[index + 1]);
2421}
2422
2423/**
2424******************************************************************************
2425* Name: CIccSampledCalculatorCurve::Validate
2426*
2427* Purpose:
2428*
2429* Args:
2430*
2431* Return:
2432******************************************************************************/
2433icValidateStatus CIccSampledCalculatorCurve::Validate(std::string sigPath, std::string &sReport, const CIccTagMultiProcessElement* pMPE/*=NULL*/, const CIccProfile *pProfile/*=NULL*/) const
2434{
2435 CIccInfo Info;
2436 std::string sSigPathName = Info.GetSigPathName(sigPath);
2437
2439 if (m_nReserved || m_nReserved2) {
2440 sReport += icMsgValidateWarning;
2441 sReport += sSigPathName;
2442 sReport += " sampled calculator curve has non zero reserved data.\r\n";
2443 rv = icValidateWarning;
2444 }
2445
2446 if (m_extensionType > icMaxSingleSampledCurveType) {
2447 sReport += icMsgValidateCriticalError;
2448 sReport += sSigPathName;
2449 sReport += " sampled calculator curve has unknown extension type\r\n";
2451 }
2452
2453 if (m_nDesiredSize < 2) {
2454 sReport += icMsgValidateWarning;
2455 sReport += sSigPathName;
2456 sReport += " sampled calculator curve has too few desired sample points.\r\n";
2458 }
2459
2460 if (m_lastEntry - m_firstEntry <= 0.0) {
2461 sReport += icMsgValidateWarning;
2462 sReport += sSigPathName;
2463 sReport += " sampled calculator curve has an invalid sample range.\n";
2465 }
2466
2467 if (pProfile && pProfile->m_Header.version < icVersionNumberV5_1) {
2468 sReport += icMsgValidateWarning;
2469 sReport += sSigPathName;
2470 sReport += " sampled calculator curve is not supported by version of profile.\n";
2472 }
2473
2474 if (!m_pCalc) {
2475 sReport += icMsgValidateCriticalError;
2476 sReport += sSigPathName;
2477 sReport += " sampled calculator curve has no calculator element\r\n";
2479 }
2480 else {
2481 icValidateStatus stat = m_pCalc->Validate(sSigPathName, sReport, pMPE, pProfile);
2482
2483 rv = icMaxStatus(rv, stat);
2484 }
2485
2486 return rv;
2487}
2488
2489
2490/**
2491 ******************************************************************************
2492 * Name: CIccCurveSegment::Create
2493 *
2494 * Purpose:
2495 *
2496 * Args:
2497 *
2498 * Return:
2499 ******************************************************************************/
2501{
2502 switch(sig) {
2504 return new CIccFormulaCurveSegment(start, end);
2506 return new CIccSampledCurveSegment(start, end);
2507 default:
2508 return NULL;
2509 }
2510
2511}
2512
2513/**
2514 ******************************************************************************
2515 * Name: CIccSegmentedCurve::CIccSegmentedCurve
2516 *
2517 * Purpose:
2518 *
2519 * Args:
2520 *
2521 * Return:
2522 ******************************************************************************/
2524{
2525 m_list = new CIccCurveSegmentList();
2526 m_nReserved1 = 0;
2527 m_nReserved2 = 0;
2528
2529}
2530
2531
2532/**
2533 ******************************************************************************
2534 * Name: CIccSegmentedCurve::CIccSegmentedCurve
2535 *
2536 * Purpose:
2537 *
2538 * Args:
2539 *
2540 * Return:
2541 ******************************************************************************/
2543{
2544 CIccCurveSegmentList::iterator i;
2545
2546 m_list = new CIccCurveSegmentList();
2547
2548 for (i=curve.m_list->begin(); i!=curve.m_list->end(); i++) {
2549 m_list->push_back((*i)->NewCopy());
2550 }
2551 m_nReserved1 = curve.m_nReserved1;
2552 m_nReserved2 = curve.m_nReserved2;
2553}
2554
2555
2556/**
2557 ******************************************************************************
2558 * Name: &CIccSegmentedCurve::operator=
2559 *
2560 * Purpose:
2561 *
2562 * Args:
2563 *
2564 * Return:
2565 ******************************************************************************/
2567{
2568 Reset();
2569
2570 CIccCurveSegmentList::iterator i;
2571
2572 for (i=curve.m_list->begin(); i!=curve.m_list->end(); i++) {
2573 m_list->push_back((*i)->NewCopy());
2574 }
2575 m_nReserved1 = curve.m_nReserved1;
2576 m_nReserved2 = curve.m_nReserved2;
2577
2578 return (*this);
2579}
2580
2581
2582/**
2583 ******************************************************************************
2584 * Name: CIccSegmentedCurve::~CIccSegmentedCurve
2585 *
2586 * Purpose:
2587 *
2588 * Args:
2589 *
2590 * Return:
2591 ******************************************************************************/
2593{
2594 Reset();
2595 delete m_list;
2596}
2597
2598
2599/**
2600 ******************************************************************************
2601 * Name: CIccSegmentedCurve::Describe
2602 *
2603 * Purpose:
2604 *
2605 * Args:
2606 *
2607 * Return:
2608 ******************************************************************************/
2609void CIccSegmentedCurve::Describe(std::string &sDescription, int nVerboseness)
2610{
2611 CIccCurveSegmentList::iterator i;
2612
2613 sDescription += "BEGIN_CURVE\n";
2614 for (i=m_list->begin(); i!=m_list->end(); i++) {
2615 (*i)->Describe(sDescription, nVerboseness);
2616 }
2617}
2618
2619
2620
2621/**
2622 ******************************************************************************
2623 * Name: CIccSegmentedCurve::Read
2624 *
2625 * Purpose:
2626 *
2627 * Args:
2628 *
2629 * Return:
2630 ******************************************************************************/
2632{
2634
2635 icUInt32Number startPos = pIO->Tell();
2636
2637 icUInt32Number headerSize = sizeof(icCurveElemSignature) +
2638 sizeof(icUInt32Number) +
2639 sizeof(icUInt16Number) +
2640 sizeof(icUInt16Number);
2641
2642 if (headerSize > size)
2643 return false;
2644
2645 if (!pIO) {
2646 return false;
2647 }
2648
2649 if (!pIO->Read32(&sig))
2650 return false;
2651
2652 if (sig!=GetType())
2653 return false;
2654
2655 if (!pIO->Read32(&m_nReserved1))
2656 return false;
2657
2658 icUInt16Number nSegments;
2659
2660 if (!pIO->Read16(&nSegments))
2661 return false;
2662
2663 if (!pIO->Read16(&m_nReserved2))
2664 return false;
2665
2666 Reset();
2667
2668 icUInt32Number pos = pIO->Tell();
2669 icCurveSegSignature segSig;
2670 CIccCurveSegment *pSeg;
2671
2672 if (nSegments==1) {
2673 if (sizeof(segSig) > size - headerSize)
2674 return false;
2675
2676 if (!pIO->Read32(&segSig))
2677 return false;
2679 if (!pSeg)
2680 return false;
2681
2682 pIO->Seek(pos, icSeekSet);
2683
2684 if (!pSeg->Read(size-(pos-startPos), pIO)) {
2685 delete pSeg;
2686 return false;
2687 }
2688
2689 m_list->push_back(pSeg);
2690 }
2691 else if (nSegments) {
2692 if (nSegments > size - headerSize)
2693 return false;
2694
2695 icFloatNumber *breakpoints=(icFloatNumber*)calloc(nSegments-1, sizeof(icFloatNumber));
2696
2697 if (!breakpoints)
2698 return false;
2699
2700 if (pIO->ReadFloat32Float(breakpoints, nSegments-1)!=nSegments-1) {
2701 free(breakpoints);
2702 return false;
2703 }
2704
2705 int i;
2706 for (i=0; i<nSegments; i++) {
2707 pos = pIO->Tell();
2708 if (!pIO->Read32(&segSig)) {
2709 free(breakpoints);
2710 return false;
2711 }
2712 if (pIO->Seek(pos, icSeekSet)!=(icInt32Number)pos)
2713 return false;;
2714
2715 if (!i)
2716 pSeg = CIccCurveSegment::Create(segSig, icMinFloat32Number, breakpoints[i]);
2717 else if (i==nSegments-1)
2718 pSeg = CIccCurveSegment::Create(segSig, breakpoints[i-1], icMaxFloat32Number);
2719 else
2720 pSeg = CIccCurveSegment::Create(segSig, breakpoints[i-1], breakpoints[i]);
2721
2722 if (!pSeg) {
2723 free(breakpoints);
2724 return false;
2725 }
2726
2727 if (!pSeg->Read(size-(pos-startPos), pIO)) {
2728 delete pSeg;
2729 free(breakpoints);
2730 return false;
2731 }
2732
2733 m_list->push_back(pSeg);
2734 }
2735
2736 free(breakpoints);
2737 }
2738
2739 return true;
2740}
2741
2742
2743/**
2744 ******************************************************************************
2745 * Name: CIccSegmentedCurve::Write
2746 *
2747 * Purpose:
2748 *
2749 * Args:
2750 *
2751 * Return:
2752 ******************************************************************************/
2754{
2755 icCurveElemSignature sig = GetType();
2756
2757 if (!pIO)
2758 return false;
2759
2760 if (!pIO->Write32(&sig))
2761 return false;
2762
2763 if (!pIO->Write32(&m_nReserved1))
2764 return false;
2765
2766 icUInt16Number nSegments = (icUInt16Number)m_list->size();
2767
2768 if (!pIO->Write16(&nSegments))
2769 return false;
2770
2771 if (!pIO->Write16(&m_nReserved2))
2772 return false;
2773
2774 CIccCurveSegmentList::iterator i;
2775 if (nSegments>1) {
2776 icFloatNumber breakpoint;
2777
2778 i=m_list->begin();
2779 for (i++; i!=m_list->end(); i++) {
2780 breakpoint = (*i)->StartPoint();
2781 if (!pIO->WriteFloat32Float(&breakpoint))
2782 return false;
2783 }
2784 }
2785 for (i=m_list->begin(); i!=m_list->end(); i++) {
2786 if (!(*i)->Write(pIO))
2787 return false;
2788 }
2789
2790 return true;
2791}
2792
2793
2794/**
2795 ******************************************************************************
2796 * Name: CIccSegmentedCurve::Reset
2797 *
2798 * Purpose:
2799 *
2800 * Args:
2801 *
2802 * Return:
2803 ******************************************************************************/
2805{
2806 CIccCurveSegmentList::iterator i;
2807
2808 for (i=m_list->begin(); i!=m_list->end(); i++) {
2809 delete (*i);
2810 }
2811 m_list->clear();
2812}
2813
2814
2815/**
2816 ******************************************************************************
2817 * Name: CIccSegmentedCurve::Insert
2818 *
2819 * Purpose:
2820 *
2821 * Args:
2822 *
2823 * Return:
2824 ******************************************************************************/
2826{
2827 CIccCurveSegmentList::reverse_iterator last = m_list->rbegin();
2828
2829 if (last!=m_list->rend()) {
2830 if (pCurveSegment->StartPoint() == (*last)->EndPoint()) {
2831 m_list->push_back(pCurveSegment);
2832 return true;
2833 }
2834 }
2835 else {
2836 m_list->push_back(pCurveSegment);
2837 return true;
2838 }
2839
2840 return false;
2841}
2842
2843
2844/**
2845 ******************************************************************************
2846 * Name: CIccSegmentedCurve::Begin
2847 *
2848 * Purpose:
2849 *
2850 * Args:
2851 *
2852 * Return:
2853 ******************************************************************************/
2855{
2856 if (m_list->size()==0)
2857 return false;
2858
2859 CIccCurveSegmentList::iterator i;
2860 CIccCurveSegment *pLast = NULL;
2861
2862 for (i=m_list->begin(); i!=m_list->end(); i++) {
2863 if (!(*i)->Begin(pLast))
2864 return false;
2865 pLast = *i;
2866 }
2867
2868 return true;
2869}
2870
2871
2872/**
2873 ******************************************************************************
2874 * Name: CIccSegmentedCurve::Apply
2875 *
2876 * Purpose:
2877 *
2878 * Args:
2879 *
2880 * Return:
2881 ******************************************************************************/
2883{
2884 CIccCurveSegmentList::iterator i;
2885
2886 for (i=m_list->begin(); i!=m_list->end(); i++) {
2887 if (v <= (*i)->EndPoint())
2888 return (*i)->Apply(v);
2889 }
2890 return v;
2891}
2892
2893/**
2894 ******************************************************************************
2895 * Name: CIccSegmentedCurve::Validate
2896 *
2897 * Purpose:
2898 *
2899 * Args:
2900 *
2901 * Return:
2902 ******************************************************************************/
2903icValidateStatus CIccSegmentedCurve::Validate(std::string sigPath, std::string &sReport, const CIccTagMultiProcessElement* pMPE/*=NULL*/, const CIccProfile *pProfile/*=NULL*/) const
2904{
2905 CIccInfo Info;
2906 std::string sSigPathName = Info.GetSigPathName(sigPath);
2907
2909 if (m_nReserved1 || m_nReserved2) {
2910 sReport += icMsgValidateWarning;
2911 sReport += sSigPathName;
2912 sReport += " Segmented curve has non zero reserved data.\n";
2913 rv = icValidateWarning;
2914 }
2915
2916 if (m_list->size()==0) {
2917 sReport += icMsgValidateCriticalError;
2918 sReport += sSigPathName;
2919 sReport += " Has Empty CurveSegment!\n";
2921 }
2922
2923 CIccCurveSegmentList::iterator i;
2924
2925 for (i=m_list->begin(); i!=m_list->end(); i++) {
2926 rv = icMaxStatus(rv, (*i)->Validate(sigPath+icGetSigPath(GetType()), sReport, pMPE, pProfile));
2927 }
2928
2929 return rv;
2930}
2931
2932
2933/**
2934 ******************************************************************************
2935 * Name: CIccCurveSetCurve::Create
2936 *
2937 * Purpose:
2938 *
2939 * Args:
2940 *
2941 * Return:
2942 ******************************************************************************/
2944{
2945 switch (sig) {
2947 return new CIccSegmentedCurve();
2949 return new CIccSingleSampledCurve();
2951 return new CIccSampledCalculatorCurve();
2952 default:
2953 return NULL;
2954 }
2955}
2956
2957/**
2958 ******************************************************************************
2959 * Name: CIccMpeCurveSet::CIccMpeCurveSet
2960 *
2961 * Purpose:
2962 *
2963 * Args:
2964 *
2965 * Return:
2966 ******************************************************************************/
2968{
2969 m_nReserved = 0;
2970 if (nSize) {
2971 m_nInputChannels = m_nOutputChannels = nSize;
2972 m_curve = (icCurveSetCurvePtr*)calloc(nSize, sizeof(icCurveSetCurvePtr));
2973 m_position = (icPositionNumber*)calloc(nSize, sizeof(icPositionNumber));
2974 }
2975 else {
2976 m_nInputChannels = m_nOutputChannels = 0;
2977 m_curve = NULL;
2978 m_position = NULL;
2979 }
2980}
2981
2982typedef std::map<icCurveSetCurvePtr, icCurveSetCurvePtr> icCurveMap;
2983
2984/**
2985 ******************************************************************************
2986 * Name: CIccMpeCurveSet::CIccMpeCurveSet
2987 *
2988 * Purpose:
2989 *
2990 * Args:
2991 *
2992 * Return:
2993 ******************************************************************************/
2995{
2996 m_nReserved = curveSet.m_nReserved;
2997
2998 if (curveSet.m_nInputChannels) {
2999 int i;
3000
3001 m_nInputChannels = m_nOutputChannels = curveSet.m_nInputChannels;
3002 m_curve = (icCurveSetCurvePtr*)calloc(m_nInputChannels, sizeof(icCurveSetCurvePtr));
3003 m_position = (icPositionNumber*)calloc(m_nInputChannels, sizeof(icPositionNumber));
3004
3005 icCurveMap map;
3006 for (i=0; i<m_nInputChannels; i++) {
3007 CIccCurveSetCurve *ptr = curveSet.m_curve[i];
3008 if (ptr) {
3009 if (!map[ptr]) {
3010 m_curve[i] = ptr->NewCopy();
3011 map[ptr] = m_curve[i];
3012 }
3013 else
3014 m_curve[i] = map[ptr];
3015 }
3016 }
3017 }
3018 else {
3019 m_nInputChannels = m_nOutputChannels = 0;
3020 m_curve = NULL;
3021 }
3022}
3023
3024/**
3025 ******************************************************************************
3026 * Name: &CIccMpeCurveSet::operator=
3027 *
3028 * Purpose:
3029 *
3030 * Args:
3031 *
3032 * Return:
3033 ******************************************************************************/
3035{
3036 m_nReserved = m_nReserved;
3037
3038 if (m_curve) {
3039 free(m_curve);
3040 }
3041
3042 if (curveSet.m_nInputChannels) {
3043 int i;
3044
3045 m_nInputChannels = m_nOutputChannels = curveSet.m_nInputChannels;
3046 m_curve = (icCurveSetCurvePtr*)calloc(m_nInputChannels, sizeof(icCurveSetCurvePtr));
3047 m_position = (icPositionNumber*)calloc(m_nInputChannels, sizeof(icPositionNumber));
3048
3049 icCurveMap map;
3050 for (i=0; i<m_nInputChannels; i++) {
3051 CIccCurveSetCurve *ptr = curveSet.m_curve[i];
3052 if (ptr) {
3053 if (!map[ptr]) {
3054 m_curve[i] = ptr->NewCopy();
3055 map[ptr] = m_curve[i];
3056 }
3057 else
3058 m_curve[i] = map[ptr];
3059 }
3060 }
3061 }
3062 else {
3063 m_nInputChannels = m_nOutputChannels = 0;
3064 m_curve = NULL;
3065 }
3066
3067 return *this;
3068}
3069
3070/**
3071 ******************************************************************************
3072 * Name: CIccMpeCurveSet::~CIccMpeCurveSet
3073 *
3074 * Purpose:
3075 *
3076 * Args:
3077 *
3078 * Return:
3079 ******************************************************************************/
3081{
3082 SetSize(0);
3083}
3084
3085/**
3086 ******************************************************************************
3087 * Name: CIccMpeCurveSet::SetSize
3088 *
3089 * Purpose:
3090 *
3091 * Args:
3092 *
3093 * Return:
3094 ******************************************************************************/
3096{
3097 if (m_curve) {
3098 icCurveMap map;
3099 int i;
3100
3101 for (i=0; i<m_nInputChannels; i++) {
3102 if (!map[m_curve[i]]) {
3103 map[m_curve[i]] = (CIccCurveSetCurve*)1;
3104 delete m_curve[i];
3105 }
3106 }
3107 free(m_curve);
3108 }
3109 if (m_position) {
3110 free(m_position);
3111 }
3112
3113 if (nNewSize) {
3114 m_curve = (icCurveSetCurvePtr*)calloc(nNewSize, sizeof(icCurveSetCurvePtr));
3115
3116 if (!m_curve) {
3117 m_position = NULL;
3118 m_nInputChannels = m_nOutputChannels = 0;
3119 return false;
3120 }
3121
3122 m_position = (icPositionNumber*)calloc(nNewSize, sizeof(icPositionNumber));
3123
3124 if (!m_position) {
3125 free(m_curve);
3126 m_curve = NULL;
3127
3128 m_nInputChannels = m_nOutputChannels = 0;
3129 return false;
3130 }
3131 m_nInputChannels = m_nOutputChannels = nNewSize;
3132 }
3133 else {
3134 m_curve = NULL;
3135 m_nInputChannels = m_nOutputChannels = 0;
3136 }
3137
3138 return true;
3139}
3140
3141/**
3142 ******************************************************************************
3143 * Name: CIccMpeCurveSet::SetCurve
3144 *
3145 * Purpose:
3146 *
3147 * Args:
3148 *
3149 * Return:
3150 ******************************************************************************/
3152{
3153 if (nIndex<0 || nIndex>m_nInputChannels)
3154 return false;
3155
3156 if (m_curve) {
3157 int i;
3158
3159 for (i=0; i<m_nInputChannels; i++)
3160 if (i!=nIndex && m_curve[i]==m_curve[nIndex])
3161 break;
3162
3163 if (i==m_nInputChannels && m_curve[nIndex]) {
3164 delete m_curve[nIndex];
3165 }
3166 }
3167 m_curve[nIndex] = newCurve;
3168
3169 return true;
3170}
3171
3172
3173/**
3174 ******************************************************************************
3175 * Name: CIccMpeCurveSet::Describe
3176 *
3177 * Purpose:
3178 *
3179 * Args:
3180 *
3181 * Return:
3182 ******************************************************************************/
3183void CIccMpeCurveSet::Describe(std::string &sDescription, int nVerboseness)
3184{
3185 if (m_curve) {
3186 icChar buf[81];
3187 int i;
3188
3189 sprintf(buf, "BEGIN_CURVE_SET %d\n", m_nInputChannels);
3190 sDescription += buf;
3191
3192 for (i=0; i<m_nInputChannels; i++) {
3193 sprintf(buf, "Curve %d of %d\n", i+1, m_nInputChannels);
3194 sDescription += buf;
3195 if (m_curve[i]) {
3196 m_curve[i]->Describe(sDescription, nVerboseness);
3197 }
3198 }
3199 sDescription += "END_CURVE_SET\n";
3200 }
3201}
3202
3203typedef std::map<icUInt32Number, CIccCurveSetCurve*> icCurveOffsetMap;
3204typedef std::map<CIccCurveSetCurve*, icPositionNumber> icCurvePtrMap;
3205
3206/**
3207 ******************************************************************************
3208 * Name: CIccMpeCurveSet::Read
3209 *
3210 * Purpose:
3211 *
3212 * Args:
3213 *
3214 * Return:
3215 ******************************************************************************/
3217{
3219
3220 icUInt32Number startPos = pIO->Tell();
3221
3222 icUInt32Number headerSize = sizeof(icTagTypeSignature) +
3223 sizeof(icUInt32Number) +
3224 sizeof(icUInt16Number) +
3225 sizeof(icUInt16Number);
3226
3227 if (headerSize > size)
3228 return false;
3229
3230 if (!pIO) {
3231 return false;
3232 }
3233
3234 icUInt16Number nInputChannels, nOutputChannels;
3235
3236 if (!pIO->Read32(&sig))
3237 return false;
3238
3239 if (!pIO->Read32(&m_nReserved))
3240 return false;
3241
3242 if (!pIO->Read16(&nInputChannels))
3243 return false;
3244
3245 if (!pIO->Read16(&nOutputChannels))
3246 return false;
3247
3248 if (nInputChannels != nOutputChannels)
3249 return false;
3250
3251 if (nInputChannels > size - headerSize || nInputChannels * 2*sizeof(icUInt32Number) > size - headerSize)
3252 return false;
3253
3254 if (!SetSize(nInputChannels))
3255 return false;
3256
3257 if (m_curve) {
3258 int i;
3259
3260 if (headerSize + m_nInputChannels*2*sizeof(icUInt32Number) > size)
3261 return false;
3262
3263 for (i=0; i<m_nInputChannels; i++) {
3264 if (!pIO->Read32(&m_position[i].offset)) {
3265 return false;
3266 }
3267 if (!pIO->Read32(&m_position[i].size)) {
3268 return false;
3269 }
3270 }
3271
3272 icCurveOffsetMap map;
3273 icCurveElemSignature curveSig;
3274 for (i=0; i<m_nInputChannels; i++) {
3275 if (!map[m_position[i].offset]) {
3276 icUInt32Number pos;
3277 if (!m_position[i].offset || !m_position[i].size) {
3278 return false;
3279 }
3280
3281 pos = startPos + m_position[i].offset;
3282 if (pIO->Seek(pos, icSeekSet)!=(icInt32Number)pos) {
3283 return false;
3284 }
3285
3286 if (!pIO->Read32(&curveSig)) {
3287 return false;
3288 }
3289 m_curve[i] = CIccCurveSetCurve::Create(curveSig);
3290
3291 if (!m_curve[i]) {
3292 return false;
3293 }
3294
3295 if (pIO->Seek(pos, icSeekSet)!=(icInt32Number)pos) {
3296 return false;
3297 }
3298
3299 if (!m_curve[i]->Read(m_position[i].size, pIO)) {
3300 return false;
3301 }
3302
3303 map[m_position[i].offset] = m_curve[i];
3304 }
3305 else {
3306 m_curve[i] = map[m_position[i].offset];
3307 }
3308 }
3309 }
3310
3311 return true;
3312}
3313
3314/**
3315 ******************************************************************************
3316 * Name: CIccMpeCurveSet::Write
3317 *
3318 * Purpose:
3319 *
3320 * Args:
3321 *
3322 * Return:
3323 ******************************************************************************/
3325{
3326 icElemTypeSignature sig = GetType();
3327
3328 if (!pIO)
3329 return false;
3330
3331 icUInt32Number elemStart = pIO->Tell();
3332
3333 if (!pIO->Write32(&sig))
3334 return false;
3335
3336 if (!pIO->Write32(&m_nReserved))
3337 return false;
3338
3339 if (!pIO->Write16(&m_nInputChannels))
3340 return false;
3341
3342 if (!pIO->Write16(&m_nInputChannels))
3343 return false;
3344
3345 if (m_curve && m_nInputChannels) {
3346 int i;
3347 icCurvePtrMap map;
3348 icUInt32Number start, end;
3349 icUInt32Number zeros[2] = { 0, 0};
3350 icPositionNumber position;
3351
3352 icUInt32Number startTable = pIO->Tell();
3353
3354 //First write empty position table
3355 for (i=0; i<m_nInputChannels; i++) {
3356 if (pIO->Write32(&zeros[0], 2)!=2)
3357 return false;
3358 }
3359
3360 //Now Write curves
3361 for (i=0; i<m_nInputChannels; i++) {
3362 if (m_curve[i]) {
3363 if (map.find(m_curve[i])==map.end()) {
3364 start = pIO->Tell();
3365 m_curve[i]->Write(pIO);
3366 end = pIO->Tell();
3367 pIO->Align32();
3368 position.offset = start - elemStart;
3369 position.size = end - start;
3370 map[m_curve[i]] = position;
3371 }
3372 m_position[i] = map[m_curve[i]];
3373 }
3374 }
3375 end = pIO->Tell();
3376
3377 //Back fill position table
3378 pIO->Seek(startTable, icSeekSet);
3379 for (i=0; i<m_nInputChannels; i++) {
3380 if (!pIO->Write32(&m_position[i].offset))
3381 return false;
3382 if (!pIO->Write32(&m_position[i].size))
3383 return false;
3384 }
3385
3386 pIO->Seek(end, icSeekSet);
3387 }
3388
3389 return true;
3390}
3391
3392/**
3393 ******************************************************************************
3394 * Name: CIccMpeCurveSet::Begin
3395 *
3396 * Purpose:
3397 *
3398 * Args:
3399 *
3400 * Return:
3401 ******************************************************************************/
3403{
3404 if (!m_curve)
3405 return false;
3406
3407 icCurveMap map;
3408
3409 int i;
3410 for (i=0; i<m_nInputChannels; i++) {
3411 if (!m_curve[i])
3412 return false;
3413
3414 if (!map[m_curve[i]]) {
3415 if (!m_curve[i]->Begin(nInterp, pMPE)) {
3416 return false;
3417 }
3418 //ensure that Begin is called only once for each curve
3419 map[m_curve[i]] = (CIccCurveSetCurve*)1;
3420 }
3421 }
3422
3423 return true;
3424}
3425
3426/**
3427 ******************************************************************************
3428 * Name: CIccMpeCurveSet::Apply
3429 *
3430 * Purpose:
3431 *
3432 * Args:
3433 *
3434 * Return:
3435 ******************************************************************************/
3436void CIccMpeCurveSet::Apply(CIccApplyMpe *pApply, icFloatNumber *pDestPixel, const icFloatNumber *pSrcPixel) const
3437{
3438 int i;
3439 for (i=0; i<m_nInputChannels; i++) {
3440 *pDestPixel++ = m_curve[i]->Apply(*pSrcPixel++);
3441 }
3442}
3443
3444/**
3445 ******************************************************************************
3446 * Name: CIccMpeCurveSet::Validate
3447 *
3448 * Purpose:
3449 *
3450 * Args:
3451 *
3452 * Return:
3453 ******************************************************************************/
3454icValidateStatus CIccMpeCurveSet::Validate(std::string sigPath, std::string &sReport, const CIccTagMultiProcessElement* pMPE/*=NULL*/, const CIccProfile *pProfile/*=NULL*/) const
3455{
3456 std::string mpeSigPath = sigPath + icGetSigPath(GetType());
3457 icValidateStatus rv = CIccMultiProcessElement::Validate(sigPath, sReport, pMPE, pProfile);
3458
3459 bool empty=false;
3460 if (m_curve) {
3461 int i;
3462 for (i=0; !empty && i<m_nInputChannels; i++) {
3463 if (!m_curve[i]) {
3464 empty = true;
3465 }
3466 else {
3467 rv = icMaxStatus(rv, m_curve[i]->Validate(mpeSigPath, sReport, pMPE, pProfile));
3468 }
3469 }
3470 }
3471 else
3472 empty = true;
3473
3474 if (empty) {
3475 CIccInfo Info;
3476 std::string sSigPathName = Info.GetSigPathName(mpeSigPath);
3477
3478 sReport += icMsgValidateCriticalError;
3479 sReport += sSigPathName;
3480 sReport += " - Has Empty Curve Element(s)!\n";
3482 }
3483
3484 return rv;
3485}
3486
3487/**
3488 ******************************************************************************
3489 * Name: CIccMpeTintArray::CIccMpeTintArray
3490 *
3491 * Purpose:
3492 *
3493 * Args:
3494 *
3495 * Return:
3496 ******************************************************************************/
3498{
3499 m_nReserved = 0;
3500 m_nInputChannels = 1;
3501 m_nOutputChannels = nVectorSize;
3502 m_Array = NULL;
3503}
3504
3505typedef std::map<icCurveSetCurvePtr, icCurveSetCurvePtr> icCurveMap;
3506
3507/**
3508 ******************************************************************************
3509 * Name: CIccMpeTintArray::CIccMpeTintArray
3510 *
3511 * Purpose:
3512 *
3513 * Args:
3514 *
3515 * Return:
3516 ******************************************************************************/
3518{
3519 m_nReserved = tintArray.m_nReserved;
3520
3521 m_nInputChannels = tintArray.m_nInputChannels;
3522 m_nOutputChannels = tintArray.m_nOutputChannels;
3523
3524 if (tintArray.m_Array)
3525 m_Array = (CIccTagNumArray*)tintArray.m_Array->NewCopy();
3526
3527}
3528
3529/**
3530 ******************************************************************************
3531 * Name: &CIccMpeTintArray::operator=
3532 *
3533 * Purpose:
3534 *
3535 * Args:
3536 *
3537 * Return:
3538 ******************************************************************************/
3540{
3541 m_nReserved = m_nReserved;
3542
3543 if (m_Array) {
3544 delete m_Array;
3545 }
3546
3547 m_nInputChannels = tintArray.m_nInputChannels;
3548 m_nOutputChannels = tintArray.m_nOutputChannels;
3549
3550 if (tintArray.m_Array)
3551 m_Array = (CIccTagNumArray*)tintArray.m_Array->NewCopy();
3552
3553 return *this;
3554}
3555
3556/**
3557 ******************************************************************************
3558 * Name: CIccMpeTintArray::~CIccMpeTintArray
3559 *
3560 * Purpose:
3561 *
3562 * Args:
3563 *
3564 * Return:
3565 ******************************************************************************/
3567{
3568 if (m_Array)
3569 delete m_Array;
3570}
3571
3572/**
3573 ******************************************************************************
3574 * Name: CIccMpeTintArray::SetVectorSize
3575 *
3576 * Purpose:
3577 *
3578 * Args:
3579 *
3580 * Return:
3581 ******************************************************************************/
3583{
3584 m_nOutputChannels = nVectorSize;
3585}
3586
3587/**
3588 ******************************************************************************
3589 * Name: CIccMpeTintArray::SetCurve
3590 *
3591 * Purpose:
3592 *
3593 * Args:
3594 *
3595 * Return:
3596 ******************************************************************************/
3598{
3599 if (m_Array)
3600 delete m_Array;
3601
3602 m_Array = pArray;
3603}
3604
3605
3606/**
3607 ******************************************************************************
3608 * Name: CIccMpeTintArray::Describe
3609 *
3610 * Purpose:
3611 *
3612 * Args:
3613 *
3614 * Return:
3615 ******************************************************************************/
3616void CIccMpeTintArray::Describe(std::string &sDescription, int nVerboseness)
3617{
3618 if (m_Array) {
3619 icChar buf[81];
3620
3621 sprintf(buf, "BEGIN_TINT_ARRAY %d\n", m_nOutputChannels);
3622 sDescription += buf;
3623
3624 m_Array->Describe(sDescription, nVerboseness);
3625
3626 sDescription += "END_TINT_ARRAY\n";
3627 }
3628}
3629
3630/**
3631 ******************************************************************************
3632 * Name: CIccMpeTintArray::Read
3633 *
3634 * Purpose:
3635 *
3636 * Args:
3637 *
3638 * Return:
3639 ******************************************************************************/
3641{
3642 if (m_Array)
3643 delete m_Array;
3644 m_Array = NULL;
3645
3647
3648 icUInt32Number startPos = pIO->Tell();
3649
3650 icUInt32Number headerSize = sizeof(icElemTypeSignature) +
3651 sizeof(icUInt32Number) +
3652 sizeof(icUInt16Number) +
3653 sizeof(icUInt16Number);
3654
3655 if (headerSize +sizeof(icTagTypeSignature) > size)
3656 return false;
3657
3658 if (!pIO) {
3659 return false;
3660 }
3661
3662 icUInt16Number nInputChannels, nOutputChannels;
3663
3664 if (!pIO->Read32(&sig))
3665 return false;
3666
3667 if (!pIO->Read32(&m_nReserved))
3668 return false;
3669
3670 if (!pIO->Read16(&nInputChannels))
3671 return false;
3672
3673 if (!pIO->Read16(&nOutputChannels))
3674 return false;
3675
3676 if (nInputChannels != 1 || !nOutputChannels)
3677 return false;
3678
3679 m_nInputChannels = nInputChannels;
3680 m_nOutputChannels = nOutputChannels;
3681
3682 icUInt32Number arrayPos = pIO->Tell();
3683
3684 icTagTypeSignature tagType;
3685 if (!pIO->Read32(&tagType))
3686 return false;
3687
3688 CIccTag *pTag = CIccTag::Create(tagType);
3689 if (!pTag)
3690 return false;
3691
3692 if (!pTag->IsNumArrayType()) {
3693 delete pTag;
3694 }
3695
3696 m_Array = (CIccTagNumArray*)pTag;
3697 pIO->Seek(arrayPos, icSeekSet);
3698 if (!m_Array->Read(size-headerSize, pIO)) {
3699 return false;
3700 }
3701
3702 icUInt32Number nVals = m_Array->GetNumValues();
3703 if (nVals/m_nOutputChannels <2 || (nVals%m_nOutputChannels) != 0) {
3704 return false;
3705 }
3706
3707 return true;
3708}
3709
3710/**
3711 ******************************************************************************
3712 * Name: CIccMpeTintArray::Write
3713 *
3714 * Purpose:
3715 *
3716 * Args:
3717 *
3718 * Return:
3719 ******************************************************************************/
3721{
3722 if (!m_Array)
3723 return false;
3724
3725 icElemTypeSignature sig = GetType();
3726
3727 if (!pIO)
3728 return false;
3729
3730 if (!pIO->Write32(&sig))
3731 return false;
3732
3733 if (!pIO->Write32(&m_nReserved))
3734 return false;
3735
3736 if (!pIO->Write16(&m_nInputChannels))
3737 return false;
3738
3739 if (!pIO->Write16(&m_nOutputChannels))
3740 return false;
3741
3742 return m_Array->Write(pIO);
3743}
3744
3745/**
3746 ******************************************************************************
3747 * Name: CIccMpeTintArray::Begin
3748 *
3749 * Purpose:
3750 *
3751 * Args:
3752 *
3753 * Return:
3754 ******************************************************************************/
3756{
3757 if (!m_Array)
3758 return false;
3759
3760 icUInt32Number nVals = m_Array->GetNumValues();
3761
3762 if (nVals/m_nOutputChannels<2 || nVals % m_nOutputChannels != 0)
3763 return false;
3764
3765 return true;
3766}
3767
3768/**
3769 ******************************************************************************
3770 * Name: CIccMpeTintArray::Apply
3771 *
3772 * Purpose:
3773 *
3774 * Args:
3775 *
3776 * Return:
3777 ******************************************************************************/
3778void CIccMpeTintArray::Apply(CIccApplyMpe *pApply, icFloatNumber *pDestPixel, const icFloatNumber *pSrcPixel) const
3779{
3780 if (m_Array) {
3781 m_Array->Interpolate(pDestPixel, *pSrcPixel, m_nOutputChannels);
3782 }
3783 else
3784 memset(pDestPixel, 0, m_nOutputChannels*sizeof(icFloatNumber));
3785}
3786
3787/**
3788 ******************************************************************************
3789 * Name: CIccMpeTintArray::Validate
3790 *
3791 * Purpose:
3792 *
3793 * Args:
3794 *
3795 * Return:
3796 ******************************************************************************/
3797icValidateStatus CIccMpeTintArray::Validate(std::string sigPath, std::string &sReport, const CIccTagMultiProcessElement* pMPE/*=NULL*/, const CIccProfile *pProfile/*=NULL*/) const
3798{
3799 std::string mpeSigPath = sigPath + icGetSigPath(GetType());
3800 icValidateStatus rv = CIccMultiProcessElement::Validate(sigPath, sReport, pMPE, pProfile);
3801
3802 if (m_nInputChannels!=1) {
3803 CIccInfo Info;
3804 std::string sSigPathName = Info.GetSigPathName(mpeSigPath);
3805
3806 sReport += icMsgValidateCriticalError;
3807 sReport += sSigPathName;
3808 sReport += " - Bad number of input channels!\n";
3810 }
3811
3812 if (!m_nOutputChannels) {
3813 CIccInfo Info;
3814 std::string sSigPathName = Info.GetSigPathName(mpeSigPath);
3815
3816 sReport += icMsgValidateCriticalError;
3817 sReport += sSigPathName;
3818 sReport += " - Bad number of output channels!\n";
3820 }
3821
3822 if (!m_Array) {
3823 CIccInfo Info;
3824 std::string sSigPathName = Info.GetSigPathName(mpeSigPath);
3825
3826 sReport += icMsgValidateCriticalError;
3827 sReport += sSigPathName;
3828 sReport += " - Has no tint values(s)!\n";
3830 }
3831 else {
3832 icUInt32Number nVals = m_Array->GetNumValues();
3833 bool bBad = false;
3834
3835 /*
3836 * NOTE: nVals is unsigned as is m_nOutputChannels
3837 * so the result will never be < 0
3838 */
3839 /*
3840 if (nVals/m_nOutputChannels<0) {
3841 CIccInfo Info;
3842 std::string sSigPathName = Info.GetSigPathName(mpeSigPath);
3843
3844 sReport += icMsgValidateCriticalError;
3845 sReport += sSigPathName;
3846 sReport += " - Needs two or more tint steps!\n";
3847 bBad = true;
3848 }
3849 */
3850 if ((nVals % m_nOutputChannels)!=0) {
3851 CIccInfo Info;
3852 std::string sSigPathName = Info.GetSigPathName(mpeSigPath);
3853
3854 sReport += icMsgValidateCriticalError;
3855 sReport += sSigPathName;
3856 sReport += " - Array size must be multiple of output channels!\n";
3857 bBad = true;
3858 }
3859
3860 if (bBad) {
3862 }
3863 }
3864
3865 return rv;
3866}
3867
3869{
3870 m_nFunctionType = 0;
3871 m_nParameters = 0;
3872 m_params = NULL;
3873 m_nReserved = 0;
3874 m_nReserved2 = 0;
3875}
3876
3877
3879{
3880 if (m_params)
3881 free(m_params);
3882}
3883
3885{
3886 if (&toneMapFunc == this)
3887 return *this;
3888
3889 m_nFunctionType = toneMapFunc.m_nFunctionType;
3890 m_nParameters = toneMapFunc.m_nParameters;
3891
3892 if (m_params)
3893 free(m_params);
3894 if (toneMapFunc.m_nParameters && toneMapFunc.m_params) {
3895 m_params = (icFloatNumber*)malloc(m_nParameters * sizeof(icFloatNumber));
3896 if (m_params)
3897 memcpy(m_params, toneMapFunc.m_params, m_nParameters * sizeof(icFloatNumber));
3898 }
3899 else
3900 m_params = NULL;
3901
3902 m_nReserved = toneMapFunc.m_nReserved;
3903 m_nReserved2 = toneMapFunc.m_nReserved2;
3904
3905 return *this;
3906}
3907
3909{
3910 CIccToneMapFunc* rv = new CIccToneMapFunc();
3911
3912 if (rv)
3913 *rv = *this;
3914
3915 return rv;
3916}
3917
3919{
3920 if (m_nFunctionType == 0)
3921 return 3;
3922 return 0;
3923}
3924
3926{
3927 m_nFunctionType = nFunc;
3928
3929 if (m_params)
3930 free(m_params);
3931
3932 int nArgs = NumArgs();
3933 m_nParameters = (icUInt8Number)icIntMin(nParams, NumArgs());
3934 if (nArgs && pParams) {
3935 m_params = (icFloatNumber*)calloc(nArgs, sizeof(icFloatNumber));
3936 if (m_params)
3937 memcpy(m_params, pParams, icIntMin(nArgs, nParams) * sizeof(icFloatNumber));
3938 }
3939
3940 return nParams == NumArgs();
3941}
3942
3943void CIccToneMapFunc::Describe(std::string& sDescription, int nVerboseness)
3944{
3945 icChar buf[128];
3946
3947 sprintf(buf, "ToneFunctionType: %04Xh\n", m_nFunctionType);
3948 sDescription += buf;
3949
3950 switch (m_nFunctionType) {
3951 case 0x0000:
3952 sprintf(buf, "Y = %.8f * M * ( X + %.8f) + %.8f\n\n", m_params[0], m_params[1], m_params[2]);
3953 sDescription += buf;
3954 return;
3955
3956 default:
3957 int i;
3958 sprintf(buf, "Unknown Function with %d parameters:\n\n", m_nParameters);
3959 sDescription += buf;
3960
3961 for (i = 0; i < m_nParameters; i++) {
3962 sprintf(buf, "Param[%d] = %.8lf\n\n", i, m_params[i]);
3963 sDescription += buf;
3964 }
3965
3966 }
3967}
3968
3970{
3972
3973 icUInt32Number headerSize = sizeof(icTagTypeSignature) +
3974 sizeof(icUInt32Number) +
3975 sizeof(icUInt16Number) +
3976 sizeof(icUInt16Number);
3977
3978 if (headerSize > size)
3979 return false;
3980
3981 if (!pIO) {
3982 return false;
3983 }
3984
3985 if (!pIO->Read32(&sig))
3986 return false;
3987
3989 return false;
3990
3991 if (!pIO->Read32(&m_nReserved))
3992 return false;
3993
3994 if (!pIO->Read16(&m_nFunctionType))
3995 return false;
3996
3997 if (!pIO->Read16(&m_nReserved2))
3998 return false;
3999
4000 if (m_params) {
4001 free(m_params);
4002 }
4003
4004 m_nParameters = (icUInt8Number)((size - headerSize)/sizeof(icFloatNumber));
4005
4006 if (m_nParameters) {
4007
4008 m_params = (icFloatNumber*)malloc(m_nParameters * sizeof(icFloatNumber));
4009 if (!m_params)
4010 return false;
4011
4012 if (pIO->ReadFloat32Float(m_params, m_nParameters) != m_nParameters) {
4013 return false;
4014 }
4015 }
4016 else
4017 m_params = NULL;
4018
4019 return true;
4020
4021}
4022
4024{
4025 icToneFunctionSignature sig = GetType();
4026
4027 if (!pIO)
4028 return false;
4029
4030 if (!pIO->Write32(&sig))
4031 return false;
4032
4033 if (!pIO->Write32(&m_nReserved))
4034 return false;
4035
4036 if (!pIO->Write16(&m_nFunctionType))
4037 return false;
4038
4039 if (!pIO->Write16(&m_nReserved2))
4040 return false;
4041
4042
4043 if (m_nParameters != NumArgs())
4044 return false;
4045
4046 if (m_nParameters) {
4047 if (pIO->WriteFloat32Float(m_params, m_nParameters) != m_nParameters)
4048 return false;
4049 }
4050
4051 return true;
4052
4053}
4054
4056{
4057 if (m_nFunctionType != 0x0000)
4058 return false;
4059
4060 if (m_nParameters < NumArgs() || !m_params)
4061 return false;
4062
4063 return true;
4064}
4065
4067{
4068 if (!m_nFunctionType && m_params) {
4069 return m_params[0] * lumValue * (pixelValue + m_params[1]) + m_params[2];
4070 }
4071
4072 return 0;
4073}
4074
4075icValidateStatus CIccToneMapFunc::Validate(std::string& sReport, int nVerboseness) const
4076{
4077 CIccInfo Info;
4078
4080
4081 if (m_nReserved || m_nReserved2) {
4082 sReport += icMsgValidateWarning;
4083 sReport += " formula curve has non zero reserved data.\n";
4085 }
4086
4087 switch (m_nFunctionType) {
4088 case 0x0000:
4089 if (!m_params || m_nParameters < 3) {
4090 sReport += icMsgValidateCriticalError;
4091 sReport += " Tone mapping function has invalid parameters.\n";
4093 }
4094 else if (m_nParameters > 3) {
4095 sReport += icMsgValidateWarning;
4096 sReport += " tone mapping function has too many formulaCurveSegment parameters.\n";
4098 }
4099 break;
4100
4101 default:
4102 {
4103 icChar buf[128];
4104 sReport += icMsgValidateCriticalError;
4105 sprintf(buf, " tone mapping function uses unknown function type %d\n", m_nFunctionType);
4106 sReport += buf;
4108 }
4109 }
4110
4111 return rv;
4112}
4113
4114
4115
4116
4117/**
4118 ******************************************************************************
4119 * Name: CIccMpeToneMap::CIccMpeToneMap
4120 *
4121 * Purpose:
4122 *
4123 * Args:
4124 *
4125 * Return:
4126 ******************************************************************************/
4128{
4129 m_nReserved = 0;
4130 m_nInputChannels = nOutputChannels + 1;
4131 m_nOutputChannels = nOutputChannels;
4132 m_pLumCurve = NULL;
4133 m_pToneFuncs = NULL;
4134
4135 SetNumOutputChannels(nOutputChannels);
4136
4137}
4138
4139/**
4140 ******************************************************************************
4141 * Name: CIccMpeToneMap::CIccMpeToneMap
4142 *
4143 * Purpose:
4144 *
4145 * Args:
4146 *
4147 * Return:
4148 ******************************************************************************/
4150{
4151 m_nReserved = toneMap.m_nReserved;
4152
4153 m_nInputChannels = toneMap.m_nInputChannels;
4154 m_nOutputChannels = toneMap.m_nOutputChannels;
4155
4156 if (toneMap.m_pLumCurve)
4157 m_pLumCurve = toneMap.m_pLumCurve->NewCopy();
4158
4159 m_nFunc = toneMap.m_nFunc;
4160 if (toneMap.m_pToneFuncs)
4161 m_pToneFuncs = toneMap.CopyToneFuncs();
4162 else
4163 m_pToneFuncs = NULL;
4164}
4165
4166/**
4167 ******************************************************************************
4168 * Name: &CIccMpeToneMap::operator=
4169 *
4170 * Purpose:
4171 *
4172 * Args:
4173 *
4174 * Return:
4175 ******************************************************************************/
4177{
4178 if (&toneMap == this)
4179 return *this;
4180
4181 m_nReserved = toneMap.m_nReserved;
4182
4183 m_nInputChannels = toneMap.m_nInputChannels;
4184 m_nOutputChannels = toneMap.m_nOutputChannels;
4185
4186 if (m_pLumCurve)
4187 delete m_pLumCurve;
4188
4189 if (toneMap.m_pLumCurve)
4190 m_pLumCurve = toneMap.m_pLumCurve->NewCopy();
4191 else
4192 m_pLumCurve = NULL;
4193
4194 ClearToneFuncs();
4195
4196 m_nFunc = toneMap.m_nFunc;
4197 if (toneMap.m_pToneFuncs)
4198 m_pToneFuncs = toneMap.CopyToneFuncs();
4199 else
4200 m_pToneFuncs = NULL;
4201
4202 return *this;
4203}
4204
4205/**
4206 ******************************************************************************
4207 * Name: CIccMpeToneMap::~CIccMpeToneMap
4208 *
4209 * Purpose:
4210 *
4211 * Args:
4212 *
4213 * Return:
4214 ******************************************************************************/
4216{
4217 if (m_pLumCurve)
4218 delete m_pLumCurve;
4219
4220 ClearToneFuncs();
4221}
4222
4223/**
4224 ******************************************************************************
4225 * Name: CIccMpeToneMap::CopyToneFuncs
4226 *
4227 * Purpose:
4228 *
4229 * Args:
4230 *
4231 * Return:
4232 ******************************************************************************/
4234{
4235 if (!m_pToneFuncs || m_nOutputChannels==0)
4236 return NULL;
4237
4238 CIccToneMapFunc** rv = (CIccToneMapFunc**)calloc(m_nOutputChannels, sizeof(CIccToneMapFunc*));
4239 if (!rv)
4240 return NULL;
4241
4242 rv[0] = m_pToneFuncs[0] ? m_pToneFuncs[0]->NewCopy() : NULL;
4243
4244 int j;
4245 for (int i = 1; i < m_nOutputChannels; i++) {
4246 for (j = 0; j < i; j++)
4247 if (m_pToneFuncs[j] == m_pToneFuncs[i])
4248 break;
4249 if (j < i)
4250 rv[i] = rv[j];
4251 else
4252 rv[i] = m_pToneFuncs[i] ? m_pToneFuncs[i]->NewCopy() : NULL;
4253 }
4254
4255 return rv;
4256}
4257
4258
4259/**
4260 ******************************************************************************
4261 * Name: CIccMpeToneMap::ClearToneFuncs
4262 *
4263 * Purpose:
4264 *
4265 * Args:
4266 *
4267 * Return:
4268 ******************************************************************************/
4270{
4271 if (m_pToneFuncs) {
4272
4273 if (m_nOutputChannels) {
4274 if (m_pToneFuncs[0])
4275 delete m_pToneFuncs[0];
4276
4277 int j;
4278 for (int i = 1; i < m_nOutputChannels; i++) {
4279 for (j = 0; j < i; j++)
4280 if (m_pToneFuncs[j] == m_pToneFuncs[i])
4281 break;
4282 if (j == i && m_pToneFuncs[i])
4283 delete m_pToneFuncs[i];
4284 }
4285 }
4286
4287 free(m_pToneFuncs);
4288 m_pToneFuncs = NULL;
4289 }
4290}
4291
4292/**
4293 ******************************************************************************
4294 * Name: CIccMpeToneMap::SetLumCurve
4295 *
4296 * Purpose:
4297 *
4298 * Args:
4299 *
4300 * Return:
4301 ******************************************************************************/
4303{
4304 if (pLumCurve == m_pLumCurve)
4305 return;
4306
4307 if (m_pLumCurve)
4308 delete m_pLumCurve;
4309
4310 m_pLumCurve = pLumCurve;
4311}
4312
4313
4314/**
4315 ******************************************************************************
4316 * Name: CIccMpeToneMap::SetNumOutputChannels
4317 *
4318 * Purpose:
4319 *
4320 * Args:
4321 *
4322 * Return:
4323 ******************************************************************************/
4325{
4326 ClearToneFuncs();
4327 m_nOutputChannels = nVectorSize;
4328 if (m_nOutputChannels) {
4329 m_pToneFuncs = (CIccToneMapFunc**)calloc(m_nOutputChannels, sizeof(CIccToneMapFunc*));
4330 }
4331 m_nFunc = 0;
4332}
4333
4334
4335/**
4336 ******************************************************************************
4337 * Name: CIccMpeToneMap::PushBackFunc
4338 *
4339 * Purpose:
4340 *
4341 * Args:
4342 *
4343 * Return:
4344 ******************************************************************************/
4346{
4347 if (!m_pToneFuncs || m_nFunc >= m_nOutputChannels)
4348 return false;
4349
4350 m_pToneFuncs[m_nFunc++] = pToneMapFunc;
4351
4352 return true;
4353}
4354
4355
4356/**
4357 ******************************************************************************
4358 * Name: CIccMpeToneMap::Describe
4359 *
4360 * Purpose:
4361 *
4362 * Args:
4363 *
4364 * Return:
4365 ******************************************************************************/
4366void CIccMpeToneMap::Describe(std::string& sDescription, int nVerboseness)
4367{
4368 char buf[256];
4369
4370 sprintf(buf, "BEGIN_TONE_MAP %d\n", m_nOutputChannels);
4371 sDescription += buf;
4372
4373 if (m_pLumCurve) {
4374 sDescription += "LUM_FUNCTION:\n";
4375 m_pLumCurve->Describe(sDescription, nVerboseness);
4376 }
4377
4378 if (m_pToneFuncs) {
4379 for (int i = 0; i < m_nOutputChannels; i++) {
4380 sprintf(buf, "TONE_FUNCTION_%d:\n", i);
4381 sDescription += buf;
4382 if (m_pToneFuncs[i])
4383 m_pToneFuncs[i]->Describe(sDescription, nVerboseness);
4384 }
4385 }
4386
4387 sDescription += "END_TINT_ARRAY\n";
4388}
4389
4390/**
4391 ******************************************************************************
4392 * Name: CIccMpeToneMap::Read
4393 *
4394 * Purpose:
4395 *
4396 * Args:
4397 *
4398 * Return:
4399 ******************************************************************************/
4401{
4402 if (m_pLumCurve)
4403 delete m_pLumCurve;
4404 m_pLumCurve = NULL;
4405
4406 ClearToneFuncs();
4407
4409
4410 icUInt32Number startPos = pIO->Tell();
4411
4412 icUInt32Number headerSize = sizeof(icElemTypeSignature) +
4413 sizeof(icUInt32Number) +
4414 sizeof(icUInt16Number) +
4415 sizeof(icUInt16Number) +
4416 sizeof(icUInt32Number)*2;
4417
4418 if (headerSize + sizeof(icTagTypeSignature) > size)
4419 return false;
4420
4421 if (!pIO) {
4422 return false;
4423 }
4424
4425 icUInt16Number nInputChannels, nOutputChannels;
4426
4427 if (!pIO->Read32(&sig))
4428 return false;
4429
4430 if (!pIO->Read32(&m_nReserved))
4431 return false;
4432
4433 if (!pIO->Read16(&nInputChannels))
4434 return false;
4435
4436 if (!pIO->Read16(&nOutputChannels))
4437 return false;
4438
4439 if (nInputChannels != nOutputChannels+1 || !nOutputChannels)
4440 return false;
4441
4442 m_nInputChannels = nInputChannels;
4443 SetNumOutputChannels(nOutputChannels);
4444
4445 //setup to read luminance curve based on position
4446 icPositionNumber lumPos;
4447 if (!pIO->Read32(&lumPos.offset) ||
4448 !pIO->Read32(&lumPos.size))
4449 return false;
4450
4451 icUInt32Number curPos = pIO->Tell();
4452
4453 //We need signature of curve type to construct and read it
4454 icCurveElemSignature curveSig;
4455 if (lumPos.size < sizeof(curveSig))
4456 return false;
4457
4458 pIO->Seek(startPos + lumPos.offset, icSeekSet);
4459 if (!pIO->Read32(&curveSig))
4460 return false;
4461 pIO->Seek(startPos + lumPos.offset, icSeekSet);
4462
4463 CIccCurveSetCurve* pCurve = CIccCurveSetCurve::Create(curveSig);
4464
4465 if (!pCurve) {
4466 return false;
4467 }
4468
4469 if (!pCurve->Read(lumPos.size, pIO)) {
4470 return false;
4471 }
4472
4473 SetLumCurve(pCurve);
4474
4475 //setup positions to get the output channel mapping functions
4476 pIO->Seek(curPos, icSeekSet);
4477
4478 headerSize += nOutputChannels + sizeof(icUInt32Number)*2;
4479
4480 if (headerSize + sizeof(icTagTypeSignature) > size)
4481 return false;
4482
4483 if (!icValidTagPos(lumPos, headerSize, size))
4484 return false;
4485
4486 icPositionNumber* funcPos = new icPositionNumber[m_nOutputChannels];
4487 if (!funcPos)
4488 return false;
4489
4490 //read output tone mapping function positions
4491 int j;
4492 for (int i = 0; i < m_nOutputChannels; i++) {
4493 if (!pIO->Read32(&funcPos[i].offset) ||
4494 !pIO->Read32(&funcPos[i].size) ||
4495 !icValidTagPos(funcPos[i], headerSize, size)) {
4496 delete[] funcPos;
4497 return false;
4498 }
4499
4500 if (!icValidOverlap(lumPos, funcPos[i], false)) {
4501 delete[] funcPos;
4502 return false;
4503 }
4504 for (j = 0; j < i; j++) {
4505 if (!icValidOverlap(funcPos[j], funcPos[i], true)) {
4506 delete[] funcPos;
4507 return false;
4508 }
4509 }
4510 }
4511
4512 //Read tone mapping functions making copies as we go
4513 m_pToneFuncs[0] = NewToneMapFunc();
4514 if (!m_pToneFuncs[0]) {
4515 delete[] funcPos;
4516 return false;
4517 }
4518 pIO->Seek(startPos + funcPos[0].offset, icSeekSet);
4519 if (!m_pToneFuncs[0]->Read(funcPos[0].size, pIO)) {
4520 delete[] funcPos;
4521 return false;
4522 }
4523
4524 for (int i = 1; i < m_nOutputChannels; i++) {
4525 for (j = 0; j < i; i++) {
4526 if (funcPos[j].offset == funcPos[i].offset)
4527 break;
4528 }
4529 if (j != i)
4530 m_pToneFuncs[i] = m_pToneFuncs[j];
4531 else {
4532 m_pToneFuncs[i] = NewToneMapFunc();
4533 if (!m_pToneFuncs[i]) {
4534 delete[] funcPos;
4535 return false;
4536 }
4537 pIO->Seek(startPos + funcPos[i].offset, icSeekSet);
4538 if (!m_pToneFuncs[i]->Read(funcPos[i].size, pIO)) {
4539 delete[] funcPos;
4540 return false;
4541 }
4542 }
4543 }
4544
4545 //keep track of functions read in
4546 m_nFunc = m_nOutputChannels;
4547
4548 return true;
4549}
4550
4551/**
4552 ******************************************************************************
4553 * Name: CIccMpeToneMap::Write
4554 *
4555 * Purpose:
4556 *
4557 * Args:
4558 *
4559 * Return:
4560 ******************************************************************************/
4562{
4563 if (!m_pLumCurve || !m_pToneFuncs || !m_nOutputChannels)
4564 return false;
4565
4566 icElemTypeSignature sig = GetType();
4567
4568 if (!pIO)
4569 return false;
4570
4571 icUInt32Number nTagStartPos = pIO->Tell();
4572
4573 if (!pIO->Write32(&sig))
4574 return false;
4575
4576 if (!pIO->Write32(&m_nReserved))
4577 return false;
4578
4579 if (!pIO->Write16(&m_nInputChannels))
4580 return false;
4581
4582 if (!pIO->Write16(&m_nOutputChannels))
4583 return false;
4584
4585 icUInt32Number lumOffset = pIO->Tell();
4586
4587 //Reserve position entry for Luminance Curve
4588 icUInt32Number zero = 0;
4589 if (!pIO->Write32(&zero) ||
4590 !pIO->Write32(&zero))
4591 return false;
4592
4593 //Reserve Position entry for mapping functions
4594 for (int i = 0; i < m_nOutputChannels; i++) {
4595 if (!pIO->Write32(&zero) ||
4596 !pIO->Write32(&zero))
4597 return false;
4598 }
4599
4600 //write out luminance curve
4601 icPositionNumber lumPos;
4602 lumPos.offset = pIO->Tell()- nTagStartPos;
4603
4604 if (!m_pLumCurve->Write(pIO))
4605 return false;
4606
4607 lumPos.size = pIO->Tell() - (lumPos.offset + nTagStartPos);
4608
4609 //Keep track of tone function positions
4610 icPositionNumber* funcPos = new icPositionNumber[m_nOutputChannels];
4611 if (!funcPos)
4612 return false;
4613
4614 //write out first tone function
4615 int j;
4616 funcPos[0].offset = pIO->Tell() - nTagStartPos;
4617 if (!m_pToneFuncs[0]->Write(pIO)) {
4618 delete[] funcPos;
4619 return false;
4620 }
4621 funcPos[0].size = pIO->Tell() - (funcPos[0].offset + nTagStartPos);
4622
4623 //write out additional non-copied tone functions
4624 for (int i = 1; i < m_nOutputChannels; i++) {
4625 for (j = 0; j < i; j++)
4626 if (m_pToneFuncs[j] == m_pToneFuncs[i])
4627 break;
4628 if (j < i) {
4629 funcPos[i] = funcPos[j];
4630 }
4631 else {
4632 funcPos[i].offset = pIO->Tell() - nTagStartPos;
4633 if (!m_pToneFuncs[i]->Write(pIO)) {
4634 delete[] funcPos;
4635 return false;
4636 }
4637 funcPos[i].size = pIO->Tell() - (funcPos[i].offset + nTagStartPos);
4638 }
4639 }
4640
4641 //Everything but positions is written so make sure we end on 32 bit boundary
4642 pIO->Align32();
4643 icUInt32Number endOffset = pIO->Tell();
4644
4645 //write out luminance curve position
4646 pIO->Seek(lumOffset, icSeekSet);
4647
4648 if (!pIO->Write32(&lumPos.offset) ||
4649 !pIO->Write32(&lumPos.size)) {
4650 delete[] funcPos;
4651 return false;
4652 }
4653
4654 //write out tone mapping function positions
4655 for (int i = 0; i < m_nOutputChannels; i++) {
4656 if (!pIO->Write32(&funcPos[i].offset) ||
4657 !pIO->Write32(&funcPos[i].size)) {
4658 delete[] funcPos;
4659 return false;
4660 }
4661 }
4662 delete[] funcPos;
4663
4664 //Go back to end and we are done
4665 pIO->Seek(endOffset, icSeekSet);
4666
4667 return true;
4668}
4669
4670/**
4671 ******************************************************************************
4672 * Name: CIccMpeToneMap::Begin
4673 *
4674 * Purpose:
4675 *
4676 * Args:
4677 *
4678 * Return:
4679 ******************************************************************************/
4681{
4682 if (!m_pLumCurve || !m_pToneFuncs)
4683 return false;
4684
4685 if (!m_pLumCurve->Begin(nInterp, pMPE))
4686 return false;
4687
4688 if (!m_pToneFuncs[0] || !m_pToneFuncs[0]->Begin())
4689 return false;
4690
4691 int j;
4692 for (int i=1; i<m_nOutputChannels; i++) {
4693 for (j = 0; j < i; j++)
4694 if (m_pToneFuncs[j] == m_pToneFuncs[i])
4695 break;
4696 if (j==i && (!m_pToneFuncs[i] || !m_pToneFuncs[i]->Begin()))
4697 return false;
4698 }
4699 return true;
4700}
4701
4702
4703/**
4704 ******************************************************************************
4705 * Name: CIccMpeToneMap::Apply
4706 *
4707 * Purpose:
4708 *
4709 * Args:
4710 *
4711 * Return:
4712 ******************************************************************************/
4713void CIccMpeToneMap::Apply(CIccApplyMpe* pApply, icFloatNumber* pDestPixel, const icFloatNumber* pSrcPixel) const
4714{
4715 icFloatNumber lum = m_pLumCurve->Apply(pSrcPixel[m_nOutputChannels]);
4716 for (int i = 0; i < m_nOutputChannels; i++) {
4717 pDestPixel[i] = m_pToneFuncs[i]->Apply(lum, pSrcPixel[i]);
4718 }
4719}
4720
4721/**
4722 ******************************************************************************
4723 * Name: CIccMpeToneMap::Validate
4724 *
4725 * Purpose:
4726 *
4727 * Args:
4728 *
4729 * Return:
4730 ******************************************************************************/
4731icValidateStatus CIccMpeToneMap::Validate(std::string sigPath, std::string& sReport, const CIccTagMultiProcessElement* pMPE/*=NULL*/, const CIccProfile* pProfile/*=NULL*/) const
4732{
4733 std::string mpeSigPath = sigPath + icGetSigPath(GetType());
4734 icValidateStatus rv = CIccMultiProcessElement::Validate(sigPath, sReport, pMPE, pProfile);
4735
4736 if (m_nInputChannels != m_nOutputChannels + 1) {
4737 CIccInfo Info;
4738 std::string sSigPathName = Info.GetSigPathName(mpeSigPath);
4739
4740 sReport += icMsgValidateCriticalError;
4741 sReport += sSigPathName;
4742 sReport += " - Bad number of input channels!\n";
4744 }
4745
4746 if (!m_nOutputChannels) {
4747 CIccInfo Info;
4748 std::string sSigPathName = Info.GetSigPathName(mpeSigPath);
4749
4750 sReport += icMsgValidateCriticalError;
4751 sReport += sSigPathName;
4752 sReport += " - Bad number of output channels!\n";
4754 }
4755
4756 if (!m_pLumCurve) {
4757 CIccInfo Info;
4758 std::string sSigPathName = Info.GetSigPathName(mpeSigPath);
4759
4760 sReport += icMsgValidateCriticalError;
4761 sReport += sSigPathName;
4762 sReport += " - Has no luminance mapping curve!\n";
4764 }
4765 else {
4766 rv = icMaxStatus(rv, m_pLumCurve->Validate(mpeSigPath, sReport, pMPE, pProfile));
4767 }
4768
4769 if (!m_pToneFuncs) {
4770 CIccInfo Info;
4771 std::string sSigPathName = Info.GetSigPathName(mpeSigPath);
4772
4773 sReport += icMsgValidateCriticalError;
4774 sReport += sSigPathName;
4775 sReport += " - Has no tone mapping functions!\n";
4777 }
4778 else {
4779 for (int i = 0; i < m_nOutputChannels; i++) {
4780 std::string funcReport;
4781 char buf[20];
4782 sprintf(buf, "#%d", i);
4783 if (!m_pToneFuncs[i]) {
4784 CIccInfo Info;
4785 std::string sSigPathName = Info.GetSigPathName(mpeSigPath);
4786
4787 sReport += icMsgValidateCriticalError;
4788 sReport += sSigPathName;
4789 sReport += std::string(" - Missing Tone function #") + buf + "\n";
4790
4792 }
4793
4794 icValidateStatus crv = m_pToneFuncs[i]->Validate(funcReport);
4795 if (crv != icValidateOK) {
4796 CIccInfo Info;
4797 std::string sSigPathName = Info.GetSigPathName(mpeSigPath);
4798
4799 sReport += icMsgValidateInformation;
4800 sReport += sSigPathName;
4801 sReport += std::string(" - Tone Function #") + buf + " status:\n" + funcReport;
4802
4803 rv = icMaxStatus(rv, crv);
4804 }
4805 }
4806 }
4807
4808 return rv;
4809}
4810
4811
4812
4813/**
4814 ******************************************************************************
4815 * Name: CIccMpeMatrix::CIccMpeMatrix
4816 *
4817 * Purpose:
4818 *
4819 * Args:
4820 *
4821 * Return:
4822 ******************************************************************************/
4824{
4825 m_nReserved = 0;
4826 m_nInputChannels = m_nOutputChannels = 0;
4827 m_size = 0;
4828 m_pMatrix = NULL;
4829 m_pConstants = NULL;
4830}
4831
4832
4833/**
4834 ******************************************************************************
4835 * Name: CIccMpeMatrix::CIccMpeMatrix
4836 *
4837 * Purpose:
4838 *
4839 * Args:
4840 *
4841 * Return:
4842 ******************************************************************************/
4844{
4845 m_nReserved = matrix.m_nReserved;
4846
4847 m_nInputChannels = matrix.m_nInputChannels;
4848 m_nOutputChannels = matrix.m_nOutputChannels;
4849
4850 m_size = matrix.m_size;
4851 if(matrix.m_pMatrix) {
4852 int num = m_size * sizeof(icFloatNumber);
4853 m_pMatrix = (icFloatNumber*)malloc(num);
4854 memcpy(m_pMatrix, matrix.m_pMatrix, num);
4855 }
4856 else
4857 m_pMatrix = NULL;
4858
4859 if (matrix.m_pConstants) {
4860 int num = m_nOutputChannels*sizeof(icFloatNumber);
4861 m_pConstants = (icFloatNumber*)malloc(num);
4862 memcpy(m_pConstants, matrix.m_pConstants, num);
4863 }
4864 else
4865 m_pConstants = NULL;
4866
4867 m_bApplyConstants = true;
4868}
4869
4870/**
4871 ******************************************************************************
4872 * Name: &CIccMpeMatrix::operator=
4873 *
4874 * Purpose:
4875 *
4876 * Args:
4877 *
4878 * Return:
4879 ******************************************************************************/
4881{
4882 m_nReserved = matrix.m_nReserved;
4883
4884 m_nInputChannels = matrix.m_nInputChannels;
4885 m_nOutputChannels = matrix.m_nOutputChannels;
4886
4887 if (m_pMatrix)
4888 free(m_pMatrix);
4889
4890 m_size = matrix.m_size;
4891 if (matrix.m_pMatrix) {
4892 int num = m_size * sizeof(icFloatNumber);
4893 m_pMatrix = (icFloatNumber*)malloc(num);
4894 memcpy(m_pMatrix, matrix.m_pMatrix, num);
4895 }
4896 else
4897 m_pMatrix = NULL;
4898
4899 if (m_pConstants)
4900 free(m_pConstants);
4901
4902 if (matrix.m_pConstants) {
4903 int num = m_nOutputChannels*sizeof(icFloatNumber);
4904 m_pConstants = (icFloatNumber*)malloc(num);
4905 memcpy(m_pConstants, matrix.m_pConstants, num);
4906 }
4907 else
4908 m_pConstants = NULL;
4909
4910 m_bApplyConstants = matrix.m_bApplyConstants;
4911
4912 return *this;
4913}
4914
4915/**
4916 ******************************************************************************
4917 * Name: CIccMpeMatrix::~CIccMpeMatrix
4918 *
4919 * Purpose:
4920 *
4921 * Args:
4922 *
4923 * Return:
4924 ******************************************************************************/
4926{
4927 if (m_pMatrix)
4928 free(m_pMatrix);
4929
4930 if (m_pConstants)
4931 free(m_pConstants);
4932}
4933
4934/**
4935 ******************************************************************************
4936 * Name: CIccMpeMatrix::SetSize
4937 *
4938 * Purpose:
4939 *
4940 * Args:
4941 *
4942 * Return:
4943 ******************************************************************************/
4944bool CIccMpeMatrix::SetSize(icUInt16Number nInputChannels, icUInt16Number nOutputChannels, bool bUseConstants)
4945{
4946 if (m_pMatrix) {
4947 free(m_pMatrix);
4948 m_pMatrix = NULL;
4949 }
4950 if (m_pConstants) {
4951 free(m_pConstants);
4952 m_pConstants = NULL;
4953 }
4954
4955 m_size = (icUInt32Number)nInputChannels * nOutputChannels;
4956
4957 if (m_size) {
4958 m_pMatrix = (icFloatNumber*)calloc(m_size, sizeof(icFloatNumber));
4959 if (!m_pMatrix)
4960 return false;
4961 }
4962
4963 if (bUseConstants) {
4964 m_pConstants = (icFloatNumber*)calloc(nOutputChannels, sizeof(icFloatNumber));
4965
4966 if (!m_pConstants)
4967 return false;
4968 }
4969
4970 m_nInputChannels = nInputChannels;
4971 m_nOutputChannels = nOutputChannels;
4972
4973 return true;
4974}
4975
4976/**
4977 ******************************************************************************
4978 * Name: CIccMpeMatrix::Describe
4979 *
4980 * Purpose:
4981 *
4982 * Args:
4983 *
4984 * Return:
4985 ******************************************************************************/
4986void CIccMpeMatrix::Describe(std::string &sDescription, int nVerboseness)
4987{
4988 icChar buf[81];
4989 int i, j;
4990 icFloatNumber *data = m_pMatrix;
4991
4992 sprintf(buf, "BEGIN_ELEM_MATRIX %d %d\n", m_nInputChannels, m_nOutputChannels);
4993 sDescription += buf;
4994
4995 for (j=0; j<m_nOutputChannels; j++) {
4996 if (data) {
4997 for (i=0; i<m_nInputChannels; i++) {
4998 if (i)
4999 sDescription += " ";
5000 sprintf(buf, "%12.8lf", data[i]);
5001 sDescription += buf;
5002 }
5003 if (m_pConstants) {
5004 sprintf(buf, " + %12.8lf\n", m_pConstants[j]);
5005 sDescription += buf;
5006 }
5007 data += i;
5008 }
5009 else {
5010 sprintf(buf, "ZeroRow + %12.8lf\n", m_pConstants[j]);
5011 sDescription += buf;
5012 }
5013 }
5014 sDescription += "END_ELEM_MATRIX\n";
5015}
5016
5017/**
5018 ******************************************************************************
5019 * Name: CIccMpeMatrix::Read
5020 *
5021 * Purpose:
5022 *
5023 * Args:
5024 *
5025 * Return:
5026 ******************************************************************************/
5028{
5030
5031 icUInt32Number headerSize = sizeof(icElemTypeSignature) +
5032 sizeof(icUInt32Number) +
5033 sizeof(icUInt16Number) +
5034 sizeof(icUInt16Number);
5035
5036 if (headerSize > size)
5037 return false;
5038
5039 icUInt32Number dataSize = size - headerSize;
5040
5041 if (!pIO) {
5042 return false;
5043 }
5044
5045 icUInt16Number nInputChannels, nOutputChannels;
5046
5047 if (!pIO->Read32(&sig))
5048 return false;
5049
5050 if (!pIO->Read32(&m_nReserved))
5051 return false;
5052
5053 if (!pIO->Read16(&nInputChannels))
5054 return false;
5055
5056 if (!pIO->Read16(&nOutputChannels))
5057 return false;
5058
5059 if (dataSize >= (icUInt32Number)nInputChannels * nOutputChannels * sizeof(icFloatNumber) &&
5060 dataSize < ((icUInt32Number)nInputChannels+1) * nOutputChannels * sizeof(icFloatNumber)) {
5061 //Matrix with no constants
5062 if (!SetSize(nInputChannels, nOutputChannels, false))
5063 return false;
5064
5065 if (!m_pMatrix)
5066 return false;
5067
5068 //Read Matrix data
5069 if (pIO->ReadFloat32Float(m_pMatrix, m_size) != (icInt32Number)m_size)
5070 return false;
5071 }
5072 else if (dataSize < (icUInt32Number)nInputChannels * nOutputChannels *sizeof(icFloatNumber) &&
5073 dataSize >= (icUInt32Number)nOutputChannels * sizeof(icFloatNumber)) {
5074 //Constants with no matrix
5075 if (!SetSize(0, nOutputChannels))
5076 return false;
5077
5078 m_nInputChannels = nInputChannels;
5079
5080 //Read Constant data
5081 if (pIO->ReadFloat32Float(m_pConstants, m_nOutputChannels)!=m_nOutputChannels)
5082 return false;
5083 }
5084 else {
5085 if ((icUInt32Number)nInputChannels*nOutputChannels > dataSize ||
5086 ((icUInt32Number)nInputChannels*nOutputChannels + nOutputChannels) > dataSize ||
5087 ((icUInt32Number)nInputChannels*nOutputChannels + nOutputChannels) * sizeof(icFloat32Number) > dataSize)
5088 return false;
5089
5090 //Matrix with constants
5091 if (!SetSize(nInputChannels, nOutputChannels))
5092 return false;
5093
5094 if (!m_pMatrix)
5095 return false;
5096
5097 if ((m_size + nOutputChannels)*sizeof(icFloat32Number) > dataSize)
5098 return false;
5099
5100 //Read Matrix data
5101 if (pIO->ReadFloat32Float(m_pMatrix, m_size)!=(icInt32Number)m_size)
5102 return false;
5103
5104 //Read Constant data
5105 if (pIO->ReadFloat32Float(m_pConstants, m_nOutputChannels)!=m_nOutputChannels)
5106 return false;
5107 }
5108
5109 return true;
5110}
5111
5112/**
5113 ******************************************************************************
5114 * Name: CIccMpeMatrix::Write
5115 *
5116 * Purpose:
5117 *
5118 * Args:
5119 *
5120 * Return:
5121 ******************************************************************************/
5123{
5124 icElemTypeSignature sig = GetType();
5125
5126 if (!pIO)
5127 return false;
5128
5129 if (!pIO->Write32(&sig))
5130 return false;
5131
5132 if (!pIO->Write32(&m_nReserved))
5133 return false;
5134
5135 if (!pIO->Write16(&m_nInputChannels))
5136 return false;
5137
5138 if (!pIO->Write16(&m_nOutputChannels))
5139 return false;
5140
5141 if (m_pMatrix) {
5142 if (pIO->WriteFloat32Float(m_pMatrix, m_size)!=(icInt32Number)m_size)
5143 return false;
5144 }
5145
5146 //Write Constant data
5147 if (m_pConstants) {
5148 if (pIO->WriteFloat32Float(m_pConstants, m_nOutputChannels)!=m_nOutputChannels)
5149 return false;
5150 }
5151 else {
5152 //Write zero constants because spec says it they have to be there
5153 icFloat32Number zero = 0;
5154 int i;
5155 for (i = 0; i < m_nOutputChannels; i++) {
5156 if (!pIO->WriteFloat32Float(&zero, 1))
5157 return false;
5158 }
5159 }
5160
5161 return true;
5162}
5163
5164/**
5165 ******************************************************************************
5166 * Name: CIccMpeMatrix::Begin
5167 *
5168 * Purpose:
5169 *
5170 * Args:
5171 *
5172 * Return:
5173 ******************************************************************************/
5175{
5176 m_bApplyConstants = false;
5177 if (m_pConstants) {
5178 int i;
5179 for (i = 0; i < m_nOutputChannels; i++) {
5180 if (icNotZero(m_pConstants[i])) {
5181 m_bApplyConstants = true;
5182 break;
5183 }
5184 }
5185 }
5186
5187 if (m_nInputChannels==3 && m_nOutputChannels==3)
5188 m_type = ic3x3Matrix;
5189 else if (m_nInputChannels==3 && m_nOutputChannels==4)
5190 m_type = ic3x4Matrix;
5191 else if (m_nInputChannels==4 && m_nOutputChannels==3)
5192 m_type = ic4x3Matrix;
5193 else if (m_nInputChannels==4 && m_nOutputChannels==4)
5194 m_type = ic4x4Matrix;
5195 else
5196 m_type = icOtherMatrix;
5197
5198 return true;
5199}
5200
5201/**
5202 ******************************************************************************
5203 * Name: CIccMpeMatrix::Apply
5204 *
5205 * Purpose:
5206 *
5207 * Args:
5208 *
5209 * Return:
5210 ******************************************************************************/
5211void CIccMpeMatrix::Apply(CIccApplyMpe *pApply, icFloatNumber *dstPixel, const icFloatNumber *srcPixel) const
5212{
5213 icFloatNumber *data = m_pMatrix;
5214 if (data) {
5215 if (m_bApplyConstants) {
5216 switch (m_type) {
5217 case ic3x3Matrix:
5218 *dstPixel++ = data[ 0]*srcPixel[0] + data[ 1]*srcPixel[1] + data[ 2]*srcPixel[2] + m_pConstants[0];
5219 *dstPixel++ = data[ 3]*srcPixel[0] + data[ 4]*srcPixel[1] + data[ 5]*srcPixel[2] + m_pConstants[1];
5220 *dstPixel = data[ 6]*srcPixel[0] + data[ 7]*srcPixel[1] + data[ 8]*srcPixel[2] + m_pConstants[2];
5221 break;
5222
5223 case ic3x4Matrix:
5224 *dstPixel++ = data[ 0]*srcPixel[0] + data[ 1]*srcPixel[1] + data[ 2]*srcPixel[2] + m_pConstants[0];
5225 *dstPixel++ = data[ 3]*srcPixel[0] + data[ 4]*srcPixel[1] + data[ 5]*srcPixel[2] + m_pConstants[1];
5226 *dstPixel++ = data[ 6]*srcPixel[0] + data[ 7]*srcPixel[1] + data[ 8]*srcPixel[2] + m_pConstants[2];
5227 *dstPixel = data[ 9]*srcPixel[0] + data[10]*srcPixel[1] + data[11]*srcPixel[2] + m_pConstants[3];
5228 break;
5229
5230 case ic4x3Matrix:
5231 *dstPixel++ = data[ 0]*srcPixel[0] + data[ 1]*srcPixel[1] + data[ 2]*srcPixel[2] + data[ 3]*srcPixel[3] + m_pConstants[0];
5232 *dstPixel++ = data[ 4]*srcPixel[0] + data[ 5]*srcPixel[1] + data[ 6]*srcPixel[2] + data[ 7]*srcPixel[3] + m_pConstants[1];
5233 *dstPixel = data[ 8]*srcPixel[0] + data[ 9]*srcPixel[1] + data[10]*srcPixel[2] + data[11]*srcPixel[3] + m_pConstants[2];
5234 break;
5235
5236 case ic4x4Matrix:
5237 *dstPixel++ = data[ 0]*srcPixel[0] + data[ 1]*srcPixel[1] + data[ 2]*srcPixel[2] + data[ 3]*srcPixel[3] + m_pConstants[0];
5238 *dstPixel++ = data[ 4]*srcPixel[0] + data[ 5]*srcPixel[1] + data[ 6]*srcPixel[2] + data[ 7]*srcPixel[3] + m_pConstants[1];
5239 *dstPixel++ = data[ 8]*srcPixel[0] + data[ 9]*srcPixel[1] + data[10]*srcPixel[2] + data[11]*srcPixel[3] + m_pConstants[2];
5240 *dstPixel = data[12]*srcPixel[0] + data[13]*srcPixel[1] + data[14]*srcPixel[2] + data[15]*srcPixel[3] + m_pConstants[3];
5241 break;
5242
5243 case icOtherMatrix:
5244 default:
5245 {
5246 int i, j;
5247
5248 for (j=0; j<m_nOutputChannels; j++) {
5249 *dstPixel = m_pConstants[j];
5250
5251 for (i=0; i<m_nInputChannels; i++) {
5252 *dstPixel += data[i]*srcPixel[i];
5253 }
5254
5255 data += i;
5256 dstPixel++;
5257 }
5258 }
5259 break;
5260 }
5261 }
5262 else {
5263 switch (m_type) {
5264 case ic3x3Matrix:
5265 *dstPixel++ = data[0] * srcPixel[0] + data[1] * srcPixel[1] + data[2] * srcPixel[2];
5266 *dstPixel++ = data[3] * srcPixel[0] + data[4] * srcPixel[1] + data[5] * srcPixel[2];
5267 *dstPixel = data[6] * srcPixel[0] + data[7] * srcPixel[1] + data[8] * srcPixel[2];
5268 break;
5269
5270 case ic3x4Matrix:
5271 *dstPixel++ = data[0] * srcPixel[0] + data[1] * srcPixel[1] + data[2] * srcPixel[2];
5272 *dstPixel++ = data[3] * srcPixel[0] + data[4] * srcPixel[1] + data[5] * srcPixel[2];
5273 *dstPixel++ = data[6] * srcPixel[0] + data[7] * srcPixel[1] + data[8] * srcPixel[2];
5274 *dstPixel = data[9] * srcPixel[0] + data[10] * srcPixel[1] + data[11] * srcPixel[2];
5275 break;
5276
5277 case ic4x3Matrix:
5278 *dstPixel++ = data[0] * srcPixel[0] + data[1] * srcPixel[1] + data[2] * srcPixel[2] + data[3] * srcPixel[3];
5279 *dstPixel++ = data[4] * srcPixel[0] + data[5] * srcPixel[1] + data[6] * srcPixel[2] + data[7] * srcPixel[3];
5280 *dstPixel = data[8] * srcPixel[0] + data[9] * srcPixel[1] + data[10] * srcPixel[2] + data[11] * srcPixel[3];
5281 break;
5282
5283 case ic4x4Matrix:
5284 *dstPixel++ = data[0] * srcPixel[0] + data[1] * srcPixel[1] + data[2] * srcPixel[2] + data[3] * srcPixel[3];
5285 *dstPixel++ = data[4] * srcPixel[0] + data[5] * srcPixel[1] + data[6] * srcPixel[2] + data[7] * srcPixel[3];
5286 *dstPixel++ = data[8] * srcPixel[0] + data[9] * srcPixel[1] + data[10] * srcPixel[2] + data[11] * srcPixel[3];
5287 *dstPixel = data[12] * srcPixel[0] + data[13] * srcPixel[1] + data[14] * srcPixel[2] + data[15] * srcPixel[3];
5288 break;
5289
5290 case icOtherMatrix:
5291 default:
5292 {
5293 int i, j;
5294
5295 for (j = 0; j < m_nOutputChannels; j++) {
5296 *dstPixel = 0.0f;
5297
5298 for (i = 0; i < m_nInputChannels; i++) {
5299 *dstPixel += data[i] * srcPixel[i];
5300 }
5301
5302 data += i;
5303 dstPixel++;
5304 }
5305 }
5306 break;
5307 }
5308 }
5309 }
5310 else if (m_bApplyConstants) {
5311 memcpy(dstPixel, m_pConstants, m_nOutputChannels*sizeof(icFloatNumber));
5312 }
5313 else {
5314 memset(dstPixel, 0, m_nOutputChannels * sizeof(icFloatNumber));
5315 }
5316}
5317
5318/**
5319 ******************************************************************************
5320 * Name: CIccMpeMatrix::Validate
5321 *
5322 * Purpose:
5323 *
5324 * Args:
5325 *
5326 * Return:
5327 ******************************************************************************/
5328icValidateStatus CIccMpeMatrix::Validate(std::string sigPath, std::string &sReport, const CIccTagMultiProcessElement* pMPE/*=NULL*/, const CIccProfile *pProfile/*=NULL*/) const
5329{
5330 std::string mpeSigPath = sigPath + icGetSigPath(GetType());
5331 icValidateStatus rv = CIccMultiProcessElement::Validate(sigPath, sReport, pMPE, pProfile);
5332
5333 if (!m_pConstants) {
5334 CIccInfo Info;
5335 std::string sSigPathName = Info.GetSigPathName(mpeSigPath);
5336
5337 sReport += icMsgValidateCriticalError;
5338 sReport += sSigPathName;
5339 sReport += " - Has Empty Matrix Constant data!\n";
5341 }
5342
5343 return rv;
5344}
5345
5346
5348{
5349 return v;
5350}
5351
5352/**
5353 ******************************************************************************
5354 * Name: CIccMpeCLUT::CIccMpeCLUT
5355 *
5356 * Purpose:
5357 *
5358 * Args:
5359 *
5360 * Return:
5361 ******************************************************************************/
5363{
5364 m_pCLUT = NULL;
5365 m_nInputChannels = 0;
5366 m_nOutputChannels = 0;
5367 m_interpType = ic1dInterp;
5368 m_nReserved = 0;
5369}
5370
5371/**
5372 ******************************************************************************
5373 * Name: CIccMpeCLUT::CIccMpeCLUT
5374 *
5375 * Purpose:
5376 *
5377 * Args:
5378 *
5379 * Return:
5380 ******************************************************************************/
5382{
5383 if (clut.m_pCLUT)
5384 m_pCLUT = new CIccCLUT(*clut.m_pCLUT);
5385 else
5386 m_pCLUT = NULL;
5387
5388 m_nReserved = clut.m_nReserved;
5389 m_nInputChannels = clut.m_nInputChannels;
5390 m_nOutputChannels = clut.m_nOutputChannels;
5391 m_interpType = ic1dInterp;
5392}
5393
5394/**
5395 ******************************************************************************
5396 * Name: &CIccMpeCLUT::operator=
5397 *
5398 * Purpose:
5399 *
5400 * Args:
5401 *
5402 * Return:
5403 ******************************************************************************/
5405{
5406 if (m_pCLUT)
5407 delete m_pCLUT;
5408
5409 if (clut.m_pCLUT)
5410 m_pCLUT = new CIccCLUT(*clut.m_pCLUT);
5411 else
5412 m_pCLUT = NULL;
5413
5414 m_nReserved = clut.m_nReserved;
5415 m_nInputChannels = clut.m_nInputChannels;
5416 m_nOutputChannels = clut.m_nOutputChannels;
5417
5418 return *this;
5419}
5420
5421/**
5422 ******************************************************************************
5423 * Name: CIccMpeCLUT::~CIccMpeCLUT
5424 *
5425 * Purpose:
5426 *
5427 * Args:
5428 *
5429 * Return:
5430 ******************************************************************************/
5432{
5433 if (m_pCLUT)
5434 delete m_pCLUT;
5435}
5436
5437/**
5438 ******************************************************************************
5439 * Name: CIccMpeCLUT::SetCLUT
5440 *
5441 * Purpose:
5442 *
5443 * Args:
5444 *
5445 * Return:
5446 ******************************************************************************/
5448{
5449 if (m_pCLUT)
5450 delete m_pCLUT;
5451
5452 m_pCLUT = pCLUT;
5453 if (pCLUT) {
5454 pCLUT->SetClipFunc(NoClip);
5455 m_nInputChannels = pCLUT->GetInputDim();
5456 m_nOutputChannels = pCLUT->GetOutputChannels();
5457 }
5458}
5459
5460/**
5461 ******************************************************************************
5462 * Name: CIccMpeCLUT::Describe
5463 *
5464 * Purpose:
5465 *
5466 * Args:
5467 *
5468 * Return:
5469 ******************************************************************************/
5470void CIccMpeCLUT::Describe(std::string &sDescription, int nVerboseness)
5471{
5472 if (m_pCLUT) {
5473 m_pCLUT->DumpLut(sDescription, "ELEM_CLUT", icSigUnknownData, icSigUnknownData, nVerboseness);
5474 }
5475}
5476
5477/**
5478 ******************************************************************************
5479 * Name: CIccMpeCLUT::Read
5480 *
5481 * Purpose:
5482 *
5483 * Args:
5484 *
5485 * Return:
5486 ******************************************************************************/
5488{
5490
5491 icUInt32Number headerSize = sizeof(icTagTypeSignature) +
5492 sizeof(icUInt32Number) +
5493 sizeof(icUInt16Number) +
5494 sizeof(icUInt16Number) +
5495 16 * sizeof(icUInt8Number);
5496
5497 if (headerSize > size)
5498 return false;
5499
5500 icUInt32Number dataSize = size - headerSize;
5501
5502 if (!pIO) {
5503 return false;
5504 }
5505
5506 if (!pIO->Read32(&sig))
5507 return false;
5508
5509 if (!pIO->Read32(&m_nReserved))
5510 return false;
5511
5512 if (!pIO->Read16(&m_nInputChannels))
5513 return false;
5514
5515 if (!pIO->Read16(&m_nOutputChannels))
5516 return false;
5517
5518 icUInt8Number gridPoints[16];
5519
5520 if (pIO->Read8(gridPoints, 16)!=16) {
5521 return false;
5522 }
5523
5524 icUInt32Number nPoints = (icUInt32Number)m_nInputChannels * m_nOutputChannels;
5525
5526 if (m_nInputChannels > 16 || nPoints > dataSize || nPoints * sizeof (icFloat32Number) > dataSize)
5527 return false;
5528
5529 m_pCLUT = new CIccCLUT((icUInt8Number)m_nInputChannels, (icUInt16Number)m_nOutputChannels, 4);
5530
5531 if (!m_pCLUT)
5532 return false;
5533
5534 m_pCLUT->SetClipFunc(NoClip);
5535
5536 m_pCLUT->Init(gridPoints);
5537
5538 icFloatNumber *pData = m_pCLUT->GetData(0);
5539
5540 if (!pData)
5541 return false;
5542
5543 nPoints = m_pCLUT->NumPoints()*m_nOutputChannels;
5544
5545 if (pIO->ReadFloat32Float(pData,nPoints)!= nPoints)
5546 return false;
5547
5548 return true;
5549}
5550
5551/**
5552 ******************************************************************************
5553 * Name: CIccMpeCLUT::Write
5554 *
5555 * Purpose:
5556 *
5557 * Args:
5558 *
5559 * Return:
5560 ******************************************************************************/
5562{
5563 icElemTypeSignature sig = GetType();
5564
5565 if (!pIO)
5566 return false;
5567
5568 if (!pIO->Write32(&sig))
5569 return false;
5570
5571 if (!pIO->Write32(&m_nReserved))
5572 return false;
5573
5574 if (!pIO->Write16(&m_nInputChannels))
5575 return false;
5576
5577 if (!pIO->Write16(&m_nOutputChannels))
5578 return false;
5579
5580 if (m_pCLUT) {
5581 icUInt8Number gridPoints[16];
5582 int i;
5583
5584 for (i=0; i<16; i++)
5585 gridPoints[i] = m_pCLUT->GridPoint(i);
5586
5587 if (pIO->Write8(gridPoints, 16)!=16)
5588 return false;
5589
5590 icFloatNumber *pData = m_pCLUT->GetData(0);
5591 icInt32Number nPoints = m_pCLUT->NumPoints()*m_nOutputChannels;
5592
5593 if (pIO->WriteFloat32Float(pData, nPoints) != nPoints)
5594 return false;
5595 }
5596
5597 return true;
5598}
5599
5600/**
5601 ******************************************************************************
5602 * Name: CIccMpeCLUT::Begin
5603 *
5604 * Purpose:
5605 *
5606 * Args:
5607 *
5608 * Return:
5609 ******************************************************************************/
5611{
5612 if (!m_pCLUT)
5613 return false;
5614
5615 m_pCLUT->Begin();
5616
5617 switch (m_nInputChannels) {
5618 case 1:
5619 m_interpType = ic1dInterp;
5620 break;
5621 case 2:
5622 m_interpType = ic2dInterp;
5623 break;
5624 case 3:
5625 if (nInterp==icElemInterpTetra)
5626 m_interpType = ic3dInterpTetra;
5627 else
5628 m_interpType = ic3dInterp;
5629 break;
5630 case 4:
5631 m_interpType = ic4dInterp;
5632 break;
5633 case 5:
5634 m_interpType = ic5dInterp;
5635 break;
5636 case 6:
5637 m_interpType = ic6dInterp;
5638 break;
5639 default:
5640 m_interpType = icNdInterp;
5641 break;
5642 }
5643 return true;
5644}
5645
5646/**
5647 ******************************************************************************
5648 * Name: CIccMpeCLUT::Apply
5649 *
5650 * Purpose:
5651 *
5652 * Args:
5653 *
5654 * Return:
5655 ******************************************************************************/
5656void CIccMpeCLUT::Apply(CIccApplyMpe *pApply, icFloatNumber *dstPixel, const icFloatNumber *srcPixel) const
5657{
5658 const CIccCLUT *pCLUT = m_pCLUT;
5659
5660 switch(m_interpType) {
5661 case ic1dInterp:
5662 pCLUT->Interp1d(dstPixel, srcPixel);
5663 break;
5664 case ic2dInterp:
5665 pCLUT->Interp2d(dstPixel, srcPixel);
5666 break;
5667 case ic3dInterpTetra:
5668 pCLUT->Interp3dTetra(dstPixel, srcPixel);
5669 break;
5670 case ic3dInterp:
5671 pCLUT->Interp3d(dstPixel, srcPixel);
5672 break;
5673 case ic4dInterp:
5674 pCLUT->Interp4d(dstPixel, srcPixel);
5675 break;
5676 case ic5dInterp:
5677 pCLUT->Interp5d(dstPixel, srcPixel);
5678 break;
5679 case ic6dInterp:
5680 pCLUT->Interp6d(dstPixel, srcPixel);
5681 break;
5682 case icNdInterp:
5683 CIccApplyMpeCLUT* pApplyCLUT = (CIccApplyMpeCLUT*)pApply;
5684 pCLUT->InterpND(dstPixel, srcPixel, pApplyCLUT->m_pApply);
5685 break;
5686 }
5687}
5688
5689/**
5690 ******************************************************************************
5691 * Name: CIccMpeCLUT::Validate
5692 *
5693 * Purpose:
5694 *
5695 * Args:
5696 *
5697 * Return:
5698 ******************************************************************************/
5699icValidateStatus CIccMpeCLUT::Validate(std::string sigPath, std::string &sReport, const CIccTagMultiProcessElement* pMPE/*=NULL*/, const CIccProfile *pProfile/*=NULL*/) const
5700{
5701 std::string mpeSigPath = sigPath + icGetSigPath(GetType());
5702 icValidateStatus rv = CIccMultiProcessElement::Validate(sigPath, sReport, pMPE, pProfile);
5703
5704 if (!m_pCLUT) {
5705 CIccInfo Info;
5706 std::string sSigPathName = Info.GetSigPathName(mpeSigPath);
5707
5708 sReport += icMsgValidateCriticalError;
5709 sReport += sSigPathName;
5710 sReport += " - Has No CLUT!\n";
5712 }
5713
5714 return rv;
5715}
5716
5717
5718/**
5719******************************************************************************
5720* Name: CIccMpeCLUT::Begin
5721*
5722* Purpose:
5723*
5724* Args:
5725*
5726* Return:
5727******************************************************************************/
5729{
5730 if (!m_pCLUT) {
5731 return NULL;
5732 }
5733
5734 CIccApplyCLUT* pApply = m_pCLUT->GetNewApply();
5735 if (!pApply)
5736 return NULL;
5737
5738 CIccApplyMpeCLUT * rv = new CIccApplyMpeCLUT(this, pApply);
5739 if (!rv)
5740 delete pApply;
5741
5742 return rv;
5743}
5744
5745/**
5746**************************************************************************
5747* Name: CIccApplyMpeCLUT::CIccApplyMpeCLUT
5748*
5749* Purpose:
5750* Constructor
5751**************************************************************************
5752*/
5757
5758
5759/**
5760**************************************************************************
5761* Name: CIccApplyMpeCLUT::~CIccApplyMpeCLUT
5762*
5763* Purpose:
5764* Destructor
5765**************************************************************************
5766*/
5768{
5769 if (m_pApply)
5770 delete m_pApply;
5771}
5772
5773
5774/**
5775******************************************************************************
5776* Name: CIccMpeExtCLUT::CIccMpeExtCLUT
5777*
5778* Purpose:
5779*
5780* Args:
5781*
5782* Return:
5783******************************************************************************/
5785{
5786 m_pCLUT = NULL;
5787 m_nInputChannels = 0;
5789
5790 m_nReserved = 0;
5791 m_nReserved2 = 0;
5792
5794}
5795
5796/**
5797******************************************************************************
5798* Name: CIccMpeExtCLUT::CIccMpeExtCLUT
5799*
5800* Purpose:
5801*
5802* Args:
5803*
5804* Return:
5805******************************************************************************/
5811
5812/**
5813******************************************************************************
5814* Name: &CIccMpeExtCLUT::operator=
5815*
5816* Purpose:
5817*
5818* Args:
5819*
5820* Return:
5821******************************************************************************/
5823{
5825
5828
5829 return *this;
5830}
5831
5832/**
5833******************************************************************************
5834* Name: CIccMpeExtCLUT::Describe
5835*
5836* Purpose:
5837*
5838* Args:
5839*
5840* Return:
5841******************************************************************************/
5842void CIccMpeExtCLUT::Describe(std::string &sDescription, int nVerboseness)
5843{
5844 if (m_pCLUT) {
5845 char desc[256];
5846 sprintf(desc, "EXT_ELEM_CLUT(%d)", m_storageType);
5847
5848 m_pCLUT->DumpLut(sDescription, desc, icSigUnknownData, icSigUnknownData, nVerboseness);
5849 }
5850}
5851
5852/**
5853******************************************************************************
5854* Name: CIccMpeExtCLUT::SetStorageType
5855*
5856* Purpose:
5857* Sets storage type of the data stored in the CLUT
5858*
5859* Args:
5860* nStorageType is type of data to use
5861*
5862* Return:
5863* true if valid storage type, false otherwise
5864******************************************************************************/
5866{
5867 m_storageType = nStorateType;
5868
5869 switch (nStorateType) {
5870 case icValueTypeUInt8:
5871 case icValueTypeUInt16:
5872 case icValueTypeFloat16:
5873 case icValueTypeFloat32:
5874 return true;
5875 }
5876 return false;
5877}
5878
5879
5880/**
5881******************************************************************************
5882* Name: CIccMpeExtCLUT::Read
5883*
5884* Purpose:
5885*
5886* Args:
5887*
5888* Return:
5889******************************************************************************/
5891{
5893
5894 icUInt32Number headerSize = sizeof(icTagTypeSignature) +
5895 sizeof(icUInt32Number) +
5896 sizeof(icUInt16Number) +
5897 sizeof(icUInt16Number) +
5898 sizeof(icUInt16Number) +
5899 sizeof(icUInt16Number) +
5900 16 * sizeof(icUInt8Number);
5901
5902 if (headerSize > size)
5903 return false;
5904
5905 icUInt32Number dataSize = size - headerSize;
5906
5907 if (!pIO) {
5908 return false;
5909 }
5910
5911 if (!pIO->Read32(&sig))
5912 return false;
5913
5914 if (!pIO->Read32(&m_nReserved))
5915 return false;
5916
5917 if (!pIO->Read16(&m_nInputChannels))
5918 return false;
5919
5920 if (!pIO->Read16(&m_nOutputChannels))
5921 return false;
5922
5923 if (!pIO->Read16(&m_storageType))
5924 return false;
5925
5926 if (!pIO->Read16(&m_nReserved2))
5927 return false;
5928
5929 icUInt8Number gridPoints[16];
5930
5931 if (pIO->Read8(gridPoints, 16)!=16) {
5932 return false;
5933 }
5934
5936
5937 if (m_nInputChannels > 16 || nPoints > dataSize)
5938 return false;
5939
5941
5942 if (!m_pCLUT)
5943 return false;
5944
5946
5947 if (!m_pCLUT->Init(gridPoints, dataSize, icGetStorageTypeBytes(m_storageType)))
5948 return false;
5949
5950 icFloatNumber *pData = m_pCLUT->GetData(0);
5951
5952 if (!pData)
5953 return false;
5954
5955 nPoints = m_pCLUT->NumPoints()*m_nOutputChannels;
5956
5957 if (nPoints > dataSize)
5958 return false;
5959
5960 switch(m_storageType) {
5961 case icValueTypeUInt8:
5962 if (pIO->ReadUInt8Float(pData,nPoints)!= nPoints)
5963 return false;
5964 break;
5965
5966 case icValueTypeUInt16:
5967 if (nPoints * 2 > dataSize)
5968 return false;
5969
5970 if (pIO->ReadUInt16Float(pData,nPoints)!= nPoints)
5971 return false;
5972 break;
5973
5974 case icValueTypeFloat16:
5975 if (nPoints * 2 > dataSize)
5976 return false;
5977
5978 if (pIO->ReadFloat16Float(pData,nPoints)!= nPoints)
5979 return false;
5980 break;
5981
5982 case icValueTypeFloat32:
5983 if (pIO->ReadFloat32Float(pData,nPoints)!= nPoints)
5984 return false;
5985 break;
5986
5987 default:
5988 return false;
5989 }
5990 return true;
5991}
5992
5993/**
5994******************************************************************************
5995* Name: CIccMpeExtCLUT::Write
5996*
5997* Purpose:
5998*
5999* Args:
6000*
6001* Return:
6002******************************************************************************/
6004{
6006
6007 if (!pIO)
6008 return false;
6009
6010 if (!pIO->Write32(&sig))
6011 return false;
6012
6013 if (!pIO->Write32(&m_nReserved))
6014 return false;
6015
6016 if (!pIO->Write16(&m_nInputChannels))
6017 return false;
6018
6019 if (!pIO->Write16(&m_nOutputChannels))
6020 return false;
6021
6022 if (!pIO->Write16(&m_storageType))
6023 return false;
6024
6025 if (!pIO->Write16(&m_nReserved2))
6026 return false;
6027
6028 if (m_pCLUT) {
6029 icUInt8Number gridPoints[16];
6030 int i;
6031
6032 for (i=0; i<16; i++)
6033 gridPoints[i] = m_pCLUT->GridPoint(i);
6034
6035 if (pIO->Write8(gridPoints, 16)!=16)
6036 return false;
6037
6038 icFloatNumber *pData = m_pCLUT->GetData(0);
6040
6041 switch(m_storageType) {
6042 case icValueTypeUInt8:
6043 if (pIO->WriteUInt8Float(pData,nPoints)!= nPoints)
6044 return false;
6045 break;
6046
6047 case icValueTypeUInt16:
6048 if (pIO->WriteUInt16Float(pData,nPoints)!= nPoints)
6049 return false;
6050 break;
6051
6052 case icValueTypeFloat16:
6053 if (pIO->WriteFloat16Float(pData,nPoints)!= nPoints)
6054 return false;
6055 break;
6056
6057 case icValueTypeFloat32:
6058 if (pIO->WriteFloat32Float(pData,nPoints)!= nPoints)
6059 return false;
6060 break;
6061
6062 default:
6063 return false;
6064 }
6065 }
6066
6067 return true;
6068}
6069
6070
6071/**
6072******************************************************************************
6073* Name: CIccMpeExtCLUT::Validate
6074*
6075* Purpose:
6076*
6077* Args:
6078*
6079* Return:
6080******************************************************************************/
6081icValidateStatus CIccMpeExtCLUT::Validate(std::string sigPath, std::string &sReport, const CIccTagMultiProcessElement* pMPE/*=NULL*/, const CIccProfile *pProfile/*=NULL*/) const
6082{
6083 std::string mpeSigPath = sigPath + icGetSigPath(GetType());
6084 icValidateStatus rv = CIccMpeCLUT::Validate(sigPath, sReport, pMPE, pProfile);
6085
6087 CIccInfo Info;
6088 std::string sSigPathName = Info.GetSigPathName(mpeSigPath);
6089
6090 sReport += icMsgValidateCriticalError;
6091 sReport += sSigPathName;
6092 sReport += " - Invalid value type!\n";
6094 }
6095
6096 return rv;
6097}
6098
6099
6101{
6102 m_pCAM = NULL;
6103 m_nInputChannels = 3;
6105 m_nReserved = 0;
6106}
6107
6109{
6110 if (m_pCAM)
6111 delete m_pCAM;
6112}
6113
6115{
6117
6118 icUInt32Number headerSize = sizeof(icTagTypeSignature) +
6119 sizeof(icUInt32Number) +
6120 sizeof(icUInt16Number)*2 +
6121 8 * sizeof(icFloat32Number);
6122
6123 if (headerSize > size)
6124 return false;
6125
6126 if (!pIO) {
6127 return false;
6128 }
6129
6130 if (!pIO->Read32(&sig))
6131 return false;
6132
6133 if (sig!=GetType())
6134 return false;
6135
6136 if (!pIO->Read32(&m_nReserved))
6137 return false;
6138
6139 if (!pIO->Read16(&m_nInputChannels))
6140 return false;
6141
6142 if (!pIO->Read16(&m_nOutputChannels))
6143 return false;
6144
6145 icFloatNumber param[8];
6146
6147 if (pIO->ReadFloat32Float(param, 8)!=8)
6148 return false;
6149
6150 if (m_pCAM)
6151 delete m_pCAM;
6152
6154
6155 m_pCAM->SetParameter_WhitePoint(&param[0]);
6156 m_pCAM->SetParameter_La(param[3]);
6157 m_pCAM->SetParameter_Yb(param[4]);
6158 m_pCAM->SetParameter_C(param[5]);
6159 m_pCAM->SetParameter_Nc(param[6]);
6160 m_pCAM->SetParameter_F(param[7]);
6161
6162 return true;
6163}
6164
6166{
6167 if (!m_pCAM)
6168 return false;
6169
6171
6172 if (!pIO)
6173 return false;
6174
6175 if (!pIO->Write32(&sig))
6176 return false;
6177
6178 if (!pIO->Write32(&m_nReserved))
6179 return false;
6180
6181 if (!pIO->Write16(&m_nInputChannels))
6182 return false;
6183
6184 if (!pIO->Write16(&m_nOutputChannels))
6185 return false;
6186
6187
6188 icFloatNumber param[8];
6189
6190 m_pCAM->GetParameter_WhitePoint(&param[0]); //sets param[0], param[1], and param[2]
6191 param[3] = m_pCAM->GetParameter_La();
6192 param[4] = m_pCAM->GetParameter_Yb();
6193 param[5] = m_pCAM->GetParameter_C();
6194 param[6] = m_pCAM->GetParameter_Nc();
6195 param[7] = m_pCAM->GetParameter_F();
6196
6197 if (pIO->WriteFloat32Float(&param, 8)!=8)
6198 return false;
6199
6200 return true;
6201}
6202
6204{
6205 if (m_pCAM) {
6206 return true;
6207 }
6208 return false;
6209}
6210
6212{
6213 if (m_pCAM)
6214 delete m_pCAM;
6215 m_pCAM = pCAM;
6216}
6217
6218void CIccMpeCAM::Describe(std::string &sDescription, int nVerboseness)
6219{
6220 sDescription += "Begin ";
6221 sDescription += GetXformName();
6222 sDescription += "\n";
6223
6224 if (m_pCAM) {
6225 char line[256];
6226
6227 icFloatNumber xyz[3];
6229 sprintf(line, "WhitePoint (X=%f, Y=%f, Z=%f)\n", xyz[0], xyz[1], xyz[2]);
6230 sDescription += line;
6231
6232 sprintf(line, "Luminance(La)=%f cd/m^2\n", m_pCAM->GetParameter_La());
6233 sDescription += line;
6234
6235 sprintf(line, "Background Luminance(Yb)=%f cd/m^2\n", m_pCAM->GetParameter_Yb());
6236 sDescription += line;
6237
6238 sprintf(line, "Impact Surround(C)=%f\n", m_pCAM->GetParameter_C());
6239 sDescription += line;
6240
6241 sprintf(line, "Chromatic Induction Factor(Nc)=%f\n", m_pCAM->GetParameter_Nc());
6242 sDescription += line;
6243
6244 sprintf(line, "Adaptation Factor(F)=%f\n", m_pCAM->GetParameter_F());
6245 sDescription += line;
6246
6247 }
6248 sDescription += "End";
6249 sDescription += GetXformName();
6250 sDescription += "\n";
6251}
6252
6253
6254icValidateStatus CIccMpeCAM::Validate(std::string sigPath, std::string &sReport, const CIccTagMultiProcessElement* pMPE/*=NULL*/, const CIccProfile *pProfile/*=NULL*/) const
6255{
6257
6258 if (m_nInputChannels!=3) {
6259 sReport += icMsgValidateCriticalError;
6260 sReport += "CAM Element Must have 3 input channels\n";
6262 }
6263 if (m_nOutputChannels!=3) {
6264 sReport += icMsgValidateCriticalError;
6265 sReport += "CAM Element Must have 3 output channels";
6267 }
6268 if (!m_pCAM) {
6269 sReport += icMsgValidateCriticalError;
6270 sReport += "Invalid CAM";
6272 }
6273
6274 return rv;
6275}
6276
6280
6297
6299{
6300 if (cam.m_pCAM) {
6301 if (m_pCAM)
6302 delete m_pCAM;
6303
6304 m_pCAM = new CIccCamConverter();
6305 icFloatNumber xyz[3];
6306
6314 }
6315 else
6316 m_pCAM = NULL;
6317
6318 return *this;
6319}
6320
6324
6325void CIccMpeJabToXYZ::Apply(CIccApplyMpe *pApply, icFloatNumber *dstPixel, const icFloatNumber *srcPixel) const
6326{
6327 if (m_pCAM)
6328 m_pCAM->JabToXYZ(srcPixel, dstPixel, 1);
6329}
6330
6334
6352
6354{
6355 if (cam.m_pCAM) {
6356 if (m_pCAM)
6357 delete m_pCAM;
6358
6359 m_pCAM = new CIccCamConverter();
6360 icFloatNumber xyz[3];
6361
6369 }
6370 else
6371 m_pCAM = NULL;
6372
6373 return *this;
6374}
6375
6379
6380void CIccMpeXYZToJab::Apply(CIccApplyMpe *pApply, icFloatNumber *dstPixel, const icFloatNumber *srcPixel) const
6381{
6382 if (m_pCAM)
6383 m_pCAM->XYZToJab(srcPixel, dstPixel, 1);
6384}
6385
6386
6387#ifdef USEREFICCMAXNAMESPACE
6388} //namespace refIccMAX
6389#endif
icArraySignature sig
File: IccCAM.h.
float icFloatNumber
All floating point operations/variables in IccProfLib use the icFloatNumber data type.
Definition IccDefs.h:100
char icChar
Definition IccDefs.h:109
icValidateStatus
Definition IccDefs.h:118
@ icValidateOK
Definition IccDefs.h:119
@ icValidateWarning
Definition IccDefs.h:120
@ icValidateCriticalError
Definition IccDefs.h:122
File: IccIO.h.
@ icSeekSet
Definition IccIO.h:83
static icFloatNumber clipPow(double v, double g)
static icFloatNumber NoClip(icFloatNumber v)
std::map< icCurveSetCurvePtr, icCurveSetCurvePtr > icCurveMap
std::map< CIccCurveSetCurve *, icPositionNumber > icCurvePtrMap
std::map< icUInt32Number, CIccCurveSetCurve * > icCurveOffsetMap
File: IccMpeBasic.h.
std::list< CIccCurveSegment * > CIccCurveSegmentList
@ ic3x3Matrix
@ icOtherMatrix
@ ic3x4Matrix
@ ic4x3Matrix
@ ic4x4Matrix
@ ic1dInterp
@ ic3dInterpTetra
@ ic6dInterp
@ icNdInterp
@ ic2dInterp
@ ic4dInterp
@ ic5dInterp
@ ic3dInterp
#define ICC_MAXCALCCURVESIZE
File: IccMpeCalc.h.
icElemInterp
Definition IccTagMPE.h:93
@ icElemInterpTetra
Definition IccTagMPE.h:95
icValidateStatus icMaxStatus(icValidateStatus s1, icValidateStatus s2)
Name: icMaxStatus.
Definition IccUtil.cpp:244
std::string icGetSigPath(icUInt32Number nSig)
Definition IccUtil.cpp:1191
const char * icMsgValidateWarning
Definition IccUtil.cpp:90
bool icValidTagPos(const icPositionNumber &pos, icUInt32Number nTagHeaderSize, icUInt32Number nTagSize, bool bAllowEmpty)
Name: icValidTagPos.
Definition IccUtil.cpp:163
bool icIsNear(icFloatNumber v1, icFloatNumber v2, icFloatNumber nearRange)
Name: icIsNear.
Definition IccUtil.cpp:142
const char * icMsgValidateInformation
Definition IccUtil.cpp:93
icFloatNumber icMax(icFloatNumber v1, icFloatNumber v2)
Definition IccUtil.cpp:903
icUInt32Number icIntMin(icUInt32Number v1, icUInt32Number v2)
Definition IccUtil.cpp:908
icUInt8Number icGetStorageTypeBytes(icUInt16Number nStorageType)
Definition IccUtil.cpp:1375
const char * icMsgValidateCriticalError
Definition IccUtil.cpp:92
bool icValidOverlap(const icPositionNumber &pos1, const icPositionNumber &pos2, bool bAllowSame)
Name: icValidOverlap.
Definition IccUtil.cpp:195
File: IccUtil.h.
#define icNotZero(v)
Definition IccUtil.h:89
icTagTypeSignature
unsigned int icUInt32Number
Class: CIccApplyCLUT.
Definition IccTagLut.h:302
Class: CIccApplyMpeCLUT.
CIccApplyMpeCLUT(CIccMultiProcessElement *pElem, CIccApplyCLUT *pApply)
Name: CIccApplyMpeCLUT::CIccApplyMpeCLUT.
CIccApplyCLUT * m_pApply
virtual ~CIccApplyMpeCLUT()
Name: CIccApplyMpeCLUT::~CIccApplyMpeCLUT.
Class: CIccApplyMpe.
Definition IccTagMPE.h:203
void Apply(icFloatNumber *pDestPixel, const icFloatNumber *pSrcPixel)
Definition IccTagMPE.h:213
Class: CIccTagMultiProcessElement.
Definition IccTagMPE.h:321
Class: CIccCLUT.
Definition IccTagLut.h:326
void Interp4d(icFloatNumber *destPixel, const icFloatNumber *srcPixel) const
Name: CIccCLUT::Interp4d.
icUInt8Number GetInputDim() const
Definition IccTagLut.h:356
icUInt16Number GetOutputChannels() const
Definition IccTagLut.h:357
void SetClipFunc(icCLUTCLIPFUNC ClipFunc)
Definition IccTagLut.h:379
void Interp2d(icFloatNumber *destPixel, const icFloatNumber *srcPixel) const
Name: CIccCLUT::Interp2d.
void Interp6d(icFloatNumber *destPixel, const icFloatNumber *srcPixel) const
Name: CIccCLUT::Interp6d.
void Interp3d(icFloatNumber *destPixel, const icFloatNumber *srcPixel) const
Name: CIccCLUT::Interp3d.
void DumpLut(std::string &sDescription, const icChar *szName, icColorSpaceSignature csInput, icColorSpaceSignature csOutput, int nVerboseness, bool bUseLegacy=false)
Name: CIccCLUT::DumpLut.
void Interp5d(icFloatNumber *destPixel, const icFloatNumber *srcPixel) const
Name: CIccCLUT::Interp5d.
icUInt32Number NumPoints() const
Definition IccTagLut.h:348
icUInt8Number GridPoint(int index) const
Definition IccTagLut.h:350
icFloatNumber * GetData(int index)
Definition IccTagLut.h:347
void Interp3dTetra(icFloatNumber *destPixel, const icFloatNumber *srcPixel) const
Name: CIccCLUT::Interp3dTetra.
void Interp1d(icFloatNumber *destPixel, const icFloatNumber *srcPixel) const
Name: CIccCLUT::Interp1d.
void InterpND(icFloatNumber *destPixel, const icFloatNumber *srcPixel, CIccApplyCLUT *pApply) const
Name: CIccCLUT::InterpND.
bool Init(icUInt8Number nGridPoints, icUInt32Number nMaxSize=0, icUInt8Number nBytesPerPoint=4)
Name: CIccCLUT::Init.
void JabToXYZ(const icFloatNumber *jab, icFloatNumber *xyz, int nbr)
Definition IccCAM.cpp:528
void SetParameter_Nc(icFloatNumber Nc)
Definition IccCAM.cpp:402
void SetParameter_La(icFloatNumber La)
Definition IccCAM.cpp:375
void SetParameter_F(icFloatNumber F)
Definition IccCAM.cpp:411
void GetParameter_WhitePoint(icFloatNumber *whitePoint)
Definition IccCAM.cpp:420
void SetParameter_C(icFloatNumber c)
Definition IccCAM.cpp:393
icFloatNumber GetParameter_C()
Definition IccCAM.cpp:446
icFloatNumber GetParameter_Nc()
Definition IccCAM.cpp:454
icFloatNumber GetParameter_Yb()
Definition IccCAM.cpp:438
void XYZToJab(const icFloatNumber *xyz, icFloatNumber *jab, int nbr)
Definition IccCAM.cpp:470
icFloatNumber GetParameter_F()
Definition IccCAM.cpp:462
void SetParameter_Yb(icFloatNumber YB)
Definition IccCAM.cpp:384
icFloatNumber GetParameter_La()
Definition IccCAM.cpp:430
void SetParameter_WhitePoint(icFloatNumber *whitePoint)
Definition IccCAM.cpp:364
Class: CIccCurveSegment.
Definition IccMpeBasic.h:95
icFloatNumber StartPoint()
icFloatNumber m_startPoint
icFloatNumber m_endPoint
virtual bool Read(icUInt32Number size, CIccIO *pIO)=0
static CIccCurveSegment * Create(icCurveSegSignature sig, icFloatNumber start, icFloatNumber end)
Name: CIccCurveSegment::Create.
icUInt32Number m_nReserved
virtual icFloatNumber Apply(icFloatNumber v) const =0
Class: CIccCurveSetCurve.
static CIccCurveSetCurve * Create(icCurveElemSignature sig)
Name: CIccCurveSetCurve::Create.
virtual bool Read(icUInt32Number size, CIccIO *pIO)=0
virtual CIccCurveSetCurve * NewCopy() const =0
Class: CIccTagFormulaCurveSegment.
icUInt8Number m_nParameters
void SetFunction(icUInt16Number functionType, icUInt8Number num_parameters, icFloatNumber *parameters)
Name: CIccFormulaCurveSegment::SetFunction.
virtual bool Read(icUInt32Number size, CIccIO *pIO)
Name: CIccFormulaCurveSegment::Read.
icUInt16Number m_nFunctionType
icUInt16Number m_nReserved2
virtual bool Begin(CIccCurveSegment *pPrevSeg)
Name: CIccFormulaCurveSegment::Begin.
virtual bool Write(CIccIO *pIO)
Name: CIccFormulaCurveSegment::Write.
CIccFormulaCurveSegment & operator=(const CIccFormulaCurveSegment &seg)
Name: &CIccFormulaCurveSegment::operator=.
virtual void Describe(std::string &sDescription, int nVerboseness)
Name: CIccFormulaCurveSegment::Describe.
virtual icValidateStatus Validate(std::string sigPath, std::string &sReport, const CIccTagMultiProcessElement *pMPE=NULL, const CIccProfile *pProfile=NULL) const
Name: CIccFormulaCurveSegment::Validate.
virtual ~CIccFormulaCurveSegment()
Name: CIccFormulaCurveSegment::~CIccFormulaCurveSegment.
icUInt16Number m_nShortcutType
icFloatNumber * m_params
CIccFormulaCurveSegment(icFloatNumber start, icFloatNumber end)
Name: CIccFormulaCurveSegment::CIccFormulaCurveSegment.
virtual icFloatNumber Apply(icFloatNumber v) const
Name: CIccFormulaCurveSegment::Apply.
Type: Class.
Definition IccIO.h:97
icInt32Number ReadFloat16Float(void *pBufFloat, icInt32Number nNum=1)
Definition IccIO.cpp:269
icInt32Number ReadFloat32Float(void *pBufFloat, icInt32Number nNum=1)
Definition IccIO.cpp:302
virtual icInt32Number Write8(void *pBuf8, icInt32Number nNum=1)
Definition IccIO.h:105
icInt32Number Write16(void *pBuf16, icInt32Number nNum=1)
Definition IccIO.cpp:122
virtual icInt32Number Read8(void *pBuf8, icInt32Number nNum=1)
Definition IccIO.h:104
icInt32Number Read16(void *pBuf16, icInt32Number nNum=1)
Definition IccIO.cpp:114
icInt32Number WriteFloat16Float(void *pBuf16, icInt32Number nNum=1)
Definition IccIO.cpp:285
virtual icInt32Number Tell()
Definition IccIO.h:133
bool Align32()
Write operation to make sure that filelength is evenly divisible by 4.
Definition IccIO.cpp:341
icInt32Number ReadUInt8Float(void *pBufFloat, icInt32Number nNum=1)
Definition IccIO.cpp:203
icInt32Number Write32(void *pBuf32, icInt32Number nNum=1)
Definition IccIO.cpp:152
virtual icInt32Number Seek(icInt32Number nOffset, icSeekVal pos)
Definition IccIO.h:132
icInt32Number WriteFloat32Float(void *pBufFloat, icInt32Number nNum=1)
Definition IccIO.cpp:321
icInt32Number WriteUInt8Float(void *pBuf16, icInt32Number nNum=1)
Definition IccIO.cpp:219
icInt32Number ReadUInt16Float(void *pBufFloat, icInt32Number nNum=1)
Definition IccIO.cpp:236
icInt32Number Read32(void *pBuf32, icInt32Number nNum=1)
Definition IccIO.cpp:143
icInt32Number WriteUInt16Float(void *pBuf16, icInt32Number nNum=1)
Definition IccIO.cpp:252
Type: Class.
Definition IccUtil.h:303
std::string GetSigPathName(std::string sigPath)
Definition IccUtil.cpp:1614
Class: CIccMpeCAM.
virtual bool Begin(icElemInterp nInterp, CIccTagMultiProcessElement *pMPE)
virtual const icChar * GetXformName() const =0
void SetCAM(CIccCamConverter *pCAM)
virtual ~CIccMpeCAM()
CIccCamConverter * m_pCAM
virtual icElemTypeSignature GetType() const =0
virtual bool Write(CIccIO *pIO)
virtual icValidateStatus Validate(std::string sigPath, std::string &sReport, const CIccTagMultiProcessElement *pMPE=NULL, const CIccProfile *pProfile=NULL) const
Name: CIccProcessElement::Validate.
virtual bool Read(icUInt32Number size, CIccIO *pIO)
virtual void Describe(std::string &sDescription, int nVerboseness)
Class: CIccMpeCLUT.
virtual void Describe(std::string &sDescription, int nVerboseness)
Name: CIccMpeCLUT::Describe.
virtual bool Write(CIccIO *pIO)
Name: CIccMpeCLUT::Write.
virtual bool Begin(icElemInterp nInterp, CIccTagMultiProcessElement *pMPE)
Name: CIccMpeCLUT::Begin.
virtual icValidateStatus Validate(std::string sigPath, std::string &sReport, const CIccTagMultiProcessElement *pMPE=NULL, const CIccProfile *pProfile=NULL) const
Name: CIccMpeCLUT::Validate.
void SetCLUT(CIccCLUT *pCLUT)
Name: CIccMpeCLUT::SetCLUT.
virtual ~CIccMpeCLUT()
Name: CIccMpeCLUT::~CIccMpeCLUT.
virtual bool Read(icUInt32Number size, CIccIO *pIO)
Name: CIccMpeCLUT::Read.
virtual void Apply(CIccApplyMpe *pApply, icFloatNumber *dstPixel, const icFloatNumber *srcPixel) const
Name: CIccMpeCLUT::Apply.
CIccCLUT * m_pCLUT
virtual CIccApplyMpe * GetNewApply(CIccApplyTagMpe *pApplyTag)
Name: CIccMpeCLUT::Begin.
CIccMpeCLUT()
Name: CIccMpeCLUT::CIccMpeCLUT.
CIccMpeCLUT & operator=(const CIccMpeCLUT &clut)
Name: &CIccMpeCLUT::operator=.
Class: CIccMpeCalculator.
Definition IccMpeCalc.h:447
virtual CIccMpeCalculator * NewCopy() const
Definition IccMpeCalc.h:452
Class: CIccMpeCurveSet.
virtual bool Begin(icElemInterp nInterp, CIccTagMultiProcessElement *pMPE)
Name: CIccMpeCurveSet::Begin.
virtual ~CIccMpeCurveSet()
Name: CIccMpeCurveSet::~CIccMpeCurveSet.
bool SetSize(int nNewSize)
Name: CIccMpeCurveSet::SetSize.
virtual bool Read(icUInt32Number size, CIccIO *pIO)
Name: CIccMpeCurveSet::Read.
virtual void Describe(std::string &sDescription, int nVerboseness)
Name: CIccMpeCurveSet::Describe.
virtual bool Write(CIccIO *pIO)
Name: CIccMpeCurveSet::Write.
CIccMpeCurveSet & operator=(const CIccMpeCurveSet &curveSet)
Name: &CIccMpeCurveSet::operator=.
icCurveSetCurvePtr * m_curve
bool SetCurve(int nIndex, icCurveSetCurvePtr newCurve)
Name: CIccMpeCurveSet::SetCurve.
CIccMpeCurveSet(int nSize=0)
Name: CIccMpeCurveSet::CIccMpeCurveSet.
virtual void Apply(CIccApplyMpe *pApply, icFloatNumber *dstPixel, const icFloatNumber *srcPixel) const
Name: CIccMpeCurveSet::Apply.
virtual icValidateStatus Validate(std::string sigPath, std::string &sReport, const CIccTagMultiProcessElement *pMPE=NULL, const CIccProfile *pProfile=NULL) const
Name: CIccMpeCurveSet::Validate.
CIccMpeExtCLUT()
Name: CIccMpeExtCLUT::CIccMpeExtCLUT.
bool SetStorageType(icUInt16Number nStorateType)
Name: CIccMpeExtCLUT::SetStorageType.
virtual bool Read(icUInt32Number size, CIccIO *pIO)
Name: CIccMpeExtCLUT::Read.
virtual icValidateStatus Validate(std::string sigPath, std::string &sReport, const CIccTagMultiProcessElement *pMPE=NULL, const CIccProfile *pProfile=NULL) const
Name: CIccMpeExtCLUT::Validate.
virtual void Describe(std::string &sDescription, int nVerboseness)
Name: CIccMpeExtCLUT::Describe.
icUInt16Number m_nReserved2
CIccMpeExtCLUT & operator=(const CIccMpeExtCLUT &clut)
Name: &CIccMpeExtCLUT::operator=.
virtual icElemTypeSignature GetType() const
virtual bool Write(CIccIO *pIO)
Name: CIccMpeExtCLUT::Write.
icUInt16Number m_storageType
Class: CIccMpeJabToXYZ.
virtual void Apply(CIccApplyMpe *pApply, icFloatNumber *dstPixel, const icFloatNumber *srcPixel) const
virtual ~CIccMpeJabToXYZ()
CIccMpeJabToXYZ & operator=(const CIccMpeJabToXYZ &cam)
Class: CIccMpeMatrix.
icUInt32Number m_size
icFloatNumber * m_pConstants
virtual ~CIccMpeMatrix()
Name: CIccMpeMatrix::~CIccMpeMatrix.
CIccMpeMatrix & operator=(const CIccMpeMatrix &ParamCurveTag)
Name: &CIccMpeMatrix::operator=.
virtual bool Begin(icElemInterp nInterp, CIccTagMultiProcessElement *pMPE)
Name: CIccMpeMatrix::Begin.
virtual icValidateStatus Validate(std::string sigPath, std::string &sReport, const CIccTagMultiProcessElement *pMPE=NULL, const CIccProfile *pProfile=NULL) const
Name: CIccMpeMatrix::Validate.
virtual bool Write(CIccIO *pIO)
Name: CIccMpeMatrix::Write.
CIccMpeMatrix()
Name: CIccMpeMatrix::CIccMpeMatrix.
bool SetSize(icUInt16Number nInputChannels, icUInt16Number nOutputChannels, bool bUseConstants=true)
Name: CIccMpeMatrix::SetSize.
virtual bool Read(icUInt32Number size, CIccIO *pIO)
Name: CIccMpeMatrix::Read.
virtual void Apply(CIccApplyMpe *pApply, icFloatNumber *dstPixel, const icFloatNumber *srcPixel) const
Name: CIccMpeMatrix::Apply.
bool m_bApplyConstants
icFloatNumber * m_pMatrix
virtual void Describe(std::string &sDescription, int nVerboseness)
Name: CIccMpeMatrix::Describe.
Class: CIccMpeTintArray.
void SetVectorSize(int nVectorSize)
Name: CIccMpeTintArray::SetVectorSize.
virtual ~CIccMpeTintArray()
Name: CIccMpeTintArray::~CIccMpeTintArray.
virtual bool Read(icUInt32Number size, CIccIO *pIO)
Name: CIccMpeTintArray::Read.
CIccTagNumArray * m_Array
virtual icValidateStatus Validate(std::string sigPath, std::string &sReport, const CIccTagMultiProcessElement *pMPE=NULL, const CIccProfile *pProfile=NULL) const
Name: CIccMpeTintArray::Validate.
CIccMpeTintArray(int nVectorSize=1)
Name: CIccMpeTintArray::CIccMpeTintArray.
virtual void Apply(CIccApplyMpe *pApply, icFloatNumber *dstPixel, const icFloatNumber *srcPixel) const
Name: CIccMpeTintArray::Apply.
CIccMpeTintArray & operator=(const CIccMpeTintArray &tintArray)
Name: &CIccMpeTintArray::operator=.
virtual void Describe(std::string &sDescription, int nVerboseness=0)
Name: CIccMpeTintArray::Describe.
virtual bool Begin(icElemInterp nInterp, CIccTagMultiProcessElement *pMPE)
Name: CIccMpeTintArray::Begin.
void SetArray(CIccTagNumArray *pTag)
Name: CIccMpeTintArray::SetCurve.
virtual bool Write(CIccIO *pIO)
Name: CIccMpeTintArray::Write.
Class: CIccMpeToneMap.
virtual bool Begin(icElemInterp nInterp, CIccTagMultiProcessElement *pMPE)
Name: CIccMpeToneMap::Begin.
virtual bool Read(icUInt32Number size, CIccIO *pIO)
Name: CIccMpeToneMap::Read.
CIccToneMapFunc ** m_pToneFuncs
virtual bool Write(CIccIO *pIO)
Name: CIccMpeToneMap::Write.
CIccMpeToneMap(icUInt16Number nOutputChannels=1)
Name: CIccMpeToneMap::CIccMpeToneMap.
virtual void Apply(CIccApplyMpe *pApply, icFloatNumber *dstPixel, const icFloatNumber *srcPixel) const
Name: CIccMpeToneMap::Apply.
icUInt16Number m_nFunc
void ClearToneFuncs()
Name: CIccMpeToneMap::ClearToneFuncs.
void SetNumOutputChannels(icUInt16Number nOutputChannels)
Name: CIccMpeToneMap::SetNumOutputChannels.
bool Insert(CIccToneMapFunc *pToneMapFunc)
Name: CIccMpeToneMap::PushBackFunc.
void SetLumCurve(CIccCurveSetCurve *pLumCurve)
Name: CIccMpeToneMap::SetLumCurve.
CIccCurveSetCurve * m_pLumCurve
virtual ~CIccMpeToneMap()
Name: CIccMpeToneMap::~CIccMpeToneMap.
CIccToneMapFunc ** CopyToneFuncs() const
Name: CIccMpeToneMap::CopyToneFuncs.
CIccMpeToneMap & operator=(const CIccMpeToneMap &toneMap)
Name: &CIccMpeToneMap::operator=.
virtual icValidateStatus Validate(std::string sigPath, std::string &sReport, const CIccTagMultiProcessElement *pMPE=NULL, const CIccProfile *pProfile=NULL) const
Name: CIccMpeToneMap::Validate.
virtual void Describe(std::string &sDescription, int nVerboseness=0)
Name: CIccMpeToneMap::Describe.
Class: CIccMpeXYZToJab.
virtual ~CIccMpeXYZToJab()
CIccMpeXYZToJab & operator=(const CIccMpeXYZToJab &cam)
virtual void Apply(CIccApplyMpe *pApply, icFloatNumber *dstPixel, const icFloatNumber *srcPixel) const
Class: CIccMultiProcessElement.
Definition IccTagMPE.h:146
icUInt16Number m_nOutputChannels
Definition IccTagMPE.h:192
static CIccMultiProcessElement * Create(icElemTypeSignature sig)
Name: CIccMultiProcessElement::Create.
icUInt16Number m_nInputChannels
Definition IccTagMPE.h:191
icUInt32Number m_nReserved
Definition IccTagMPE.h:188
virtual icValidateStatus Validate(std::string sigPath, std::string &sReport, const CIccTagMultiProcessElement *pMPE=NULL, const CIccProfile *pProfile=NULL) const =0
Name: CIccProcessElement::Validate.
Class: CIccSampledCalculatorCurve.
icUInt32Number m_nDesiredSize
virtual bool Read(icUInt32Number size, CIccIO *pIO)
Name: CIccSampledCalculatorCurve::Read.
virtual icValidateStatus Validate(std::string sigPath, std::string &sReport, const CIccTagMultiProcessElement *pMPE=NULL, const CIccProfile *pProfile=NULL) const
Name: CIccSampledCalculatorCurve::Validate.
virtual ~CIccSampledCalculatorCurve()
Name: CIccSampledCalculatorCurve::~CIccSampledCalculatorCurve.
icUInt16Number m_extensionType
CIccSampledCalculatorCurve & operator=(const CIccSampledCalculatorCurve &SampledCurve)
Name: &CIccSampledCalculatorCurve::operator=.
CIccSampledCalculatorCurve(icFloatNumber first=0.0, icFloatNumber last=1.0)
Name: CIccSampledCalculatorCurve::CIccSampledCalculatorCurve.
icUInt16Number m_nReserved2
virtual bool Write(CIccIO *pIO)
Name: CIccSampledCalculatorCurve::Write.
virtual bool SetRecommendedSize(icUInt32Number nSize)
Name: CIccSampledCalculatorCurve::SetRecommendedSize.
CIccMpeCalculator * m_pCalc
bool SetExtensionType(icUInt16Number nExtensionType)
Name: CIccSampledCalculatorCurve::SetExtensionType.
bool SetCalculator(CIccMpeCalculator *pCalc)
Name: CIccSampledCalculatorCurve::SetCalculator Purpose: Sets calculator associated with the curve.
virtual bool Begin(icElemInterp nInterp, CIccTagMultiProcessElement *pMPE)
Name: CIccSampledCalculatorCurve::Begin.
virtual bool SetSize(icUInt32Number nSize, bool bZeroAlloc=true)
Name: CIccSampledCalculatorCurve::SetSize.
virtual void Describe(std::string &sDescription, int nVerboseness=100)
Name: CIccSampledCalculatorCurve::Describe.
virtual icFloatNumber Apply(icFloatNumber v) const
Name: CIccSampledCalculatorCurve::Apply.
void SetRange(icFloatNumber first=0.0f, icFloatNumber last=1.0f)
Name: CIccSampledCalculatorCurve::SetRange.
icFloatNumber * m_pSamples
Class: CIccSampledCurveSegment.
virtual icFloatNumber Apply(icFloatNumber v) const
Name: CIccSampledCurveSegment::Apply.
icFloatNumber * m_pSamples
CIccSampledCurveSegment & operator=(const CIccSampledCurveSegment &ParamCurveTag)
Name: &CIccSampledCurveSegment::operator=.
virtual bool SetSize(icUInt32Number nSize, bool bZeroAlloc=true)
Name: CIccSampledCurveSegment::SetSize.
CIccSampledCurveSegment(icFloatNumber start, icFloatNumber end)
Name: CIccSampledCurveSegment::CIccSampledCurveSegment.
virtual bool Begin(CIccCurveSegment *pPrevSeg)
Name: CIccSampledCurveSegment::Begin.
virtual bool Read(icUInt32Number size, CIccIO *pIO)
Name: CIccSampledCurveSegment::Read.
virtual icValidateStatus Validate(std::string sigPath, std::string &sReport, const CIccTagMultiProcessElement *pMPE=NULL, const CIccProfile *pProfile=NULL) const
Name: CIccSampledCurveSegment::Validate.
virtual ~CIccSampledCurveSegment()
Name: CIccSampledCurveSegment::~CIccSampledCurveSegment.
virtual bool Write(CIccIO *pIO)
Name: CIccSampledCurveSegment::Write.
virtual void Describe(std::string &sDescription, int nVerboseness)
Name: CIccSampledCurveSegment::Describe.
icUInt32Number m_nCount
Class: CIccSegmentedCurve.
icUInt32Number m_nReserved2
virtual ~CIccSegmentedCurve()
Name: CIccSegmentedCurve::~CIccSegmentedCurve.
CIccSegmentedCurve & operator=(const CIccSegmentedCurve &ParamCurveTag)
Name: &CIccSegmentedCurve::operator=.
virtual bool Begin(icElemInterp nInterp, CIccTagMultiProcessElement *pMPE)
Name: CIccSegmentedCurve::Begin.
virtual void Describe(std::string &sDescription, int nVerboseness)
Name: CIccSegmentedCurve::Describe.
virtual bool Read(icUInt32Number size, CIccIO *pIO)
Name: CIccSegmentedCurve::Read.
void Reset()
Name: CIccSegmentedCurve::Reset.
bool Insert(CIccCurveSegment *pCurveSegment)
Name: CIccSegmentedCurve::Insert.
CIccCurveSegmentList * m_list
icUInt32Number m_nReserved1
virtual icValidateStatus Validate(std::string sigPath, std::string &sReport, const CIccTagMultiProcessElement *pMPE=NULL, const CIccProfile *pProfile=NULL) const
Name: CIccSegmentedCurve::Validate.
virtual bool Write(CIccIO *pIO)
Name: CIccSegmentedCurve::Write.
virtual icFloatNumber Apply(icFloatNumber v) const
Name: CIccSegmentedCurve::Apply.
CIccSegmentedCurve()
Name: CIccSegmentedCurve::CIccSegmentedCurve.
Class: CIccSingleSampledCurve.
icUInt32Number m_nReserved
icFloatNumber m_hiSlope
icFloatNumber m_firstEntry
icUInt16Number m_extensionType
bool SetStorageType(icUInt16Number nStorateType)
Name: CIccSingleSampledCurve::SetStorageType.
void SetRange(icFloatNumber first=0.0f, icFloatNumber last=1.0f)
Name: CIccSingleSampledCurve::SetRange.
icUInt32Number m_nCount
virtual icFloatNumber Apply(icFloatNumber v) const
Name: CIccSingleSampledCurve::Apply.
virtual ~CIccSingleSampledCurve()
Name: CIccSingleSampledCurve::~CIccSingleSampledCurve.
virtual void Describe(std::string &sDescription, int nVerboseness)
Name: CIccSingleSampledCurve::Describe.
virtual bool Read(icUInt32Number size, CIccIO *pIO)
Name: CIccSingleSampledCurve::Read.
virtual bool Begin(icElemInterp nInterp, CIccTagMultiProcessElement *pMPE)
Name: CIccSingleSampledCurve::Begin.
icFloatNumber m_lastEntry
icFloatNumber m_loIntercept
icFloatNumber * m_pSamples
bool SetExtensionType(icUInt16Number nExtensionType)
Name: CIccSingleSampledCurve::SetExtensionType.
icUInt16Number m_storageType
CIccSingleSampledCurve(icFloatNumber first=0.0, icFloatNumber last=1.0)
Name: CIccSingleSampledCurve::CIccSingleSampledCurve.
icFloatNumber m_loSlope
virtual bool SetSize(icUInt32Number nSize, bool bZeroAlloc=true)
Name: CIccSingleSampledCurve::SetSize.
virtual icValidateStatus Validate(std::string sigPath, std::string &sReport, const CIccTagMultiProcessElement *pMPE=NULL, const CIccProfile *pProfile=NULL) const
Name: CIccSingleSampledCurve::Validate.
CIccSingleSampledCurve & operator=(const CIccSingleSampledCurve &SampledCurve)
Name: &CIccSingleSampledCurve::operator=.
icFloatNumber m_hiIntercept
virtual bool Write(CIccIO *pIO)
Name: CIccSingleSampledCurve::Write.
Class: CIccTag.
static CIccTag * Create(icTagTypeSignature sig)
Name: CIccTag::Create.
virtual bool IsNumArrayType() const
virtual CIccTag * NewCopy() const
Function: NewCopy(sDescription) Each derived tag will implement it's own NewCopy() function.
Class: CIccTagMultiProcessElement.
Definition IccTagMPE.h:358
Class: CIccTagNumArray.
Class: CIccToneMapFunc.
icUInt16Number m_nReserved2
virtual ~CIccToneMapFunc()
CIccToneMapFunc & operator=(const CIccToneMapFunc &toneMap)
icUInt32Number m_nReserved
void Describe(std::string &sDescription, int nVerboseness=0)
icUInt16Number m_nFunctionType
int NumArgs() const
icUInt8Number m_nParameters
icFloatNumber * m_params
icFloatNumber Apply(icFloatNumber lumValue, icFloatNumber pixelValue) const
icValidateStatus Validate(std::string &sFuncReport, int nVerboseness=0) const
bool SetFunction(icUInt16Number nFunc, icUInt8Number, icFloatNumber *pParams)
bool Read(icUInt32Number size, CIccIO *pIO)
bool Write(CIccIO *pIO)
virtual CIccToneMapFunc * NewCopy() const
icCurveElemSignature
MPE Curve Set Curve signature.
@ icSigSegmentedCurve
@ icSigSampledCalculatorCurve
@ icSigSingleSampledCurve
unsigned char icUInt8Number
Number definitions.
#define icMaxSingleSampledCurveType
float icFloat32Number
icToneFunctionSignature
MPE Tone Map Function signature.
@ icSigToneMapFunction
unsigned short icUInt16Number
long icInt32Number
#define icMaxValueType
icCurveSegSignature
MPE Curve segment Signatures.
@ icSigSampledCurveSeg
@ icSigFormulaCurveSeg
icElemTypeSignature
Multi-Processing Element type signatures.
@ icSigCalculatorElemType
#define icVersionNumberV5_1
@ icExtendSingleSampledCurve
@ icClipSingleSampledCurve
#define icMinFloat32Number
#define icSigUnknownData
@ icValueTypeFloat16
@ icValueTypeUInt8
@ icValueTypeUInt16
@ icValueTypeFloat32
#define icMaxFloat32Number
Useful macros for defining Curve Segment breakpoints.
icUInt32Number offset
icUInt32Number size