< prev index next >

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

Print this page




  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  */
  24 
  25 // This file is available under and governed by the GNU General Public
  26 // License version 2 only, as published by the Free Software Foundation.
  27 // However, the following notice accompanied the original version of this
  28 // file:
  29 //
  30 //---------------------------------------------------------------------------------
  31 //
  32 //  Little Color Management System
  33 //  Copyright (c) 1998-2017 Marti Maria Saguer
  34 //
  35 // Permission is hereby granted, free of charge, to any person obtaining
  36 // a copy of this software and associated documentation files (the "Software"),
  37 // to deal in the Software without restriction, including without limitation
  38 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
  39 // and/or sell copies of the Software, and to permit persons to whom the Software
  40 // is furnished to do so, subject to the following conditions:
  41 //
  42 // The above copyright notice and this permission notice shall be included in
  43 // all copies or substantial portions of the Software.
  44 //
  45 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  46 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  47 // THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  48 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  49 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  50 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  51 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  52 //
  53 //---------------------------------------------------------------------------------


 178 
 179             if (!_cmsReadUInt16Number(io, &tmp)) return FALSE;
 180             Array[i] = (wchar_t) tmp;
 181         }
 182         else {
 183             if (!_cmsReadUInt16Number(io, NULL)) return FALSE;
 184         }
 185 
 186     }
 187     return TRUE;
 188 }
 189 
 190 // To deal with position tables
 191 typedef cmsBool (* PositionTableEntryFn)(struct _cms_typehandler_struct* self,
 192                                              cmsIOHANDLER* io,
 193                                              void* Cargo,
 194                                              cmsUInt32Number n,
 195                                              cmsUInt32Number SizeOfTag);
 196 
 197 // Helper function to deal with position tables as described in ICC spec 4.3
 198 // A table of n elements is readed, where first comes n records containing offsets and sizes and
 199 // then a block containing the data itself. This allows to reuse same data in more than one entry
 200 static
 201 cmsBool ReadPositionTable(struct _cms_typehandler_struct* self,
 202                               cmsIOHANDLER* io,
 203                               cmsUInt32Number Count,
 204                               cmsUInt32Number BaseOffset,
 205                               void *Cargo,
 206                               PositionTableEntryFn ElementFn)
 207 {
 208     cmsUInt32Number i;
 209     cmsUInt32Number *ElementOffsets = NULL, *ElementSizes = NULL;
 210     cmsUInt32Number currentPosition;
 211 
 212     currentPosition = io->Tell(io);
 213 
 214     // Verify there is enough space left to read at least two cmsUInt32Number items for Count items.
 215     if (((io->ReportedSize - currentPosition) / (2 * sizeof(cmsUInt32Number))) < Count)
 216         return FALSE;
 217 
 218     // Let's take the offsets to each element


 986 
 987 
 988 // This tag can come IN UNALIGNED SIZE. In order to prevent issues, we force zeros on description to align it
 989 static
 990 cmsBool  Type_Text_Description_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
 991 {
 992     cmsMLU* mlu = (cmsMLU*) Ptr;
 993     char *Text = NULL;
 994     wchar_t *Wide = NULL;
 995     cmsUInt32Number len, len_text, len_tag_requirement, len_aligned;
 996     cmsBool  rc = FALSE;
 997     char Filler[68];
 998 
 999     // Used below for writing zeroes
1000     memset(Filler, 0, sizeof(Filler));
1001 
1002     // Get the len of string
1003     len = cmsMLUgetASCII(mlu, cmsNoLanguage, cmsNoCountry, NULL, 0);
1004 
1005     // Specification ICC.1:2001-04 (v2.4.0): It has been found that textDescriptionType can contain misaligned data
1006     //(see clause 4.1 for the definition of “aligned”). Because the Unicode language
1007     // code and Unicode count immediately follow the ASCII description, their
1008     // alignment is not correct if the ASCII count is not a multiple of four. The
1009     // ScriptCode code is misaligned when the ASCII count is odd. Profile reading and
1010     // writing software must be written carefully in order to handle these alignment
1011     // problems.
1012     //
1013     // The above last sentence suggest to handle alignment issues in the
1014     // parser. The provided example (Table 69 on Page 60) makes this clear.
1015     // The padding only in the ASCII count is not sufficient for a aligned tag
1016     // size, with the same text size in ASCII and Unicode.
1017 
1018     // Null strings
1019     if (len <= 0) {
1020 
1021         Text = (char*)    _cmsDupMem(self ->ContextID, "", sizeof(char));
1022         Wide = (wchar_t*) _cmsDupMem(self ->ContextID, L"", sizeof(wchar_t));
1023     }
1024     else {
1025         // Create independent buffers
1026         Text = (char*) _cmsCalloc(self ->ContextID, len, sizeof(char));


1492 
1493     SizeOfHeader = 12 * Count + sizeof(_cmsTagBase);
1494     LargestPosition = 0;
1495 
1496     for (i=0; i < Count; i++) {
1497 
1498         if (!_cmsReadUInt16Number(io, &mlu ->Entries[i].Language)) goto Error;
1499         if (!_cmsReadUInt16Number(io, &mlu ->Entries[i].Country))  goto Error;
1500 
1501         // Now deal with Len and offset.
1502         if (!_cmsReadUInt32Number(io, &Len)) goto Error;
1503         if (!_cmsReadUInt32Number(io, &Offset)) goto Error;
1504 
1505         // Check for overflow
1506         if (Offset < (SizeOfHeader + 8)) goto Error;
1507         if (((Offset + Len) < Len) || ((Offset + Len) > SizeOfTag + 8)) goto Error;
1508 
1509         // True begin of the string
1510         BeginOfThisString = Offset - SizeOfHeader - 8;
1511 
1512         // Ajust to wchar_t elements
1513         mlu ->Entries[i].Len = (Len * sizeof(wchar_t)) / sizeof(cmsUInt16Number);
1514         mlu ->Entries[i].StrW = (BeginOfThisString * sizeof(wchar_t)) / sizeof(cmsUInt16Number);
1515 
1516         // To guess maximum size, add offset + len
1517         EndOfThisString = BeginOfThisString + Len;
1518         if (EndOfThisString > LargestPosition)
1519             LargestPosition = EndOfThisString;
1520     }
1521 
1522     // Now read the remaining of tag and fill all strings. Subtract the directory
1523     SizeOfTag   = (LargestPosition * sizeof(wchar_t)) / sizeof(cmsUInt16Number);
1524     if (SizeOfTag == 0)
1525     {
1526         Block = NULL;
1527         NumOfWchar = 0;
1528 
1529     }
1530     else
1531     {
1532         Block = (wchar_t*) _cmsMalloc(self ->ContextID, SizeOfTag);


1865     }
1866 
1867 
1868     // Get output tables
1869     if (!Read8bitTables(self ->ContextID, io,  NewLUT, OutputChannels)) goto Error;
1870 
1871     *nItems = 1;
1872     return NewLUT;
1873 
1874 Error:
1875     if (NewLUT != NULL) cmsPipelineFree(NewLUT);
1876     return NULL;
1877 
1878     cmsUNUSED_PARAMETER(SizeOfTag);
1879 }
1880 
1881 // We only allow a specific MPE structure: Matrix plus prelin, plus clut, plus post-lin.
1882 static
1883 cmsBool  Type_LUT8_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
1884 {
1885     cmsUInt32Number j, nTabSize;
1886     cmsUInt8Number  val;
1887     cmsPipeline* NewLUT = (cmsPipeline*) Ptr;
1888     cmsStage* mpe;
1889     _cmsStageToneCurvesData* PreMPE = NULL, *PostMPE = NULL;
1890     _cmsStageMatrixData* MatMPE = NULL;
1891     _cmsStageCLutData* clut = NULL;
1892     cmsUInt32Number clutPoints;
1893 
1894     // Disassemble the LUT into components.
1895     mpe = NewLUT -> Elements;
1896     if (mpe ->Type == cmsSigMatrixElemType) {
1897 
1898         MatMPE = (_cmsStageMatrixData*) mpe ->Data;
1899         mpe = mpe -> Next;
1900     }
1901 
1902     if (mpe != NULL && mpe ->Type == cmsSigCurveSetElemType) {
1903         PreMPE = (_cmsStageToneCurvesData*) mpe ->Data;
1904         mpe = mpe -> Next;
1905     }


1914         mpe = mpe -> Next;
1915     }
1916 
1917     // That should be all
1918     if (mpe != NULL) {
1919         cmsSignalError(mpe->ContextID, cmsERROR_UNKNOWN_EXTENSION, "LUT is not suitable to be saved as LUT8");
1920         return FALSE;
1921     }
1922 
1923 
1924     if (clut == NULL)
1925         clutPoints = 0;
1926     else
1927         clutPoints    = clut->Params->nSamples[0];
1928 
1929     if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) NewLUT ->InputChannels)) return FALSE;
1930     if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) NewLUT ->OutputChannels)) return FALSE;
1931     if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) clutPoints)) return FALSE;
1932     if (!_cmsWriteUInt8Number(io, 0)) return FALSE; // Padding
1933 

1934 
1935     if (MatMPE != NULL) {
1936 
1937         if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[0])) return FALSE;
1938         if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[1])) return FALSE;
1939         if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[2])) return FALSE;
1940         if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[3])) return FALSE;
1941         if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[4])) return FALSE;
1942         if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[5])) return FALSE;
1943         if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[6])) return FALSE;
1944         if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[7])) return FALSE;
1945         if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[8])) return FALSE;
1946 
1947     }
1948     else {
1949 


1950         if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE;
1951         if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
1952         if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
1953         if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
1954         if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE;
1955         if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
1956         if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
1957         if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
1958         if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE;
1959     }
1960 
1961     // The prelinearization table
1962     if (!Write8bitTables(self ->ContextID, io, NewLUT ->InputChannels, PreMPE)) return FALSE;
1963 
1964     nTabSize = uipow(NewLUT->OutputChannels, clutPoints, NewLUT ->InputChannels);
1965     if (nTabSize == (cmsUInt32Number) -1) return FALSE;
1966     if (nTabSize > 0) {
1967 
1968         // The 3D CLUT.
1969         if (clut != NULL) {


2168 
2169 // We only allow some specific MPE structures: Matrix plus prelin, plus clut, plus post-lin.
2170 // Some empty defaults are created for missing parts
2171 
2172 static
2173 cmsBool  Type_LUT16_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
2174 {
2175     cmsUInt32Number nTabSize;
2176     cmsPipeline* NewLUT = (cmsPipeline*) Ptr;
2177     cmsStage* mpe;
2178     _cmsStageToneCurvesData* PreMPE = NULL, *PostMPE = NULL;
2179     _cmsStageMatrixData* MatMPE = NULL;
2180     _cmsStageCLutData* clut = NULL;
2181     cmsUInt32Number i, InputChannels, OutputChannels, clutPoints;
2182 
2183     // Disassemble the LUT into components.
2184     mpe = NewLUT -> Elements;
2185     if (mpe != NULL && mpe ->Type == cmsSigMatrixElemType) {
2186 
2187         MatMPE = (_cmsStageMatrixData*) mpe ->Data;

2188         mpe = mpe -> Next;
2189     }
2190 
2191 
2192     if (mpe != NULL && mpe ->Type == cmsSigCurveSetElemType) {
2193         PreMPE = (_cmsStageToneCurvesData*) mpe ->Data;
2194         mpe = mpe -> Next;
2195     }
2196 
2197     if (mpe != NULL && mpe ->Type == cmsSigCLutElemType) {
2198         clut  = (_cmsStageCLutData*) mpe -> Data;
2199         mpe = mpe ->Next;
2200     }
2201 
2202     if (mpe != NULL && mpe ->Type == cmsSigCurveSetElemType) {
2203         PostMPE = (_cmsStageToneCurvesData*) mpe ->Data;
2204         mpe = mpe -> Next;
2205     }
2206 
2207     // That should be all
2208     if (mpe != NULL) {
2209         cmsSignalError(mpe->ContextID, cmsERROR_UNKNOWN_EXTENSION, "LUT is not suitable to be saved as LUT16");
2210         return FALSE;
2211     }
2212 
2213     InputChannels  = cmsPipelineInputChannels(NewLUT);
2214     OutputChannels = cmsPipelineOutputChannels(NewLUT);
2215 
2216     if (clut == NULL)
2217         clutPoints = 0;
2218     else
2219         clutPoints    = clut->Params->nSamples[0];
2220 
2221     if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) InputChannels)) return FALSE;
2222     if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) OutputChannels)) return FALSE;
2223     if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) clutPoints)) return FALSE;
2224     if (!_cmsWriteUInt8Number(io, 0)) return FALSE; // Padding
2225 
2226 
2227     if (MatMPE != NULL) {
2228 
2229         if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[0])) return FALSE;
2230         if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[1])) return FALSE;
2231         if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[2])) return FALSE;
2232         if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[3])) return FALSE;
2233         if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[4])) return FALSE;
2234         if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[5])) return FALSE;
2235         if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[6])) return FALSE;
2236         if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[7])) return FALSE;
2237         if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[8])) return FALSE;
2238     }
2239     else {
2240 
2241         if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE;
2242         if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
2243         if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
2244         if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
2245         if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE;
2246         if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
2247         if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
2248         if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
2249         if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE;
2250     }
2251 
2252 
2253     if (PreMPE != NULL) {
2254         if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) PreMPE ->TheCurves[0]->nEntries)) return FALSE;
2255     } else {
2256             if (!_cmsWriteUInt16Number(io, 2)) return FALSE;
2257     }


2562     }
2563 
2564     if (offsetB != 0) {
2565         if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetB, outputChan)))
2566             goto Error;
2567     }
2568 
2569     *nItems = 1;
2570     return NewLUT;
2571 Error:
2572     cmsPipelineFree(NewLUT);
2573     return NULL;
2574 
2575     cmsUNUSED_PARAMETER(SizeOfTag);
2576 }
2577 
2578 // Write a set of curves
2579 static
2580 cmsBool  WriteMatrix(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsStage* mpe)
2581 {


2582     _cmsStageMatrixData* m = (_cmsStageMatrixData*) mpe -> Data;
2583 


2584     // Write the Matrix
2585     if (!_cmsWrite15Fixed16Number(io, m -> Double[0])) return FALSE;
2586     if (!_cmsWrite15Fixed16Number(io, m -> Double[1])) return FALSE;
2587     if (!_cmsWrite15Fixed16Number(io, m -> Double[2])) return FALSE;
2588     if (!_cmsWrite15Fixed16Number(io, m -> Double[3])) return FALSE;
2589     if (!_cmsWrite15Fixed16Number(io, m -> Double[4])) return FALSE;
2590     if (!_cmsWrite15Fixed16Number(io, m -> Double[5])) return FALSE;
2591     if (!_cmsWrite15Fixed16Number(io, m -> Double[6])) return FALSE;
2592     if (!_cmsWrite15Fixed16Number(io, m -> Double[7])) return FALSE;
2593     if (!_cmsWrite15Fixed16Number(io, m -> Double[8])) return FALSE;
2594 
2595     if (m ->Offset != NULL) {
2596 
2597     if (!_cmsWrite15Fixed16Number(io, m -> Offset[0])) return FALSE;
2598     if (!_cmsWrite15Fixed16Number(io, m -> Offset[1])) return FALSE;
2599     if (!_cmsWrite15Fixed16Number(io, m -> Offset[2])) return FALSE;
2600     }
2601     else {


2602         if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
2603         if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
2604         if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
2605 
2606     }
2607 
2608 
2609     return TRUE;
2610 
2611     cmsUNUSED_PARAMETER(self);
2612 }
2613 
2614 
2615 // Write a set of curves
2616 static
2617 cmsBool WriteSetOfCurves(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsTagTypeSignature Type, cmsStage* mpe)
2618 {
2619     cmsUInt32Number i, n;
2620     cmsTagTypeSignature CurrentType;
2621     cmsToneCurve** Curves;
2622 
2623 
2624     n      = cmsStageOutputChannels(mpe);
2625     Curves = _cmsStageGetPtrToCurveSet(mpe);


3103 }
3104 
3105 
3106 static
3107 void Type_ColorantTable_Free(struct _cms_typehandler_struct* self, void* Ptr)
3108 {
3109     cmsFreeNamedColorList((cmsNAMEDCOLORLIST*) Ptr);
3110     return;
3111 
3112     cmsUNUSED_PARAMETER(self);
3113 }
3114 
3115 
3116 // ********************************************************************************
3117 // Type cmsSigNamedColor2Type
3118 // ********************************************************************************
3119 //
3120 //The namedColor2Type is a count value and array of structures that provide color
3121 //coordinates for 7-bit ASCII color names. For each named color, a PCS and optional
3122 //device representation of the color are given. Both representations are 16-bit values.
3123 //The device representation corresponds to the header’s “color space of data” field.
3124 //This representation should be consistent with the “number of device components”
3125 //field in the namedColor2Type. If this field is 0, device coordinates are not provided.
3126 //The PCS representation corresponds to the header’s PCS field. The PCS representation
3127 //is always provided. Color names are fixed-length, 32-byte fields including null
3128 //termination. In order to maintain maximum portability, it is strongly recommended
3129 //that special characters of the 7-bit ASCII set not be used.
3130 
3131 static
3132 void *Type_NamedColor_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
3133 {
3134 
3135     cmsUInt32Number      vendorFlag;     // Bottom 16 bits for ICC use
3136     cmsUInt32Number      count;          // Count of named colors
3137     cmsUInt32Number      nDeviceCoords;  // Num of device coordinates
3138     char                 prefix[32];     // Prefix for each color name
3139     char                 suffix[32];     // Suffix for each color name
3140     cmsNAMEDCOLORLIST*   v;
3141     cmsUInt32Number      i;
3142 
3143 
3144     *nItems = 0;
3145     if (!_cmsReadUInt32Number(io, &vendorFlag)) return NULL;
3146     if (!_cmsReadUInt32Number(io, &count)) return NULL;


3851 static
3852 void* Type_Screening_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
3853 {
3854    return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsScreening));
3855 
3856    cmsUNUSED_PARAMETER(n);
3857 }
3858 
3859 
3860 static
3861 void Type_Screening_Free(struct _cms_typehandler_struct* self, void* Ptr)
3862 {
3863    _cmsFree(self ->ContextID, Ptr);
3864 }
3865 
3866 // ********************************************************************************
3867 // Type cmsSigViewingConditionsType
3868 // ********************************************************************************
3869 //
3870 //This type represents a set of viewing condition parameters including:
3871 //CIE ’absolute’ illuminant white point tristimulus values and CIE ’absolute’
3872 //surround tristimulus values.
3873 
3874 static
3875 void *Type_ViewingConditions_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
3876 {
3877     cmsICCViewingConditions* vc = NULL;
3878 
3879     vc = (cmsICCViewingConditions*) _cmsMallocZero(self ->ContextID, sizeof(cmsICCViewingConditions));
3880     if (vc == NULL) return NULL;
3881 
3882     *nItems = 0;
3883 
3884     if (!_cmsReadXYZNumber(io, &vc ->IlluminantXYZ)) goto Error;
3885     if (!_cmsReadXYZNumber(io, &vc ->SurroundXYZ)) goto Error;
3886     if (!_cmsReadUInt32Number(io, &vc ->IlluminantType)) goto Error;
3887 
3888     *nItems = 1;
3889 
3890     return (void*) vc;
3891 


3938 
3939 static
3940 void* GenericMPEdup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
3941 {
3942     return (void*) cmsStageDup((cmsStage*) Ptr);
3943 
3944     cmsUNUSED_PARAMETER(n);
3945     cmsUNUSED_PARAMETER(self);
3946 }
3947 
3948 static
3949 void GenericMPEfree(struct _cms_typehandler_struct* self, void *Ptr)
3950 {
3951     cmsStageFree((cmsStage*) Ptr);
3952     return;
3953 
3954     cmsUNUSED_PARAMETER(self);
3955 }
3956 
3957 // Each curve is stored in one or more curve segments, with break-points specified between curve segments.
3958 // The first curve segment always starts at –Infinity, and the last curve segment always ends at +Infinity. The
3959 // first and last curve segments shall be specified in terms of a formula, whereas the other segments shall be
3960 // specified either in terms of a formula, or by a sampled curve.
3961 
3962 
3963 // Read an embedded segmented curve
3964 static
3965 cmsToneCurve* ReadSegmentedCurve(struct _cms_typehandler_struct* self, cmsIOHANDLER* io)
3966 {
3967     cmsCurveSegSignature ElementSig;
3968     cmsUInt32Number i, j;
3969     cmsUInt16Number nSegments;
3970     cmsCurveSegment*  Segments;
3971     cmsToneCurve* Curve;
3972     cmsFloat32Number PrevBreak = MINUS_INF;    // - infinite
3973 
3974     // Take signature and channels for each element.
3975      if (!_cmsReadUInt32Number(io, (cmsUInt32Number*) &ElementSig)) return NULL;
3976 
3977      // That should be a segmented curve
3978      if (ElementSig != cmsSigSegmentedCurve) return NULL;


4219     BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);
4220 
4221     // Write the header. Since those are curves, input and output channels are same
4222     if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->InputChannels)) return FALSE;
4223     if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->InputChannels)) return FALSE;
4224 
4225     if (!WritePositionTable(self, io, 0,
4226                                 mpe ->InputChannels, BaseOffset, Curves, WriteMPECurve)) return FALSE;
4227 
4228 
4229     return TRUE;
4230 
4231     cmsUNUSED_PARAMETER(nItems);
4232 }
4233 
4234 
4235 
4236 // The matrix is organized as an array of PxQ+Q elements, where P is the number of input channels to the
4237 // matrix, and Q is the number of output channels. The matrix elements are each float32Numbers. The array
4238 // is organized as follows:
4239 // array = [e11, e12, …, e1P, e21, e22, …, e2P, …, eQ1, eQ2, …, eQP, e1, e2, …, eQ]
4240 
4241 static
4242 void *Type_MPEmatrix_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
4243 {
4244     cmsStage* mpe;
4245     cmsUInt16Number   InputChans, OutputChans;
4246     cmsUInt32Number   nElems, i;
4247     cmsFloat64Number* Matrix;
4248     cmsFloat64Number* Offsets;
4249 
4250     if (!_cmsReadUInt16Number(io, &InputChans)) return NULL;
4251     if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL;
4252 
4253 
4254     // Input and output chans may be ANY (up to 0xffff),
4255     // but we choose to limit to 16 channels for now
4256     if (InputChans >= cmsMAXCHANNELS) return NULL;
4257     if (OutputChans >= cmsMAXCHANNELS) return NULL;
4258 
4259     nElems = (cmsUInt32Number) InputChans * OutputChans;


4742 
4743    // In this case, gamma is stored as a formula
4744    case cmsVideoCardGammaFormulaType:
4745    {
4746        _cmsVCGTGAMMA Colorant[3];
4747 
4748         // Populate tone curves
4749        for (n=0; n < 3; n++) {
4750 
4751            double Params[10];
4752 
4753            if (!_cmsRead15Fixed16Number(io, &Colorant[n].Gamma)) goto Error;
4754            if (!_cmsRead15Fixed16Number(io, &Colorant[n].Min)) goto Error;
4755            if (!_cmsRead15Fixed16Number(io, &Colorant[n].Max)) goto Error;
4756 
4757             // Parametric curve type 5 is:
4758             // Y = (aX + b)^Gamma + e | X >= d
4759             // Y = cX + f             | X < d
4760 
4761             // vcgt formula is:
4762             // Y = (Max – Min) * (X ^ Gamma) + Min
4763 
4764             // So, the translation is
4765             // a = (Max – Min) ^ ( 1 / Gamma)
4766             // e = Min
4767             // b=c=d=f=0
4768 
4769            Params[0] = Colorant[n].Gamma;
4770            Params[1] = pow((Colorant[n].Max - Colorant[n].Min), (1.0 / Colorant[n].Gamma));
4771            Params[2] = 0;
4772            Params[3] = 0;
4773            Params[4] = 0;
4774            Params[5] = Colorant[n].Min;
4775            Params[6] = 0;
4776 
4777            Curves[n] = cmsBuildParametricToneCurve(self ->ContextID, 5, Params);
4778            if (Curves[n] == NULL) goto Error;
4779        }
4780    }
4781    break;
4782 
4783    // Unsupported
4784    default:
4785       cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported tag type for VCGT '%d'", TagType);




  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  */
  24 
  25 // This file is available under and governed by the GNU General Public
  26 // License version 2 only, as published by the Free Software Foundation.
  27 // However, the following notice accompanied the original version of this
  28 // file:
  29 //
  30 //---------------------------------------------------------------------------------
  31 //
  32 //  Little Color Management System
  33 //  Copyright (c) 1998-2020 Marti Maria Saguer
  34 //
  35 // Permission is hereby granted, free of charge, to any person obtaining
  36 // a copy of this software and associated documentation files (the "Software"),
  37 // to deal in the Software without restriction, including without limitation
  38 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
  39 // and/or sell copies of the Software, and to permit persons to whom the Software
  40 // is furnished to do so, subject to the following conditions:
  41 //
  42 // The above copyright notice and this permission notice shall be included in
  43 // all copies or substantial portions of the Software.
  44 //
  45 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  46 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  47 // THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  48 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  49 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  50 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  51 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  52 //
  53 //---------------------------------------------------------------------------------


 178 
 179             if (!_cmsReadUInt16Number(io, &tmp)) return FALSE;
 180             Array[i] = (wchar_t) tmp;
 181         }
 182         else {
 183             if (!_cmsReadUInt16Number(io, NULL)) return FALSE;
 184         }
 185 
 186     }
 187     return TRUE;
 188 }
 189 
 190 // To deal with position tables
 191 typedef cmsBool (* PositionTableEntryFn)(struct _cms_typehandler_struct* self,
 192                                              cmsIOHANDLER* io,
 193                                              void* Cargo,
 194                                              cmsUInt32Number n,
 195                                              cmsUInt32Number SizeOfTag);
 196 
 197 // Helper function to deal with position tables as described in ICC spec 4.3
 198 // A table of n elements is read, where first comes n records containing offsets and sizes and
 199 // then a block containing the data itself. This allows to reuse same data in more than one entry
 200 static
 201 cmsBool ReadPositionTable(struct _cms_typehandler_struct* self,
 202                               cmsIOHANDLER* io,
 203                               cmsUInt32Number Count,
 204                               cmsUInt32Number BaseOffset,
 205                               void *Cargo,
 206                               PositionTableEntryFn ElementFn)
 207 {
 208     cmsUInt32Number i;
 209     cmsUInt32Number *ElementOffsets = NULL, *ElementSizes = NULL;
 210     cmsUInt32Number currentPosition;
 211 
 212     currentPosition = io->Tell(io);
 213 
 214     // Verify there is enough space left to read at least two cmsUInt32Number items for Count items.
 215     if (((io->ReportedSize - currentPosition) / (2 * sizeof(cmsUInt32Number))) < Count)
 216         return FALSE;
 217 
 218     // Let's take the offsets to each element


 986 
 987 
 988 // This tag can come IN UNALIGNED SIZE. In order to prevent issues, we force zeros on description to align it
 989 static
 990 cmsBool  Type_Text_Description_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
 991 {
 992     cmsMLU* mlu = (cmsMLU*) Ptr;
 993     char *Text = NULL;
 994     wchar_t *Wide = NULL;
 995     cmsUInt32Number len, len_text, len_tag_requirement, len_aligned;
 996     cmsBool  rc = FALSE;
 997     char Filler[68];
 998 
 999     // Used below for writing zeroes
1000     memset(Filler, 0, sizeof(Filler));
1001 
1002     // Get the len of string
1003     len = cmsMLUgetASCII(mlu, cmsNoLanguage, cmsNoCountry, NULL, 0);
1004 
1005     // Specification ICC.1:2001-04 (v2.4.0): It has been found that textDescriptionType can contain misaligned data
1006     //(see clause 4.1 for the definition of 'aligned'). Because the Unicode language
1007     // code and Unicode count immediately follow the ASCII description, their
1008     // alignment is not correct if the ASCII count is not a multiple of four. The
1009     // ScriptCode code is misaligned when the ASCII count is odd. Profile reading and
1010     // writing software must be written carefully in order to handle these alignment
1011     // problems.
1012     //
1013     // The above last sentence suggest to handle alignment issues in the
1014     // parser. The provided example (Table 69 on Page 60) makes this clear.
1015     // The padding only in the ASCII count is not sufficient for a aligned tag
1016     // size, with the same text size in ASCII and Unicode.
1017 
1018     // Null strings
1019     if (len <= 0) {
1020 
1021         Text = (char*)    _cmsDupMem(self ->ContextID, "", sizeof(char));
1022         Wide = (wchar_t*) _cmsDupMem(self ->ContextID, L"", sizeof(wchar_t));
1023     }
1024     else {
1025         // Create independent buffers
1026         Text = (char*) _cmsCalloc(self ->ContextID, len, sizeof(char));


1492 
1493     SizeOfHeader = 12 * Count + sizeof(_cmsTagBase);
1494     LargestPosition = 0;
1495 
1496     for (i=0; i < Count; i++) {
1497 
1498         if (!_cmsReadUInt16Number(io, &mlu ->Entries[i].Language)) goto Error;
1499         if (!_cmsReadUInt16Number(io, &mlu ->Entries[i].Country))  goto Error;
1500 
1501         // Now deal with Len and offset.
1502         if (!_cmsReadUInt32Number(io, &Len)) goto Error;
1503         if (!_cmsReadUInt32Number(io, &Offset)) goto Error;
1504 
1505         // Check for overflow
1506         if (Offset < (SizeOfHeader + 8)) goto Error;
1507         if (((Offset + Len) < Len) || ((Offset + Len) > SizeOfTag + 8)) goto Error;
1508 
1509         // True begin of the string
1510         BeginOfThisString = Offset - SizeOfHeader - 8;
1511 
1512         // Adjust to wchar_t elements
1513         mlu ->Entries[i].Len = (Len * sizeof(wchar_t)) / sizeof(cmsUInt16Number);
1514         mlu ->Entries[i].StrW = (BeginOfThisString * sizeof(wchar_t)) / sizeof(cmsUInt16Number);
1515 
1516         // To guess maximum size, add offset + len
1517         EndOfThisString = BeginOfThisString + Len;
1518         if (EndOfThisString > LargestPosition)
1519             LargestPosition = EndOfThisString;
1520     }
1521 
1522     // Now read the remaining of tag and fill all strings. Subtract the directory
1523     SizeOfTag   = (LargestPosition * sizeof(wchar_t)) / sizeof(cmsUInt16Number);
1524     if (SizeOfTag == 0)
1525     {
1526         Block = NULL;
1527         NumOfWchar = 0;
1528 
1529     }
1530     else
1531     {
1532         Block = (wchar_t*) _cmsMalloc(self ->ContextID, SizeOfTag);


1865     }
1866 
1867 
1868     // Get output tables
1869     if (!Read8bitTables(self ->ContextID, io,  NewLUT, OutputChannels)) goto Error;
1870 
1871     *nItems = 1;
1872     return NewLUT;
1873 
1874 Error:
1875     if (NewLUT != NULL) cmsPipelineFree(NewLUT);
1876     return NULL;
1877 
1878     cmsUNUSED_PARAMETER(SizeOfTag);
1879 }
1880 
1881 // We only allow a specific MPE structure: Matrix plus prelin, plus clut, plus post-lin.
1882 static
1883 cmsBool  Type_LUT8_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
1884 {
1885     cmsUInt32Number j, nTabSize, i, n;
1886     cmsUInt8Number  val;
1887     cmsPipeline* NewLUT = (cmsPipeline*) Ptr;
1888     cmsStage* mpe;
1889     _cmsStageToneCurvesData* PreMPE = NULL, *PostMPE = NULL;
1890     _cmsStageMatrixData* MatMPE = NULL;
1891     _cmsStageCLutData* clut = NULL;
1892     cmsUInt32Number clutPoints;
1893 
1894     // Disassemble the LUT into components.
1895     mpe = NewLUT -> Elements;
1896     if (mpe ->Type == cmsSigMatrixElemType) {
1897 
1898         MatMPE = (_cmsStageMatrixData*) mpe ->Data;
1899         mpe = mpe -> Next;
1900     }
1901 
1902     if (mpe != NULL && mpe ->Type == cmsSigCurveSetElemType) {
1903         PreMPE = (_cmsStageToneCurvesData*) mpe ->Data;
1904         mpe = mpe -> Next;
1905     }


1914         mpe = mpe -> Next;
1915     }
1916 
1917     // That should be all
1918     if (mpe != NULL) {
1919         cmsSignalError(mpe->ContextID, cmsERROR_UNKNOWN_EXTENSION, "LUT is not suitable to be saved as LUT8");
1920         return FALSE;
1921     }
1922 
1923 
1924     if (clut == NULL)
1925         clutPoints = 0;
1926     else
1927         clutPoints    = clut->Params->nSamples[0];
1928 
1929     if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) NewLUT ->InputChannels)) return FALSE;
1930     if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) NewLUT ->OutputChannels)) return FALSE;
1931     if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) clutPoints)) return FALSE;
1932     if (!_cmsWriteUInt8Number(io, 0)) return FALSE; // Padding
1933 
1934         n = NewLUT->InputChannels * NewLUT->OutputChannels;
1935 
1936     if (MatMPE != NULL) {
1937 
1938                 for (i = 0; i < n; i++)
1939                 {
1940                         if (!_cmsWrite15Fixed16Number(io, MatMPE->Double[i])) return FALSE;
1941                 }






1942     }
1943     else {
1944 
1945                 if (n != 9) return FALSE;
1946 
1947         if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE;
1948         if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
1949         if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
1950         if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
1951         if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE;
1952         if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
1953         if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
1954         if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
1955         if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE;
1956     }
1957 
1958     // The prelinearization table
1959     if (!Write8bitTables(self ->ContextID, io, NewLUT ->InputChannels, PreMPE)) return FALSE;
1960 
1961     nTabSize = uipow(NewLUT->OutputChannels, clutPoints, NewLUT ->InputChannels);
1962     if (nTabSize == (cmsUInt32Number) -1) return FALSE;
1963     if (nTabSize > 0) {
1964 
1965         // The 3D CLUT.
1966         if (clut != NULL) {


2165 
2166 // We only allow some specific MPE structures: Matrix plus prelin, plus clut, plus post-lin.
2167 // Some empty defaults are created for missing parts
2168 
2169 static
2170 cmsBool Type_LUT16_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
2171 {
2172     cmsUInt32Number nTabSize;
2173     cmsPipeline* NewLUT = (cmsPipeline*) Ptr;
2174     cmsStage* mpe;
2175     _cmsStageToneCurvesData* PreMPE = NULL, *PostMPE = NULL;
2176     _cmsStageMatrixData* MatMPE = NULL;
2177     _cmsStageCLutData* clut = NULL;
2178     cmsUInt32Number i, InputChannels, OutputChannels, clutPoints;
2179 
2180     // Disassemble the LUT into components.
2181     mpe = NewLUT -> Elements;
2182     if (mpe != NULL && mpe ->Type == cmsSigMatrixElemType) {
2183 
2184         MatMPE = (_cmsStageMatrixData*) mpe ->Data;
2185         if (mpe->InputChannels != 3 || mpe->OutputChannels != 3) return FALSE;
2186         mpe = mpe -> Next;
2187     }
2188 
2189 
2190     if (mpe != NULL && mpe ->Type == cmsSigCurveSetElemType) {
2191         PreMPE = (_cmsStageToneCurvesData*) mpe ->Data;
2192         mpe = mpe -> Next;
2193     }
2194 
2195     if (mpe != NULL && mpe ->Type == cmsSigCLutElemType) {
2196         clut  = (_cmsStageCLutData*) mpe -> Data;
2197         mpe = mpe ->Next;
2198     }
2199 
2200     if (mpe != NULL && mpe ->Type == cmsSigCurveSetElemType) {
2201         PostMPE = (_cmsStageToneCurvesData*) mpe ->Data;
2202         mpe = mpe -> Next;
2203     }
2204 
2205     // That should be all
2206     if (mpe != NULL) {
2207         cmsSignalError(mpe->ContextID, cmsERROR_UNKNOWN_EXTENSION, "LUT is not suitable to be saved as LUT16");
2208         return FALSE;
2209     }
2210 
2211     InputChannels  = cmsPipelineInputChannels(NewLUT);
2212     OutputChannels = cmsPipelineOutputChannels(NewLUT);
2213 
2214     if (clut == NULL)
2215         clutPoints = 0;
2216     else
2217         clutPoints    = clut->Params->nSamples[0];
2218 
2219     if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) InputChannels)) return FALSE;
2220     if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) OutputChannels)) return FALSE;
2221     if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) clutPoints)) return FALSE;
2222     if (!_cmsWriteUInt8Number(io, 0)) return FALSE; // Padding
2223 

2224     if (MatMPE != NULL) {
2225 
2226                 for (i = 0; i < 9; i++)
2227                 {
2228                         if (!_cmsWrite15Fixed16Number(io, MatMPE->Double[i])) return FALSE;
2229                 }
2230 




2231     }
2232     else {
2233 
2234         if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE;
2235         if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
2236         if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
2237         if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
2238         if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE;
2239         if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
2240         if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
2241         if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
2242         if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE;
2243     }
2244 
2245 
2246     if (PreMPE != NULL) {
2247         if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) PreMPE ->TheCurves[0]->nEntries)) return FALSE;
2248     } else {
2249             if (!_cmsWriteUInt16Number(io, 2)) return FALSE;
2250     }


2555     }
2556 
2557     if (offsetB != 0) {
2558         if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetB, outputChan)))
2559             goto Error;
2560     }
2561 
2562     *nItems = 1;
2563     return NewLUT;
2564 Error:
2565     cmsPipelineFree(NewLUT);
2566     return NULL;
2567 
2568     cmsUNUSED_PARAMETER(SizeOfTag);
2569 }
2570 
2571 // Write a set of curves
2572 static
2573 cmsBool  WriteMatrix(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsStage* mpe)
2574 {
2575         cmsUInt32Number i, n;
2576 
2577     _cmsStageMatrixData* m = (_cmsStageMatrixData*) mpe -> Data;
2578 
2579         n = mpe->InputChannels * mpe->OutputChannels;
2580 
2581         // Write the Matrix
2582         for (i = 0; i < n; i++)
2583         {
2584                 if (!_cmsWrite15Fixed16Number(io, m->Double[i])) return FALSE;
2585         }
2586 
2587         if (m->Offset != NULL) {
2588 
2589                 for (i = 0; i < mpe->OutputChannels; i++)
2590                 {
2591                         if (!_cmsWrite15Fixed16Number(io, m->Offset[i])) return FALSE;
2592                 }




2593         }
2594         else {
2595                 for (i = 0; i < mpe->OutputChannels; i++)
2596                 {
2597                         if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
2598                 }


2599         }
2600 
2601 
2602     return TRUE;
2603 
2604     cmsUNUSED_PARAMETER(self);
2605 }
2606 
2607 
2608 // Write a set of curves
2609 static
2610 cmsBool WriteSetOfCurves(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsTagTypeSignature Type, cmsStage* mpe)
2611 {
2612     cmsUInt32Number i, n;
2613     cmsTagTypeSignature CurrentType;
2614     cmsToneCurve** Curves;
2615 
2616 
2617     n      = cmsStageOutputChannels(mpe);
2618     Curves = _cmsStageGetPtrToCurveSet(mpe);


3096 }
3097 
3098 
3099 static
3100 void Type_ColorantTable_Free(struct _cms_typehandler_struct* self, void* Ptr)
3101 {
3102     cmsFreeNamedColorList((cmsNAMEDCOLORLIST*) Ptr);
3103     return;
3104 
3105     cmsUNUSED_PARAMETER(self);
3106 }
3107 
3108 
3109 // ********************************************************************************
3110 // Type cmsSigNamedColor2Type
3111 // ********************************************************************************
3112 //
3113 //The namedColor2Type is a count value and array of structures that provide color
3114 //coordinates for 7-bit ASCII color names. For each named color, a PCS and optional
3115 //device representation of the color are given. Both representations are 16-bit values.
3116 //The device representation corresponds to the header's 'color space of data' field.
3117 //This representation should be consistent with the 'number of device components'
3118 //field in the namedColor2Type. If this field is 0, device coordinates are not provided.
3119 //The PCS representation corresponds to the header's PCS field. The PCS representation
3120 //is always provided. Color names are fixed-length, 32-byte fields including null
3121 //termination. In order to maintain maximum portability, it is strongly recommended
3122 //that special characters of the 7-bit ASCII set not be used.
3123 
3124 static
3125 void *Type_NamedColor_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
3126 {
3127 
3128     cmsUInt32Number      vendorFlag;     // Bottom 16 bits for ICC use
3129     cmsUInt32Number      count;          // Count of named colors
3130     cmsUInt32Number      nDeviceCoords;  // Num of device coordinates
3131     char                 prefix[32];     // Prefix for each color name
3132     char                 suffix[32];     // Suffix for each color name
3133     cmsNAMEDCOLORLIST*   v;
3134     cmsUInt32Number      i;
3135 
3136 
3137     *nItems = 0;
3138     if (!_cmsReadUInt32Number(io, &vendorFlag)) return NULL;
3139     if (!_cmsReadUInt32Number(io, &count)) return NULL;


3844 static
3845 void* Type_Screening_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
3846 {
3847    return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsScreening));
3848 
3849    cmsUNUSED_PARAMETER(n);
3850 }
3851 
3852 
3853 static
3854 void Type_Screening_Free(struct _cms_typehandler_struct* self, void* Ptr)
3855 {
3856    _cmsFree(self ->ContextID, Ptr);
3857 }
3858 
3859 // ********************************************************************************
3860 // Type cmsSigViewingConditionsType
3861 // ********************************************************************************
3862 //
3863 //This type represents a set of viewing condition parameters including:
3864 //CIE 'absolute' illuminant white point tristimulus values and CIE 'absolute'
3865 //surround tristimulus values.
3866 
3867 static
3868 void *Type_ViewingConditions_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
3869 {
3870     cmsICCViewingConditions* vc = NULL;
3871 
3872     vc = (cmsICCViewingConditions*) _cmsMallocZero(self ->ContextID, sizeof(cmsICCViewingConditions));
3873     if (vc == NULL) return NULL;
3874 
3875     *nItems = 0;
3876 
3877     if (!_cmsReadXYZNumber(io, &vc ->IlluminantXYZ)) goto Error;
3878     if (!_cmsReadXYZNumber(io, &vc ->SurroundXYZ)) goto Error;
3879     if (!_cmsReadUInt32Number(io, &vc ->IlluminantType)) goto Error;
3880 
3881     *nItems = 1;
3882 
3883     return (void*) vc;
3884 


3931 
3932 static
3933 void* GenericMPEdup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
3934 {
3935     return (void*) cmsStageDup((cmsStage*) Ptr);
3936 
3937     cmsUNUSED_PARAMETER(n);
3938     cmsUNUSED_PARAMETER(self);
3939 }
3940 
3941 static
3942 void GenericMPEfree(struct _cms_typehandler_struct* self, void *Ptr)
3943 {
3944     cmsStageFree((cmsStage*) Ptr);
3945     return;
3946 
3947     cmsUNUSED_PARAMETER(self);
3948 }
3949 
3950 // Each curve is stored in one or more curve segments, with break-points specified between curve segments.
3951 // The first curve segment always starts at -Infinity, and the last curve segment always ends at +Infinity. The
3952 // first and last curve segments shall be specified in terms of a formula, whereas the other segments shall be
3953 // specified either in terms of a formula, or by a sampled curve.
3954 
3955 
3956 // Read an embedded segmented curve
3957 static
3958 cmsToneCurve* ReadSegmentedCurve(struct _cms_typehandler_struct* self, cmsIOHANDLER* io)
3959 {
3960     cmsCurveSegSignature ElementSig;
3961     cmsUInt32Number i, j;
3962     cmsUInt16Number nSegments;
3963     cmsCurveSegment*  Segments;
3964     cmsToneCurve* Curve;
3965     cmsFloat32Number PrevBreak = MINUS_INF;    // - infinite
3966 
3967     // Take signature and channels for each element.
3968      if (!_cmsReadUInt32Number(io, (cmsUInt32Number*) &ElementSig)) return NULL;
3969 
3970      // That should be a segmented curve
3971      if (ElementSig != cmsSigSegmentedCurve) return NULL;


4212     BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);
4213 
4214     // Write the header. Since those are curves, input and output channels are same
4215     if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->InputChannels)) return FALSE;
4216     if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->InputChannels)) return FALSE;
4217 
4218     if (!WritePositionTable(self, io, 0,
4219                                 mpe ->InputChannels, BaseOffset, Curves, WriteMPECurve)) return FALSE;
4220 
4221 
4222     return TRUE;
4223 
4224     cmsUNUSED_PARAMETER(nItems);
4225 }
4226 
4227 
4228 
4229 // The matrix is organized as an array of PxQ+Q elements, where P is the number of input channels to the
4230 // matrix, and Q is the number of output channels. The matrix elements are each float32Numbers. The array
4231 // is organized as follows:
4232 // array = [e11, e12, ..., e1P, e21, e22, ..., e2P, ..., eQ1, eQ2, ..., eQP, e1, e2, ..., eQ]
4233 
4234 static
4235 void *Type_MPEmatrix_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
4236 {
4237     cmsStage* mpe;
4238     cmsUInt16Number   InputChans, OutputChans;
4239     cmsUInt32Number   nElems, i;
4240     cmsFloat64Number* Matrix;
4241     cmsFloat64Number* Offsets;
4242 
4243     if (!_cmsReadUInt16Number(io, &InputChans)) return NULL;
4244     if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL;
4245 
4246 
4247     // Input and output chans may be ANY (up to 0xffff),
4248     // but we choose to limit to 16 channels for now
4249     if (InputChans >= cmsMAXCHANNELS) return NULL;
4250     if (OutputChans >= cmsMAXCHANNELS) return NULL;
4251 
4252     nElems = (cmsUInt32Number) InputChans * OutputChans;


4735 
4736    // In this case, gamma is stored as a formula
4737    case cmsVideoCardGammaFormulaType:
4738    {
4739        _cmsVCGTGAMMA Colorant[3];
4740 
4741         // Populate tone curves
4742        for (n=0; n < 3; n++) {
4743 
4744            double Params[10];
4745 
4746            if (!_cmsRead15Fixed16Number(io, &Colorant[n].Gamma)) goto Error;
4747            if (!_cmsRead15Fixed16Number(io, &Colorant[n].Min)) goto Error;
4748            if (!_cmsRead15Fixed16Number(io, &Colorant[n].Max)) goto Error;
4749 
4750             // Parametric curve type 5 is:
4751             // Y = (aX + b)^Gamma + e | X >= d
4752             // Y = cX + f             | X < d
4753 
4754             // vcgt formula is:
4755             // Y = (Max - Min) * (X ^ Gamma) + Min
4756 
4757             // So, the translation is
4758             // a = (Max - Min) ^ ( 1 / Gamma)
4759             // e = Min
4760             // b=c=d=f=0
4761 
4762            Params[0] = Colorant[n].Gamma;
4763            Params[1] = pow((Colorant[n].Max - Colorant[n].Min), (1.0 / Colorant[n].Gamma));
4764            Params[2] = 0;
4765            Params[3] = 0;
4766            Params[4] = 0;
4767            Params[5] = Colorant[n].Min;
4768            Params[6] = 0;
4769 
4770            Curves[n] = cmsBuildParametricToneCurve(self ->ContextID, 5, Params);
4771            if (Curves[n] == NULL) goto Error;
4772        }
4773    }
4774    break;
4775 
4776    // Unsupported
4777    default:
4778       cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported tag type for VCGT '%d'", TagType);


< prev index next >