< prev index next >

src/java.desktop/share/native/liblcms/cmstypes.c

Print this page




 311 //The XYZType contains an array of three encoded values for the XYZ tristimulus
 312 //values. Tristimulus values must be non-negative. The signed encoding allows for
 313 //implementation optimizations by minimizing the number of fixed formats.
 314 
 315 
 316 static
 317 void *Type_XYZ_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
 318 {
 319     cmsCIEXYZ* xyz;
 320 
 321     *nItems = 0;
 322     xyz = (cmsCIEXYZ*) _cmsMallocZero(self ->ContextID, sizeof(cmsCIEXYZ));
 323     if (xyz == NULL) return NULL;
 324 
 325     if (!_cmsReadXYZNumber(io, xyz)) {
 326         _cmsFree(self ->ContextID, xyz);
 327         return NULL;
 328     }
 329 
 330     *nItems = 1;
 331     return (void*) xyz;
 332 
 333     cmsUNUSED_PARAMETER(SizeOfTag);



 334 }
 335 
 336 static
 337 cmsBool  Type_XYZ_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
 338 {
 339     return _cmsWriteXYZNumber(io, (cmsCIEXYZ*) Ptr);
 340 
 341     cmsUNUSED_PARAMETER(nItems);
 342     cmsUNUSED_PARAMETER(self);



 343 }
 344 
 345 static
 346 void* Type_XYZ_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
 347 {


 348     return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsCIEXYZ));
 349 
 350     cmsUNUSED_PARAMETER(n);
 351 }
 352 
 353 static
 354 void Type_XYZ_Free(struct _cms_typehandler_struct* self, void *Ptr)
 355 {
 356     _cmsFree(self ->ContextID, Ptr);
 357 }
 358 
 359 
 360 static
 361 cmsTagTypeSignature DecideXYZtype(cmsFloat64Number ICCVersion, const void *Data)
 362 {
 363     return cmsSigXYZType;
 364 
 365     cmsUNUSED_PARAMETER(ICCVersion);
 366     cmsUNUSED_PARAMETER(Data);



 367 }
 368 
 369 
 370 // ********************************************************************************
 371 // Type chromaticity. Only one value is allowed
 372 // ********************************************************************************
 373 // The chromaticity tag type provides basic chromaticity data and type of
 374 // phosphors or colorants of a monitor to applications and utilities.
 375 
 376 static
 377 void *Type_Chromaticity_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
 378 {
 379     cmsCIExyYTRIPLE* chrm;
 380     cmsUInt16Number nChans, Table;
 381 
 382     *nItems = 0;
 383     chrm =  (cmsCIExyYTRIPLE*) _cmsMallocZero(self ->ContextID, sizeof(cmsCIExyYTRIPLE));
 384     if (chrm == NULL) return NULL;
 385 
 386     if (!_cmsReadUInt16Number(io, &nChans)) goto Error;


 399     if (!_cmsRead15Fixed16Number(io, &chrm ->Red.x)) goto Error;
 400     if (!_cmsRead15Fixed16Number(io, &chrm ->Red.y)) goto Error;
 401 
 402     chrm ->Red.Y = 1.0;
 403 
 404     if (!_cmsRead15Fixed16Number(io, &chrm ->Green.x)) goto Error;
 405     if (!_cmsRead15Fixed16Number(io, &chrm ->Green.y)) goto Error;
 406 
 407     chrm ->Green.Y = 1.0;
 408 
 409     if (!_cmsRead15Fixed16Number(io, &chrm ->Blue.x)) goto Error;
 410     if (!_cmsRead15Fixed16Number(io, &chrm ->Blue.y)) goto Error;
 411 
 412     chrm ->Blue.Y = 1.0;
 413 
 414     *nItems = 1;
 415     return (void*) chrm;
 416 
 417 Error:
 418     _cmsFree(self ->ContextID, (void*) chrm);


 419     return NULL;
 420 
 421     cmsUNUSED_PARAMETER(SizeOfTag);
 422 }
 423 
 424 static
 425 cmsBool  SaveOneChromaticity(cmsFloat64Number x, cmsFloat64Number y, cmsIOHANDLER* io)
 426 {
 427     if (!_cmsWriteUInt32Number(io, _cmsDoubleTo15Fixed16(x))) return FALSE;
 428     if (!_cmsWriteUInt32Number(io, _cmsDoubleTo15Fixed16(y))) return FALSE;
 429 
 430     return TRUE;
 431 }
 432 
 433 static
 434 cmsBool  Type_Chromaticity_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
 435 {
 436     cmsCIExyYTRIPLE* chrm = (cmsCIExyYTRIPLE*) Ptr;
 437 
 438     if (!_cmsWriteUInt16Number(io, 3)) return FALSE;        // nChannels
 439     if (!_cmsWriteUInt16Number(io, 0)) return FALSE;        // Table
 440 
 441     if (!SaveOneChromaticity(chrm -> Red.x,   chrm -> Red.y, io)) return FALSE;
 442     if (!SaveOneChromaticity(chrm -> Green.x, chrm -> Green.y, io)) return FALSE;
 443     if (!SaveOneChromaticity(chrm -> Blue.x,  chrm -> Blue.y, io)) return FALSE;
 444 
 445     return TRUE;
 446 
 447     cmsUNUSED_PARAMETER(nItems);
 448     cmsUNUSED_PARAMETER(self);



 449 }
 450 
 451 static
 452 void* Type_Chromaticity_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
 453 {


 454     return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsCIExyYTRIPLE));
 455 
 456     cmsUNUSED_PARAMETER(n);
 457 }
 458 
 459 static
 460 void Type_Chromaticity_Free(struct _cms_typehandler_struct* self, void* Ptr)
 461 {
 462     _cmsFree(self ->ContextID, Ptr);
 463 }
 464 
 465 
 466 // ********************************************************************************
 467 // Type cmsSigColorantOrderType
 468 // ********************************************************************************
 469 
 470 // This is an optional tag which specifies the laydown order in which colorants will
 471 // be printed on an n-colorant device. The laydown order may be the same as the
 472 // channel generation order listed in the colorantTableTag or the channel order of a
 473 // colour space such as CMYK, in which case this tag is not needed. When this is not
 474 // the case (for example, ink-towers sometimes use the order KCMY), this tag may be
 475 // used to specify the laydown order of the colorants.
 476 


 481     cmsUInt8Number* ColorantOrder;
 482     cmsUInt32Number Count;
 483 
 484     *nItems = 0;
 485     if (!_cmsReadUInt32Number(io, &Count)) return NULL;
 486     if (Count > cmsMAXCHANNELS) return NULL;
 487 
 488     ColorantOrder = (cmsUInt8Number*) _cmsCalloc(self ->ContextID, cmsMAXCHANNELS, sizeof(cmsUInt8Number));
 489     if (ColorantOrder == NULL) return NULL;
 490 
 491     // We use FF as end marker
 492     memset(ColorantOrder, 0xFF, cmsMAXCHANNELS * sizeof(cmsUInt8Number));
 493 
 494     if (io ->Read(io, ColorantOrder, sizeof(cmsUInt8Number), Count) != Count) {
 495 
 496         _cmsFree(self ->ContextID, (void*) ColorantOrder);
 497         return NULL;
 498     }
 499 
 500     *nItems = 1;


 501     return (void*) ColorantOrder;
 502 
 503     cmsUNUSED_PARAMETER(SizeOfTag);
 504 }
 505 
 506 static
 507 cmsBool Type_ColorantOrderType_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
 508 {
 509     cmsUInt8Number*  ColorantOrder = (cmsUInt8Number*) Ptr;
 510     cmsUInt32Number i, sz, Count;
 511 
 512     // Get the length
 513     for (Count=i=0; i < cmsMAXCHANNELS; i++) {
 514         if (ColorantOrder[i] != 0xFF) Count++;
 515     }
 516 
 517     if (!_cmsWriteUInt32Number(io, Count)) return FALSE;
 518 
 519     sz = Count * sizeof(cmsUInt8Number);
 520     if (!io -> Write(io, sz, ColorantOrder)) return FALSE;
 521 
 522     return TRUE;
 523 
 524     cmsUNUSED_PARAMETER(nItems);
 525     cmsUNUSED_PARAMETER(self);



 526 }
 527 
 528 static
 529 void* Type_ColorantOrderType_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
 530 {


 531     return _cmsDupMem(self ->ContextID, Ptr, cmsMAXCHANNELS * sizeof(cmsUInt8Number));
 532 
 533     cmsUNUSED_PARAMETER(n);
 534 }
 535 
 536 
 537 static
 538 void Type_ColorantOrderType_Free(struct _cms_typehandler_struct* self, void* Ptr)
 539 {
 540     _cmsFree(self ->ContextID, Ptr);
 541 }
 542 
 543 // ********************************************************************************
 544 // Type cmsSigS15Fixed16ArrayType
 545 // ********************************************************************************
 546 // This type represents an array of generic 4-byte/32-bit fixed point quantity.
 547 // The number of values is determined from the size of the tag.
 548 
 549 static
 550 void *Type_S15Fixed16_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
 551 {
 552     cmsFloat64Number*  array_double;
 553     cmsUInt32Number i, n;


 564             _cmsFree(self ->ContextID, array_double);
 565             return NULL;
 566         }
 567     }
 568 
 569     *nItems = n;
 570     return (void*) array_double;
 571 }
 572 
 573 static
 574 cmsBool Type_S15Fixed16_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
 575 {
 576     cmsFloat64Number* Value = (cmsFloat64Number*) Ptr;
 577     cmsUInt32Number i;
 578 
 579     for (i=0; i < nItems; i++) {
 580 
 581         if (!_cmsWrite15Fixed16Number(io, Value[i])) return FALSE;
 582     }
 583 


 584     return TRUE;
 585 
 586     cmsUNUSED_PARAMETER(self);
 587 }
 588 
 589 static
 590 void* Type_S15Fixed16_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
 591 {
 592     return _cmsDupMem(self ->ContextID, Ptr, n * sizeof(cmsFloat64Number));
 593 }
 594 
 595 
 596 static
 597 void Type_S15Fixed16_Free(struct _cms_typehandler_struct* self, void* Ptr)
 598 {
 599     _cmsFree(self ->ContextID, Ptr);
 600 }
 601 
 602 // ********************************************************************************
 603 // Type cmsSigU16Fixed16ArrayType
 604 // ********************************************************************************
 605 // This type represents an array of generic 4-byte/32-bit quantity.
 606 // The number of values is determined from the size of the tag.


 629         array_double[i] =  (cmsFloat64Number) (v / 65536.0);
 630     }
 631 
 632     *nItems = n;
 633     return (void*) array_double;
 634 }
 635 
 636 static
 637 cmsBool Type_U16Fixed16_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
 638 {
 639     cmsFloat64Number* Value = (cmsFloat64Number*) Ptr;
 640     cmsUInt32Number i;
 641 
 642     for (i=0; i < nItems; i++) {
 643 
 644         cmsUInt32Number v = (cmsUInt32Number) floor(Value[i]*65536.0 + 0.5);
 645 
 646         if (!_cmsWriteUInt32Number(io, v)) return FALSE;
 647     }
 648 


 649     return TRUE;
 650 
 651     cmsUNUSED_PARAMETER(self);
 652 }
 653 
 654 
 655 static
 656 void* Type_U16Fixed16_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
 657 {
 658     return _cmsDupMem(self ->ContextID, Ptr, n * sizeof(cmsFloat64Number));
 659 }
 660 
 661 static
 662 void Type_U16Fixed16_Free(struct _cms_typehandler_struct* self, void* Ptr)
 663 {
 664     _cmsFree(self ->ContextID, Ptr);
 665 }
 666 
 667 // ********************************************************************************
 668 // Type cmsSigSignatureType
 669 // ********************************************************************************
 670 //
 671 // The signatureType contains a four-byte sequence, Sequences of less than four
 672 // characters are padded at the end with spaces, 20h.
 673 // Typically this type is used for registered tags that can be displayed on many
 674 // development systems as a sequence of four characters.
 675 
 676 static
 677 void *Type_Signature_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
 678 {
 679     cmsSignature* SigPtr = (cmsSignature*) _cmsMalloc(self ->ContextID, sizeof(cmsSignature));
 680     if (SigPtr == NULL) return NULL;
 681 
 682      if (!_cmsReadUInt32Number(io, SigPtr)) return NULL;
 683      *nItems = 1;
 684 


 685      return SigPtr;
 686 
 687      cmsUNUSED_PARAMETER(SizeOfTag);
 688 }
 689 
 690 static
 691 cmsBool  Type_Signature_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
 692 {
 693     cmsSignature* SigPtr = (cmsSignature*) Ptr;
 694 
 695     return _cmsWriteUInt32Number(io, *SigPtr);
 696 
 697     cmsUNUSED_PARAMETER(nItems);
 698     cmsUNUSED_PARAMETER(self);



 699 }
 700 
 701 static
 702 void* Type_Signature_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
 703 {
 704     return _cmsDupMem(self ->ContextID, Ptr, n * sizeof(cmsSignature));
 705 }
 706 
 707 static
 708 void Type_Signature_Free(struct _cms_typehandler_struct* self, void* Ptr)
 709 {
 710     _cmsFree(self ->ContextID, Ptr);
 711 }
 712 
 713 
 714 // ********************************************************************************
 715 // Type cmsSigTextType
 716 // ********************************************************************************
 717 //
 718 // The textType is a simple text structure that contains a 7-bit ASCII text string.


 764 {
 765     cmsMLU* mlu = (cmsMLU*) Ptr;
 766     cmsUInt32Number size;
 767     cmsBool  rc;
 768     char* Text;
 769 
 770     // Get the size of the string. Note there is an extra "\0" at the end
 771     size = cmsMLUgetASCII(mlu, cmsNoLanguage, cmsNoCountry, NULL, 0);
 772     if (size == 0) return FALSE;       // Cannot be zero!
 773 
 774     // Create memory
 775     Text = (char*) _cmsMalloc(self ->ContextID, size);
 776     if (Text == NULL) return FALSE;
 777 
 778     cmsMLUgetASCII(mlu, cmsNoLanguage, cmsNoCountry, Text, size);
 779 
 780     // Write it, including separator
 781     rc = io ->Write(io, size, Text);
 782 
 783     _cmsFree(self ->ContextID, Text);


 784     return rc;
 785 
 786     cmsUNUSED_PARAMETER(nItems);
 787 }
 788 
 789 static
 790 void* Type_Text_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
 791 {
 792     return (void*) cmsMLUdup((cmsMLU*) Ptr);
 793 
 794     cmsUNUSED_PARAMETER(n);
 795     cmsUNUSED_PARAMETER(self);



 796 }
 797 
 798 
 799 static
 800 void Type_Text_Free(struct _cms_typehandler_struct* self, void* Ptr)
 801 {
 802     cmsMLU* mlu = (cmsMLU*) Ptr;
 803     cmsMLUfree(mlu);


 804     return;
 805 
 806     cmsUNUSED_PARAMETER(self);
 807 }
 808 
 809 static
 810 cmsTagTypeSignature DecideTextType(cmsFloat64Number ICCVersion, const void *Data)
 811 {


 812     if (ICCVersion >= 4.0)
 813         return cmsSigMultiLocalizedUnicodeType;
 814 
 815     return cmsSigTextType;
 816 
 817     cmsUNUSED_PARAMETER(Data);
 818 }
 819 
 820 
 821 // ********************************************************************************
 822 // Type cmsSigDataType
 823 // ********************************************************************************
 824 
 825 // General purpose data type
 826 static
 827 void *Type_Data_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
 828 {
 829     cmsICCData* BinData;
 830     cmsUInt32Number LenOfData;
 831 
 832     *nItems = 0;
 833 
 834     if (SizeOfTag < sizeof(cmsUInt32Number)) return NULL;
 835 
 836     LenOfData = SizeOfTag - sizeof(cmsUInt32Number);
 837     if (LenOfData > INT_MAX) return NULL;


 845         return NULL;
 846     }
 847 
 848     if (io -> Read(io, BinData ->data, sizeof(cmsUInt8Number), LenOfData) != LenOfData) {
 849 
 850         _cmsFree(self ->ContextID, BinData);
 851         return NULL;
 852     }
 853 
 854     *nItems = 1;
 855 
 856     return (void*) BinData;
 857 }
 858 
 859 
 860 static
 861 cmsBool Type_Data_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
 862 {
 863    cmsICCData* BinData = (cmsICCData*) Ptr;
 864 



 865    if (!_cmsWriteUInt32Number(io, BinData ->flag)) return FALSE;
 866 
 867    return io ->Write(io, BinData ->len, BinData ->data);
 868 
 869    cmsUNUSED_PARAMETER(nItems);
 870    cmsUNUSED_PARAMETER(self);
 871 }
 872 
 873 
 874 static
 875 void* Type_Data_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
 876 {
 877     cmsICCData* BinData = (cmsICCData*) Ptr;
 878 


 879     return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsICCData) + BinData ->len - 1);
 880 
 881     cmsUNUSED_PARAMETER(n);
 882 }
 883 
 884 static
 885 void Type_Data_Free(struct _cms_typehandler_struct* self, void* Ptr)
 886 {
 887     _cmsFree(self ->ContextID, Ptr);
 888 }
 889 
 890 // ********************************************************************************
 891 // Type cmsSigTextDescriptionType
 892 // ********************************************************************************
 893 
 894 static
 895 void *Type_Text_Description_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
 896 {
 897     char* Text = NULL;
 898     cmsMLU* mlu = NULL;
 899     cmsUInt32Number  AsciiCount;
 900     cmsUInt32Number  i, UnicodeCode, UnicodeCount;
 901     cmsUInt16Number  ScriptCodeCode, Dummy;


1040     // takes 70 bytes, so we need 2 extra bytes to do the alignment
1041 
1042     if (!_cmsWriteUInt32Number(io, len_aligned+1)) goto Error;
1043 
1044     // Note that in some compilers sizeof(cmsUInt16Number) != sizeof(wchar_t)
1045     if (!_cmsWriteWCharArray(io, len, Wide)) goto Error;
1046     if (!_cmsWriteUInt16Array(io, len_filler_alignment+1, (cmsUInt16Number*) Filler)) goto Error;
1047 
1048     // ScriptCode Code & count (unused)
1049     if (!_cmsWriteUInt16Number(io, 0)) goto Error;
1050     if (!_cmsWriteUInt8Number(io, 0)) goto Error;
1051 
1052     if (!io ->Write(io, 67, Filler)) goto Error;
1053 
1054     rc = TRUE;
1055 
1056 Error:
1057     if (Text) _cmsFree(self ->ContextID, Text);
1058     if (Wide) _cmsFree(self ->ContextID, Wide);
1059 


1060     return rc;
1061 
1062     cmsUNUSED_PARAMETER(nItems);
1063 }
1064 
1065 
1066 static
1067 void* Type_Text_Description_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
1068 {
1069     return (void*) cmsMLUdup((cmsMLU*) Ptr);
1070 
1071     cmsUNUSED_PARAMETER(n);
1072     cmsUNUSED_PARAMETER(self);



1073 }
1074 
1075 static
1076 void Type_Text_Description_Free(struct _cms_typehandler_struct* self, void* Ptr)
1077 {
1078     cmsMLU* mlu = (cmsMLU*) Ptr;
1079 
1080     cmsMLUfree(mlu);


1081     return;
1082 
1083     cmsUNUSED_PARAMETER(self);
1084 }
1085 
1086 
1087 static
1088 cmsTagTypeSignature DecideTextDescType(cmsFloat64Number ICCVersion, const void *Data)
1089 {


1090     if (ICCVersion >= 4.0)
1091         return cmsSigMultiLocalizedUnicodeType;
1092 
1093     return cmsSigTextDescriptionType;
1094 
1095     cmsUNUSED_PARAMETER(Data);
1096 }
1097 
1098 
1099 // ********************************************************************************
1100 // Type cmsSigCurveType
1101 // ********************************************************************************
1102 
1103 static
1104 void *Type_Curve_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
1105 {
1106     cmsUInt32Number Count;
1107     cmsToneCurve* NewGamma;
1108 
1109     *nItems = 0;


1110     if (!_cmsReadUInt32Number(io, &Count)) return NULL;
1111 
1112     switch (Count) {
1113 
1114            case 0:   // Linear.
1115                {
1116                    cmsFloat64Number SingleGamma = 1.0;
1117 
1118                    NewGamma = cmsBuildParametricToneCurve(self ->ContextID, 1, &SingleGamma);
1119                    if (!NewGamma) return NULL;
1120                    *nItems = 1;
1121                    return NewGamma;
1122                }
1123 
1124            case 1:  // Specified as the exponent of gamma function
1125                {
1126                    cmsUInt16Number SingleGammaFixed;
1127                    cmsFloat64Number SingleGamma;
1128 
1129                    if (!_cmsReadUInt16Number(io, &SingleGammaFixed)) return NULL;
1130                    SingleGamma = _cms8Fixed8toDouble(SingleGammaFixed);
1131 
1132                    *nItems = 1;
1133                    return cmsBuildParametricToneCurve(self ->ContextID, 1, &SingleGamma);
1134                }
1135 
1136            default:  // Curve
1137 
1138                if (Count > 0x7FFF)
1139                    return NULL; // This is to prevent bad guys for doing bad things
1140 
1141                NewGamma = cmsBuildTabulatedToneCurve16(self ->ContextID, Count, NULL);
1142                if (!NewGamma) return NULL;
1143 
1144                if (!_cmsReadUInt16Array(io, Count, NewGamma -> Table16)) return NULL;
1145 
1146                *nItems = 1;
1147                return NewGamma;
1148     }
1149 
1150     cmsUNUSED_PARAMETER(SizeOfTag);
1151 }
1152 
1153 
1154 static
1155 cmsBool  Type_Curve_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
1156 {
1157     cmsToneCurve* Curve = (cmsToneCurve*) Ptr;
1158 



1159     if (Curve ->nSegments == 1 && Curve ->Segments[0].Type == 1) {
1160 
1161             // Single gamma, preserve number
1162             cmsUInt16Number SingleGammaFixed = _cmsDoubleTo8Fixed8(Curve ->Segments[0].Params[0]);
1163 
1164             if (!_cmsWriteUInt32Number(io, 1)) return FALSE;
1165             if (!_cmsWriteUInt16Number(io, SingleGammaFixed)) return FALSE;
1166             return TRUE;
1167 
1168     }
1169 
1170     if (!_cmsWriteUInt32Number(io, Curve ->nEntries)) return FALSE;
1171     return _cmsWriteUInt16Array(io, Curve ->nEntries, Curve ->Table16);
1172 
1173     cmsUNUSED_PARAMETER(nItems);
1174     cmsUNUSED_PARAMETER(self);
1175 }
1176 
1177 
1178 static
1179 void* Type_Curve_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
1180 {
1181     return (void*) cmsDupToneCurve((cmsToneCurve*) Ptr);
1182 
1183     cmsUNUSED_PARAMETER(n);
1184     cmsUNUSED_PARAMETER(self);



1185 }
1186 
1187 static
1188 void Type_Curve_Free(struct _cms_typehandler_struct* self, void* Ptr)
1189 {
1190     cmsToneCurve* gamma = (cmsToneCurve*) Ptr;
1191 
1192     cmsFreeToneCurve(gamma);


1193     return;
1194 
1195     cmsUNUSED_PARAMETER(self);
1196 }
1197 
1198 
1199 // ********************************************************************************
1200 // Type cmsSigParametricCurveType
1201 // ********************************************************************************
1202 
1203 
1204 // Decide which curve type to use on writting
1205 static
1206 cmsTagTypeSignature DecideCurveType(cmsFloat64Number ICCVersion, const void *Data)
1207 {
1208     cmsToneCurve* Curve = (cmsToneCurve*) Data;
1209 
1210     if (ICCVersion < 4.0) return cmsSigCurveType;
1211     if (Curve ->nSegments != 1) return cmsSigCurveType;          // Only 1-segment curves can be saved as parametric
1212     if (Curve ->Segments[0].Type < 0) return cmsSigCurveType;    // Only non-inverted curves
1213     if (Curve ->Segments[0].Type > 5) return cmsSigCurveType;    // Only ICC parametric curves
1214 
1215     return cmsSigParametricCurveType;
1216 }
1217 
1218 static
1219 void *Type_ParametricCurve_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
1220 {
1221     static const int ParamsByType[] = { 1, 3, 4, 5, 7 };
1222     cmsFloat64Number Params[10];
1223     cmsUInt16Number Type;
1224     int i, n;
1225     cmsToneCurve* NewGamma;
1226 


1227     if (!_cmsReadUInt16Number(io, &Type)) return NULL;
1228     if (!_cmsReadUInt16Number(io, NULL)) return NULL;   // Reserved
1229 
1230     if (Type > 4) {
1231 
1232         cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown parametric curve type '%d'", Type);
1233         return NULL;
1234     }
1235 
1236     memset(Params, 0, sizeof(Params));
1237     n = ParamsByType[Type];
1238 
1239     for (i=0; i < n; i++) {
1240 
1241         if (!_cmsRead15Fixed16Number(io, &Params[i])) return NULL;
1242     }
1243 
1244     NewGamma = cmsBuildParametricToneCurve(self ->ContextID, Type+1, Params);
1245 
1246     *nItems = 1;

1247     return NewGamma;
1248 
1249     cmsUNUSED_PARAMETER(SizeOfTag);
1250 }
1251 
1252 
1253 static
1254 cmsBool  Type_ParametricCurve_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
1255 {
1256     cmsToneCurve* Curve = (cmsToneCurve*) Ptr;
1257     int i, nParams, typen;
1258     static const int ParamsByType[] = { 0, 1, 3, 4, 5, 7 };
1259 
1260     typen = Curve -> Segments[0].Type;
1261 


1262     if (Curve ->nSegments > 1 || typen < 1) {
1263 
1264         cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Multisegment or Inverted parametric curves cannot be written");
1265         return FALSE;
1266     }
1267 
1268     if (typen > 5) {
1269         cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported parametric curve");
1270         return FALSE;
1271     }
1272 
1273     nParams = ParamsByType[typen];
1274 
1275     if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) (Curve ->Segments[0].Type - 1))) return FALSE;
1276     if (!_cmsWriteUInt16Number(io, 0)) return FALSE;        // Reserved
1277 
1278     for (i=0; i < nParams; i++) {
1279 
1280         if (!_cmsWrite15Fixed16Number(io, Curve -> Segments[0].Params[i])) return FALSE;
1281     }
1282 
1283     return TRUE;
1284 
1285     cmsUNUSED_PARAMETER(nItems);
1286 }
1287 
1288 static
1289 void* Type_ParametricCurve_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
1290 {
1291     return (void*) cmsDupToneCurve((cmsToneCurve*) Ptr);
1292 
1293     cmsUNUSED_PARAMETER(n);
1294     cmsUNUSED_PARAMETER(self);



1295 }
1296 
1297 static
1298 void Type_ParametricCurve_Free(struct _cms_typehandler_struct* self, void* Ptr)
1299 {
1300     cmsToneCurve* gamma = (cmsToneCurve*) Ptr;
1301 
1302     cmsFreeToneCurve(gamma);


1303     return;
1304 
1305     cmsUNUSED_PARAMETER(self);
1306 }
1307 
1308 
1309 // ********************************************************************************
1310 // Type cmsSigDateTimeType
1311 // ********************************************************************************
1312 
1313 // A 12-byte value representation of the time and date, where the byte usage is assigned
1314 // as specified in table 1. The actual values are encoded as 16-bit unsigned integers
1315 // (uInt16Number - see 5.1.6).
1316 //
1317 // All the dateTimeNumber values in a profile shall be in Coordinated Universal Time
1318 // (UTC, also known as GMT or ZULU Time). Profile writers are required to convert local
1319 // time to UTC when setting these values. Programmes that display these values may show
1320 // the dateTimeNumber as UTC, show the equivalent local time (at current locale), or
1321 // display both UTC and local versions of the dateTimeNumber.
1322 
1323 static
1324 void *Type_DateTime_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
1325 {
1326     cmsDateTimeNumber timestamp;
1327     struct tm * NewDateTime;
1328 
1329     *nItems = 0;
1330     NewDateTime = (struct tm*) _cmsMalloc(self ->ContextID, sizeof(struct tm));


1331     if (NewDateTime == NULL) return NULL;
1332 
1333     if (io->Read(io, &timestamp, sizeof(cmsDateTimeNumber), 1) != 1) return NULL;
1334 
1335      _cmsDecodeDateTimeNumber(&timestamp, NewDateTime);
1336 
1337      *nItems = 1;
1338      return NewDateTime;
1339 
1340      cmsUNUSED_PARAMETER(SizeOfTag);
1341 }
1342 
1343 
1344 static
1345 cmsBool  Type_DateTime_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
1346 {
1347     struct tm * DateTime = (struct tm*) Ptr;
1348     cmsDateTimeNumber timestamp;
1349 
1350     _cmsEncodeDateTimeNumber(&timestamp, DateTime);



1351     if (!io ->Write(io, sizeof(cmsDateTimeNumber), &timestamp)) return FALSE;
1352 
1353     return TRUE;
1354 
1355     cmsUNUSED_PARAMETER(nItems);
1356     cmsUNUSED_PARAMETER(self);
1357 }
1358 
1359 static
1360 void* Type_DateTime_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
1361 {


1362     return _cmsDupMem(self ->ContextID, Ptr, sizeof(struct tm));
1363 
1364     cmsUNUSED_PARAMETER(n);
1365 }
1366 
1367 static
1368 void Type_DateTime_Free(struct _cms_typehandler_struct* self, void* Ptr)
1369 {
1370     _cmsFree(self ->ContextID, Ptr);
1371 }
1372 
1373 
1374 
1375 // ********************************************************************************
1376 // Type icMeasurementType
1377 // ********************************************************************************
1378 
1379 /*
1380 The measurementType information refers only to the internal profile data and is
1381 meant to provide profile makers an alternative to the default measurement
1382 specifications.
1383 */
1384 
1385 static
1386 void *Type_Measurement_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
1387 {
1388     cmsICCMeasurementConditions mc;
1389 
1390 
1391     memset(&mc, 0, sizeof(mc));
1392 


1393     if (!_cmsReadUInt32Number(io, &mc.Observer)) return NULL;
1394     if (!_cmsReadXYZNumber(io,    &mc.Backing)) return NULL;
1395     if (!_cmsReadUInt32Number(io, &mc.Geometry)) return NULL;
1396     if (!_cmsRead15Fixed16Number(io, &mc.Flare)) return NULL;
1397     if (!_cmsReadUInt32Number(io, &mc.IlluminantType)) return NULL;
1398 
1399     *nItems = 1;
1400     return _cmsDupMem(self ->ContextID, &mc, sizeof(cmsICCMeasurementConditions));
1401 
1402     cmsUNUSED_PARAMETER(SizeOfTag);
1403 }
1404 
1405 
1406 static
1407 cmsBool  Type_Measurement_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
1408 {
1409     cmsICCMeasurementConditions* mc =(cmsICCMeasurementConditions*) Ptr;
1410 



1411     if (!_cmsWriteUInt32Number(io, mc->Observer)) return FALSE;
1412     if (!_cmsWriteXYZNumber(io,    &mc->Backing)) return FALSE;
1413     if (!_cmsWriteUInt32Number(io, mc->Geometry)) return FALSE;
1414     if (!_cmsWrite15Fixed16Number(io, mc->Flare)) return FALSE;
1415     if (!_cmsWriteUInt32Number(io, mc->IlluminantType)) return FALSE;
1416 
1417     return TRUE;
1418 
1419     cmsUNUSED_PARAMETER(nItems);
1420     cmsUNUSED_PARAMETER(self);
1421 }
1422 
1423 static
1424 void* Type_Measurement_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
1425 {


1426      return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsICCMeasurementConditions));
1427 
1428      cmsUNUSED_PARAMETER(n);
1429 }
1430 
1431 static
1432 void Type_Measurement_Free(struct _cms_typehandler_struct* self, void* Ptr)
1433 {
1434    _cmsFree(self ->ContextID, Ptr);
1435 }
1436 
1437 
1438 // ********************************************************************************
1439 // Type cmsSigMultiLocalizedUnicodeType
1440 // ********************************************************************************
1441 //
1442 //   Do NOT trust SizeOfTag as there is an issue on the definition of profileSequenceDescTag. See the TechNote from
1443 //   Max Derhak and Rohit Patil about this: basically the size of the string table should be guessed and cannot be
1444 //   taken from the size of tag if this tag is embedded as part of bigger structures (profileSequenceDescTag, for instance)
1445 //
1446 
1447 static
1448 void *Type_MLU_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)


1517     mlu ->MemPool  = Block;
1518     mlu ->PoolSize = SizeOfTag;
1519     mlu ->PoolUsed = SizeOfTag;
1520 
1521     *nItems = 1;
1522     return (void*) mlu;
1523 
1524 Error:
1525     if (mlu) cmsMLUfree(mlu);
1526     return NULL;
1527 }
1528 
1529 static
1530 cmsBool  Type_MLU_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
1531 {
1532     cmsMLU* mlu =(cmsMLU*) Ptr;
1533     cmsUInt32Number HeaderSize;
1534     cmsUInt32Number  Len, Offset;
1535     int i;
1536 


1537     if (Ptr == NULL) {
1538 
1539           // Empty placeholder
1540           if (!_cmsWriteUInt32Number(io, 0)) return FALSE;
1541           if (!_cmsWriteUInt32Number(io, 12)) return FALSE;
1542           return TRUE;
1543     }
1544 
1545     if (!_cmsWriteUInt32Number(io, mlu ->UsedEntries)) return FALSE;
1546     if (!_cmsWriteUInt32Number(io, 12)) return FALSE;
1547 
1548     HeaderSize = 12 * mlu ->UsedEntries + sizeof(_cmsTagBase);
1549 
1550     for (i=0; i < mlu ->UsedEntries; i++) {
1551 
1552         Len    =  mlu ->Entries[i].Len;
1553         Offset =  mlu ->Entries[i].StrW;
1554 
1555         Len    = (Len * sizeof(cmsUInt16Number)) / sizeof(wchar_t);
1556         Offset = (Offset * sizeof(cmsUInt16Number)) / sizeof(wchar_t) + HeaderSize + 8;
1557 
1558         if (!_cmsWriteUInt16Number(io, mlu ->Entries[i].Language)) return FALSE;
1559         if (!_cmsWriteUInt16Number(io, mlu ->Entries[i].Country))  return FALSE;
1560         if (!_cmsWriteUInt32Number(io, Len)) return FALSE;
1561         if (!_cmsWriteUInt32Number(io, Offset)) return FALSE;
1562     }
1563 
1564     if (!_cmsWriteWCharArray(io, mlu ->PoolUsed / sizeof(wchar_t), (wchar_t*)  mlu ->MemPool)) return FALSE;
1565 
1566     return TRUE;
1567 
1568     cmsUNUSED_PARAMETER(nItems);
1569     cmsUNUSED_PARAMETER(self);
1570 }
1571 
1572 
1573 static
1574 void* Type_MLU_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
1575 {
1576     return (void*) cmsMLUdup((cmsMLU*) Ptr);
1577 
1578     cmsUNUSED_PARAMETER(n);
1579     cmsUNUSED_PARAMETER(self);



1580 }
1581 
1582 static
1583 void Type_MLU_Free(struct _cms_typehandler_struct* self, void* Ptr)
1584 {
1585     cmsMLUfree((cmsMLU*) Ptr);


1586     return;
1587 
1588     cmsUNUSED_PARAMETER(self);
1589 }
1590 
1591 
1592 // ********************************************************************************
1593 // Type cmsSigLut8Type
1594 // ********************************************************************************
1595 
1596 // Decide which LUT type to use on writting
1597 static
1598 cmsTagTypeSignature DecideLUTtypeA2B(cmsFloat64Number ICCVersion, const void *Data)
1599 {
1600     cmsPipeline* Lut = (cmsPipeline*) Data;
1601 
1602     if (ICCVersion < 4.0) {
1603         if (Lut ->SaveAs8Bits) return cmsSigLut8Type;
1604         return cmsSigLut16Type;
1605     }
1606     else {
1607          return cmsSigLutAtoBType;
1608     }


1833 
1834             *PtrW++ = FROM_8_TO_16(Temp[i]);
1835         }
1836         _cmsFree(self ->ContextID, Temp);
1837         Temp = NULL;
1838 
1839         if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, cmsStageAllocCLut16bit(self ->ContextID, CLUTpoints, InputChannels, OutputChannels, T)))
1840             goto Error;
1841         _cmsFree(self ->ContextID, T);
1842     }
1843 
1844 
1845     // Get output tables
1846     if (!Read8bitTables(self ->ContextID, io,  NewLUT, OutputChannels)) goto Error;
1847 
1848     *nItems = 1;
1849     return NewLUT;
1850 
1851 Error:
1852     if (NewLUT != NULL) cmsPipelineFree(NewLUT);


1853     return NULL;
1854 
1855     cmsUNUSED_PARAMETER(SizeOfTag);
1856 }
1857 
1858 // We only allow a specific MPE structure: Matrix plus prelin, plus clut, plus post-lin.
1859 static
1860 cmsBool  Type_LUT8_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
1861 {
1862     cmsUInt32Number j, nTabSize;
1863     cmsUInt8Number  val;
1864     cmsPipeline* NewLUT = (cmsPipeline*) Ptr;
1865     cmsStage* mpe;
1866     _cmsStageToneCurvesData* PreMPE = NULL, *PostMPE = NULL;
1867     _cmsStageMatrixData* MatMPE = NULL;
1868     _cmsStageCLutData* clut = NULL;
1869     int clutPoints;
1870 
1871     // Disassemble the LUT into components.
1872     mpe = NewLUT -> Elements;
1873     if (mpe ->Type == cmsSigMatrixElemType) {
1874 
1875         MatMPE = (_cmsStageMatrixData*) mpe ->Data;


1936     }
1937 
1938     // The prelinearization table
1939     if (!Write8bitTables(self ->ContextID, io, NewLUT ->InputChannels, PreMPE)) return FALSE;
1940 
1941     nTabSize = uipow(NewLUT->OutputChannels, clutPoints, NewLUT ->InputChannels);
1942     if (nTabSize == (cmsUInt32Number) -1) return FALSE;
1943     if (nTabSize > 0) {
1944 
1945         // The 3D CLUT.
1946         if (clut != NULL) {
1947 
1948             for (j=0; j < nTabSize; j++) {
1949 
1950                 val = (cmsUInt8Number) FROM_16_TO_8(clut ->Tab.T[j]);
1951                 if (!_cmsWriteUInt8Number(io, val)) return FALSE;
1952             }
1953         }
1954     }
1955 

1956     // The postlinearization table
1957     if (!Write8bitTables(self ->ContextID, io, NewLUT ->OutputChannels, PostMPE)) return FALSE;
1958 
1959     return TRUE;
1960 
1961     cmsUNUSED_PARAMETER(nItems);
1962 }
1963 
1964 
1965 static
1966 void* Type_LUT8_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
1967 {
1968     return (void*) cmsPipelineDup((cmsPipeline*) Ptr);
1969 
1970     cmsUNUSED_PARAMETER(n);
1971     cmsUNUSED_PARAMETER(self);



1972 }
1973 
1974 static
1975 void Type_LUT8_Free(struct _cms_typehandler_struct* self, void* Ptr)
1976 {
1977     cmsPipelineFree((cmsPipeline*) Ptr);


1978     return;
1979 
1980     cmsUNUSED_PARAMETER(self);
1981 }
1982 
1983 // ********************************************************************************
1984 // Type cmsSigLut16Type
1985 // ********************************************************************************
1986 
1987 // Read 16 bit tables as gamma functions
1988 static
1989 cmsBool  Read16bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsPipeline* lut, int nChannels, int nEntries)
1990 {
1991     int i;
1992     cmsToneCurve* Tables[cmsMAXCHANNELS];
1993 
1994     // Maybe an empty table? (this is a lcms extension)
1995     if (nEntries <= 0) return TRUE;
1996 
1997     // Check for malicious profiles
1998     if (nEntries < 2) return FALSE;
1999     if (nChannels > cmsMAXCHANNELS) return FALSE;
2000 


2022 Error:
2023     for (i=0; i < nChannels; i++) {
2024         if (Tables[i]) cmsFreeToneCurve(Tables[i]);
2025     }
2026 
2027     return FALSE;
2028 }
2029 
2030 static
2031 cmsBool Write16bitTables(cmsContext ContextID, cmsIOHANDLER* io, _cmsStageToneCurvesData* Tables)
2032 {
2033     int j;
2034     cmsUInt32Number i;
2035     cmsUInt16Number val;
2036     int nEntries;
2037 
2038     _cmsAssert(Tables != NULL);
2039 
2040     nEntries = Tables->TheCurves[0]->nEntries;
2041 

2042     for (i=0; i < Tables ->nCurves; i++) {
2043 
2044         for (j=0; j < nEntries; j++) {
2045 
2046             val = Tables->TheCurves[i]->Table16[j];
2047             if (!_cmsWriteUInt16Number(io, val)) return FALSE;
2048         }
2049     }
2050     return TRUE;
2051 
2052     cmsUNUSED_PARAMETER(ContextID);
2053 }
2054 
2055 static
2056 void *Type_LUT16_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
2057 {
2058     cmsUInt8Number InputChannels, OutputChannels, CLUTpoints;
2059     cmsPipeline* NewLUT = NULL;
2060     cmsUInt32Number nTabSize;
2061     cmsFloat64Number Matrix[3*3];
2062     cmsUInt16Number InputEntries, OutputEntries;
2063 
2064     *nItems = 0;
2065 
2066     if (!_cmsReadUInt8Number(io, &InputChannels)) return NULL;
2067     if (!_cmsReadUInt8Number(io, &OutputChannels)) return NULL;
2068     if (!_cmsReadUInt8Number(io, &CLUTpoints)) return NULL;   // 255 maximum
2069 
2070     // Padding
2071     if (!_cmsReadUInt8Number(io, NULL)) return NULL;
2072 


2120             _cmsFree(self ->ContextID, T);
2121             goto Error;
2122         }
2123 
2124         if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, cmsStageAllocCLut16bit(self ->ContextID, CLUTpoints, InputChannels, OutputChannels, T))) {
2125             _cmsFree(self ->ContextID, T);
2126             goto Error;
2127         }
2128         _cmsFree(self ->ContextID, T);
2129     }
2130 
2131 
2132     // Get output tables
2133     if (!Read16bitTables(self ->ContextID, io,  NewLUT, OutputChannels, OutputEntries)) goto Error;
2134 
2135     *nItems = 1;
2136     return NewLUT;
2137 
2138 Error:
2139     if (NewLUT != NULL) cmsPipelineFree(NewLUT);


2140     return NULL;
2141 
2142     cmsUNUSED_PARAMETER(SizeOfTag);
2143 }
2144 
2145 // We only allow some specific MPE structures: Matrix plus prelin, plus clut, plus post-lin.
2146 // Some empty defaults are created for missing parts
2147 
2148 static
2149 cmsBool  Type_LUT16_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
2150 {
2151     cmsUInt32Number nTabSize;
2152     cmsPipeline* NewLUT = (cmsPipeline*) Ptr;
2153     cmsStage* mpe;
2154     _cmsStageToneCurvesData* PreMPE = NULL, *PostMPE = NULL;
2155     _cmsStageMatrixData* MatMPE = NULL;
2156     _cmsStageCLutData* clut = NULL;
2157     int i, InputChannels, OutputChannels, clutPoints;
2158 
2159     // Disassemble the LUT into components.
2160     mpe = NewLUT -> Elements;
2161     if (mpe != NULL && mpe ->Type == cmsSigMatrixElemType) {
2162 


2256     if (nTabSize == (cmsUInt32Number) -1) return FALSE;
2257     if (nTabSize > 0) {
2258         // The 3D CLUT.
2259         if (clut != NULL) {
2260             if (!_cmsWriteUInt16Array(io, nTabSize, clut->Tab.T)) return FALSE;
2261         }
2262     }
2263 
2264     // The postlinearization table
2265     if (PostMPE != NULL) {
2266         if (!Write16bitTables(self ->ContextID, io, PostMPE)) return FALSE;
2267     }
2268     else {
2269         for (i=0; i < OutputChannels; i++) {
2270 
2271             if (!_cmsWriteUInt16Number(io, 0)) return FALSE;
2272             if (!_cmsWriteUInt16Number(io, 0xffff)) return FALSE;
2273         }
2274     }
2275 

2276     return TRUE;
2277 
2278     cmsUNUSED_PARAMETER(nItems);
2279 }
2280 
2281 static
2282 void* Type_LUT16_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
2283 {
2284     return (void*) cmsPipelineDup((cmsPipeline*) Ptr);
2285 
2286     cmsUNUSED_PARAMETER(n);
2287     cmsUNUSED_PARAMETER(self);



2288 }
2289 
2290 static
2291 void Type_LUT16_Free(struct _cms_typehandler_struct* self, void* Ptr)
2292 {
2293     cmsPipelineFree((cmsPipeline*) Ptr);


2294     return;
2295 
2296     cmsUNUSED_PARAMETER(self);
2297 }
2298 
2299 
2300 // ********************************************************************************
2301 // Type cmsSigLutAToBType
2302 // ********************************************************************************
2303 
2304 
2305 // V4 stuff. Read matrix for LutAtoB and LutBtoA
2306 
2307 static
2308 cmsStage* ReadMatrix(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number Offset)
2309 {
2310     cmsFloat64Number dMat[3*3];
2311     cmsFloat64Number dOff[3];
2312     cmsStage* Mat;
2313 
2314     // Go to address
2315     if (!io -> Seek(io, Offset)) return NULL;
2316 


2522 
2523     if (offsetM != 0) {
2524         if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetM, outputChan)))
2525             goto Error;
2526     }
2527 
2528     if (offsetMat != 0) {
2529         if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadMatrix(self, io, BaseOffset + offsetMat)))
2530             goto Error;
2531     }
2532 
2533     if (offsetB != 0) {
2534         if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetB, outputChan)))
2535             goto Error;
2536     }
2537 
2538     *nItems = 1;
2539     return NewLUT;
2540 Error:
2541     cmsPipelineFree(NewLUT);

2542     return NULL;
2543 
2544     cmsUNUSED_PARAMETER(SizeOfTag);
2545 }
2546 
2547 // Write a set of curves
2548 static
2549 cmsBool  WriteMatrix(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsStage* mpe)
2550 {
2551     _cmsStageMatrixData* m = (_cmsStageMatrixData*) mpe -> Data;
2552 
2553     // Write the Matrix
2554     if (!_cmsWrite15Fixed16Number(io, m -> Double[0])) return FALSE;
2555     if (!_cmsWrite15Fixed16Number(io, m -> Double[1])) return FALSE;
2556     if (!_cmsWrite15Fixed16Number(io, m -> Double[2])) return FALSE;
2557     if (!_cmsWrite15Fixed16Number(io, m -> Double[3])) return FALSE;
2558     if (!_cmsWrite15Fixed16Number(io, m -> Double[4])) return FALSE;
2559     if (!_cmsWrite15Fixed16Number(io, m -> Double[5])) return FALSE;
2560     if (!_cmsWrite15Fixed16Number(io, m -> Double[6])) return FALSE;
2561     if (!_cmsWrite15Fixed16Number(io, m -> Double[7])) return FALSE;
2562     if (!_cmsWrite15Fixed16Number(io, m -> Double[8])) return FALSE;
2563 
2564     if (m ->Offset != NULL) {
2565 
2566     if (!_cmsWrite15Fixed16Number(io, m -> Offset[0])) return FALSE;
2567     if (!_cmsWrite15Fixed16Number(io, m -> Offset[1])) return FALSE;
2568     if (!_cmsWrite15Fixed16Number(io, m -> Offset[2])) return FALSE;
2569     }
2570     else {
2571         if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
2572         if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
2573         if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
2574 
2575     }
2576 
2577 

2578     return TRUE;
2579 
2580     cmsUNUSED_PARAMETER(self);
2581 }
2582 
2583 
2584 // Write a set of curves
2585 static
2586 cmsBool WriteSetOfCurves(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsTagTypeSignature Type, cmsStage* mpe)
2587 {
2588     cmsUInt32Number i, n;
2589     cmsTagTypeSignature CurrentType;
2590     cmsToneCurve** Curves;
2591 
2592 
2593     n      = cmsStageOutputChannels(mpe);
2594     Curves = _cmsStageGetPtrToCurveSet(mpe);
2595 
2596     for (i=0; i < n; i++) {
2597 
2598         // If this is a table-based curve, use curve type even on V4
2599         CurrentType = Type;
2600 


2751     }
2752 
2753     if (B != NULL) {
2754 
2755         offsetB = io ->Tell(io) - BaseOffset;
2756         if (!WriteSetOfCurves(self, io, cmsSigParametricCurveType, B)) return FALSE;
2757     }
2758 
2759     CurrentPos = io ->Tell(io);
2760 
2761     if (!io ->Seek(io, DirectoryPos)) return FALSE;
2762 
2763     if (!_cmsWriteUInt32Number(io, offsetB)) return FALSE;
2764     if (!_cmsWriteUInt32Number(io, offsetMat)) return FALSE;
2765     if (!_cmsWriteUInt32Number(io, offsetM)) return FALSE;
2766     if (!_cmsWriteUInt32Number(io, offsetC)) return FALSE;
2767     if (!_cmsWriteUInt32Number(io, offsetA)) return FALSE;
2768 
2769     if (!io ->Seek(io, CurrentPos)) return FALSE;
2770 

2771     return TRUE;
2772 
2773     cmsUNUSED_PARAMETER(nItems);
2774 }
2775 
2776 
2777 static
2778 void* Type_LUTA2B_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
2779 {
2780     return (void*) cmsPipelineDup((cmsPipeline*) Ptr);
2781 
2782     cmsUNUSED_PARAMETER(n);
2783     cmsUNUSED_PARAMETER(self);



2784 }
2785 
2786 static
2787 void Type_LUTA2B_Free(struct _cms_typehandler_struct* self, void* Ptr)
2788 {
2789     cmsPipelineFree((cmsPipeline*) Ptr);


2790     return;
2791 
2792     cmsUNUSED_PARAMETER(self);
2793 }
2794 
2795 
2796 // LutBToA type
2797 
2798 static
2799 void* Type_LUTB2A_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
2800 {
2801     cmsUInt8Number       inputChan;      // Number of input channels
2802     cmsUInt8Number       outputChan;     // Number of output channels
2803     cmsUInt32Number      BaseOffset;     // Actual position in file
2804     cmsUInt32Number      offsetB;        // Offset to first "B" curve
2805     cmsUInt32Number      offsetMat;      // Offset to matrix
2806     cmsUInt32Number      offsetM;        // Offset to first "M" curve
2807     cmsUInt32Number      offsetC;        // Offset to CLUT
2808     cmsUInt32Number      offsetA;        // Offset to first "A" curve
2809     cmsPipeline* NewLUT = NULL;
2810 
2811 
2812     BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);


2839 
2840     if (offsetM != 0) {
2841         if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetM, inputChan)))
2842             goto Error;
2843     }
2844 
2845     if (offsetC != 0) {
2846         if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadCLUT(self, io, BaseOffset + offsetC, inputChan, outputChan)))
2847             goto Error;
2848     }
2849 
2850     if (offsetA!= 0) {
2851         if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetA, outputChan)))
2852             goto Error;
2853     }
2854 
2855     *nItems = 1;
2856     return NewLUT;
2857 Error:
2858     cmsPipelineFree(NewLUT);


2859     return NULL;
2860 
2861     cmsUNUSED_PARAMETER(SizeOfTag);
2862 }
2863 
2864 
2865 /*
2866 B
2867 B - Matrix - M
2868 B - CLUT - A
2869 B - Matrix - M - CLUT - A
2870 */
2871 
2872 static
2873 cmsBool  Type_LUTB2A_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
2874 {
2875     cmsPipeline* Lut = (cmsPipeline*) Ptr;
2876     int inputChan, outputChan;
2877     cmsStage *A = NULL, *B = NULL, *M = NULL;
2878     cmsStage *Matrix = NULL;
2879     cmsStage *CLUT = NULL;
2880     cmsUInt32Number offsetB = 0, offsetMat = 0, offsetM = 0, offsetC = 0, offsetA = 0;
2881     cmsUInt32Number BaseOffset, DirectoryPos, CurrentPos;


2930     }
2931 
2932     if (B != NULL) {
2933 
2934         offsetB = io ->Tell(io) - BaseOffset;
2935         if (!WriteSetOfCurves(self, io, cmsSigParametricCurveType, B)) return FALSE;
2936     }
2937 
2938     CurrentPos = io ->Tell(io);
2939 
2940     if (!io ->Seek(io, DirectoryPos)) return FALSE;
2941 
2942     if (!_cmsWriteUInt32Number(io, offsetB)) return FALSE;
2943     if (!_cmsWriteUInt32Number(io, offsetMat)) return FALSE;
2944     if (!_cmsWriteUInt32Number(io, offsetM)) return FALSE;
2945     if (!_cmsWriteUInt32Number(io, offsetC)) return FALSE;
2946     if (!_cmsWriteUInt32Number(io, offsetA)) return FALSE;
2947 
2948     if (!io ->Seek(io, CurrentPos)) return FALSE;
2949 


2950     return TRUE;
2951 
2952     cmsUNUSED_PARAMETER(nItems);
2953 }
2954 
2955 
2956 
2957 static
2958 void* Type_LUTB2A_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
2959 {
2960     return (void*) cmsPipelineDup((cmsPipeline*) Ptr);
2961 
2962     cmsUNUSED_PARAMETER(n);
2963     cmsUNUSED_PARAMETER(self);



2964 }
2965 
2966 static
2967 void Type_LUTB2A_Free(struct _cms_typehandler_struct* self, void* Ptr)
2968 {
2969     cmsPipelineFree((cmsPipeline*) Ptr);


2970     return;
2971 
2972     cmsUNUSED_PARAMETER(self);
2973 }
2974 
2975 
2976 
2977 // ********************************************************************************
2978 // Type cmsSigColorantTableType
2979 // ********************************************************************************
2980 /*
2981 The purpose of this tag is to identify the colorants used in the profile by a
2982 unique name and set of XYZ or L*a*b* values to give the colorant an unambiguous
2983 value. The first colorant listed is the colorant of the first device channel of
2984 a lut tag. The second colorant listed is the colorant of the second device channel
2985 of a lut tag, and so on.
2986 */
2987 
2988 static
2989 void *Type_ColorantTable_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
2990 {
2991     cmsUInt32Number i, Count;
2992     cmsNAMEDCOLORLIST* List;


3002     }
3003 
3004     List = cmsAllocNamedColorList(self ->ContextID, Count, 0, "", "");
3005     for (i=0; i < Count; i++) {
3006 
3007         if (io ->Read(io, Name, 32, 1) != 1) goto Error;
3008         Name[33] = 0;
3009 
3010         if (!_cmsReadUInt16Array(io, 3, PCS)) goto Error;
3011 
3012         if (!cmsAppendNamedColor(List, Name, PCS, NULL)) goto Error;
3013 
3014     }
3015 
3016     *nItems = 1;
3017     return List;
3018 
3019 Error:
3020     *nItems = 0;
3021     cmsFreeNamedColorList(List);


3022     return NULL;
3023 
3024     cmsUNUSED_PARAMETER(SizeOfTag);
3025 }
3026 
3027 
3028 
3029 // Saves a colorant table. It is using the named color structure for simplicity sake
3030 static
3031 cmsBool  Type_ColorantTable_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
3032 {
3033     cmsNAMEDCOLORLIST* NamedColorList = (cmsNAMEDCOLORLIST*) Ptr;
3034     int i, nColors;
3035 
3036     nColors = cmsNamedColorCount(NamedColorList);
3037 
3038     if (!_cmsWriteUInt32Number(io, nColors)) return FALSE;
3039 
3040     for (i=0; i < nColors; i++) {
3041 
3042         char root[33];
3043         cmsUInt16Number PCS[3];
3044 
3045         if (!cmsNamedColorInfo(NamedColorList, i, root, NULL, NULL, PCS, NULL)) return 0;
3046         root[32] = 0;
3047 
3048         if (!io ->Write(io, 32, root)) return FALSE;
3049         if (!_cmsWriteUInt16Array(io, 3, PCS)) return FALSE;
3050     }
3051 
3052     return TRUE;
3053 
3054     cmsUNUSED_PARAMETER(nItems);
3055     cmsUNUSED_PARAMETER(self);



3056 }
3057 
3058 
3059 static
3060 void* Type_ColorantTable_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n)
3061 {
3062     cmsNAMEDCOLORLIST* nc = (cmsNAMEDCOLORLIST*) Ptr;
3063     return (void*) cmsDupNamedColorList(nc);
3064 
3065     cmsUNUSED_PARAMETER(n);
3066     cmsUNUSED_PARAMETER(self);



3067 }
3068 
3069 
3070 static
3071 void Type_ColorantTable_Free(struct _cms_typehandler_struct* self, void* Ptr)
3072 {
3073     cmsFreeNamedColorList((cmsNAMEDCOLORLIST*) Ptr);

3074     return;
3075 
3076     cmsUNUSED_PARAMETER(self);
3077 }
3078 
3079 
3080 // ********************************************************************************
3081 // Type cmsSigNamedColor2Type
3082 // ********************************************************************************
3083 //
3084 //The namedColor2Type is a count value and array of structures that provide color
3085 //coordinates for 7-bit ASCII color names. For each named color, a PCS and optional
3086 //device representation of the color are given. Both representations are 16-bit values.
3087 //The device representation corresponds to the header’s “color space of data” field.
3088 //This representation should be consistent with the “number of device components”
3089 //field in the namedColor2Type. If this field is 0, device coordinates are not provided.
3090 //The PCS representation corresponds to the header’s PCS field. The PCS representation
3091 //is always provided. Color names are fixed-length, 32-byte fields including null
3092 //termination. In order to maintain maximum portability, it is strongly recommended
3093 //that special characters of the 7-bit ASCII set not be used.
3094 
3095 static
3096 void *Type_NamedColor_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)


3127     }
3128     for (i=0; i < count; i++) {
3129 
3130         cmsUInt16Number PCS[3];
3131         cmsUInt16Number Colorant[cmsMAXCHANNELS];
3132         char Root[33];
3133 
3134         memset(Colorant, 0, sizeof(Colorant));
3135         if (io -> Read(io, Root, 32, 1) != 1) return NULL;
3136         if (!_cmsReadUInt16Array(io, 3, PCS)) goto Error;
3137         if (!_cmsReadUInt16Array(io, nDeviceCoords, Colorant)) goto Error;
3138 
3139         if (!cmsAppendNamedColor(v, Root, PCS, Colorant)) goto Error;
3140     }
3141 
3142     *nItems = 1;
3143     return (void*) v ;
3144 
3145 Error:
3146     cmsFreeNamedColorList(v);


3147     return NULL;
3148 
3149     cmsUNUSED_PARAMETER(SizeOfTag);
3150 }
3151 
3152 
3153 // Saves a named color list into a named color profile
3154 static
3155 cmsBool Type_NamedColor_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
3156 {
3157     cmsNAMEDCOLORLIST* NamedColorList = (cmsNAMEDCOLORLIST*) Ptr;
3158     char                prefix[32];     // Prefix for each color name
3159     char                suffix[32];     // Suffix for each color name
3160     int i, nColors;
3161 
3162     nColors = cmsNamedColorCount(NamedColorList);
3163 
3164     if (!_cmsWriteUInt32Number(io, 0)) return FALSE;
3165     if (!_cmsWriteUInt32Number(io, nColors)) return FALSE;
3166     if (!_cmsWriteUInt32Number(io, NamedColorList ->ColorantCount)) return FALSE;
3167 
3168     strncpy(prefix, (const char*) NamedColorList->Prefix, 32);
3169     strncpy(suffix, (const char*) NamedColorList->Suffix, 32);
3170 
3171     suffix[31] = prefix[31] = 0;
3172 
3173     if (!io ->Write(io, 32, prefix)) return FALSE;
3174     if (!io ->Write(io, 32, suffix)) return FALSE;
3175 
3176     for (i=0; i < nColors; i++) {
3177 
3178        cmsUInt16Number PCS[3];
3179        cmsUInt16Number Colorant[cmsMAXCHANNELS];
3180        char Root[33];
3181 
3182         if (!cmsNamedColorInfo(NamedColorList, i, Root, NULL, NULL, PCS, Colorant)) return 0;
3183         if (!io ->Write(io, 32 , Root)) return FALSE;
3184         if (!_cmsWriteUInt16Array(io, 3, PCS)) return FALSE;
3185         if (!_cmsWriteUInt16Array(io, NamedColorList ->ColorantCount, Colorant)) return FALSE;
3186     }
3187 
3188     return TRUE;
3189 
3190     cmsUNUSED_PARAMETER(nItems);
3191     cmsUNUSED_PARAMETER(self);



3192 }
3193 
3194 static
3195 void* Type_NamedColor_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n)
3196 {
3197     cmsNAMEDCOLORLIST* nc = (cmsNAMEDCOLORLIST*) Ptr;
3198 
3199     return (void*) cmsDupNamedColorList(nc);
3200 
3201     cmsUNUSED_PARAMETER(n);
3202     cmsUNUSED_PARAMETER(self);



3203 }
3204 
3205 
3206 static
3207 void Type_NamedColor_Free(struct _cms_typehandler_struct* self, void* Ptr)
3208 {
3209     cmsFreeNamedColorList((cmsNAMEDCOLORLIST*) Ptr);


3210     return;
3211 
3212     cmsUNUSED_PARAMETER(self);
3213 }
3214 
3215 
3216 // ********************************************************************************
3217 // Type cmsSigProfileSequenceDescType
3218 // ********************************************************************************
3219 
3220 // This type is an array of structures, each of which contains information from the
3221 // header fields and tags from the original profiles which were combined to create
3222 // the final profile. The order of the structures is the order in which the profiles
3223 // were combined and includes a structure for the final profile. This provides a
3224 // description of the profile sequence from source to destination,
3225 // typically used with the DeviceLink profile.
3226 
3227 static
3228 cmsBool ReadEmbeddedText(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsMLU** mlu, cmsUInt32Number SizeOfTag)
3229 {
3230     cmsTagTypeSignature  BaseType;
3231     cmsUInt32Number nItems;
3232 


3333 cmsBool  Type_ProfileSequenceDesc_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
3334 {
3335     cmsSEQ* Seq = (cmsSEQ*) Ptr;
3336     cmsUInt32Number i;
3337 
3338     if (!_cmsWriteUInt32Number(io, Seq->n)) return FALSE;
3339 
3340     for (i=0; i < Seq ->n; i++) {
3341 
3342         cmsPSEQDESC* sec = &Seq -> seq[i];
3343 
3344         if (!_cmsWriteUInt32Number(io, sec ->deviceMfg)) return FALSE;
3345         if (!_cmsWriteUInt32Number(io, sec ->deviceModel)) return FALSE;
3346         if (!_cmsWriteUInt64Number(io, &sec ->attributes)) return FALSE;
3347         if (!_cmsWriteUInt32Number(io, sec ->technology)) return FALSE;
3348 
3349         if (!SaveDescription(self, io, sec ->Manufacturer)) return FALSE;
3350         if (!SaveDescription(self, io, sec ->Model)) return FALSE;
3351     }
3352 


3353      return TRUE;
3354 
3355      cmsUNUSED_PARAMETER(nItems);
3356 }
3357 
3358 
3359 static
3360 void* Type_ProfileSequenceDesc_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n)
3361 {
3362     return (void*) cmsDupProfileSequenceDescription((cmsSEQ*) Ptr);
3363 
3364     cmsUNUSED_PARAMETER(n);
3365     cmsUNUSED_PARAMETER(self);



3366 }
3367 
3368 static
3369 void Type_ProfileSequenceDesc_Free(struct _cms_typehandler_struct* self, void* Ptr)
3370 {
3371     cmsFreeProfileSequenceDescription((cmsSEQ*) Ptr);


3372     return;
3373 
3374     cmsUNUSED_PARAMETER(self);
3375 }
3376 
3377 
3378 // ********************************************************************************
3379 // Type cmsSigProfileSequenceIdType
3380 // ********************************************************************************
3381 /*
3382 In certain workflows using ICC Device Link Profiles, it is necessary to identify the
3383 original profiles that were combined to create the Device Link Profile.
3384 This type is an array of structures, each of which contains information for
3385 identification of a profile used in a sequence
3386 */
3387 
3388 
3389 static
3390 cmsBool ReadSeqID(struct _cms_typehandler_struct* self,
3391                                              cmsIOHANDLER* io,
3392                                              void* Cargo,
3393                                              cmsUInt32Number n,
3394                                              cmsUInt32Number SizeOfTag)


3436     *nItems = 1;
3437     return OutSeq;
3438 
3439 }
3440 
3441 
3442 static
3443 cmsBool WriteSeqID(struct _cms_typehandler_struct* self,
3444                                              cmsIOHANDLER* io,
3445                                              void* Cargo,
3446                                              cmsUInt32Number n,
3447                                              cmsUInt32Number SizeOfTag)
3448 {
3449     cmsSEQ* Seq = (cmsSEQ*) Cargo;
3450 
3451     if (!io ->Write(io, 16, Seq ->seq[n].ProfileID.ID8)) return FALSE;
3452 
3453     // Store here the MLU
3454     if (!SaveDescription(self, io, Seq ->seq[n].Description)) return FALSE;
3455 


3456     return TRUE;
3457 
3458     cmsUNUSED_PARAMETER(SizeOfTag);
3459 }
3460 
3461 static
3462 cmsBool  Type_ProfileSequenceId_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
3463 {
3464     cmsSEQ* Seq = (cmsSEQ*) Ptr;
3465     cmsUInt32Number BaseOffset;
3466 
3467     // Keep the base offset
3468     BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);
3469 
3470     // This is the table count
3471     if (!_cmsWriteUInt32Number(io, Seq ->n)) return FALSE;
3472 
3473     // This is the position table and content
3474     if (!WritePositionTable(self, io, 0, Seq ->n, BaseOffset, Seq, WriteSeqID)) return FALSE;
3475 


3476     return TRUE;
3477 
3478     cmsUNUSED_PARAMETER(nItems);
3479 }
3480 
3481 static
3482 void* Type_ProfileSequenceId_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n)
3483 {
3484     return (void*) cmsDupProfileSequenceDescription((cmsSEQ*) Ptr);
3485 
3486     cmsUNUSED_PARAMETER(n);
3487     cmsUNUSED_PARAMETER(self);



3488 }
3489 
3490 static
3491 void Type_ProfileSequenceId_Free(struct _cms_typehandler_struct* self, void* Ptr)
3492 {
3493     cmsFreeProfileSequenceDescription((cmsSEQ*) Ptr);


3494     return;
3495 
3496     cmsUNUSED_PARAMETER(self);
3497 }
3498 
3499 
3500 // ********************************************************************************
3501 // Type cmsSigUcrBgType
3502 // ********************************************************************************
3503 /*
3504 This type contains curves representing the under color removal and black
3505 generation and a text string which is a general description of the method used
3506 for the ucr/bg.
3507 */
3508 
3509 static
3510 void *Type_UcrBg_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
3511 {
3512     cmsUcrBg* n = (cmsUcrBg*) _cmsMallocZero(self ->ContextID, sizeof(cmsUcrBg));
3513     cmsUInt32Number CountUcr, CountBg;
3514     char* ASCIIString;
3515 
3516     *nItems = 0;


3560     cmsUcrBg* Value = (cmsUcrBg*) Ptr;
3561     cmsUInt32Number TextSize;
3562     char* Text;
3563 
3564     // First curve is Under color removal
3565     if (!_cmsWriteUInt32Number(io, Value ->Ucr ->nEntries)) return FALSE;
3566     if (!_cmsWriteUInt16Array(io, Value ->Ucr ->nEntries, Value ->Ucr ->Table16)) return FALSE;
3567 
3568     // Then black generation
3569     if (!_cmsWriteUInt32Number(io, Value ->Bg ->nEntries)) return FALSE;
3570     if (!_cmsWriteUInt16Array(io, Value ->Bg ->nEntries, Value ->Bg ->Table16)) return FALSE;
3571 
3572     // Now comes the text. The length is specified by the tag size
3573     TextSize = cmsMLUgetASCII(Value ->Desc, cmsNoLanguage, cmsNoCountry, NULL, 0);
3574     Text     = (char*) _cmsMalloc(self ->ContextID, TextSize);
3575     if (cmsMLUgetASCII(Value ->Desc, cmsNoLanguage, cmsNoCountry, Text, TextSize) != TextSize) return FALSE;
3576 
3577     if (!io ->Write(io, TextSize, Text)) return FALSE;
3578     _cmsFree(self ->ContextID, Text);
3579 


3580     return TRUE;
3581 
3582     cmsUNUSED_PARAMETER(nItems);
3583 }
3584 
3585 static
3586 void* Type_UcrBg_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
3587 {
3588     cmsUcrBg* Src = (cmsUcrBg*) Ptr;
3589     cmsUcrBg* NewUcrBg = (cmsUcrBg*) _cmsMallocZero(self ->ContextID, sizeof(cmsUcrBg));
3590 
3591     if (NewUcrBg == NULL) return NULL;
3592 
3593     NewUcrBg ->Bg   = cmsDupToneCurve(Src ->Bg);
3594     NewUcrBg ->Ucr  = cmsDupToneCurve(Src ->Ucr);
3595     NewUcrBg ->Desc = cmsMLUdup(Src ->Desc);
3596 


3597     return (void*) NewUcrBg;
3598 
3599     cmsUNUSED_PARAMETER(n);
3600 }
3601 
3602 static
3603 void Type_UcrBg_Free(struct _cms_typehandler_struct* self, void *Ptr)
3604 {
3605    cmsUcrBg* Src = (cmsUcrBg*) Ptr;
3606 
3607    if (Src ->Ucr) cmsFreeToneCurve(Src ->Ucr);
3608    if (Src ->Bg)  cmsFreeToneCurve(Src ->Bg);
3609    if (Src ->Desc) cmsMLUfree(Src ->Desc);
3610 
3611    _cmsFree(self ->ContextID, Ptr);
3612 }
3613 
3614 // ********************************************************************************
3615 // Type cmsSigCrdInfoType
3616 // ********************************************************************************
3617 
3618 /*
3619 This type contains the PostScript product name to which this profile corresponds


3699     cmsMLUfree(mlu);
3700     return NULL;
3701 
3702 }
3703 
3704 static
3705 cmsBool  Type_CrdInfo_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
3706 {
3707 
3708     cmsMLU* mlu = (cmsMLU*) Ptr;
3709 
3710     if (!WriteCountAndSting(self, io, mlu, "nm")) goto Error;
3711     if (!WriteCountAndSting(self, io, mlu, "#0")) goto Error;
3712     if (!WriteCountAndSting(self, io, mlu, "#1")) goto Error;
3713     if (!WriteCountAndSting(self, io, mlu, "#2")) goto Error;
3714     if (!WriteCountAndSting(self, io, mlu, "#3")) goto Error;
3715 
3716     return TRUE;
3717 
3718 Error:

3719     return FALSE;
3720 
3721     cmsUNUSED_PARAMETER(nItems);
3722 }
3723 
3724 
3725 static
3726 void* Type_CrdInfo_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
3727 {
3728     return (void*) cmsMLUdup((cmsMLU*) Ptr);
3729 
3730     cmsUNUSED_PARAMETER(n);
3731     cmsUNUSED_PARAMETER(self);



3732 }
3733 
3734 static
3735 void Type_CrdInfo_Free(struct _cms_typehandler_struct* self, void *Ptr)
3736 {
3737     cmsMLUfree((cmsMLU*) Ptr);


3738     return;
3739 
3740     cmsUNUSED_PARAMETER(self);
3741 }
3742 
3743 // ********************************************************************************
3744 // Type cmsSigScreeningType
3745 // ********************************************************************************
3746 //
3747 //The screeningType describes various screening parameters including screen
3748 //frequency, screening angle, and spot shape.
3749 
3750 static
3751 void *Type_Screening_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
3752 {
3753     cmsScreening* sc = NULL;
3754     cmsUInt32Number i;
3755 
3756     sc = (cmsScreening*) _cmsMallocZero(self ->ContextID, sizeof(cmsScreening));
3757     if (sc == NULL) return NULL;
3758 
3759     *nItems = 0;
3760 


3763 
3764     if (sc ->nChannels > cmsMAXCHANNELS - 1)
3765         sc ->nChannels = cmsMAXCHANNELS - 1;
3766 
3767     for (i=0; i < sc ->nChannels; i++) {
3768 
3769         if (!_cmsRead15Fixed16Number(io, &sc ->Channels[i].Frequency)) goto Error;
3770         if (!_cmsRead15Fixed16Number(io, &sc ->Channels[i].ScreenAngle)) goto Error;
3771         if (!_cmsReadUInt32Number(io, &sc ->Channels[i].SpotShape)) goto Error;
3772     }
3773 
3774 
3775     *nItems = 1;
3776 
3777     return (void*) sc;
3778 
3779 Error:
3780     if (sc != NULL)
3781         _cmsFree(self ->ContextID, sc);
3782 

3783     return NULL;
3784 
3785     cmsUNUSED_PARAMETER(SizeOfTag);
3786 }
3787 
3788 
3789 static
3790 cmsBool Type_Screening_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
3791 {
3792     cmsScreening* sc = (cmsScreening* ) Ptr;
3793     cmsUInt32Number i;
3794 
3795     if (!_cmsWriteUInt32Number(io, sc ->Flag)) return FALSE;
3796     if (!_cmsWriteUInt32Number(io, sc ->nChannels)) return FALSE;
3797 
3798     for (i=0; i < sc ->nChannels; i++) {
3799 
3800         if (!_cmsWrite15Fixed16Number(io, sc ->Channels[i].Frequency)) return FALSE;
3801         if (!_cmsWrite15Fixed16Number(io, sc ->Channels[i].ScreenAngle)) return FALSE;
3802         if (!_cmsWriteUInt32Number(io, sc ->Channels[i].SpotShape)) return FALSE;
3803     }
3804 

3805     return TRUE;
3806 
3807     cmsUNUSED_PARAMETER(nItems);
3808     cmsUNUSED_PARAMETER(self);
3809 }
3810 
3811 
3812 static
3813 void* Type_Screening_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
3814 {

3815    return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsScreening));
3816 
3817    cmsUNUSED_PARAMETER(n);
3818 }
3819 
3820 
3821 static
3822 void Type_Screening_Free(struct _cms_typehandler_struct* self, void* Ptr)
3823 {
3824    _cmsFree(self ->ContextID, Ptr);
3825 }
3826 
3827 // ********************************************************************************
3828 // Type cmsSigViewingConditionsType
3829 // ********************************************************************************
3830 //
3831 //This type represents a set of viewing condition parameters including:
3832 //CIE ’absolute’ illuminant white point tristimulus values and CIE ’absolute’
3833 //surround tristimulus values.
3834 
3835 static
3836 void *Type_ViewingConditions_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
3837 {
3838     cmsICCViewingConditions* vc = NULL;
3839 
3840     vc = (cmsICCViewingConditions*) _cmsMallocZero(self ->ContextID, sizeof(cmsICCViewingConditions));
3841     if (vc == NULL) return NULL;
3842 
3843     *nItems = 0;
3844 
3845     if (!_cmsReadXYZNumber(io, &vc ->IlluminantXYZ)) goto Error;
3846     if (!_cmsReadXYZNumber(io, &vc ->SurroundXYZ)) goto Error;
3847     if (!_cmsReadUInt32Number(io, &vc ->IlluminantType)) goto Error;
3848 
3849     *nItems = 1;
3850 
3851     return (void*) vc;
3852 
3853 Error:
3854     if (vc != NULL)
3855         _cmsFree(self ->ContextID, vc);
3856 

3857     return NULL;
3858 
3859     cmsUNUSED_PARAMETER(SizeOfTag);
3860 }
3861 
3862 
3863 static
3864 cmsBool Type_ViewingConditions_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
3865 {
3866     cmsICCViewingConditions* sc = (cmsICCViewingConditions* ) Ptr;
3867 
3868     if (!_cmsWriteXYZNumber(io, &sc ->IlluminantXYZ)) return FALSE;
3869     if (!_cmsWriteXYZNumber(io, &sc ->SurroundXYZ)) return FALSE;
3870     if (!_cmsWriteUInt32Number(io, sc ->IlluminantType)) return FALSE;
3871 
3872     return TRUE;
3873 
3874     cmsUNUSED_PARAMETER(nItems);
3875     cmsUNUSED_PARAMETER(self);


3876 }
3877 
3878 
3879 static
3880 void* Type_ViewingConditions_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
3881 {

3882    return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsScreening));
3883 
3884    cmsUNUSED_PARAMETER(n);
3885 }
3886 
3887 
3888 static
3889 void Type_ViewingConditions_Free(struct _cms_typehandler_struct* self, void* Ptr)
3890 {
3891    _cmsFree(self ->ContextID, Ptr);
3892 }
3893 
3894 
3895 // ********************************************************************************
3896 // Type cmsSigMultiProcessElementType
3897 // ********************************************************************************
3898 
3899 
3900 static
3901 void* GenericMPEdup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
3902 {
3903     return (void*) cmsStageDup((cmsStage*) Ptr);
3904 
3905     cmsUNUSED_PARAMETER(n);
3906     cmsUNUSED_PARAMETER(self);


3907 }
3908 
3909 static
3910 void GenericMPEfree(struct _cms_typehandler_struct* self, void *Ptr)
3911 {
3912     cmsStageFree((cmsStage*) Ptr);

3913     return;
3914 
3915     cmsUNUSED_PARAMETER(self);
3916 }
3917 
3918 // Each curve is stored in one or more curve segments, with break-points specified between curve segments.
3919 // The first curve segment always starts at –Infinity, and the last curve segment always ends at +Infinity. The
3920 // first and last curve segments shall be specified in terms of a formula, whereas the other segments shall be
3921 // specified either in terms of a formula, or by a sampled curve.
3922 
3923 
3924 // Read an embedded segmented curve
3925 static
3926 cmsToneCurve* ReadSegmentedCurve(struct _cms_typehandler_struct* self, cmsIOHANDLER* io)
3927 {
3928     cmsCurveSegSignature ElementSig;
3929     cmsUInt32Number i, j;
3930     cmsUInt16Number nSegments;
3931     cmsCurveSegment*  Segments;
3932     cmsToneCurve* Curve;
3933     cmsFloat32Number PrevBreak = -1E22F;    // - infinite
3934 
3935     // Take signature and channels for each element.


4020      }
4021      _cmsFree(self ->ContextID, Segments);
4022      return Curve;
4023 
4024 Error:
4025      if (Segments) _cmsFree(self ->ContextID, Segments);
4026      return NULL;
4027 }
4028 
4029 
4030 static
4031 cmsBool ReadMPECurve(struct _cms_typehandler_struct* self,
4032                      cmsIOHANDLER* io,
4033                      void* Cargo,
4034                      cmsUInt32Number n,
4035                      cmsUInt32Number SizeOfTag)
4036 {
4037       cmsToneCurve** GammaTables = ( cmsToneCurve**) Cargo;
4038 
4039       GammaTables[n] = ReadSegmentedCurve(self, io);

4040       return (GammaTables[n] != NULL);
4041 
4042       cmsUNUSED_PARAMETER(SizeOfTag);
4043 }
4044 
4045 static
4046 void *Type_MPEcurve_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
4047 {
4048     cmsStage* mpe = NULL;
4049     cmsUInt16Number InputChans, OutputChans;
4050     cmsUInt32Number i, BaseOffset;
4051     cmsToneCurve** GammaTables;
4052 
4053     *nItems = 0;
4054 
4055     // Get actual position as a basis for element offsets
4056     BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);
4057 
4058     if (!_cmsReadUInt16Number(io, &InputChans)) return NULL;
4059     if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL;
4060 
4061     if (InputChans != OutputChans) return NULL;
4062 
4063     GammaTables = (cmsToneCurve**) _cmsCalloc(self ->ContextID, InputChans, sizeof(cmsToneCurve*));
4064     if (GammaTables == NULL) return NULL;
4065 
4066     if (ReadPositionTable(self, io, InputChans, BaseOffset, GammaTables, ReadMPECurve)) {
4067 
4068         mpe = cmsStageAllocToneCurves(self ->ContextID, InputChans, GammaTables);
4069     }
4070     else {
4071         mpe = NULL;
4072     }
4073 
4074     for (i=0; i < InputChans; i++) {
4075         if (GammaTables[i]) cmsFreeToneCurve(GammaTables[i]);
4076     }
4077 
4078     _cmsFree(self ->ContextID, GammaTables);
4079     *nItems = (mpe != NULL) ? 1 : 0;

4080     return mpe;
4081 
4082     cmsUNUSED_PARAMETER(SizeOfTag);
4083 }
4084 
4085 
4086 // Write a single segmented curve. NO CHECK IS PERFORMED ON VALIDITY
4087 static
4088 cmsBool WriteSegmentedCurve(cmsIOHANDLER* io, cmsToneCurve* g)
4089 {
4090     cmsUInt32Number i, j;
4091     cmsCurveSegment* Segments = g ->Segments;
4092     cmsUInt32Number nSegments = g ->nSegments;
4093 
4094     if (!_cmsWriteUInt32Number(io, cmsSigSegmentedCurve)) goto Error;
4095     if (!_cmsWriteUInt32Number(io, 0)) goto Error;
4096     if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) nSegments)) goto Error;
4097     if (!_cmsWriteUInt16Number(io, 0)) goto Error;
4098 
4099     // Write the break-points
4100     for (i=0; i < nSegments - 1; i++) {
4101         if (!_cmsWriteFloat32Number(io, Segments[i].x1)) goto Error;
4102     }


4141         // It seems there is no need to align. Code is here, and for safety commented out
4142         // if (!_cmsWriteAlignment(io)) goto Error;
4143     }
4144 
4145     return TRUE;
4146 
4147 Error:
4148     return FALSE;
4149 }
4150 
4151 
4152 static
4153 cmsBool WriteMPECurve(struct _cms_typehandler_struct* self,
4154                       cmsIOHANDLER* io,
4155                       void* Cargo,
4156                       cmsUInt32Number n,
4157                       cmsUInt32Number SizeOfTag)
4158 {
4159     _cmsStageToneCurvesData* Curves  = (_cmsStageToneCurvesData*) Cargo;
4160 
4161     return WriteSegmentedCurve(io, Curves ->TheCurves[n]);
4162 
4163     cmsUNUSED_PARAMETER(SizeOfTag);
4164     cmsUNUSED_PARAMETER(self);


4165 }
4166 
4167 // Write a curve, checking first for validity
4168 static
4169 cmsBool  Type_MPEcurve_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
4170 {
4171     cmsUInt32Number BaseOffset;
4172     cmsStage* mpe = (cmsStage*) Ptr;
4173     _cmsStageToneCurvesData* Curves = (_cmsStageToneCurvesData*) mpe ->Data;
4174 
4175     BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);
4176 
4177     // Write the header. Since those are curves, input and output channels are same
4178     if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->InputChannels)) return FALSE;
4179     if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->InputChannels)) return FALSE;
4180 
4181     if (!WritePositionTable(self, io, 0,
4182                                 mpe ->InputChannels, BaseOffset, Curves, WriteMPECurve)) return FALSE;
4183 
4184 

4185     return TRUE;
4186 
4187     cmsUNUSED_PARAMETER(nItems);
4188 }
4189 
4190 
4191 
4192 // The matrix is organized as an array of PxQ+Q elements, where P is the number of input channels to the
4193 // matrix, and Q is the number of output channels. The matrix elements are each float32Numbers. The array
4194 // is organized as follows:
4195 // array = [e11, e12, …, e1P, e21, e22, …, e2P, …, eQ1, eQ2, …, eQP, e1, e2, …, eQ]
4196 
4197 static
4198 void *Type_MPEmatrix_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
4199 {
4200     cmsStage* mpe;
4201     cmsUInt16Number   InputChans, OutputChans;
4202     cmsUInt32Number   nElems, i;
4203     cmsFloat64Number* Matrix;
4204     cmsFloat64Number* Offsets;
4205 
4206     if (!_cmsReadUInt16Number(io, &InputChans)) return NULL;
4207     if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL;


4227         if (!_cmsReadFloat32Number(io, &v)) return NULL;
4228         Matrix[i] = v;
4229     }
4230 
4231 
4232     for (i=0; i < OutputChans; i++) {
4233 
4234         cmsFloat32Number v;
4235 
4236         if (!_cmsReadFloat32Number(io, &v)) return NULL;
4237         Offsets[i] = v;
4238     }
4239 
4240 
4241     mpe = cmsStageAllocMatrix(self ->ContextID, OutputChans, InputChans, Matrix, Offsets);
4242     _cmsFree(self ->ContextID, Matrix);
4243     _cmsFree(self ->ContextID, Offsets);
4244 
4245     *nItems = 1;
4246 

4247     return mpe;
4248 
4249     cmsUNUSED_PARAMETER(SizeOfTag);
4250 }
4251 
4252 static
4253 cmsBool  Type_MPEmatrix_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
4254 {
4255     cmsUInt32Number i, nElems;
4256     cmsStage* mpe = (cmsStage*) Ptr;
4257     _cmsStageMatrixData* Matrix = (_cmsStageMatrixData*) mpe ->Data;
4258 
4259     if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->InputChannels)) return FALSE;
4260     if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->OutputChannels)) return FALSE;
4261 
4262     nElems = mpe ->InputChannels * mpe ->OutputChannels;
4263 
4264     for (i=0; i < nElems; i++) {
4265         if (!_cmsWriteFloat32Number(io, (cmsFloat32Number) Matrix->Double[i])) return FALSE;
4266     }
4267 
4268 
4269     for (i=0; i < mpe ->OutputChannels; i++) {
4270 
4271         if (Matrix ->Offset == NULL) {
4272 
4273                if (!_cmsWriteFloat32Number(io, 0)) return FALSE;
4274         }
4275         else {
4276                if (!_cmsWriteFloat32Number(io, (cmsFloat32Number) Matrix->Offset[i])) return FALSE;
4277         }
4278     }
4279 
4280     return TRUE;
4281 
4282     cmsUNUSED_PARAMETER(nItems);
4283     cmsUNUSED_PARAMETER(self);


4284 }
4285 
4286 
4287 
4288 static
4289 void *Type_MPEclut_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
4290 {
4291     cmsStage* mpe = NULL;
4292     cmsUInt16Number InputChans, OutputChans;
4293     cmsUInt8Number Dimensions8[16];
4294     cmsUInt32Number i, nMaxGrids, GridPoints[MAX_INPUT_DIMENSIONS];
4295     _cmsStageCLutData* clut;
4296 
4297     if (!_cmsReadUInt16Number(io, &InputChans)) return NULL;
4298     if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL;
4299 
4300     if (InputChans == 0) goto Error;
4301     if (OutputChans == 0) goto Error;
4302 
4303     if (io ->Read(io, Dimensions8, sizeof(cmsUInt8Number), 16) != 16)


4307     nMaxGrids = InputChans > MAX_INPUT_DIMENSIONS ? MAX_INPUT_DIMENSIONS : InputChans;
4308     for (i=0; i < nMaxGrids; i++) GridPoints[i] = (cmsUInt32Number) Dimensions8[i];
4309 
4310     // Allocate the true CLUT
4311     mpe = cmsStageAllocCLutFloatGranular(self ->ContextID, GridPoints, InputChans, OutputChans, NULL);
4312     if (mpe == NULL) goto Error;
4313 
4314     // Read the data
4315     clut = (_cmsStageCLutData*) mpe ->Data;
4316     for (i=0; i < clut ->nEntries; i++) {
4317 
4318         if (!_cmsReadFloat32Number(io, &clut ->Tab.TFloat[i])) goto Error;
4319     }
4320 
4321     *nItems = 1;
4322     return mpe;
4323 
4324 Error:
4325     *nItems = 0;
4326     if (mpe != NULL) cmsStageFree(mpe);

4327     return NULL;
4328 
4329     cmsUNUSED_PARAMETER(SizeOfTag);
4330 }
4331 
4332 // Write a CLUT in floating point
4333 static
4334 cmsBool  Type_MPEclut_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
4335 {
4336     cmsUInt8Number Dimensions8[16];
4337     cmsUInt32Number i;
4338     cmsStage* mpe = (cmsStage*) Ptr;
4339     _cmsStageCLutData* clut = (_cmsStageCLutData*) mpe ->Data;
4340 
4341     // Check for maximum number of channels
4342     if (mpe -> InputChannels > 15) return FALSE;
4343 
4344     // Only floats are supported in MPE
4345     if (clut ->HasFloatValues == FALSE) return FALSE;
4346 
4347     if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->InputChannels)) return FALSE;
4348     if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->OutputChannels)) return FALSE;
4349 
4350     memset(Dimensions8, 0, sizeof(Dimensions8));
4351 
4352     for (i=0; i < mpe ->InputChannels; i++)
4353         Dimensions8[i] = (cmsUInt8Number) clut ->Params ->nSamples[i];
4354 
4355     if (!io ->Write(io, 16, Dimensions8)) return FALSE;
4356 
4357     for (i=0; i < clut ->nEntries; i++) {
4358 
4359         if (!_cmsWriteFloat32Number(io, clut ->Tab.TFloat[i])) return FALSE;
4360     }
4361 
4362     return TRUE;
4363 
4364     cmsUNUSED_PARAMETER(nItems);
4365     cmsUNUSED_PARAMETER(self);


4366 }
4367 
4368 
4369 
4370 // This is the list of built-in MPE types
4371 static _cmsTagTypeLinkedList SupportedMPEtypes[] = {
4372 
4373 {{ (cmsTagTypeSignature) cmsSigBAcsElemType, NULL, NULL, NULL, NULL, NULL, 0 }, &SupportedMPEtypes[1] },   // Ignore those elements for now
4374 {{ (cmsTagTypeSignature) cmsSigEAcsElemType, NULL, NULL, NULL, NULL, NULL, 0 }, &SupportedMPEtypes[2] },   // (That's what the spec says)
4375 
4376 {TYPE_MPE_HANDLER((cmsTagTypeSignature) cmsSigCurveSetElemType,     MPEcurve),      &SupportedMPEtypes[3] },
4377 {TYPE_MPE_HANDLER((cmsTagTypeSignature) cmsSigMatrixElemType,       MPEmatrix),     &SupportedMPEtypes[4] },
4378 {TYPE_MPE_HANDLER((cmsTagTypeSignature) cmsSigCLutElemType,         MPEclut),        NULL },
4379 };
4380 
4381 _cmsTagTypePluginChunkType _cmsMPETypePluginChunk = { NULL };
4382 
4383 static
4384 cmsBool ReadMPEElem(struct _cms_typehandler_struct* self,
4385                     cmsIOHANDLER* io,


4405     if (TypeHandler == NULL)  {
4406 
4407         char String[5];
4408 
4409         _cmsTagSignature2String(String, (cmsTagSignature) ElementSig);
4410 
4411         // An unknown element was found.
4412         cmsSignalError(self ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown MPE type '%s' found.", String);
4413         return FALSE;
4414     }
4415 
4416     // If no read method, just ignore the element (valid for cmsSigBAcsElemType and cmsSigEAcsElemType)
4417     // Read the MPE. No size is given
4418     if (TypeHandler ->ReadPtr != NULL) {
4419 
4420         // This is a real element which should be read and processed
4421         if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, (cmsStage*) TypeHandler ->ReadPtr(self, io, &nItems, SizeOfTag)))
4422             return FALSE;
4423     }
4424 
4425     return TRUE;
4426 
4427     cmsUNUSED_PARAMETER(SizeOfTag);
4428     cmsUNUSED_PARAMETER(n);


4429 }
4430 
4431 
4432 // This is the main dispatcher for MPE
4433 static
4434 void *Type_MPE_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
4435 {
4436     cmsUInt16Number InputChans, OutputChans;
4437     cmsUInt32Number ElementCount;
4438     cmsPipeline *NewLUT = NULL;
4439     cmsUInt32Number BaseOffset;
4440 
4441     // Get actual position as a basis for element offsets
4442     BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);
4443 
4444     // Read channels and element count
4445     if (!_cmsReadUInt16Number(io, &InputChans)) return NULL;
4446     if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL;
4447 
4448     // Allocates an empty LUT
4449     NewLUT = cmsPipelineAlloc(self ->ContextID, InputChans, OutputChans);
4450     if (NewLUT == NULL) return NULL;
4451 
4452     if (!_cmsReadUInt32Number(io, &ElementCount)) return NULL;
4453 
4454     if (!ReadPositionTable(self, io, ElementCount, BaseOffset, NewLUT, ReadMPEElem)) {
4455         if (NewLUT != NULL) cmsPipelineFree(NewLUT);
4456         *nItems = 0;
4457         return NULL;
4458     }
4459 
4460     // Success
4461     *nItems = 1;

4462     return NewLUT;
4463 
4464     cmsUNUSED_PARAMETER(SizeOfTag);
4465 }
4466 
4467 
4468 
4469 // This one is a liitle bit more complex, so we don't use position tables this time.
4470 static
4471 cmsBool Type_MPE_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
4472 {
4473     cmsUInt32Number i, BaseOffset, DirectoryPos, CurrentPos;
4474     int inputChan, outputChan;
4475     cmsUInt32Number ElemCount;
4476     cmsUInt32Number *ElementOffsets = NULL, *ElementSizes = NULL, Before;
4477     cmsStageSignature ElementSig;
4478     cmsPipeline* Lut = (cmsPipeline*) Ptr;
4479     cmsStage* Elem = Lut ->Elements;
4480     cmsTagTypeHandler* TypeHandler;
4481     _cmsTagTypePluginChunkType* MPETypePluginChunk  = ( _cmsTagTypePluginChunkType*) _cmsContextGetClientChunk(self->ContextID, MPEPlugin);
4482 
4483     BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);
4484 


4537 
4538     // Write the directory
4539     CurrentPos = io ->Tell(io);
4540 
4541     if (!io ->Seek(io, DirectoryPos)) goto Error;
4542 
4543     for (i=0; i < ElemCount; i++) {
4544         if (!_cmsWriteUInt32Number(io, ElementOffsets[i])) goto Error;
4545         if (!_cmsWriteUInt32Number(io, ElementSizes[i])) goto Error;
4546     }
4547 
4548     if (!io ->Seek(io, CurrentPos)) goto Error;
4549 
4550     if (ElementOffsets != NULL) _cmsFree(self ->ContextID, ElementOffsets);
4551     if (ElementSizes != NULL) _cmsFree(self ->ContextID, ElementSizes);
4552     return TRUE;
4553 
4554 Error:
4555     if (ElementOffsets != NULL) _cmsFree(self ->ContextID, ElementOffsets);
4556     if (ElementSizes != NULL) _cmsFree(self ->ContextID, ElementSizes);

4557     return FALSE;
4558 
4559     cmsUNUSED_PARAMETER(nItems);
4560 }
4561 
4562 
4563 static
4564 void* Type_MPE_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
4565 {
4566     return (void*) cmsPipelineDup((cmsPipeline*) Ptr);
4567 
4568     cmsUNUSED_PARAMETER(n);
4569     cmsUNUSED_PARAMETER(self);



4570 }
4571 
4572 static
4573 void Type_MPE_Free(struct _cms_typehandler_struct* self, void *Ptr)
4574 {
4575     cmsPipelineFree((cmsPipeline*) Ptr);

4576     return;
4577 
4578     cmsUNUSED_PARAMETER(self);
4579 }
4580 
4581 
4582 // ********************************************************************************
4583 // Type cmsSigVcgtType
4584 // ********************************************************************************
4585 
4586 
4587 #define cmsVideoCardGammaTableType    0
4588 #define cmsVideoCardGammaFormulaType  1
4589 
4590 // Used internally
4591 typedef struct {
4592     double Gamma;
4593     double Min;
4594     double Max;
4595 } _cmsVCGTGAMMA;
4596 
4597 
4598 static


4709            Curves[n] = cmsBuildParametricToneCurve(self ->ContextID, 5, Params);
4710            if (Curves[n] == NULL) goto Error;
4711        }
4712    }
4713    break;
4714 
4715    // Unsupported
4716    default:
4717       cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported tag type for VCGT '%d'", TagType);
4718       goto Error;
4719    }
4720 
4721    *nItems = 1;
4722    return (void*) Curves;
4723 
4724 // Regret,  free all resources
4725 Error:
4726 
4727     cmsFreeToneCurveTriple(Curves);
4728     _cmsFree(self ->ContextID, Curves);

4729     return NULL;
4730 
4731      cmsUNUSED_PARAMETER(SizeOfTag);
4732 }
4733 
4734 
4735 // We don't support all flavors, only 16bits tables and formula
4736 static
4737 cmsBool Type_vcgt_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
4738 {
4739     cmsToneCurve** Curves =  (cmsToneCurve**) Ptr;
4740     cmsUInt32Number i, j;
4741 
4742     if (cmsGetToneCurveParametricType(Curves[0]) == 5 &&
4743         cmsGetToneCurveParametricType(Curves[1]) == 5 &&
4744         cmsGetToneCurveParametricType(Curves[2]) == 5) {
4745 
4746             if (!_cmsWriteUInt32Number(io, cmsVideoCardGammaFormulaType)) return FALSE;
4747 
4748             // Save parameters
4749             for (i=0; i < 3; i++) {
4750 
4751                 _cmsVCGTGAMMA v;


4762 
4763     else {
4764 
4765         // Always store as a table of 256 words
4766         if (!_cmsWriteUInt32Number(io, cmsVideoCardGammaTableType)) return FALSE;
4767         if (!_cmsWriteUInt16Number(io, 3)) return FALSE;
4768         if (!_cmsWriteUInt16Number(io, 256)) return FALSE;
4769         if (!_cmsWriteUInt16Number(io, 2)) return FALSE;
4770 
4771         for (i=0; i < 3; i++) {
4772             for (j=0; j < 256; j++) {
4773 
4774                 cmsFloat32Number v = cmsEvalToneCurveFloat(Curves[i], (cmsFloat32Number) (j / 255.0));
4775                 cmsUInt16Number  n = _cmsQuickSaturateWord(v * 65535.0);
4776 
4777                 if (!_cmsWriteUInt16Number(io, n)) return FALSE;
4778             }
4779         }
4780     }
4781 
4782     return TRUE;
4783 
4784     cmsUNUSED_PARAMETER(self);
4785     cmsUNUSED_PARAMETER(nItems);


4786 }
4787 
4788 static
4789 void* Type_vcgt_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
4790 {
4791     cmsToneCurve** OldCurves =  (cmsToneCurve**) Ptr;
4792     cmsToneCurve** NewCurves;
4793 
4794     NewCurves = ( cmsToneCurve**) _cmsCalloc(self ->ContextID, 3, sizeof(cmsToneCurve*));
4795     if (NewCurves == NULL) return NULL;
4796 
4797     NewCurves[0] = cmsDupToneCurve(OldCurves[0]);
4798     NewCurves[1] = cmsDupToneCurve(OldCurves[1]);
4799     NewCurves[2] = cmsDupToneCurve(OldCurves[2]);
4800 

4801     return (void*) NewCurves;
4802 
4803     cmsUNUSED_PARAMETER(n);
4804 }
4805 
4806 
4807 static
4808 void Type_vcgt_Free(struct _cms_typehandler_struct* self, void* Ptr)
4809 {
4810     cmsFreeToneCurveTriple((cmsToneCurve**) Ptr);
4811     _cmsFree(self ->ContextID, Ptr);
4812 }
4813 
4814 
4815 // ********************************************************************************
4816 // Type cmsSigDictType
4817 // ********************************************************************************
4818 
4819 // Single column of the table can point to wchar or MLUC elements. Holds arrays of data
4820 typedef struct {
4821     cmsContext ContextID;
4822     cmsUInt32Number *Offsets;
4823     cmsUInt32Number *Sizes;


5207         if (p ->DisplayValue != NULL) {
5208             if (!WriteOneMLUC(self, io, &a.DisplayValue, i, p ->DisplayValue, BaseOffset)) goto Error;
5209         }
5210 
5211        p = cmsDictNextEntry(p);
5212     }
5213 
5214     // Write the directory
5215     CurrentPos = io ->Tell(io);
5216     if (!io ->Seek(io, DirectoryPos)) goto Error;
5217 
5218     if (!WriteOffsetArray(io, &a, Count, Length)) goto Error;
5219 
5220     if (!io ->Seek(io, CurrentPos)) goto Error;
5221 
5222     FreeArray(&a);
5223     return TRUE;
5224 
5225 Error:
5226     FreeArray(&a);

5227     return FALSE;
5228 
5229     cmsUNUSED_PARAMETER(nItems);
5230 }
5231 
5232 
5233 static
5234 void* Type_Dictionary_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
5235 {
5236     return (void*)  cmsDictDup((cmsHANDLE) Ptr);
5237 
5238     cmsUNUSED_PARAMETER(n);
5239     cmsUNUSED_PARAMETER(self);



5240 }
5241 
5242 
5243 static
5244 void Type_Dictionary_Free(struct _cms_typehandler_struct* self, void* Ptr)
5245 {
5246     cmsDictFree((cmsHANDLE) Ptr);
5247     cmsUNUSED_PARAMETER(self);
5248 }
5249 
5250 
5251 // ********************************************************************************
5252 // Type support main routines
5253 // ********************************************************************************
5254 
5255 
5256 // This is the list of built-in types
5257 static _cmsTagTypeLinkedList SupportedTagTypes[] = {
5258 
5259 {TYPE_HANDLER(cmsSigChromaticityType,          Chromaticity),        &SupportedTagTypes[1] },




 311 //The XYZType contains an array of three encoded values for the XYZ tristimulus
 312 //values. Tristimulus values must be non-negative. The signed encoding allows for
 313 //implementation optimizations by minimizing the number of fixed formats.
 314 
 315 
 316 static
 317 void *Type_XYZ_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
 318 {
 319     cmsCIEXYZ* xyz;
 320 
 321     *nItems = 0;
 322     xyz = (cmsCIEXYZ*) _cmsMallocZero(self ->ContextID, sizeof(cmsCIEXYZ));
 323     if (xyz == NULL) return NULL;
 324 
 325     if (!_cmsReadXYZNumber(io, xyz)) {
 326         _cmsFree(self ->ContextID, xyz);
 327         return NULL;
 328     }
 329 
 330     *nItems = 1;

 331 
 332     cmsUNUSED_PARAMETER(SizeOfTag);
 333 
 334     return (void*) xyz;
 335 
 336 }
 337 
 338 static
 339 cmsBool  Type_XYZ_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
 340 {


 341     cmsUNUSED_PARAMETER(nItems);
 342     cmsUNUSED_PARAMETER(self);
 343 
 344     return _cmsWriteXYZNumber(io, (cmsCIEXYZ*) Ptr);
 345 
 346 }
 347 
 348 static
 349 void* Type_XYZ_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
 350 {
 351     cmsUNUSED_PARAMETER(n);
 352 
 353     return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsCIEXYZ));
 354 

 355 }
 356 
 357 static
 358 void Type_XYZ_Free(struct _cms_typehandler_struct* self, void *Ptr)
 359 {
 360     _cmsFree(self ->ContextID, Ptr);
 361 }
 362 
 363 
 364 static
 365 cmsTagTypeSignature DecideXYZtype(cmsFloat64Number ICCVersion, const void *Data)
 366 {


 367     cmsUNUSED_PARAMETER(ICCVersion);
 368     cmsUNUSED_PARAMETER(Data);
 369 
 370     return cmsSigXYZType;
 371 
 372 }
 373 
 374 
 375 // ********************************************************************************
 376 // Type chromaticity. Only one value is allowed
 377 // ********************************************************************************
 378 // The chromaticity tag type provides basic chromaticity data and type of
 379 // phosphors or colorants of a monitor to applications and utilities.
 380 
 381 static
 382 void *Type_Chromaticity_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
 383 {
 384     cmsCIExyYTRIPLE* chrm;
 385     cmsUInt16Number nChans, Table;
 386 
 387     *nItems = 0;
 388     chrm =  (cmsCIExyYTRIPLE*) _cmsMallocZero(self ->ContextID, sizeof(cmsCIExyYTRIPLE));
 389     if (chrm == NULL) return NULL;
 390 
 391     if (!_cmsReadUInt16Number(io, &nChans)) goto Error;


 404     if (!_cmsRead15Fixed16Number(io, &chrm ->Red.x)) goto Error;
 405     if (!_cmsRead15Fixed16Number(io, &chrm ->Red.y)) goto Error;
 406 
 407     chrm ->Red.Y = 1.0;
 408 
 409     if (!_cmsRead15Fixed16Number(io, &chrm ->Green.x)) goto Error;
 410     if (!_cmsRead15Fixed16Number(io, &chrm ->Green.y)) goto Error;
 411 
 412     chrm ->Green.Y = 1.0;
 413 
 414     if (!_cmsRead15Fixed16Number(io, &chrm ->Blue.x)) goto Error;
 415     if (!_cmsRead15Fixed16Number(io, &chrm ->Blue.y)) goto Error;
 416 
 417     chrm ->Blue.Y = 1.0;
 418 
 419     *nItems = 1;
 420     return (void*) chrm;
 421 
 422 Error:
 423     _cmsFree(self ->ContextID, (void*) chrm);
 424     cmsUNUSED_PARAMETER(SizeOfTag);
 425 
 426     return NULL;
 427 

 428 }
 429 
 430 static
 431 cmsBool  SaveOneChromaticity(cmsFloat64Number x, cmsFloat64Number y, cmsIOHANDLER* io)
 432 {
 433     if (!_cmsWriteUInt32Number(io, _cmsDoubleTo15Fixed16(x))) return FALSE;
 434     if (!_cmsWriteUInt32Number(io, _cmsDoubleTo15Fixed16(y))) return FALSE;
 435 
 436     return TRUE;
 437 }
 438 
 439 static
 440 cmsBool  Type_Chromaticity_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
 441 {
 442     cmsCIExyYTRIPLE* chrm = (cmsCIExyYTRIPLE*) Ptr;
 443 
 444     if (!_cmsWriteUInt16Number(io, 3)) return FALSE;        // nChannels
 445     if (!_cmsWriteUInt16Number(io, 0)) return FALSE;        // Table
 446 
 447     if (!SaveOneChromaticity(chrm -> Red.x,   chrm -> Red.y, io)) return FALSE;
 448     if (!SaveOneChromaticity(chrm -> Green.x, chrm -> Green.y, io)) return FALSE;
 449     if (!SaveOneChromaticity(chrm -> Blue.x,  chrm -> Blue.y, io)) return FALSE;
 450 


 451     cmsUNUSED_PARAMETER(nItems);
 452     cmsUNUSED_PARAMETER(self);
 453 
 454     return TRUE;
 455 
 456 }
 457 
 458 static
 459 void* Type_Chromaticity_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
 460 {
 461     cmsUNUSED_PARAMETER(n);
 462 
 463     return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsCIExyYTRIPLE));
 464 

 465 }
 466 
 467 static
 468 void Type_Chromaticity_Free(struct _cms_typehandler_struct* self, void* Ptr)
 469 {
 470     _cmsFree(self ->ContextID, Ptr);
 471 }
 472 
 473 
 474 // ********************************************************************************
 475 // Type cmsSigColorantOrderType
 476 // ********************************************************************************
 477 
 478 // This is an optional tag which specifies the laydown order in which colorants will
 479 // be printed on an n-colorant device. The laydown order may be the same as the
 480 // channel generation order listed in the colorantTableTag or the channel order of a
 481 // colour space such as CMYK, in which case this tag is not needed. When this is not
 482 // the case (for example, ink-towers sometimes use the order KCMY), this tag may be
 483 // used to specify the laydown order of the colorants.
 484 


 489     cmsUInt8Number* ColorantOrder;
 490     cmsUInt32Number Count;
 491 
 492     *nItems = 0;
 493     if (!_cmsReadUInt32Number(io, &Count)) return NULL;
 494     if (Count > cmsMAXCHANNELS) return NULL;
 495 
 496     ColorantOrder = (cmsUInt8Number*) _cmsCalloc(self ->ContextID, cmsMAXCHANNELS, sizeof(cmsUInt8Number));
 497     if (ColorantOrder == NULL) return NULL;
 498 
 499     // We use FF as end marker
 500     memset(ColorantOrder, 0xFF, cmsMAXCHANNELS * sizeof(cmsUInt8Number));
 501 
 502     if (io ->Read(io, ColorantOrder, sizeof(cmsUInt8Number), Count) != Count) {
 503 
 504         _cmsFree(self ->ContextID, (void*) ColorantOrder);
 505         return NULL;
 506     }
 507 
 508     *nItems = 1;
 509     cmsUNUSED_PARAMETER(SizeOfTag);
 510 
 511     return (void*) ColorantOrder;
 512 

 513 }
 514 
 515 static
 516 cmsBool Type_ColorantOrderType_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
 517 {
 518     cmsUInt8Number*  ColorantOrder = (cmsUInt8Number*) Ptr;
 519     cmsUInt32Number i, sz, Count;
 520 
 521     // Get the length
 522     for (Count=i=0; i < cmsMAXCHANNELS; i++) {
 523         if (ColorantOrder[i] != 0xFF) Count++;
 524     }
 525 
 526     if (!_cmsWriteUInt32Number(io, Count)) return FALSE;
 527 
 528     sz = Count * sizeof(cmsUInt8Number);
 529     if (!io -> Write(io, sz, ColorantOrder)) return FALSE;
 530 


 531     cmsUNUSED_PARAMETER(nItems);
 532     cmsUNUSED_PARAMETER(self);
 533 
 534     return TRUE;
 535 
 536 }
 537 
 538 static
 539 void* Type_ColorantOrderType_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
 540 {
 541     cmsUNUSED_PARAMETER(n);
 542 
 543     return _cmsDupMem(self ->ContextID, Ptr, cmsMAXCHANNELS * sizeof(cmsUInt8Number));
 544 

 545 }
 546 
 547 
 548 static
 549 void Type_ColorantOrderType_Free(struct _cms_typehandler_struct* self, void* Ptr)
 550 {
 551     _cmsFree(self ->ContextID, Ptr);
 552 }
 553 
 554 // ********************************************************************************
 555 // Type cmsSigS15Fixed16ArrayType
 556 // ********************************************************************************
 557 // This type represents an array of generic 4-byte/32-bit fixed point quantity.
 558 // The number of values is determined from the size of the tag.
 559 
 560 static
 561 void *Type_S15Fixed16_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
 562 {
 563     cmsFloat64Number*  array_double;
 564     cmsUInt32Number i, n;


 575             _cmsFree(self ->ContextID, array_double);
 576             return NULL;
 577         }
 578     }
 579 
 580     *nItems = n;
 581     return (void*) array_double;
 582 }
 583 
 584 static
 585 cmsBool Type_S15Fixed16_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
 586 {
 587     cmsFloat64Number* Value = (cmsFloat64Number*) Ptr;
 588     cmsUInt32Number i;
 589 
 590     for (i=0; i < nItems; i++) {
 591 
 592         if (!_cmsWrite15Fixed16Number(io, Value[i])) return FALSE;
 593     }
 594 
 595     cmsUNUSED_PARAMETER(self);
 596 
 597     return TRUE;
 598 

 599 }
 600 
 601 static
 602 void* Type_S15Fixed16_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
 603 {
 604     return _cmsDupMem(self ->ContextID, Ptr, n * sizeof(cmsFloat64Number));
 605 }
 606 
 607 
 608 static
 609 void Type_S15Fixed16_Free(struct _cms_typehandler_struct* self, void* Ptr)
 610 {
 611     _cmsFree(self ->ContextID, Ptr);
 612 }
 613 
 614 // ********************************************************************************
 615 // Type cmsSigU16Fixed16ArrayType
 616 // ********************************************************************************
 617 // This type represents an array of generic 4-byte/32-bit quantity.
 618 // The number of values is determined from the size of the tag.


 641         array_double[i] =  (cmsFloat64Number) (v / 65536.0);
 642     }
 643 
 644     *nItems = n;
 645     return (void*) array_double;
 646 }
 647 
 648 static
 649 cmsBool Type_U16Fixed16_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
 650 {
 651     cmsFloat64Number* Value = (cmsFloat64Number*) Ptr;
 652     cmsUInt32Number i;
 653 
 654     for (i=0; i < nItems; i++) {
 655 
 656         cmsUInt32Number v = (cmsUInt32Number) floor(Value[i]*65536.0 + 0.5);
 657 
 658         if (!_cmsWriteUInt32Number(io, v)) return FALSE;
 659     }
 660 
 661     cmsUNUSED_PARAMETER(self);
 662 
 663     return TRUE;
 664 

 665 }
 666 
 667 
 668 static
 669 void* Type_U16Fixed16_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
 670 {
 671     return _cmsDupMem(self ->ContextID, Ptr, n * sizeof(cmsFloat64Number));
 672 }
 673 
 674 static
 675 void Type_U16Fixed16_Free(struct _cms_typehandler_struct* self, void* Ptr)
 676 {
 677     _cmsFree(self ->ContextID, Ptr);
 678 }
 679 
 680 // ********************************************************************************
 681 // Type cmsSigSignatureType
 682 // ********************************************************************************
 683 //
 684 // The signatureType contains a four-byte sequence, Sequences of less than four
 685 // characters are padded at the end with spaces, 20h.
 686 // Typically this type is used for registered tags that can be displayed on many
 687 // development systems as a sequence of four characters.
 688 
 689 static
 690 void *Type_Signature_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
 691 {
 692     cmsSignature* SigPtr = (cmsSignature*) _cmsMalloc(self ->ContextID, sizeof(cmsSignature));
 693     if (SigPtr == NULL) return NULL;
 694 
 695      if (!_cmsReadUInt32Number(io, SigPtr)) return NULL;
 696      *nItems = 1;
 697 
 698      cmsUNUSED_PARAMETER(SizeOfTag);
 699 
 700      return SigPtr;
 701 

 702 }
 703 
 704 static
 705 cmsBool  Type_Signature_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
 706 {
 707     cmsSignature* SigPtr = (cmsSignature*) Ptr;
 708 


 709     cmsUNUSED_PARAMETER(nItems);
 710     cmsUNUSED_PARAMETER(self);
 711 
 712     return _cmsWriteUInt32Number(io, *SigPtr);
 713 
 714 }
 715 
 716 static
 717 void* Type_Signature_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
 718 {
 719     return _cmsDupMem(self ->ContextID, Ptr, n * sizeof(cmsSignature));
 720 }
 721 
 722 static
 723 void Type_Signature_Free(struct _cms_typehandler_struct* self, void* Ptr)
 724 {
 725     _cmsFree(self ->ContextID, Ptr);
 726 }
 727 
 728 
 729 // ********************************************************************************
 730 // Type cmsSigTextType
 731 // ********************************************************************************
 732 //
 733 // The textType is a simple text structure that contains a 7-bit ASCII text string.


 779 {
 780     cmsMLU* mlu = (cmsMLU*) Ptr;
 781     cmsUInt32Number size;
 782     cmsBool  rc;
 783     char* Text;
 784 
 785     // Get the size of the string. Note there is an extra "\0" at the end
 786     size = cmsMLUgetASCII(mlu, cmsNoLanguage, cmsNoCountry, NULL, 0);
 787     if (size == 0) return FALSE;       // Cannot be zero!
 788 
 789     // Create memory
 790     Text = (char*) _cmsMalloc(self ->ContextID, size);
 791     if (Text == NULL) return FALSE;
 792 
 793     cmsMLUgetASCII(mlu, cmsNoLanguage, cmsNoCountry, Text, size);
 794 
 795     // Write it, including separator
 796     rc = io ->Write(io, size, Text);
 797 
 798     _cmsFree(self ->ContextID, Text);
 799     cmsUNUSED_PARAMETER(nItems);
 800 
 801     return rc;
 802 

 803 }
 804 
 805 static
 806 void* Type_Text_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
 807 {


 808     cmsUNUSED_PARAMETER(n);
 809     cmsUNUSED_PARAMETER(self);
 810 
 811     return (void*) cmsMLUdup((cmsMLU*) Ptr);
 812 
 813 }
 814 
 815 
 816 static
 817 void Type_Text_Free(struct _cms_typehandler_struct* self, void* Ptr)
 818 {
 819     cmsMLU* mlu = (cmsMLU*) Ptr;
 820     cmsMLUfree(mlu);
 821     cmsUNUSED_PARAMETER(self);
 822 
 823     return;
 824 

 825 }
 826 
 827 static
 828 cmsTagTypeSignature DecideTextType(cmsFloat64Number ICCVersion, const void *Data)
 829 {
 830     cmsUNUSED_PARAMETER(Data);
 831 
 832     if (ICCVersion >= 4.0)
 833         return cmsSigMultiLocalizedUnicodeType;
 834 
 835     return cmsSigTextType;
 836 

 837 }
 838 
 839 
 840 // ********************************************************************************
 841 // Type cmsSigDataType
 842 // ********************************************************************************
 843 
 844 // General purpose data type
 845 static
 846 void *Type_Data_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
 847 {
 848     cmsICCData* BinData;
 849     cmsUInt32Number LenOfData;
 850 
 851     *nItems = 0;
 852 
 853     if (SizeOfTag < sizeof(cmsUInt32Number)) return NULL;
 854 
 855     LenOfData = SizeOfTag - sizeof(cmsUInt32Number);
 856     if (LenOfData > INT_MAX) return NULL;


 864         return NULL;
 865     }
 866 
 867     if (io -> Read(io, BinData ->data, sizeof(cmsUInt8Number), LenOfData) != LenOfData) {
 868 
 869         _cmsFree(self ->ContextID, BinData);
 870         return NULL;
 871     }
 872 
 873     *nItems = 1;
 874 
 875     return (void*) BinData;
 876 }
 877 
 878 
 879 static
 880 cmsBool Type_Data_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
 881 {
 882    cmsICCData* BinData = (cmsICCData*) Ptr;
 883 
 884    cmsUNUSED_PARAMETER(nItems);
 885    cmsUNUSED_PARAMETER(self);
 886 
 887    if (!_cmsWriteUInt32Number(io, BinData ->flag)) return FALSE;
 888 
 889    return io ->Write(io, BinData ->len, BinData ->data);
 890 


 891 }
 892 
 893 
 894 static
 895 void* Type_Data_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
 896 {
 897     cmsICCData* BinData = (cmsICCData*) Ptr;
 898 
 899     cmsUNUSED_PARAMETER(n);
 900 
 901     return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsICCData) + BinData ->len - 1);
 902 

 903 }
 904 
 905 static
 906 void Type_Data_Free(struct _cms_typehandler_struct* self, void* Ptr)
 907 {
 908     _cmsFree(self ->ContextID, Ptr);
 909 }
 910 
 911 // ********************************************************************************
 912 // Type cmsSigTextDescriptionType
 913 // ********************************************************************************
 914 
 915 static
 916 void *Type_Text_Description_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
 917 {
 918     char* Text = NULL;
 919     cmsMLU* mlu = NULL;
 920     cmsUInt32Number  AsciiCount;
 921     cmsUInt32Number  i, UnicodeCode, UnicodeCount;
 922     cmsUInt16Number  ScriptCodeCode, Dummy;


1061     // takes 70 bytes, so we need 2 extra bytes to do the alignment
1062 
1063     if (!_cmsWriteUInt32Number(io, len_aligned+1)) goto Error;
1064 
1065     // Note that in some compilers sizeof(cmsUInt16Number) != sizeof(wchar_t)
1066     if (!_cmsWriteWCharArray(io, len, Wide)) goto Error;
1067     if (!_cmsWriteUInt16Array(io, len_filler_alignment+1, (cmsUInt16Number*) Filler)) goto Error;
1068 
1069     // ScriptCode Code & count (unused)
1070     if (!_cmsWriteUInt16Number(io, 0)) goto Error;
1071     if (!_cmsWriteUInt8Number(io, 0)) goto Error;
1072 
1073     if (!io ->Write(io, 67, Filler)) goto Error;
1074 
1075     rc = TRUE;
1076 
1077 Error:
1078     if (Text) _cmsFree(self ->ContextID, Text);
1079     if (Wide) _cmsFree(self ->ContextID, Wide);
1080 
1081     cmsUNUSED_PARAMETER(nItems);
1082 
1083     return rc;
1084 

1085 }
1086 
1087 
1088 static
1089 void* Type_Text_Description_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
1090 {


1091     cmsUNUSED_PARAMETER(n);
1092     cmsUNUSED_PARAMETER(self);
1093 
1094     return (void*) cmsMLUdup((cmsMLU*) Ptr);
1095 
1096 }
1097 
1098 static
1099 void Type_Text_Description_Free(struct _cms_typehandler_struct* self, void* Ptr)
1100 {
1101     cmsMLU* mlu = (cmsMLU*) Ptr;
1102 
1103     cmsMLUfree(mlu);
1104     cmsUNUSED_PARAMETER(self);
1105 
1106     return;
1107 

1108 }
1109 
1110 
1111 static
1112 cmsTagTypeSignature DecideTextDescType(cmsFloat64Number ICCVersion, const void *Data)
1113 {
1114     cmsUNUSED_PARAMETER(Data);
1115 
1116     if (ICCVersion >= 4.0)
1117         return cmsSigMultiLocalizedUnicodeType;
1118 
1119     return cmsSigTextDescriptionType;
1120 

1121 }
1122 
1123 
1124 // ********************************************************************************
1125 // Type cmsSigCurveType
1126 // ********************************************************************************
1127 
1128 static
1129 void *Type_Curve_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
1130 {
1131     cmsUInt32Number Count;
1132     cmsToneCurve* NewGamma;
1133 
1134     *nItems = 0;
1135     cmsUNUSED_PARAMETER(SizeOfTag);
1136 
1137     if (!_cmsReadUInt32Number(io, &Count)) return NULL;
1138 
1139     switch (Count) {
1140 
1141            case 0:   // Linear.
1142                {
1143                    cmsFloat64Number SingleGamma = 1.0;
1144 
1145                    NewGamma = cmsBuildParametricToneCurve(self ->ContextID, 1, &SingleGamma);
1146                    if (!NewGamma) return NULL;
1147                    *nItems = 1;
1148                    return NewGamma;
1149                }
1150 
1151            case 1:  // Specified as the exponent of gamma function
1152                {
1153                    cmsUInt16Number SingleGammaFixed;
1154                    cmsFloat64Number SingleGamma;
1155 
1156                    if (!_cmsReadUInt16Number(io, &SingleGammaFixed)) return NULL;
1157                    SingleGamma = _cms8Fixed8toDouble(SingleGammaFixed);
1158 
1159                    *nItems = 1;
1160                    return cmsBuildParametricToneCurve(self ->ContextID, 1, &SingleGamma);
1161                }
1162 
1163            default:  // Curve
1164 
1165                if (Count > 0x7FFF)
1166                    return NULL; // This is to prevent bad guys for doing bad things
1167 
1168                NewGamma = cmsBuildTabulatedToneCurve16(self ->ContextID, Count, NULL);
1169                if (!NewGamma) return NULL;
1170 
1171                if (!_cmsReadUInt16Array(io, Count, NewGamma -> Table16)) return NULL;
1172 
1173                *nItems = 1;
1174                return NewGamma;
1175     }
1176 

1177 }
1178 
1179 
1180 static
1181 cmsBool  Type_Curve_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
1182 {
1183     cmsToneCurve* Curve = (cmsToneCurve*) Ptr;
1184 
1185     cmsUNUSED_PARAMETER(nItems);
1186     cmsUNUSED_PARAMETER(self);
1187 
1188     if (Curve ->nSegments == 1 && Curve ->Segments[0].Type == 1) {
1189 
1190             // Single gamma, preserve number
1191             cmsUInt16Number SingleGammaFixed = _cmsDoubleTo8Fixed8(Curve ->Segments[0].Params[0]);
1192 
1193             if (!_cmsWriteUInt32Number(io, 1)) return FALSE;
1194             if (!_cmsWriteUInt16Number(io, SingleGammaFixed)) return FALSE;
1195             return TRUE;
1196 
1197     }
1198 
1199     if (!_cmsWriteUInt32Number(io, Curve ->nEntries)) return FALSE;
1200     return _cmsWriteUInt16Array(io, Curve ->nEntries, Curve ->Table16);
1201 


1202 }
1203 
1204 
1205 static
1206 void* Type_Curve_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
1207 {


1208     cmsUNUSED_PARAMETER(n);
1209     cmsUNUSED_PARAMETER(self);
1210 
1211     return (void*) cmsDupToneCurve((cmsToneCurve*) Ptr);
1212 
1213 }
1214 
1215 static
1216 void Type_Curve_Free(struct _cms_typehandler_struct* self, void* Ptr)
1217 {
1218     cmsToneCurve* gamma = (cmsToneCurve*) Ptr;
1219 
1220     cmsFreeToneCurve(gamma);
1221     cmsUNUSED_PARAMETER(self);
1222 
1223     return;
1224 

1225 }
1226 
1227 
1228 // ********************************************************************************
1229 // Type cmsSigParametricCurveType
1230 // ********************************************************************************
1231 
1232 
1233 // Decide which curve type to use on writting
1234 static
1235 cmsTagTypeSignature DecideCurveType(cmsFloat64Number ICCVersion, const void *Data)
1236 {
1237     cmsToneCurve* Curve = (cmsToneCurve*) Data;
1238 
1239     if (ICCVersion < 4.0) return cmsSigCurveType;
1240     if (Curve ->nSegments != 1) return cmsSigCurveType;          // Only 1-segment curves can be saved as parametric
1241     if (Curve ->Segments[0].Type < 0) return cmsSigCurveType;    // Only non-inverted curves
1242     if (Curve ->Segments[0].Type > 5) return cmsSigCurveType;    // Only ICC parametric curves
1243 
1244     return cmsSigParametricCurveType;
1245 }
1246 
1247 static
1248 void *Type_ParametricCurve_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
1249 {
1250     static const int ParamsByType[] = { 1, 3, 4, 5, 7 };
1251     cmsFloat64Number Params[10];
1252     cmsUInt16Number Type;
1253     int i, n;
1254     cmsToneCurve* NewGamma;
1255 
1256     cmsUNUSED_PARAMETER(SizeOfTag);
1257 
1258     if (!_cmsReadUInt16Number(io, &Type)) return NULL;
1259     if (!_cmsReadUInt16Number(io, NULL)) return NULL;   // Reserved
1260 
1261     if (Type > 4) {
1262 
1263         cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown parametric curve type '%d'", Type);
1264         return NULL;
1265     }
1266 
1267     memset(Params, 0, sizeof(Params));
1268     n = ParamsByType[Type];
1269 
1270     for (i=0; i < n; i++) {
1271 
1272         if (!_cmsRead15Fixed16Number(io, &Params[i])) return NULL;
1273     }
1274 
1275     NewGamma = cmsBuildParametricToneCurve(self ->ContextID, Type+1, Params);
1276 
1277     *nItems = 1;
1278 
1279     return NewGamma;
1280 

1281 }
1282 
1283 
1284 static
1285 cmsBool  Type_ParametricCurve_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
1286 {
1287     cmsToneCurve* Curve = (cmsToneCurve*) Ptr;
1288     int i, nParams, typen;
1289     static const int ParamsByType[] = { 0, 1, 3, 4, 5, 7 };
1290 
1291     typen = Curve -> Segments[0].Type;
1292 
1293     cmsUNUSED_PARAMETER(nItems);
1294 
1295     if (Curve ->nSegments > 1 || typen < 1) {
1296 
1297         cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Multisegment or Inverted parametric curves cannot be written");
1298         return FALSE;
1299     }
1300 
1301     if (typen > 5) {
1302         cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported parametric curve");
1303         return FALSE;
1304     }
1305 
1306     nParams = ParamsByType[typen];
1307 
1308     if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) (Curve ->Segments[0].Type - 1))) return FALSE;
1309     if (!_cmsWriteUInt16Number(io, 0)) return FALSE;        // Reserved
1310 
1311     for (i=0; i < nParams; i++) {
1312 
1313         if (!_cmsWrite15Fixed16Number(io, Curve -> Segments[0].Params[i])) return FALSE;
1314     }
1315 
1316     return TRUE;
1317 

1318 }
1319 
1320 static
1321 void* Type_ParametricCurve_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
1322 {


1323     cmsUNUSED_PARAMETER(n);
1324     cmsUNUSED_PARAMETER(self);
1325 
1326     return (void*) cmsDupToneCurve((cmsToneCurve*) Ptr);
1327 
1328 }
1329 
1330 static
1331 void Type_ParametricCurve_Free(struct _cms_typehandler_struct* self, void* Ptr)
1332 {
1333     cmsToneCurve* gamma = (cmsToneCurve*) Ptr;
1334 
1335     cmsFreeToneCurve(gamma);
1336     cmsUNUSED_PARAMETER(self);
1337 
1338     return;
1339 

1340 }
1341 
1342 
1343 // ********************************************************************************
1344 // Type cmsSigDateTimeType
1345 // ********************************************************************************
1346 
1347 // A 12-byte value representation of the time and date, where the byte usage is assigned
1348 // as specified in table 1. The actual values are encoded as 16-bit unsigned integers
1349 // (uInt16Number - see 5.1.6).
1350 //
1351 // All the dateTimeNumber values in a profile shall be in Coordinated Universal Time
1352 // (UTC, also known as GMT or ZULU Time). Profile writers are required to convert local
1353 // time to UTC when setting these values. Programmes that display these values may show
1354 // the dateTimeNumber as UTC, show the equivalent local time (at current locale), or
1355 // display both UTC and local versions of the dateTimeNumber.
1356 
1357 static
1358 void *Type_DateTime_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
1359 {
1360     cmsDateTimeNumber timestamp;
1361     struct tm * NewDateTime;
1362 
1363     *nItems = 0;
1364     NewDateTime = (struct tm*) _cmsMalloc(self ->ContextID, sizeof(struct tm));
1365     cmsUNUSED_PARAMETER(SizeOfTag);
1366 
1367     if (NewDateTime == NULL) return NULL;
1368 
1369     if (io->Read(io, &timestamp, sizeof(cmsDateTimeNumber), 1) != 1) return NULL;
1370 
1371      _cmsDecodeDateTimeNumber(&timestamp, NewDateTime);
1372 
1373      *nItems = 1;
1374      return NewDateTime;
1375 

1376 }
1377 
1378 
1379 static
1380 cmsBool  Type_DateTime_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
1381 {
1382     struct tm * DateTime = (struct tm*) Ptr;
1383     cmsDateTimeNumber timestamp;
1384 
1385     _cmsEncodeDateTimeNumber(&timestamp, DateTime);
1386     cmsUNUSED_PARAMETER(nItems);
1387     cmsUNUSED_PARAMETER(self);
1388 
1389     if (!io ->Write(io, sizeof(cmsDateTimeNumber), &timestamp)) return FALSE;
1390 
1391     return TRUE;
1392 


1393 }
1394 
1395 static
1396 void* Type_DateTime_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
1397 {
1398     cmsUNUSED_PARAMETER(n);
1399 
1400     return _cmsDupMem(self ->ContextID, Ptr, sizeof(struct tm));
1401 

1402 }
1403 
1404 static
1405 void Type_DateTime_Free(struct _cms_typehandler_struct* self, void* Ptr)
1406 {
1407     _cmsFree(self ->ContextID, Ptr);
1408 }
1409 
1410 
1411 
1412 // ********************************************************************************
1413 // Type icMeasurementType
1414 // ********************************************************************************
1415 
1416 /*
1417 The measurementType information refers only to the internal profile data and is
1418 meant to provide profile makers an alternative to the default measurement
1419 specifications.
1420 */
1421 
1422 static
1423 void *Type_Measurement_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
1424 {
1425     cmsICCMeasurementConditions mc;
1426 
1427 
1428     memset(&mc, 0, sizeof(mc));
1429 
1430     cmsUNUSED_PARAMETER(SizeOfTag);
1431 
1432     if (!_cmsReadUInt32Number(io, &mc.Observer)) return NULL;
1433     if (!_cmsReadXYZNumber(io,    &mc.Backing)) return NULL;
1434     if (!_cmsReadUInt32Number(io, &mc.Geometry)) return NULL;
1435     if (!_cmsRead15Fixed16Number(io, &mc.Flare)) return NULL;
1436     if (!_cmsReadUInt32Number(io, &mc.IlluminantType)) return NULL;
1437 
1438     *nItems = 1;
1439     return _cmsDupMem(self ->ContextID, &mc, sizeof(cmsICCMeasurementConditions));
1440 

1441 }
1442 
1443 
1444 static
1445 cmsBool  Type_Measurement_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
1446 {
1447     cmsICCMeasurementConditions* mc =(cmsICCMeasurementConditions*) Ptr;
1448 
1449     cmsUNUSED_PARAMETER(nItems);
1450     cmsUNUSED_PARAMETER(self);
1451 
1452     if (!_cmsWriteUInt32Number(io, mc->Observer)) return FALSE;
1453     if (!_cmsWriteXYZNumber(io,    &mc->Backing)) return FALSE;
1454     if (!_cmsWriteUInt32Number(io, mc->Geometry)) return FALSE;
1455     if (!_cmsWrite15Fixed16Number(io, mc->Flare)) return FALSE;
1456     if (!_cmsWriteUInt32Number(io, mc->IlluminantType)) return FALSE;
1457 
1458     return TRUE;
1459 


1460 }
1461 
1462 static
1463 void* Type_Measurement_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
1464 {
1465      cmsUNUSED_PARAMETER(n);
1466 
1467      return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsICCMeasurementConditions));
1468 

1469 }
1470 
1471 static
1472 void Type_Measurement_Free(struct _cms_typehandler_struct* self, void* Ptr)
1473 {
1474    _cmsFree(self ->ContextID, Ptr);
1475 }
1476 
1477 
1478 // ********************************************************************************
1479 // Type cmsSigMultiLocalizedUnicodeType
1480 // ********************************************************************************
1481 //
1482 //   Do NOT trust SizeOfTag as there is an issue on the definition of profileSequenceDescTag. See the TechNote from
1483 //   Max Derhak and Rohit Patil about this: basically the size of the string table should be guessed and cannot be
1484 //   taken from the size of tag if this tag is embedded as part of bigger structures (profileSequenceDescTag, for instance)
1485 //
1486 
1487 static
1488 void *Type_MLU_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)


1557     mlu ->MemPool  = Block;
1558     mlu ->PoolSize = SizeOfTag;
1559     mlu ->PoolUsed = SizeOfTag;
1560 
1561     *nItems = 1;
1562     return (void*) mlu;
1563 
1564 Error:
1565     if (mlu) cmsMLUfree(mlu);
1566     return NULL;
1567 }
1568 
1569 static
1570 cmsBool  Type_MLU_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
1571 {
1572     cmsMLU* mlu =(cmsMLU*) Ptr;
1573     cmsUInt32Number HeaderSize;
1574     cmsUInt32Number  Len, Offset;
1575     int i;
1576 
1577     cmsUNUSED_PARAMETER(nItems);
1578     cmsUNUSED_PARAMETER(self);
1579     if (Ptr == NULL) {
1580 
1581           // Empty placeholder
1582           if (!_cmsWriteUInt32Number(io, 0)) return FALSE;
1583           if (!_cmsWriteUInt32Number(io, 12)) return FALSE;
1584           return TRUE;
1585     }
1586 
1587     if (!_cmsWriteUInt32Number(io, mlu ->UsedEntries)) return FALSE;
1588     if (!_cmsWriteUInt32Number(io, 12)) return FALSE;
1589 
1590     HeaderSize = 12 * mlu ->UsedEntries + sizeof(_cmsTagBase);
1591 
1592     for (i=0; i < mlu ->UsedEntries; i++) {
1593 
1594         Len    =  mlu ->Entries[i].Len;
1595         Offset =  mlu ->Entries[i].StrW;
1596 
1597         Len    = (Len * sizeof(cmsUInt16Number)) / sizeof(wchar_t);
1598         Offset = (Offset * sizeof(cmsUInt16Number)) / sizeof(wchar_t) + HeaderSize + 8;
1599 
1600         if (!_cmsWriteUInt16Number(io, mlu ->Entries[i].Language)) return FALSE;
1601         if (!_cmsWriteUInt16Number(io, mlu ->Entries[i].Country))  return FALSE;
1602         if (!_cmsWriteUInt32Number(io, Len)) return FALSE;
1603         if (!_cmsWriteUInt32Number(io, Offset)) return FALSE;
1604     }
1605 
1606     if (!_cmsWriteWCharArray(io, mlu ->PoolUsed / sizeof(wchar_t), (wchar_t*)  mlu ->MemPool)) return FALSE;
1607 
1608     return TRUE;
1609 


1610 }
1611 
1612 
1613 static
1614 void* Type_MLU_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
1615 {


1616     cmsUNUSED_PARAMETER(n);
1617     cmsUNUSED_PARAMETER(self);
1618 
1619     return (void*) cmsMLUdup((cmsMLU*) Ptr);
1620 
1621 }
1622 
1623 static
1624 void Type_MLU_Free(struct _cms_typehandler_struct* self, void* Ptr)
1625 {
1626     cmsMLUfree((cmsMLU*) Ptr);
1627     cmsUNUSED_PARAMETER(self);
1628 
1629     return;
1630 

1631 }
1632 
1633 
1634 // ********************************************************************************
1635 // Type cmsSigLut8Type
1636 // ********************************************************************************
1637 
1638 // Decide which LUT type to use on writting
1639 static
1640 cmsTagTypeSignature DecideLUTtypeA2B(cmsFloat64Number ICCVersion, const void *Data)
1641 {
1642     cmsPipeline* Lut = (cmsPipeline*) Data;
1643 
1644     if (ICCVersion < 4.0) {
1645         if (Lut ->SaveAs8Bits) return cmsSigLut8Type;
1646         return cmsSigLut16Type;
1647     }
1648     else {
1649          return cmsSigLutAtoBType;
1650     }


1875 
1876             *PtrW++ = FROM_8_TO_16(Temp[i]);
1877         }
1878         _cmsFree(self ->ContextID, Temp);
1879         Temp = NULL;
1880 
1881         if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, cmsStageAllocCLut16bit(self ->ContextID, CLUTpoints, InputChannels, OutputChannels, T)))
1882             goto Error;
1883         _cmsFree(self ->ContextID, T);
1884     }
1885 
1886 
1887     // Get output tables
1888     if (!Read8bitTables(self ->ContextID, io,  NewLUT, OutputChannels)) goto Error;
1889 
1890     *nItems = 1;
1891     return NewLUT;
1892 
1893 Error:
1894     if (NewLUT != NULL) cmsPipelineFree(NewLUT);
1895     cmsUNUSED_PARAMETER(SizeOfTag);
1896 
1897     return NULL;
1898 

1899 }
1900 
1901 // We only allow a specific MPE structure: Matrix plus prelin, plus clut, plus post-lin.
1902 static
1903 cmsBool  Type_LUT8_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
1904 {
1905     cmsUInt32Number j, nTabSize;
1906     cmsUInt8Number  val;
1907     cmsPipeline* NewLUT = (cmsPipeline*) Ptr;
1908     cmsStage* mpe;
1909     _cmsStageToneCurvesData* PreMPE = NULL, *PostMPE = NULL;
1910     _cmsStageMatrixData* MatMPE = NULL;
1911     _cmsStageCLutData* clut = NULL;
1912     int clutPoints;
1913 
1914     // Disassemble the LUT into components.
1915     mpe = NewLUT -> Elements;
1916     if (mpe ->Type == cmsSigMatrixElemType) {
1917 
1918         MatMPE = (_cmsStageMatrixData*) mpe ->Data;


1979     }
1980 
1981     // The prelinearization table
1982     if (!Write8bitTables(self ->ContextID, io, NewLUT ->InputChannels, PreMPE)) return FALSE;
1983 
1984     nTabSize = uipow(NewLUT->OutputChannels, clutPoints, NewLUT ->InputChannels);
1985     if (nTabSize == (cmsUInt32Number) -1) return FALSE;
1986     if (nTabSize > 0) {
1987 
1988         // The 3D CLUT.
1989         if (clut != NULL) {
1990 
1991             for (j=0; j < nTabSize; j++) {
1992 
1993                 val = (cmsUInt8Number) FROM_16_TO_8(clut ->Tab.T[j]);
1994                 if (!_cmsWriteUInt8Number(io, val)) return FALSE;
1995             }
1996         }
1997     }
1998 
1999     cmsUNUSED_PARAMETER(nItems);
2000     // The postlinearization table
2001     if (!Write8bitTables(self ->ContextID, io, NewLUT ->OutputChannels, PostMPE)) return FALSE;
2002 
2003     return TRUE;
2004 

2005 }
2006 
2007 
2008 static
2009 void* Type_LUT8_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
2010 {


2011     cmsUNUSED_PARAMETER(n);
2012     cmsUNUSED_PARAMETER(self);
2013 
2014     return (void*) cmsPipelineDup((cmsPipeline*) Ptr);
2015 
2016 }
2017 
2018 static
2019 void Type_LUT8_Free(struct _cms_typehandler_struct* self, void* Ptr)
2020 {
2021     cmsPipelineFree((cmsPipeline*) Ptr);
2022     cmsUNUSED_PARAMETER(self);
2023 
2024     return;
2025 

2026 }
2027 
2028 // ********************************************************************************
2029 // Type cmsSigLut16Type
2030 // ********************************************************************************
2031 
2032 // Read 16 bit tables as gamma functions
2033 static
2034 cmsBool  Read16bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsPipeline* lut, int nChannels, int nEntries)
2035 {
2036     int i;
2037     cmsToneCurve* Tables[cmsMAXCHANNELS];
2038 
2039     // Maybe an empty table? (this is a lcms extension)
2040     if (nEntries <= 0) return TRUE;
2041 
2042     // Check for malicious profiles
2043     if (nEntries < 2) return FALSE;
2044     if (nChannels > cmsMAXCHANNELS) return FALSE;
2045 


2067 Error:
2068     for (i=0; i < nChannels; i++) {
2069         if (Tables[i]) cmsFreeToneCurve(Tables[i]);
2070     }
2071 
2072     return FALSE;
2073 }
2074 
2075 static
2076 cmsBool Write16bitTables(cmsContext ContextID, cmsIOHANDLER* io, _cmsStageToneCurvesData* Tables)
2077 {
2078     int j;
2079     cmsUInt32Number i;
2080     cmsUInt16Number val;
2081     int nEntries;
2082 
2083     _cmsAssert(Tables != NULL);
2084 
2085     nEntries = Tables->TheCurves[0]->nEntries;
2086 
2087     cmsUNUSED_PARAMETER(ContextID);
2088     for (i=0; i < Tables ->nCurves; i++) {
2089 
2090         for (j=0; j < nEntries; j++) {
2091 
2092             val = Tables->TheCurves[i]->Table16[j];
2093             if (!_cmsWriteUInt16Number(io, val)) return FALSE;
2094         }
2095     }
2096     return TRUE;
2097 

2098 }
2099 
2100 static
2101 void *Type_LUT16_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
2102 {
2103     cmsUInt8Number InputChannels, OutputChannels, CLUTpoints;
2104     cmsPipeline* NewLUT = NULL;
2105     cmsUInt32Number nTabSize;
2106     cmsFloat64Number Matrix[3*3];
2107     cmsUInt16Number InputEntries, OutputEntries;
2108 
2109     *nItems = 0;
2110 
2111     if (!_cmsReadUInt8Number(io, &InputChannels)) return NULL;
2112     if (!_cmsReadUInt8Number(io, &OutputChannels)) return NULL;
2113     if (!_cmsReadUInt8Number(io, &CLUTpoints)) return NULL;   // 255 maximum
2114 
2115     // Padding
2116     if (!_cmsReadUInt8Number(io, NULL)) return NULL;
2117 


2165             _cmsFree(self ->ContextID, T);
2166             goto Error;
2167         }
2168 
2169         if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, cmsStageAllocCLut16bit(self ->ContextID, CLUTpoints, InputChannels, OutputChannels, T))) {
2170             _cmsFree(self ->ContextID, T);
2171             goto Error;
2172         }
2173         _cmsFree(self ->ContextID, T);
2174     }
2175 
2176 
2177     // Get output tables
2178     if (!Read16bitTables(self ->ContextID, io,  NewLUT, OutputChannels, OutputEntries)) goto Error;
2179 
2180     *nItems = 1;
2181     return NewLUT;
2182 
2183 Error:
2184     if (NewLUT != NULL) cmsPipelineFree(NewLUT);
2185     cmsUNUSED_PARAMETER(SizeOfTag);
2186 
2187     return NULL;
2188 

2189 }
2190 
2191 // We only allow some specific MPE structures: Matrix plus prelin, plus clut, plus post-lin.
2192 // Some empty defaults are created for missing parts
2193 
2194 static
2195 cmsBool  Type_LUT16_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
2196 {
2197     cmsUInt32Number nTabSize;
2198     cmsPipeline* NewLUT = (cmsPipeline*) Ptr;
2199     cmsStage* mpe;
2200     _cmsStageToneCurvesData* PreMPE = NULL, *PostMPE = NULL;
2201     _cmsStageMatrixData* MatMPE = NULL;
2202     _cmsStageCLutData* clut = NULL;
2203     int i, InputChannels, OutputChannels, clutPoints;
2204 
2205     // Disassemble the LUT into components.
2206     mpe = NewLUT -> Elements;
2207     if (mpe != NULL && mpe ->Type == cmsSigMatrixElemType) {
2208 


2302     if (nTabSize == (cmsUInt32Number) -1) return FALSE;
2303     if (nTabSize > 0) {
2304         // The 3D CLUT.
2305         if (clut != NULL) {
2306             if (!_cmsWriteUInt16Array(io, nTabSize, clut->Tab.T)) return FALSE;
2307         }
2308     }
2309 
2310     // The postlinearization table
2311     if (PostMPE != NULL) {
2312         if (!Write16bitTables(self ->ContextID, io, PostMPE)) return FALSE;
2313     }
2314     else {
2315         for (i=0; i < OutputChannels; i++) {
2316 
2317             if (!_cmsWriteUInt16Number(io, 0)) return FALSE;
2318             if (!_cmsWriteUInt16Number(io, 0xffff)) return FALSE;
2319         }
2320     }
2321 
2322     cmsUNUSED_PARAMETER(nItems);
2323     return TRUE;
2324 

2325 }
2326 
2327 static
2328 void* Type_LUT16_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
2329 {


2330     cmsUNUSED_PARAMETER(n);
2331     cmsUNUSED_PARAMETER(self);
2332 
2333     return (void*) cmsPipelineDup((cmsPipeline*) Ptr);
2334 
2335 }
2336 
2337 static
2338 void Type_LUT16_Free(struct _cms_typehandler_struct* self, void* Ptr)
2339 {
2340     cmsPipelineFree((cmsPipeline*) Ptr);
2341     cmsUNUSED_PARAMETER(self);
2342 
2343     return;
2344 

2345 }
2346 
2347 
2348 // ********************************************************************************
2349 // Type cmsSigLutAToBType
2350 // ********************************************************************************
2351 
2352 
2353 // V4 stuff. Read matrix for LutAtoB and LutBtoA
2354 
2355 static
2356 cmsStage* ReadMatrix(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number Offset)
2357 {
2358     cmsFloat64Number dMat[3*3];
2359     cmsFloat64Number dOff[3];
2360     cmsStage* Mat;
2361 
2362     // Go to address
2363     if (!io -> Seek(io, Offset)) return NULL;
2364 


2570 
2571     if (offsetM != 0) {
2572         if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetM, outputChan)))
2573             goto Error;
2574     }
2575 
2576     if (offsetMat != 0) {
2577         if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadMatrix(self, io, BaseOffset + offsetMat)))
2578             goto Error;
2579     }
2580 
2581     if (offsetB != 0) {
2582         if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetB, outputChan)))
2583             goto Error;
2584     }
2585 
2586     *nItems = 1;
2587     return NewLUT;
2588 Error:
2589     cmsPipelineFree(NewLUT);
2590     cmsUNUSED_PARAMETER(SizeOfTag);
2591     return NULL;
2592 

2593 }
2594 
2595 // Write a set of curves
2596 static
2597 cmsBool  WriteMatrix(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsStage* mpe)
2598 {
2599     _cmsStageMatrixData* m = (_cmsStageMatrixData*) mpe -> Data;
2600 
2601     // Write the Matrix
2602     if (!_cmsWrite15Fixed16Number(io, m -> Double[0])) return FALSE;
2603     if (!_cmsWrite15Fixed16Number(io, m -> Double[1])) return FALSE;
2604     if (!_cmsWrite15Fixed16Number(io, m -> Double[2])) return FALSE;
2605     if (!_cmsWrite15Fixed16Number(io, m -> Double[3])) return FALSE;
2606     if (!_cmsWrite15Fixed16Number(io, m -> Double[4])) return FALSE;
2607     if (!_cmsWrite15Fixed16Number(io, m -> Double[5])) return FALSE;
2608     if (!_cmsWrite15Fixed16Number(io, m -> Double[6])) return FALSE;
2609     if (!_cmsWrite15Fixed16Number(io, m -> Double[7])) return FALSE;
2610     if (!_cmsWrite15Fixed16Number(io, m -> Double[8])) return FALSE;
2611 
2612     if (m ->Offset != NULL) {
2613 
2614     if (!_cmsWrite15Fixed16Number(io, m -> Offset[0])) return FALSE;
2615     if (!_cmsWrite15Fixed16Number(io, m -> Offset[1])) return FALSE;
2616     if (!_cmsWrite15Fixed16Number(io, m -> Offset[2])) return FALSE;
2617     }
2618     else {
2619         if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
2620         if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
2621         if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
2622 
2623     }
2624 
2625 
2626     cmsUNUSED_PARAMETER(self);
2627     return TRUE;
2628 

2629 }
2630 
2631 
2632 // Write a set of curves
2633 static
2634 cmsBool WriteSetOfCurves(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsTagTypeSignature Type, cmsStage* mpe)
2635 {
2636     cmsUInt32Number i, n;
2637     cmsTagTypeSignature CurrentType;
2638     cmsToneCurve** Curves;
2639 
2640 
2641     n      = cmsStageOutputChannels(mpe);
2642     Curves = _cmsStageGetPtrToCurveSet(mpe);
2643 
2644     for (i=0; i < n; i++) {
2645 
2646         // If this is a table-based curve, use curve type even on V4
2647         CurrentType = Type;
2648 


2799     }
2800 
2801     if (B != NULL) {
2802 
2803         offsetB = io ->Tell(io) - BaseOffset;
2804         if (!WriteSetOfCurves(self, io, cmsSigParametricCurveType, B)) return FALSE;
2805     }
2806 
2807     CurrentPos = io ->Tell(io);
2808 
2809     if (!io ->Seek(io, DirectoryPos)) return FALSE;
2810 
2811     if (!_cmsWriteUInt32Number(io, offsetB)) return FALSE;
2812     if (!_cmsWriteUInt32Number(io, offsetMat)) return FALSE;
2813     if (!_cmsWriteUInt32Number(io, offsetM)) return FALSE;
2814     if (!_cmsWriteUInt32Number(io, offsetC)) return FALSE;
2815     if (!_cmsWriteUInt32Number(io, offsetA)) return FALSE;
2816 
2817     if (!io ->Seek(io, CurrentPos)) return FALSE;
2818 
2819     cmsUNUSED_PARAMETER(nItems);
2820     return TRUE;
2821 

2822 }
2823 
2824 
2825 static
2826 void* Type_LUTA2B_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
2827 {


2828     cmsUNUSED_PARAMETER(n);
2829     cmsUNUSED_PARAMETER(self);
2830 
2831     return (void*) cmsPipelineDup((cmsPipeline*) Ptr);
2832 
2833 }
2834 
2835 static
2836 void Type_LUTA2B_Free(struct _cms_typehandler_struct* self, void* Ptr)
2837 {
2838     cmsPipelineFree((cmsPipeline*) Ptr);
2839     cmsUNUSED_PARAMETER(self);
2840 
2841     return;
2842 

2843 }
2844 
2845 
2846 // LutBToA type
2847 
2848 static
2849 void* Type_LUTB2A_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
2850 {
2851     cmsUInt8Number       inputChan;      // Number of input channels
2852     cmsUInt8Number       outputChan;     // Number of output channels
2853     cmsUInt32Number      BaseOffset;     // Actual position in file
2854     cmsUInt32Number      offsetB;        // Offset to first "B" curve
2855     cmsUInt32Number      offsetMat;      // Offset to matrix
2856     cmsUInt32Number      offsetM;        // Offset to first "M" curve
2857     cmsUInt32Number      offsetC;        // Offset to CLUT
2858     cmsUInt32Number      offsetA;        // Offset to first "A" curve
2859     cmsPipeline* NewLUT = NULL;
2860 
2861 
2862     BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);


2889 
2890     if (offsetM != 0) {
2891         if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetM, inputChan)))
2892             goto Error;
2893     }
2894 
2895     if (offsetC != 0) {
2896         if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadCLUT(self, io, BaseOffset + offsetC, inputChan, outputChan)))
2897             goto Error;
2898     }
2899 
2900     if (offsetA!= 0) {
2901         if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetA, outputChan)))
2902             goto Error;
2903     }
2904 
2905     *nItems = 1;
2906     return NewLUT;
2907 Error:
2908     cmsPipelineFree(NewLUT);
2909     cmsUNUSED_PARAMETER(SizeOfTag);
2910 
2911     return NULL;
2912 

2913 }
2914 
2915 
2916 /*
2917 B
2918 B - Matrix - M
2919 B - CLUT - A
2920 B - Matrix - M - CLUT - A
2921 */
2922 
2923 static
2924 cmsBool  Type_LUTB2A_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
2925 {
2926     cmsPipeline* Lut = (cmsPipeline*) Ptr;
2927     int inputChan, outputChan;
2928     cmsStage *A = NULL, *B = NULL, *M = NULL;
2929     cmsStage *Matrix = NULL;
2930     cmsStage *CLUT = NULL;
2931     cmsUInt32Number offsetB = 0, offsetMat = 0, offsetM = 0, offsetC = 0, offsetA = 0;
2932     cmsUInt32Number BaseOffset, DirectoryPos, CurrentPos;


2981     }
2982 
2983     if (B != NULL) {
2984 
2985         offsetB = io ->Tell(io) - BaseOffset;
2986         if (!WriteSetOfCurves(self, io, cmsSigParametricCurveType, B)) return FALSE;
2987     }
2988 
2989     CurrentPos = io ->Tell(io);
2990 
2991     if (!io ->Seek(io, DirectoryPos)) return FALSE;
2992 
2993     if (!_cmsWriteUInt32Number(io, offsetB)) return FALSE;
2994     if (!_cmsWriteUInt32Number(io, offsetMat)) return FALSE;
2995     if (!_cmsWriteUInt32Number(io, offsetM)) return FALSE;
2996     if (!_cmsWriteUInt32Number(io, offsetC)) return FALSE;
2997     if (!_cmsWriteUInt32Number(io, offsetA)) return FALSE;
2998 
2999     if (!io ->Seek(io, CurrentPos)) return FALSE;
3000 
3001     cmsUNUSED_PARAMETER(nItems);
3002 
3003     return TRUE;
3004 

3005 }
3006 
3007 
3008 
3009 static
3010 void* Type_LUTB2A_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
3011 {


3012     cmsUNUSED_PARAMETER(n);
3013     cmsUNUSED_PARAMETER(self);
3014 
3015     return (void*) cmsPipelineDup((cmsPipeline*) Ptr);
3016 
3017 }
3018 
3019 static
3020 void Type_LUTB2A_Free(struct _cms_typehandler_struct* self, void* Ptr)
3021 {
3022     cmsPipelineFree((cmsPipeline*) Ptr);
3023     cmsUNUSED_PARAMETER(self);
3024 
3025     return;
3026 

3027 }
3028 
3029 
3030 
3031 // ********************************************************************************
3032 // Type cmsSigColorantTableType
3033 // ********************************************************************************
3034 /*
3035 The purpose of this tag is to identify the colorants used in the profile by a
3036 unique name and set of XYZ or L*a*b* values to give the colorant an unambiguous
3037 value. The first colorant listed is the colorant of the first device channel of
3038 a lut tag. The second colorant listed is the colorant of the second device channel
3039 of a lut tag, and so on.
3040 */
3041 
3042 static
3043 void *Type_ColorantTable_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
3044 {
3045     cmsUInt32Number i, Count;
3046     cmsNAMEDCOLORLIST* List;


3056     }
3057 
3058     List = cmsAllocNamedColorList(self ->ContextID, Count, 0, "", "");
3059     for (i=0; i < Count; i++) {
3060 
3061         if (io ->Read(io, Name, 32, 1) != 1) goto Error;
3062         Name[33] = 0;
3063 
3064         if (!_cmsReadUInt16Array(io, 3, PCS)) goto Error;
3065 
3066         if (!cmsAppendNamedColor(List, Name, PCS, NULL)) goto Error;
3067 
3068     }
3069 
3070     *nItems = 1;
3071     return List;
3072 
3073 Error:
3074     *nItems = 0;
3075     cmsFreeNamedColorList(List);
3076     cmsUNUSED_PARAMETER(SizeOfTag);
3077 
3078     return NULL;
3079 

3080 }
3081 
3082 
3083 
3084 // Saves a colorant table. It is using the named color structure for simplicity sake
3085 static
3086 cmsBool  Type_ColorantTable_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
3087 {
3088     cmsNAMEDCOLORLIST* NamedColorList = (cmsNAMEDCOLORLIST*) Ptr;
3089     int i, nColors;
3090 
3091     nColors = cmsNamedColorCount(NamedColorList);
3092 
3093     if (!_cmsWriteUInt32Number(io, nColors)) return FALSE;
3094 
3095     for (i=0; i < nColors; i++) {
3096 
3097         char root[33];
3098         cmsUInt16Number PCS[3];
3099 
3100         if (!cmsNamedColorInfo(NamedColorList, i, root, NULL, NULL, PCS, NULL)) return 0;
3101         root[32] = 0;
3102 
3103         if (!io ->Write(io, 32, root)) return FALSE;
3104         if (!_cmsWriteUInt16Array(io, 3, PCS)) return FALSE;
3105     }
3106 


3107     cmsUNUSED_PARAMETER(nItems);
3108     cmsUNUSED_PARAMETER(self);
3109 
3110     return TRUE;
3111 
3112 }
3113 
3114 
3115 static
3116 void* Type_ColorantTable_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n)
3117 {
3118     cmsNAMEDCOLORLIST* nc = (cmsNAMEDCOLORLIST*) Ptr;


3119     cmsUNUSED_PARAMETER(n);
3120     cmsUNUSED_PARAMETER(self);
3121 
3122     return (void*) cmsDupNamedColorList(nc);
3123 
3124 }
3125 
3126 
3127 static
3128 void Type_ColorantTable_Free(struct _cms_typehandler_struct* self, void* Ptr)
3129 {
3130     cmsFreeNamedColorList((cmsNAMEDCOLORLIST*) Ptr);
3131     cmsUNUSED_PARAMETER(self);
3132     return;
3133 

3134 }
3135 
3136 
3137 // ********************************************************************************
3138 // Type cmsSigNamedColor2Type
3139 // ********************************************************************************
3140 //
3141 //The namedColor2Type is a count value and array of structures that provide color
3142 //coordinates for 7-bit ASCII color names. For each named color, a PCS and optional
3143 //device representation of the color are given. Both representations are 16-bit values.
3144 //The device representation corresponds to the header’s “color space of data” field.
3145 //This representation should be consistent with the “number of device components”
3146 //field in the namedColor2Type. If this field is 0, device coordinates are not provided.
3147 //The PCS representation corresponds to the header’s PCS field. The PCS representation
3148 //is always provided. Color names are fixed-length, 32-byte fields including null
3149 //termination. In order to maintain maximum portability, it is strongly recommended
3150 //that special characters of the 7-bit ASCII set not be used.
3151 
3152 static
3153 void *Type_NamedColor_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)


3184     }
3185     for (i=0; i < count; i++) {
3186 
3187         cmsUInt16Number PCS[3];
3188         cmsUInt16Number Colorant[cmsMAXCHANNELS];
3189         char Root[33];
3190 
3191         memset(Colorant, 0, sizeof(Colorant));
3192         if (io -> Read(io, Root, 32, 1) != 1) return NULL;
3193         if (!_cmsReadUInt16Array(io, 3, PCS)) goto Error;
3194         if (!_cmsReadUInt16Array(io, nDeviceCoords, Colorant)) goto Error;
3195 
3196         if (!cmsAppendNamedColor(v, Root, PCS, Colorant)) goto Error;
3197     }
3198 
3199     *nItems = 1;
3200     return (void*) v ;
3201 
3202 Error:
3203     cmsFreeNamedColorList(v);
3204     cmsUNUSED_PARAMETER(SizeOfTag);
3205 
3206     return NULL;
3207 

3208 }
3209 
3210 
3211 // Saves a named color list into a named color profile
3212 static
3213 cmsBool Type_NamedColor_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
3214 {
3215     cmsNAMEDCOLORLIST* NamedColorList = (cmsNAMEDCOLORLIST*) Ptr;
3216     char                prefix[32];     // Prefix for each color name
3217     char                suffix[32];     // Suffix for each color name
3218     int i, nColors;
3219 
3220     nColors = cmsNamedColorCount(NamedColorList);
3221 
3222     if (!_cmsWriteUInt32Number(io, 0)) return FALSE;
3223     if (!_cmsWriteUInt32Number(io, nColors)) return FALSE;
3224     if (!_cmsWriteUInt32Number(io, NamedColorList ->ColorantCount)) return FALSE;
3225 
3226     strncpy(prefix, (const char*) NamedColorList->Prefix, 32);
3227     strncpy(suffix, (const char*) NamedColorList->Suffix, 32);
3228 
3229     suffix[31] = prefix[31] = 0;
3230 
3231     if (!io ->Write(io, 32, prefix)) return FALSE;
3232     if (!io ->Write(io, 32, suffix)) return FALSE;
3233 
3234     for (i=0; i < nColors; i++) {
3235 
3236        cmsUInt16Number PCS[3];
3237        cmsUInt16Number Colorant[cmsMAXCHANNELS];
3238        char Root[33];
3239 
3240         if (!cmsNamedColorInfo(NamedColorList, i, Root, NULL, NULL, PCS, Colorant)) return 0;
3241         if (!io ->Write(io, 32 , Root)) return FALSE;
3242         if (!_cmsWriteUInt16Array(io, 3, PCS)) return FALSE;
3243         if (!_cmsWriteUInt16Array(io, NamedColorList ->ColorantCount, Colorant)) return FALSE;
3244     }
3245 


3246     cmsUNUSED_PARAMETER(nItems);
3247     cmsUNUSED_PARAMETER(self);
3248 
3249     return TRUE;
3250 
3251 }
3252 
3253 static
3254 void* Type_NamedColor_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n)
3255 {
3256     cmsNAMEDCOLORLIST* nc = (cmsNAMEDCOLORLIST*) Ptr;
3257 


3258     cmsUNUSED_PARAMETER(n);
3259     cmsUNUSED_PARAMETER(self);
3260 
3261     return (void*) cmsDupNamedColorList(nc);
3262 
3263 }
3264 
3265 
3266 static
3267 void Type_NamedColor_Free(struct _cms_typehandler_struct* self, void* Ptr)
3268 {
3269     cmsFreeNamedColorList((cmsNAMEDCOLORLIST*) Ptr);
3270     cmsUNUSED_PARAMETER(self);
3271 
3272     return;
3273 

3274 }
3275 
3276 
3277 // ********************************************************************************
3278 // Type cmsSigProfileSequenceDescType
3279 // ********************************************************************************
3280 
3281 // This type is an array of structures, each of which contains information from the
3282 // header fields and tags from the original profiles which were combined to create
3283 // the final profile. The order of the structures is the order in which the profiles
3284 // were combined and includes a structure for the final profile. This provides a
3285 // description of the profile sequence from source to destination,
3286 // typically used with the DeviceLink profile.
3287 
3288 static
3289 cmsBool ReadEmbeddedText(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsMLU** mlu, cmsUInt32Number SizeOfTag)
3290 {
3291     cmsTagTypeSignature  BaseType;
3292     cmsUInt32Number nItems;
3293 


3394 cmsBool  Type_ProfileSequenceDesc_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
3395 {
3396     cmsSEQ* Seq = (cmsSEQ*) Ptr;
3397     cmsUInt32Number i;
3398 
3399     if (!_cmsWriteUInt32Number(io, Seq->n)) return FALSE;
3400 
3401     for (i=0; i < Seq ->n; i++) {
3402 
3403         cmsPSEQDESC* sec = &Seq -> seq[i];
3404 
3405         if (!_cmsWriteUInt32Number(io, sec ->deviceMfg)) return FALSE;
3406         if (!_cmsWriteUInt32Number(io, sec ->deviceModel)) return FALSE;
3407         if (!_cmsWriteUInt64Number(io, &sec ->attributes)) return FALSE;
3408         if (!_cmsWriteUInt32Number(io, sec ->technology)) return FALSE;
3409 
3410         if (!SaveDescription(self, io, sec ->Manufacturer)) return FALSE;
3411         if (!SaveDescription(self, io, sec ->Model)) return FALSE;
3412     }
3413 
3414      cmsUNUSED_PARAMETER(nItems);
3415 
3416      return TRUE;
3417 

3418 }
3419 
3420 
3421 static
3422 void* Type_ProfileSequenceDesc_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n)
3423 {


3424     cmsUNUSED_PARAMETER(n);
3425     cmsUNUSED_PARAMETER(self);
3426 
3427     return (void*) cmsDupProfileSequenceDescription((cmsSEQ*) Ptr);
3428 
3429 }
3430 
3431 static
3432 void Type_ProfileSequenceDesc_Free(struct _cms_typehandler_struct* self, void* Ptr)
3433 {
3434     cmsFreeProfileSequenceDescription((cmsSEQ*) Ptr);
3435     cmsUNUSED_PARAMETER(self);
3436 
3437     return;
3438 

3439 }
3440 
3441 
3442 // ********************************************************************************
3443 // Type cmsSigProfileSequenceIdType
3444 // ********************************************************************************
3445 /*
3446 In certain workflows using ICC Device Link Profiles, it is necessary to identify the
3447 original profiles that were combined to create the Device Link Profile.
3448 This type is an array of structures, each of which contains information for
3449 identification of a profile used in a sequence
3450 */
3451 
3452 
3453 static
3454 cmsBool ReadSeqID(struct _cms_typehandler_struct* self,
3455                                              cmsIOHANDLER* io,
3456                                              void* Cargo,
3457                                              cmsUInt32Number n,
3458                                              cmsUInt32Number SizeOfTag)


3500     *nItems = 1;
3501     return OutSeq;
3502 
3503 }
3504 
3505 
3506 static
3507 cmsBool WriteSeqID(struct _cms_typehandler_struct* self,
3508                                              cmsIOHANDLER* io,
3509                                              void* Cargo,
3510                                              cmsUInt32Number n,
3511                                              cmsUInt32Number SizeOfTag)
3512 {
3513     cmsSEQ* Seq = (cmsSEQ*) Cargo;
3514 
3515     if (!io ->Write(io, 16, Seq ->seq[n].ProfileID.ID8)) return FALSE;
3516 
3517     // Store here the MLU
3518     if (!SaveDescription(self, io, Seq ->seq[n].Description)) return FALSE;
3519 
3520     cmsUNUSED_PARAMETER(SizeOfTag);
3521 
3522     return TRUE;
3523 

3524 }
3525 
3526 static
3527 cmsBool  Type_ProfileSequenceId_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
3528 {
3529     cmsSEQ* Seq = (cmsSEQ*) Ptr;
3530     cmsUInt32Number BaseOffset;
3531 
3532     // Keep the base offset
3533     BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);
3534 
3535     // This is the table count
3536     if (!_cmsWriteUInt32Number(io, Seq ->n)) return FALSE;
3537 
3538     // This is the position table and content
3539     if (!WritePositionTable(self, io, 0, Seq ->n, BaseOffset, Seq, WriteSeqID)) return FALSE;
3540 
3541     cmsUNUSED_PARAMETER(nItems);
3542 
3543     return TRUE;
3544 

3545 }
3546 
3547 static
3548 void* Type_ProfileSequenceId_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n)
3549 {


3550     cmsUNUSED_PARAMETER(n);
3551     cmsUNUSED_PARAMETER(self);
3552 
3553     return (void*) cmsDupProfileSequenceDescription((cmsSEQ*) Ptr);
3554 
3555 }
3556 
3557 static
3558 void Type_ProfileSequenceId_Free(struct _cms_typehandler_struct* self, void* Ptr)
3559 {
3560     cmsFreeProfileSequenceDescription((cmsSEQ*) Ptr);
3561     cmsUNUSED_PARAMETER(self);
3562 
3563     return;
3564 

3565 }
3566 
3567 
3568 // ********************************************************************************
3569 // Type cmsSigUcrBgType
3570 // ********************************************************************************
3571 /*
3572 This type contains curves representing the under color removal and black
3573 generation and a text string which is a general description of the method used
3574 for the ucr/bg.
3575 */
3576 
3577 static
3578 void *Type_UcrBg_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
3579 {
3580     cmsUcrBg* n = (cmsUcrBg*) _cmsMallocZero(self ->ContextID, sizeof(cmsUcrBg));
3581     cmsUInt32Number CountUcr, CountBg;
3582     char* ASCIIString;
3583 
3584     *nItems = 0;


3628     cmsUcrBg* Value = (cmsUcrBg*) Ptr;
3629     cmsUInt32Number TextSize;
3630     char* Text;
3631 
3632     // First curve is Under color removal
3633     if (!_cmsWriteUInt32Number(io, Value ->Ucr ->nEntries)) return FALSE;
3634     if (!_cmsWriteUInt16Array(io, Value ->Ucr ->nEntries, Value ->Ucr ->Table16)) return FALSE;
3635 
3636     // Then black generation
3637     if (!_cmsWriteUInt32Number(io, Value ->Bg ->nEntries)) return FALSE;
3638     if (!_cmsWriteUInt16Array(io, Value ->Bg ->nEntries, Value ->Bg ->Table16)) return FALSE;
3639 
3640     // Now comes the text. The length is specified by the tag size
3641     TextSize = cmsMLUgetASCII(Value ->Desc, cmsNoLanguage, cmsNoCountry, NULL, 0);
3642     Text     = (char*) _cmsMalloc(self ->ContextID, TextSize);
3643     if (cmsMLUgetASCII(Value ->Desc, cmsNoLanguage, cmsNoCountry, Text, TextSize) != TextSize) return FALSE;
3644 
3645     if (!io ->Write(io, TextSize, Text)) return FALSE;
3646     _cmsFree(self ->ContextID, Text);
3647 
3648     cmsUNUSED_PARAMETER(nItems);
3649 
3650     return TRUE;
3651 

3652 }
3653 
3654 static
3655 void* Type_UcrBg_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
3656 {
3657     cmsUcrBg* Src = (cmsUcrBg*) Ptr;
3658     cmsUcrBg* NewUcrBg = (cmsUcrBg*) _cmsMallocZero(self ->ContextID, sizeof(cmsUcrBg));
3659 
3660     if (NewUcrBg == NULL) return NULL;
3661 
3662     NewUcrBg ->Bg   = cmsDupToneCurve(Src ->Bg);
3663     NewUcrBg ->Ucr  = cmsDupToneCurve(Src ->Ucr);
3664     NewUcrBg ->Desc = cmsMLUdup(Src ->Desc);
3665 
3666     cmsUNUSED_PARAMETER(n);
3667 
3668     return (void*) NewUcrBg;
3669 

3670 }
3671 
3672 static
3673 void Type_UcrBg_Free(struct _cms_typehandler_struct* self, void *Ptr)
3674 {
3675    cmsUcrBg* Src = (cmsUcrBg*) Ptr;
3676 
3677    if (Src ->Ucr) cmsFreeToneCurve(Src ->Ucr);
3678    if (Src ->Bg)  cmsFreeToneCurve(Src ->Bg);
3679    if (Src ->Desc) cmsMLUfree(Src ->Desc);
3680 
3681    _cmsFree(self ->ContextID, Ptr);
3682 }
3683 
3684 // ********************************************************************************
3685 // Type cmsSigCrdInfoType
3686 // ********************************************************************************
3687 
3688 /*
3689 This type contains the PostScript product name to which this profile corresponds


3769     cmsMLUfree(mlu);
3770     return NULL;
3771 
3772 }
3773 
3774 static
3775 cmsBool  Type_CrdInfo_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
3776 {
3777 
3778     cmsMLU* mlu = (cmsMLU*) Ptr;
3779 
3780     if (!WriteCountAndSting(self, io, mlu, "nm")) goto Error;
3781     if (!WriteCountAndSting(self, io, mlu, "#0")) goto Error;
3782     if (!WriteCountAndSting(self, io, mlu, "#1")) goto Error;
3783     if (!WriteCountAndSting(self, io, mlu, "#2")) goto Error;
3784     if (!WriteCountAndSting(self, io, mlu, "#3")) goto Error;
3785 
3786     return TRUE;
3787 
3788 Error:
3789     cmsUNUSED_PARAMETER(nItems);
3790     return FALSE;
3791 

3792 }
3793 
3794 
3795 static
3796 void* Type_CrdInfo_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
3797 {


3798     cmsUNUSED_PARAMETER(n);
3799     cmsUNUSED_PARAMETER(self);
3800 
3801     return (void*) cmsMLUdup((cmsMLU*) Ptr);
3802 
3803 }
3804 
3805 static
3806 void Type_CrdInfo_Free(struct _cms_typehandler_struct* self, void *Ptr)
3807 {
3808     cmsMLUfree((cmsMLU*) Ptr);
3809     cmsUNUSED_PARAMETER(self);
3810 
3811     return;
3812 

3813 }
3814 
3815 // ********************************************************************************
3816 // Type cmsSigScreeningType
3817 // ********************************************************************************
3818 //
3819 //The screeningType describes various screening parameters including screen
3820 //frequency, screening angle, and spot shape.
3821 
3822 static
3823 void *Type_Screening_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
3824 {
3825     cmsScreening* sc = NULL;
3826     cmsUInt32Number i;
3827 
3828     sc = (cmsScreening*) _cmsMallocZero(self ->ContextID, sizeof(cmsScreening));
3829     if (sc == NULL) return NULL;
3830 
3831     *nItems = 0;
3832 


3835 
3836     if (sc ->nChannels > cmsMAXCHANNELS - 1)
3837         sc ->nChannels = cmsMAXCHANNELS - 1;
3838 
3839     for (i=0; i < sc ->nChannels; i++) {
3840 
3841         if (!_cmsRead15Fixed16Number(io, &sc ->Channels[i].Frequency)) goto Error;
3842         if (!_cmsRead15Fixed16Number(io, &sc ->Channels[i].ScreenAngle)) goto Error;
3843         if (!_cmsReadUInt32Number(io, &sc ->Channels[i].SpotShape)) goto Error;
3844     }
3845 
3846 
3847     *nItems = 1;
3848 
3849     return (void*) sc;
3850 
3851 Error:
3852     if (sc != NULL)
3853         _cmsFree(self ->ContextID, sc);
3854 
3855     cmsUNUSED_PARAMETER(SizeOfTag);
3856     return NULL;
3857 

3858 }
3859 
3860 
3861 static
3862 cmsBool Type_Screening_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
3863 {
3864     cmsScreening* sc = (cmsScreening* ) Ptr;
3865     cmsUInt32Number i;
3866 
3867     if (!_cmsWriteUInt32Number(io, sc ->Flag)) return FALSE;
3868     if (!_cmsWriteUInt32Number(io, sc ->nChannels)) return FALSE;
3869 
3870     for (i=0; i < sc ->nChannels; i++) {
3871 
3872         if (!_cmsWrite15Fixed16Number(io, sc ->Channels[i].Frequency)) return FALSE;
3873         if (!_cmsWrite15Fixed16Number(io, sc ->Channels[i].ScreenAngle)) return FALSE;
3874         if (!_cmsWriteUInt32Number(io, sc ->Channels[i].SpotShape)) return FALSE;
3875     }
3876 
3877     cmsUNUSED_PARAMETER(nItems);
3878     return TRUE;
3879 


3880 }
3881 
3882 
3883 static
3884 void* Type_Screening_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
3885 {
3886    cmsUNUSED_PARAMETER(n);
3887    return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsScreening));
3888 

3889 }
3890 
3891 
3892 static
3893 void Type_Screening_Free(struct _cms_typehandler_struct* self, void* Ptr)
3894 {
3895    _cmsFree(self ->ContextID, Ptr);
3896 }
3897 
3898 // ********************************************************************************
3899 // Type cmsSigViewingConditionsType
3900 // ********************************************************************************
3901 //
3902 //This type represents a set of viewing condition parameters including:
3903 //CIE ’absolute’ illuminant white point tristimulus values and CIE ’absolute’
3904 //surround tristimulus values.
3905 
3906 static
3907 void *Type_ViewingConditions_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
3908 {
3909     cmsICCViewingConditions* vc = NULL;
3910 
3911     vc = (cmsICCViewingConditions*) _cmsMallocZero(self ->ContextID, sizeof(cmsICCViewingConditions));
3912     if (vc == NULL) return NULL;
3913 
3914     *nItems = 0;
3915 
3916     if (!_cmsReadXYZNumber(io, &vc ->IlluminantXYZ)) goto Error;
3917     if (!_cmsReadXYZNumber(io, &vc ->SurroundXYZ)) goto Error;
3918     if (!_cmsReadUInt32Number(io, &vc ->IlluminantType)) goto Error;
3919 
3920     *nItems = 1;
3921 
3922     return (void*) vc;
3923 
3924 Error:
3925     if (vc != NULL)
3926         _cmsFree(self ->ContextID, vc);
3927 
3928     cmsUNUSED_PARAMETER(SizeOfTag);
3929     return NULL;
3930 

3931 }
3932 
3933 
3934 static
3935 cmsBool Type_ViewingConditions_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
3936 {
3937     cmsICCViewingConditions* sc = (cmsICCViewingConditions* ) Ptr;
3938 
3939     if (!_cmsWriteXYZNumber(io, &sc ->IlluminantXYZ)) return FALSE;
3940     if (!_cmsWriteXYZNumber(io, &sc ->SurroundXYZ)) return FALSE;
3941     if (!_cmsWriteUInt32Number(io, sc ->IlluminantType)) return FALSE;
3942 


3943     cmsUNUSED_PARAMETER(nItems);
3944     cmsUNUSED_PARAMETER(self);
3945     return TRUE;
3946 
3947 }
3948 
3949 
3950 static
3951 void* Type_ViewingConditions_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
3952 {
3953    cmsUNUSED_PARAMETER(n);
3954    return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsScreening));
3955 

3956 }
3957 
3958 
3959 static
3960 void Type_ViewingConditions_Free(struct _cms_typehandler_struct* self, void* Ptr)
3961 {
3962    _cmsFree(self ->ContextID, Ptr);
3963 }
3964 
3965 
3966 // ********************************************************************************
3967 // Type cmsSigMultiProcessElementType
3968 // ********************************************************************************
3969 
3970 
3971 static
3972 void* GenericMPEdup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
3973 {


3974     cmsUNUSED_PARAMETER(n);
3975     cmsUNUSED_PARAMETER(self);
3976     return (void*) cmsStageDup((cmsStage*) Ptr);
3977 
3978 }
3979 
3980 static
3981 void GenericMPEfree(struct _cms_typehandler_struct* self, void *Ptr)
3982 {
3983     cmsStageFree((cmsStage*) Ptr);
3984     cmsUNUSED_PARAMETER(self);
3985     return;
3986 

3987 }
3988 
3989 // Each curve is stored in one or more curve segments, with break-points specified between curve segments.
3990 // The first curve segment always starts at –Infinity, and the last curve segment always ends at +Infinity. The
3991 // first and last curve segments shall be specified in terms of a formula, whereas the other segments shall be
3992 // specified either in terms of a formula, or by a sampled curve.
3993 
3994 
3995 // Read an embedded segmented curve
3996 static
3997 cmsToneCurve* ReadSegmentedCurve(struct _cms_typehandler_struct* self, cmsIOHANDLER* io)
3998 {
3999     cmsCurveSegSignature ElementSig;
4000     cmsUInt32Number i, j;
4001     cmsUInt16Number nSegments;
4002     cmsCurveSegment*  Segments;
4003     cmsToneCurve* Curve;
4004     cmsFloat32Number PrevBreak = -1E22F;    // - infinite
4005 
4006     // Take signature and channels for each element.


4091      }
4092      _cmsFree(self ->ContextID, Segments);
4093      return Curve;
4094 
4095 Error:
4096      if (Segments) _cmsFree(self ->ContextID, Segments);
4097      return NULL;
4098 }
4099 
4100 
4101 static
4102 cmsBool ReadMPECurve(struct _cms_typehandler_struct* self,
4103                      cmsIOHANDLER* io,
4104                      void* Cargo,
4105                      cmsUInt32Number n,
4106                      cmsUInt32Number SizeOfTag)
4107 {
4108       cmsToneCurve** GammaTables = ( cmsToneCurve**) Cargo;
4109 
4110       GammaTables[n] = ReadSegmentedCurve(self, io);
4111       cmsUNUSED_PARAMETER(SizeOfTag);
4112       return (GammaTables[n] != NULL);
4113 

4114 }
4115 
4116 static
4117 void *Type_MPEcurve_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
4118 {
4119     cmsStage* mpe = NULL;
4120     cmsUInt16Number InputChans, OutputChans;
4121     cmsUInt32Number i, BaseOffset;
4122     cmsToneCurve** GammaTables;
4123 
4124     *nItems = 0;
4125 
4126     // Get actual position as a basis for element offsets
4127     BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);
4128 
4129     if (!_cmsReadUInt16Number(io, &InputChans)) return NULL;
4130     if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL;
4131 
4132     if (InputChans != OutputChans) return NULL;
4133 
4134     GammaTables = (cmsToneCurve**) _cmsCalloc(self ->ContextID, InputChans, sizeof(cmsToneCurve*));
4135     if (GammaTables == NULL) return NULL;
4136 
4137     if (ReadPositionTable(self, io, InputChans, BaseOffset, GammaTables, ReadMPECurve)) {
4138 
4139         mpe = cmsStageAllocToneCurves(self ->ContextID, InputChans, GammaTables);
4140     }
4141     else {
4142         mpe = NULL;
4143     }
4144 
4145     for (i=0; i < InputChans; i++) {
4146         if (GammaTables[i]) cmsFreeToneCurve(GammaTables[i]);
4147     }
4148 
4149     _cmsFree(self ->ContextID, GammaTables);
4150     *nItems = (mpe != NULL) ? 1 : 0;
4151     cmsUNUSED_PARAMETER(SizeOfTag);
4152     return mpe;
4153 

4154 }
4155 
4156 
4157 // Write a single segmented curve. NO CHECK IS PERFORMED ON VALIDITY
4158 static
4159 cmsBool WriteSegmentedCurve(cmsIOHANDLER* io, cmsToneCurve* g)
4160 {
4161     cmsUInt32Number i, j;
4162     cmsCurveSegment* Segments = g ->Segments;
4163     cmsUInt32Number nSegments = g ->nSegments;
4164 
4165     if (!_cmsWriteUInt32Number(io, cmsSigSegmentedCurve)) goto Error;
4166     if (!_cmsWriteUInt32Number(io, 0)) goto Error;
4167     if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) nSegments)) goto Error;
4168     if (!_cmsWriteUInt16Number(io, 0)) goto Error;
4169 
4170     // Write the break-points
4171     for (i=0; i < nSegments - 1; i++) {
4172         if (!_cmsWriteFloat32Number(io, Segments[i].x1)) goto Error;
4173     }


4212         // It seems there is no need to align. Code is here, and for safety commented out
4213         // if (!_cmsWriteAlignment(io)) goto Error;
4214     }
4215 
4216     return TRUE;
4217 
4218 Error:
4219     return FALSE;
4220 }
4221 
4222 
4223 static
4224 cmsBool WriteMPECurve(struct _cms_typehandler_struct* self,
4225                       cmsIOHANDLER* io,
4226                       void* Cargo,
4227                       cmsUInt32Number n,
4228                       cmsUInt32Number SizeOfTag)
4229 {
4230     _cmsStageToneCurvesData* Curves  = (_cmsStageToneCurvesData*) Cargo;
4231 


4232     cmsUNUSED_PARAMETER(SizeOfTag);
4233     cmsUNUSED_PARAMETER(self);
4234     return WriteSegmentedCurve(io, Curves ->TheCurves[n]);
4235 
4236 }
4237 
4238 // Write a curve, checking first for validity
4239 static
4240 cmsBool  Type_MPEcurve_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
4241 {
4242     cmsUInt32Number BaseOffset;
4243     cmsStage* mpe = (cmsStage*) Ptr;
4244     _cmsStageToneCurvesData* Curves = (_cmsStageToneCurvesData*) mpe ->Data;
4245 
4246     BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);
4247 
4248     // Write the header. Since those are curves, input and output channels are same
4249     if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->InputChannels)) return FALSE;
4250     if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->InputChannels)) return FALSE;
4251 
4252     if (!WritePositionTable(self, io, 0,
4253                                 mpe ->InputChannels, BaseOffset, Curves, WriteMPECurve)) return FALSE;
4254 
4255 
4256     cmsUNUSED_PARAMETER(nItems);
4257     return TRUE;
4258 

4259 }
4260 
4261 
4262 
4263 // The matrix is organized as an array of PxQ+Q elements, where P is the number of input channels to the
4264 // matrix, and Q is the number of output channels. The matrix elements are each float32Numbers. The array
4265 // is organized as follows:
4266 // array = [e11, e12, …, e1P, e21, e22, …, e2P, …, eQ1, eQ2, …, eQP, e1, e2, …, eQ]
4267 
4268 static
4269 void *Type_MPEmatrix_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
4270 {
4271     cmsStage* mpe;
4272     cmsUInt16Number   InputChans, OutputChans;
4273     cmsUInt32Number   nElems, i;
4274     cmsFloat64Number* Matrix;
4275     cmsFloat64Number* Offsets;
4276 
4277     if (!_cmsReadUInt16Number(io, &InputChans)) return NULL;
4278     if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL;


4298         if (!_cmsReadFloat32Number(io, &v)) return NULL;
4299         Matrix[i] = v;
4300     }
4301 
4302 
4303     for (i=0; i < OutputChans; i++) {
4304 
4305         cmsFloat32Number v;
4306 
4307         if (!_cmsReadFloat32Number(io, &v)) return NULL;
4308         Offsets[i] = v;
4309     }
4310 
4311 
4312     mpe = cmsStageAllocMatrix(self ->ContextID, OutputChans, InputChans, Matrix, Offsets);
4313     _cmsFree(self ->ContextID, Matrix);
4314     _cmsFree(self ->ContextID, Offsets);
4315 
4316     *nItems = 1;
4317 
4318     cmsUNUSED_PARAMETER(SizeOfTag);
4319     return mpe;
4320 

4321 }
4322 
4323 static
4324 cmsBool  Type_MPEmatrix_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
4325 {
4326     cmsUInt32Number i, nElems;
4327     cmsStage* mpe = (cmsStage*) Ptr;
4328     _cmsStageMatrixData* Matrix = (_cmsStageMatrixData*) mpe ->Data;
4329 
4330     if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->InputChannels)) return FALSE;
4331     if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->OutputChannels)) return FALSE;
4332 
4333     nElems = mpe ->InputChannels * mpe ->OutputChannels;
4334 
4335     for (i=0; i < nElems; i++) {
4336         if (!_cmsWriteFloat32Number(io, (cmsFloat32Number) Matrix->Double[i])) return FALSE;
4337     }
4338 
4339 
4340     for (i=0; i < mpe ->OutputChannels; i++) {
4341 
4342         if (Matrix ->Offset == NULL) {
4343 
4344                if (!_cmsWriteFloat32Number(io, 0)) return FALSE;
4345         }
4346         else {
4347                if (!_cmsWriteFloat32Number(io, (cmsFloat32Number) Matrix->Offset[i])) return FALSE;
4348         }
4349     }
4350 


4351     cmsUNUSED_PARAMETER(nItems);
4352     cmsUNUSED_PARAMETER(self);
4353     return TRUE;
4354 
4355 }
4356 
4357 
4358 
4359 static
4360 void *Type_MPEclut_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
4361 {
4362     cmsStage* mpe = NULL;
4363     cmsUInt16Number InputChans, OutputChans;
4364     cmsUInt8Number Dimensions8[16];
4365     cmsUInt32Number i, nMaxGrids, GridPoints[MAX_INPUT_DIMENSIONS];
4366     _cmsStageCLutData* clut;
4367 
4368     if (!_cmsReadUInt16Number(io, &InputChans)) return NULL;
4369     if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL;
4370 
4371     if (InputChans == 0) goto Error;
4372     if (OutputChans == 0) goto Error;
4373 
4374     if (io ->Read(io, Dimensions8, sizeof(cmsUInt8Number), 16) != 16)


4378     nMaxGrids = InputChans > MAX_INPUT_DIMENSIONS ? MAX_INPUT_DIMENSIONS : InputChans;
4379     for (i=0; i < nMaxGrids; i++) GridPoints[i] = (cmsUInt32Number) Dimensions8[i];
4380 
4381     // Allocate the true CLUT
4382     mpe = cmsStageAllocCLutFloatGranular(self ->ContextID, GridPoints, InputChans, OutputChans, NULL);
4383     if (mpe == NULL) goto Error;
4384 
4385     // Read the data
4386     clut = (_cmsStageCLutData*) mpe ->Data;
4387     for (i=0; i < clut ->nEntries; i++) {
4388 
4389         if (!_cmsReadFloat32Number(io, &clut ->Tab.TFloat[i])) goto Error;
4390     }
4391 
4392     *nItems = 1;
4393     return mpe;
4394 
4395 Error:
4396     *nItems = 0;
4397     if (mpe != NULL) cmsStageFree(mpe);
4398     cmsUNUSED_PARAMETER(SizeOfTag);
4399     return NULL;
4400 

4401 }
4402 
4403 // Write a CLUT in floating point
4404 static
4405 cmsBool  Type_MPEclut_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
4406 {
4407     cmsUInt8Number Dimensions8[16];
4408     cmsUInt32Number i;
4409     cmsStage* mpe = (cmsStage*) Ptr;
4410     _cmsStageCLutData* clut = (_cmsStageCLutData*) mpe ->Data;
4411 
4412     // Check for maximum number of channels
4413     if (mpe -> InputChannels > 15) return FALSE;
4414 
4415     // Only floats are supported in MPE
4416     if (clut ->HasFloatValues == FALSE) return FALSE;
4417 
4418     if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->InputChannels)) return FALSE;
4419     if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->OutputChannels)) return FALSE;
4420 
4421     memset(Dimensions8, 0, sizeof(Dimensions8));
4422 
4423     for (i=0; i < mpe ->InputChannels; i++)
4424         Dimensions8[i] = (cmsUInt8Number) clut ->Params ->nSamples[i];
4425 
4426     if (!io ->Write(io, 16, Dimensions8)) return FALSE;
4427 
4428     for (i=0; i < clut ->nEntries; i++) {
4429 
4430         if (!_cmsWriteFloat32Number(io, clut ->Tab.TFloat[i])) return FALSE;
4431     }
4432 


4433     cmsUNUSED_PARAMETER(nItems);
4434     cmsUNUSED_PARAMETER(self);
4435     return TRUE;
4436 
4437 }
4438 
4439 
4440 
4441 // This is the list of built-in MPE types
4442 static _cmsTagTypeLinkedList SupportedMPEtypes[] = {
4443 
4444 {{ (cmsTagTypeSignature) cmsSigBAcsElemType, NULL, NULL, NULL, NULL, NULL, 0 }, &SupportedMPEtypes[1] },   // Ignore those elements for now
4445 {{ (cmsTagTypeSignature) cmsSigEAcsElemType, NULL, NULL, NULL, NULL, NULL, 0 }, &SupportedMPEtypes[2] },   // (That's what the spec says)
4446 
4447 {TYPE_MPE_HANDLER((cmsTagTypeSignature) cmsSigCurveSetElemType,     MPEcurve),      &SupportedMPEtypes[3] },
4448 {TYPE_MPE_HANDLER((cmsTagTypeSignature) cmsSigMatrixElemType,       MPEmatrix),     &SupportedMPEtypes[4] },
4449 {TYPE_MPE_HANDLER((cmsTagTypeSignature) cmsSigCLutElemType,         MPEclut),        NULL },
4450 };
4451 
4452 _cmsTagTypePluginChunkType _cmsMPETypePluginChunk = { NULL };
4453 
4454 static
4455 cmsBool ReadMPEElem(struct _cms_typehandler_struct* self,
4456                     cmsIOHANDLER* io,


4476     if (TypeHandler == NULL)  {
4477 
4478         char String[5];
4479 
4480         _cmsTagSignature2String(String, (cmsTagSignature) ElementSig);
4481 
4482         // An unknown element was found.
4483         cmsSignalError(self ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown MPE type '%s' found.", String);
4484         return FALSE;
4485     }
4486 
4487     // If no read method, just ignore the element (valid for cmsSigBAcsElemType and cmsSigEAcsElemType)
4488     // Read the MPE. No size is given
4489     if (TypeHandler ->ReadPtr != NULL) {
4490 
4491         // This is a real element which should be read and processed
4492         if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, (cmsStage*) TypeHandler ->ReadPtr(self, io, &nItems, SizeOfTag)))
4493             return FALSE;
4494     }
4495 


4496     cmsUNUSED_PARAMETER(SizeOfTag);
4497     cmsUNUSED_PARAMETER(n);
4498     return TRUE;
4499 
4500 }
4501 
4502 
4503 // This is the main dispatcher for MPE
4504 static
4505 void *Type_MPE_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
4506 {
4507     cmsUInt16Number InputChans, OutputChans;
4508     cmsUInt32Number ElementCount;
4509     cmsPipeline *NewLUT = NULL;
4510     cmsUInt32Number BaseOffset;
4511 
4512     // Get actual position as a basis for element offsets
4513     BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);
4514 
4515     // Read channels and element count
4516     if (!_cmsReadUInt16Number(io, &InputChans)) return NULL;
4517     if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL;
4518 
4519     // Allocates an empty LUT
4520     NewLUT = cmsPipelineAlloc(self ->ContextID, InputChans, OutputChans);
4521     if (NewLUT == NULL) return NULL;
4522 
4523     if (!_cmsReadUInt32Number(io, &ElementCount)) return NULL;
4524 
4525     if (!ReadPositionTable(self, io, ElementCount, BaseOffset, NewLUT, ReadMPEElem)) {
4526         if (NewLUT != NULL) cmsPipelineFree(NewLUT);
4527         *nItems = 0;
4528         return NULL;
4529     }
4530 
4531     // Success
4532     *nItems = 1;
4533     cmsUNUSED_PARAMETER(SizeOfTag);
4534     return NewLUT;
4535 

4536 }
4537 
4538 
4539 
4540 // This one is a liitle bit more complex, so we don't use position tables this time.
4541 static
4542 cmsBool Type_MPE_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
4543 {
4544     cmsUInt32Number i, BaseOffset, DirectoryPos, CurrentPos;
4545     int inputChan, outputChan;
4546     cmsUInt32Number ElemCount;
4547     cmsUInt32Number *ElementOffsets = NULL, *ElementSizes = NULL, Before;
4548     cmsStageSignature ElementSig;
4549     cmsPipeline* Lut = (cmsPipeline*) Ptr;
4550     cmsStage* Elem = Lut ->Elements;
4551     cmsTagTypeHandler* TypeHandler;
4552     _cmsTagTypePluginChunkType* MPETypePluginChunk  = ( _cmsTagTypePluginChunkType*) _cmsContextGetClientChunk(self->ContextID, MPEPlugin);
4553 
4554     BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);
4555 


4608 
4609     // Write the directory
4610     CurrentPos = io ->Tell(io);
4611 
4612     if (!io ->Seek(io, DirectoryPos)) goto Error;
4613 
4614     for (i=0; i < ElemCount; i++) {
4615         if (!_cmsWriteUInt32Number(io, ElementOffsets[i])) goto Error;
4616         if (!_cmsWriteUInt32Number(io, ElementSizes[i])) goto Error;
4617     }
4618 
4619     if (!io ->Seek(io, CurrentPos)) goto Error;
4620 
4621     if (ElementOffsets != NULL) _cmsFree(self ->ContextID, ElementOffsets);
4622     if (ElementSizes != NULL) _cmsFree(self ->ContextID, ElementSizes);
4623     return TRUE;
4624 
4625 Error:
4626     if (ElementOffsets != NULL) _cmsFree(self ->ContextID, ElementOffsets);
4627     if (ElementSizes != NULL) _cmsFree(self ->ContextID, ElementSizes);
4628     cmsUNUSED_PARAMETER(nItems);
4629     return FALSE;
4630 

4631 }
4632 
4633 
4634 static
4635 void* Type_MPE_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
4636 {


4637     cmsUNUSED_PARAMETER(n);
4638     cmsUNUSED_PARAMETER(self);
4639 
4640     return (void*) cmsPipelineDup((cmsPipeline*) Ptr);
4641 
4642 }
4643 
4644 static
4645 void Type_MPE_Free(struct _cms_typehandler_struct* self, void *Ptr)
4646 {
4647     cmsPipelineFree((cmsPipeline*) Ptr);
4648     cmsUNUSED_PARAMETER(self);
4649     return;
4650 

4651 }
4652 
4653 
4654 // ********************************************************************************
4655 // Type cmsSigVcgtType
4656 // ********************************************************************************
4657 
4658 
4659 #define cmsVideoCardGammaTableType    0
4660 #define cmsVideoCardGammaFormulaType  1
4661 
4662 // Used internally
4663 typedef struct {
4664     double Gamma;
4665     double Min;
4666     double Max;
4667 } _cmsVCGTGAMMA;
4668 
4669 
4670 static


4781            Curves[n] = cmsBuildParametricToneCurve(self ->ContextID, 5, Params);
4782            if (Curves[n] == NULL) goto Error;
4783        }
4784    }
4785    break;
4786 
4787    // Unsupported
4788    default:
4789       cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported tag type for VCGT '%d'", TagType);
4790       goto Error;
4791    }
4792 
4793    *nItems = 1;
4794    return (void*) Curves;
4795 
4796 // Regret,  free all resources
4797 Error:
4798 
4799     cmsFreeToneCurveTriple(Curves);
4800     _cmsFree(self ->ContextID, Curves);
4801      cmsUNUSED_PARAMETER(SizeOfTag);
4802     return NULL;
4803 

4804 }
4805 
4806 
4807 // We don't support all flavors, only 16bits tables and formula
4808 static
4809 cmsBool Type_vcgt_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
4810 {
4811     cmsToneCurve** Curves =  (cmsToneCurve**) Ptr;
4812     cmsUInt32Number i, j;
4813 
4814     if (cmsGetToneCurveParametricType(Curves[0]) == 5 &&
4815         cmsGetToneCurveParametricType(Curves[1]) == 5 &&
4816         cmsGetToneCurveParametricType(Curves[2]) == 5) {
4817 
4818             if (!_cmsWriteUInt32Number(io, cmsVideoCardGammaFormulaType)) return FALSE;
4819 
4820             // Save parameters
4821             for (i=0; i < 3; i++) {
4822 
4823                 _cmsVCGTGAMMA v;


4834 
4835     else {
4836 
4837         // Always store as a table of 256 words
4838         if (!_cmsWriteUInt32Number(io, cmsVideoCardGammaTableType)) return FALSE;
4839         if (!_cmsWriteUInt16Number(io, 3)) return FALSE;
4840         if (!_cmsWriteUInt16Number(io, 256)) return FALSE;
4841         if (!_cmsWriteUInt16Number(io, 2)) return FALSE;
4842 
4843         for (i=0; i < 3; i++) {
4844             for (j=0; j < 256; j++) {
4845 
4846                 cmsFloat32Number v = cmsEvalToneCurveFloat(Curves[i], (cmsFloat32Number) (j / 255.0));
4847                 cmsUInt16Number  n = _cmsQuickSaturateWord(v * 65535.0);
4848 
4849                 if (!_cmsWriteUInt16Number(io, n)) return FALSE;
4850             }
4851         }
4852     }
4853 


4854     cmsUNUSED_PARAMETER(self);
4855     cmsUNUSED_PARAMETER(nItems);
4856     return TRUE;
4857 
4858 }
4859 
4860 static
4861 void* Type_vcgt_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
4862 {
4863     cmsToneCurve** OldCurves =  (cmsToneCurve**) Ptr;
4864     cmsToneCurve** NewCurves;
4865 
4866     NewCurves = ( cmsToneCurve**) _cmsCalloc(self ->ContextID, 3, sizeof(cmsToneCurve*));
4867     if (NewCurves == NULL) return NULL;
4868 
4869     NewCurves[0] = cmsDupToneCurve(OldCurves[0]);
4870     NewCurves[1] = cmsDupToneCurve(OldCurves[1]);
4871     NewCurves[2] = cmsDupToneCurve(OldCurves[2]);
4872 
4873     cmsUNUSED_PARAMETER(n);
4874     return (void*) NewCurves;
4875 

4876 }
4877 
4878 
4879 static
4880 void Type_vcgt_Free(struct _cms_typehandler_struct* self, void* Ptr)
4881 {
4882     cmsFreeToneCurveTriple((cmsToneCurve**) Ptr);
4883     _cmsFree(self ->ContextID, Ptr);
4884 }
4885 
4886 
4887 // ********************************************************************************
4888 // Type cmsSigDictType
4889 // ********************************************************************************
4890 
4891 // Single column of the table can point to wchar or MLUC elements. Holds arrays of data
4892 typedef struct {
4893     cmsContext ContextID;
4894     cmsUInt32Number *Offsets;
4895     cmsUInt32Number *Sizes;


5279         if (p ->DisplayValue != NULL) {
5280             if (!WriteOneMLUC(self, io, &a.DisplayValue, i, p ->DisplayValue, BaseOffset)) goto Error;
5281         }
5282 
5283        p = cmsDictNextEntry(p);
5284     }
5285 
5286     // Write the directory
5287     CurrentPos = io ->Tell(io);
5288     if (!io ->Seek(io, DirectoryPos)) goto Error;
5289 
5290     if (!WriteOffsetArray(io, &a, Count, Length)) goto Error;
5291 
5292     if (!io ->Seek(io, CurrentPos)) goto Error;
5293 
5294     FreeArray(&a);
5295     return TRUE;
5296 
5297 Error:
5298     FreeArray(&a);
5299     cmsUNUSED_PARAMETER(nItems);
5300     return FALSE;
5301 

5302 }
5303 
5304 
5305 static
5306 void* Type_Dictionary_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
5307 {


5308     cmsUNUSED_PARAMETER(n);
5309     cmsUNUSED_PARAMETER(self);
5310 
5311     return (void*)  cmsDictDup((cmsHANDLE) Ptr);
5312 
5313 }
5314 
5315 
5316 static
5317 void Type_Dictionary_Free(struct _cms_typehandler_struct* self, void* Ptr)
5318 {
5319     cmsDictFree((cmsHANDLE) Ptr);
5320     cmsUNUSED_PARAMETER(self);
5321 }
5322 
5323 
5324 // ********************************************************************************
5325 // Type support main routines
5326 // ********************************************************************************
5327 
5328 
5329 // This is the list of built-in types
5330 static _cmsTagTypeLinkedList SupportedTagTypes[] = {
5331 
5332 {TYPE_HANDLER(cmsSigChromaticityType,          Chromaticity),        &SupportedTagTypes[1] },


< prev index next >