test: getcrd.c Source File

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# getcrd.c

Go to the documentation of this file.

    00001 #include "generic.h"
    00002 #include "stdio.h"
    00003 #pragma code_seg(_ICMSEG)
    00004
    00005 char ICMSEG BeginString[]       = "<";
    00006 char ICMSEG EndString[]         = ">";
    00007 char ICMSEG BeginArray[]        = "[";
    00008 char ICMSEG EndArray[]          = "]";
    00009 char ICMSEG BeginFunction[]     = "{";
    00010 char ICMSEG EndFunction[]       = "}bind ";
    00011 char ICMSEG BeginDict[]         = "<<" ;
    00012 char ICMSEG EndDict[]           = ">>" ;
    00013 char ICMSEG BlackPoint[]        = "[0 0 0]" ;
    00014 char ICMSEG DictType[]          = "/ColorRenderingType 1 ";
    00015 char ICMSEG IntentType[]        = "/RenderingIntent ";
    00016 char ICMSEG IntentPer[]         = "/Perceptual";
    00017 char ICMSEG IntentSat[]         = "/Saturation";
    00018 char ICMSEG IntentACol[]        = "/AbsoluteColorimetric";
    00019 char ICMSEG IntentRCol[]        = "/RelativeColorimetric";
    00020
    00021 char ICMSEG WhitePointTag[]     = "/WhitePoint " ;
    00022 char ICMSEG BlackPointTag[]     = "/BlackPoint " ;
    00023 char ICMSEG RangePQRTag[]       = "/RangePQR " ;
    00024 char ICMSEG TransformPQRTag[]   = "/TransformPQR " ;
    00025 char ICMSEG MatrixPQRTag[]      = "/MatrixPQR " ;
    00026
    00027 char ICMSEG RangeABCTag[]       = "/RangeABC " ;
    00028 char ICMSEG MatrixATag[]        = "/MatrixA ";
    00029 char ICMSEG MatrixABCTag[]      = "/MatrixABC ";
    00030 char ICMSEG EncodeABCTag[]      = "/EncodeABC " ;
    00031 char ICMSEG RangeLMNTag[]       = "/RangeLMN " ;
    00032 char ICMSEG MatrixLMNTag[]      = "/MatrixLMN " ;
    00033 char ICMSEG EncodeLMNTag[]      = "/EncodeLMN " ;
    00034 char ICMSEG RenderTableTag[]    = "/RenderTable " ;
    00035 char ICMSEG CIEBasedATag[]      = "/CIEBasedA " ;
    00036 char ICMSEG CIEBasedABCTag[]    = "/CIEBasedABC " ;
    00037 char ICMSEG CIEBasedDEFGTag[]   = "/CIEBasedDEFG " ;
    00038 char ICMSEG CIEBasedDEFTag[]    = "/CIEBasedDEF " ;
    00039 char ICMSEG DecodeATag[]        = "/DecodeA " ;
    00040 char ICMSEG DecodeABCTag[]      = "/DecodeABC " ;
    00041 char ICMSEG DecodeLMNTag[]      = "/DecodeLMN " ;
    00042 char ICMSEG DeviceRGBTag[]      = "/DeviceRGB " ;
    00043 char ICMSEG DeviceCMYKTag[]     = "/DeviceCMYK " ;
    00044 char ICMSEG DeviceGrayTag[]     = "/DeviceGray " ;
    00045 char ICMSEG TableTag[]          = "/Table " ;
    00046 char ICMSEG DecodeDEFGTag[]     = "/DecodeDEFG " ;
    00047 char ICMSEG DecodeDEFTag[]      = "/DecodeDEF " ;
    00048
    00049 char ICMSEG NullOp[]            = "";
    00050 char ICMSEG DupOp[]             = "dup ";
    00051 char ICMSEG UserDictOp[]        = "userdict ";
    00052 char ICMSEG GlobalDictOp[]      = "globaldict ";
    00053 char ICMSEG CurrentGlobalOp[]   = "currentglobal ";
    00054 char ICMSEG SetGlobalOp[]       = "setglobal ";
    00055 char ICMSEG DefOp[]             = "def ";
    00056 char ICMSEG BeginOp[]           = "begin ";
    00057 char ICMSEG EndOp[]             = "end ";
    00058 char ICMSEG TrueOp[]            = "true ";
    00059 char ICMSEG FalseOp[]           = "false ";
    00060 char ICMSEG MulOp[]             = "mul ";
    00061 char ICMSEG DivOp[]             = "div ";
    00062
    00063 char ICMSEG NewLine[]           = "\n" ;
    00064 char ICMSEG Slash[]             = "/" ;
    00065 char ICMSEG Space[]             = " " ;
    00066 char ICMSEG CRDBegin[]          = "%** CRD Begin ";
    00067 char ICMSEG CRDEnd[]            = "%** CRD End ";
    00068 char ICMSEG CieBasedDEFGBegin[] = "%** CieBasedDEFG CSA Begin ";
    00069 char ICMSEG CieBasedDEFBegin[]  = "%** CieBasedDEF CSA Begin ";
    00070 char ICMSEG CieBasedABCBegin[]  = "%** CieBasedABC CSA Begin ";
    00071 char ICMSEG CieBasedABegin[]    = "%** CieBasedA CSA Begin ";
    00072 char ICMSEG CieBasedDEFGEnd[]   = "%** CieBasedDEFG CSA End ";
    00073 char ICMSEG CieBasedDEFEnd[]    = "%** CieBasedDEF CSA End ";
    00074 char ICMSEG CieBasedABCEnd[]    = "%** CieBasedABC CSA End ";
    00075 char ICMSEG CieBasedAEnd[]      = "%** CieBasedA CSA End ";
    00076 char ICMSEG RangeABC[]          = "[ 0 1 0 1 0 1 ] ";
    00077 char ICMSEG RangeLMN[]          = "[ 0 2 0 2 0 2 ] ";
    00078 char ICMSEG Identity[]          = "[1 0 0 0 1 0 0 0 1]";
    00079 char ICMSEG RangeABC_Lab[]      = "[0 100 -128 127 -128 127]";
    00080
    00081 /********** This PostScript code clips incoming value between 0.0 and 1.0
    00082    Use:   x <clip>   --   <clipped x>                                   */
    00083 char ICMSEG Clip01[]            = "dup 1.0 ge{pop 1.0}{dup 0.0 lt{pop 0.0}if}ifelse " ;
    00084 char ICMSEG DecodeA3[]          = "256 div exp ";
    00085 char ICMSEG DecodeA3Rev[]       = "256 div 1.0 exch div exp ";
    00086 char ICMSEG DecodeABCArray[]    = "DecodeABC_";
    00087 char ICMSEG InputArray[]        = "Inp_";
    00088 char ICMSEG OutputArray[]       = "Out_";
    00089 char ICMSEG PreViewInArray[]    = "IPV_";
    00090 char ICMSEG PreViewOutArray[]   = "OPV_";
    00091
    00092 char ICMSEG AdobeCSA[] = "[ /CIEBasedABC << /DecodeLMN [\n\
    00093 {dup 0.03928 le {12.92321 div}{0.055 add 1.055 div 2.4 exp}ifelse} bind dup dup ]\n\
    00094 /MatrixLMN [0.412457 0.212673 0.019334 0.357576 0.715152 0.119192 0.180437 0.072175 0.950301]\n\
    00095 /WhitePoint [ 0.9505 1 1.0890 ] >> ]";
    00096
    00097 char ICMSEG AdobeCRD[] = " /RangePQR [ -0.5 2 -0.5 2 -0.5 2 ]\n\
    00098 /MatrixPQR [0.8951 -0.7502  0.0389 0.2664  1.7135 -0.0685 -0.1614  0.0367  1.0296]\n\
    00099 /TransformPQR [{exch pop exch 3 get mul exch pop exch 3 get div} bind\n\
    00100 {exch pop exch 4 get mul exch pop exch 4 get div} bind\n\
    00101 {exch pop exch 5 get mul exch pop exch 5 get div} bind]\n\
    00102 /MatrixLMN [3.240449 -0.969265  0.055643 -1.537136  1.876011 -0.204026 -0.498531  0.041556  1.057229]\n\
    00103 /EncodeABC [{dup 0.00304 le {12.92321 mul}{1 2.4 div exp 1.055 mul 0.055 sub}ifelse} bind dup dup]\n\
    00104 /WhitePoint[0.9505 1 1.0890] >>";
    00105
    00106 // This PostScript segment takes value in range from 0.0 to 1.0 and
    00107 //  interpolates the result using array supplied.
    00108 //   x [array]  -- <interpolated value>
    00109
    00110 char ICMSEG IndexArray16b[]     = \
    00111 " dup length 1 sub 3 -1 roll mul dup dup floor cvi \
    00112 exch ceiling cvi 3 index exch get 32768 add 4 -1 roll 3 -1 roll get 32768 add \
    00113 dup 3 1 roll sub 3 -1 roll dup floor cvi sub mul add ";
    00114
    00115 char ICMSEG IndexArray[]        = \
    00116 " dup length 1 sub 3 -1 roll mul dup dup floor cvi \
    00117 exch ceiling cvi 3 index exch get 4 -1 roll 3 -1 roll get \
    00118 dup 3 1 roll sub 3 -1 roll dup floor cvi sub mul add ";
    00119
    00120 char ICMSEG TestingDEFG[]       = \
    00121 "/SupportDEFG? {/CIEBasedDEFG /ColorSpaceFamily resourcestatus { pop pop languagelevel 3 ge}{false} ifelse} def";
    00122
    00123 char ICMSEG SupportDEFG_S[]     = "SupportDEFG? { ";
    00124 char ICMSEG NotSupportDEFG_S[]  = "SupportDEFG? not { ";
    00125 char ICMSEG SupportDEFG_E[]     = "}if ";
    00126
    00127 char ICMSEG StartClip[]         = "dup 1.0 le{dup 0.0 ge{" ;
    00128 char ICMSEG EndClip[]           = "}if}if " ;
    00129
    00130 char ICMSEG Scale8[]            = "255 div " ;
    00131 char ICMSEG Scale16[]           = "65535 div " ;
    00132 char ICMSEG Scale16XYZ[]        = "32768 div " ;
    00133 char ICMSEG TFunction8[]        = "exch 255 mul round cvi get 255 div " ;
    00134 char ICMSEG TFunction8XYZ[]     = "exch 255 mul round cvi get 128 div " ;
    00135 char ICMSEG MatrixABCLab[]      = "[1 1 1 1 0 0 0 0 -1]" ;
    00136 char ICMSEG DecodeABCLab1[]     = "[{16 add 116 div} bind {500 div} bind {200 div} bind]";
    00137 char ICMSEG DecodeALab[]        = " 50 mul 16 add 116 div ";
    00138 char ICMSEG DecodeLMNLab[]      = \
    00139 "dup 0.206897 ge{dup dup mul mul}{0.137931 sub 0.128419 mul} ifelse ";
    00140
    00141 char ICMSEG RangeLMNLab[]       = "[0 1 0 1 0 1]" ;
    00142 char ICMSEG EncodeLMNLab[]      = "\
    00143 dup 0.008856 le{7.787 mul 0.13793 add}{0.3333 exp}ifelse " ;
    00144
    00145 char ICMSEG MatrixABCLabCRD[]   = "[0 500 0 116 -500 200 0 0 -200]" ;
    00146 char ICMSEG MatrixABCXYZCRD[]   = "[0 1 0 1 0 0 0 0 1]" ;
    00147 char ICMSEG EncodeABCLab1[]     = "16 sub 100 div " ;
    00148 char ICMSEG EncodeABCLab2[]     = "128 add 255 div " ;
    00149
    00150 char ICMSEG   RangePQR[]          = "[ -0.07 2.2 -0.02 1.4 -0.2 4.8 ]";
    00151 char ICMSEG   MatrixPQR[]         = "[0.8951 -0.7502 0.0389 0.2664 1.7135 -0.0685 -0.1614 0.0367 1.0296]";
    00152
    00153 char *TransformPQR[3]             = {
    00154 "exch pop exch 3 get mul exch pop exch 3 get div ",
    00155 "exch pop exch 4 get mul exch pop exch 4 get div ",
    00156 "exch pop exch 5 get mul exch pop exch 5 get div " };
    00157
    00158 #define SRGBCRC 0x678175D2L
    00159
    00160 #pragma optimize("",off)
    00161
    00162 /***************************************************************************
    00163 *                               CreateLutCRD
    00164 *  function:
    00165 *    this is the function which creates the Color Rendering Dictionary (CRD)
    00166 *    from the data supplied in the ColorProfile's LUT8 or LUT16 tag.
    00167 *  prototype:
    00168 *       SINT EXTERN CreateLutCRD(
    00169 *                          CHANDLE      cp,
    00170 *                          SINT         Index,
    00171 *                          MEMPTR       lpMem,
    00172 *                          BOOL         AllowBinary)
    00173 *  parameters:
    00174 *       cp          --  Color Profile handle
    00175 *       Index       --  Index of the tag
    00176 *       lpMem       --  Pointer to the memory block
    00177 *       AllowBinary --  1: binary CRD allowed,  0: only ascii CRD allowed.
    00178 *
    00179 *  returns:
    00180 *       SINT        --  !=0 if the function was successful,
    00181 *                         0 otherwise.
    00182 *                       Returns number of bytes required/transferred
    00183 ***************************************************************************/
    00184
    00185 SINT EXTERN
    00186 CreateLutCRD (CHANDLE cp, SINT Index, MEMPTR lpMem, DWORD InputIntent, BOOL AllowBinary)
    00187 {
    00188     SINT nInputCh, nOutputCh, nGrids;
    00189     SINT nInputTable, nOutputTable, nNumbers;
    00190     CSIG Tag, PCS;
    00191     CSIG IntentSig;
    00192
    00193     SINT Ret;
    00194     SINT i, j;
    00195     MEMPTR lpTable;
    00196
    00197     SFLOAT IlluminantWP[3];
    00198     SFLOAT MediaWP[3];
    00199     MEMPTR Buff = NULL;
    00200     SINT MemSize = 0;
    00201     MEMPTR lpOldMem = lpMem;
    00202     char PublicArrayName[TempBfSize];
    00203     HGLOBAL hMem;
    00204     MEMPTR lpLineStart;
    00205  // Check if we can generate the CRD
    00206     if (!GetCPTagSig (cp, Index, (LPCSIG) & IntentSig) ||
    00207         !GetCPElementType (cp, Index, (LPCSIG) & Tag) ||
    00208         ((Tag != icSigLut8Type) && (Tag != icSigLut16Type)) ||
    00209         !GetCPConnSpace (cp, (LPCSIG) & PCS) ||
    00210         !GetCPElementSize (cp, Index, (LPSINT) & MemSize) ||
    00211         !MemAlloc (MemSize, (HGLOBAL FAR *)&hMem, (LPMEMPTR) & Buff) ||
    00212         !GetCPElement (cp, Index, Buff, MemSize))
    00213     {
    00214         if (NULL != Buff)
    00215         {
    00216             MemFree (hMem);
    00217         }
    00218         return (0);
    00219     }
    00220     GetCLUTinfo(Tag, Buff, &nInputCh, &nOutputCh,
    00221         &nGrids, &nInputTable, &nOutputTable, &i);
    00222  // Level 2 printers support only tri-component CIEBasedABC input,
    00223  // but can have either 3 or 4 output channels.
    00224     if (((nOutputCh != 3) &&
    00225          (nOutputCh != 4)) ||
    00226         (nInputCh != 3))
    00227     {
    00228         SetCPLastError (CP_POSTSCRIPT_ERR);
    00229         MemFree (hMem);
    00230         return (0);
    00231     }
    00232     Ret = nInputCh * nInputTable * 6 +
    00233         nOutputCh * nOutputTable * 6 +  // Number of INT bytes
    00234         nOutputCh * nGrids * nGrids * nGrids * 2 +  // LUT HEX bytes
    00235         nInputCh * (lstrlen (IndexArray) +
    00236                     lstrlen (StartClip) +
    00237                     lstrlen (EndClip)) +
    00238         nOutputCh * (lstrlen (IndexArray) +
    00239                      lstrlen (StartClip) +
    00240                      lstrlen (EndClip)) +
    00241         2048;                           // + other PS stuff
    00242
    00243     if (lpMem == NULL)                  // This is a size request
    00244     {
    00245         MemFree (hMem);
    00246         return (Ret);
    00247     }
    00248 //  Get all necessary params from the header
    00249 //  GetCPRenderIntent (cp, (LPCSIG) & Intent);  // Get Intent
    00250     GetCPWhitePoint (cp, (LPSFLOAT) & IlluminantWP);          // .. Illuminant
    00251
    00252  // Support absolute whitePoint
    00253     if (InputIntent == icAbsoluteColorimetric)
    00254     {
    00255         if (!GetCPMediaWhitePoint (cp, (LPSFLOAT) & MediaWP)) // .. Media WhitePoint
    00256         {
    00257             MediaWP[0] = IlluminantWP[0];
    00258             MediaWP[1] = IlluminantWP[1];
    00259             MediaWP[2] = IlluminantWP[2];
    00260         }
    00261     }
    00262
    00263 //******** Define golbal array used in EncodeABC and RenderTaber
    00264     GetPublicArrayName (cp, IntentSig, PublicArrayName);
    00265     lpMem += WriteNewLineObject (lpMem, CRDBegin);
    00266
    00267     lpMem += EnableGlobalDict(lpMem);
    00268     lpMem += BeginGlobalDict(lpMem);
    00269
    00270     lpMem += CreateInputArray (lpMem, nInputCh, nInputTable,
    00271              (MEMPTR) PublicArrayName, Tag, Buff, AllowBinary, NULL);
    00272
    00273     i = nInputTable * nInputCh +
    00274         nGrids * nGrids * nGrids * nOutputCh;
    00275     lpMem += CreateOutputArray (lpMem, nOutputCh, nOutputTable, i,
    00276              (MEMPTR) PublicArrayName, Tag, Buff, AllowBinary, NULL);
    00277
    00278     lpMem += EndGlobalDict(lpMem);
    00279
    00280 //************* Start writing  CRD  ****************************
    00281     lpMem += WriteNewLineObject (lpMem, BeginDict);    // Begin dictionary
    00282     lpMem += WriteObject (lpMem, DictType); // Dictionary type
    00283
    00284     lpMem += WriteNewLineObject (lpMem, IntentType); // RenderingIntent
    00285     switch (InputIntent)
    00286     {
    00287         case icPerceptual:
    00288             lpMem += WriteObject (lpMem, IntentPer);
    00289             break;
    00290
    00291         case icSaturation:
    00292             lpMem += WriteObject (lpMem, IntentSat);
    00293             break;
    00294
    00295         case icRelativeColorimetric:
    00296             lpMem += WriteObject (lpMem, IntentRCol);
    00297             break;
    00298
    00299         case icAbsoluteColorimetric:
    00300             lpMem += WriteObject (lpMem, IntentACol);
    00301             break;
    00302     }
    00303
    00304  //********** Send Black/White Point.
    00305     lpMem += SendCRDBWPoint(lpMem, IlluminantWP);
    00306
    00307  //********** Send PQR - used for Absolute Colorimetric *****
    00308     lpMem += SendCRDPQR(lpMem, InputIntent, IlluminantWP);
    00309
    00310  //********** Send LMN - For Absolute Colorimetric use WhitePoint's XYZs
    00311     lpMem += SendCRDLMN(lpMem, InputIntent, IlluminantWP, MediaWP, PCS);
    00312
    00313  // ******** Create MatrixABC and  EncodeABC  stuff
    00314     lpMem += SendCRDABC(lpMem, PublicArrayName,
    00315         PCS, nInputCh, Buff, NULL, Tag, AllowBinary);
    00316
    00317  //********** /RenderTable
    00318     lpMem += WriteNewLineObject (lpMem, RenderTableTag);
    00319     lpMem += WriteObject (lpMem, BeginArray);
    00320
    00321     lpMem += WriteInt (lpMem, nGrids);  // Send down Na
    00322     lpMem += WriteInt (lpMem, nGrids);  // Send down Nb
    00323     lpMem += WriteInt (lpMem, nGrids);  // Send down Nc
    00324
    00325     lpLineStart = lpMem;
    00326     lpMem += WriteNewLineObject (lpMem, BeginArray);
    00327     nNumbers = nGrids * nGrids * nOutputCh;
    00328     for (i = 0; i < nGrids; i++)        // Na strings should be sent
    00329     {
    00330         lpMem += WriteObject (lpMem, NewLine);
    00331         lpLineStart = lpMem;
    00332         if (Tag == icSigLut8Type)
    00333         {
    00334             lpTable = (MEMPTR) (((lpcpLut8Type) Buff)->lut.data) +
    00335                 nInputTable * nInputCh +
    00336                 nNumbers * i;
    00337         } else
    00338         {
    00339             lpTable = (MEMPTR) (((lpcpLut16Type) Buff)->lut.data) +
    00340                 2 * nInputTable * nInputCh +
    00341                 2 * nNumbers * i;
    00342         }
    00343         if (!AllowBinary)               // Output ASCII CRD
    00344         {
    00345             lpMem += WriteObject (lpMem, BeginString);
    00346             if (Tag == icSigLut8Type)
    00347                 lpMem += WriteHexBuffer (lpMem, lpTable, lpLineStart, nNumbers);
    00348             else
    00349             {
    00350                 for (j = 0; j < nNumbers; j++)
    00351                 {
    00352                     lpMem += WriteHex (lpMem, ui16toSINT (lpTable) / 256);
    00353                     lpTable += sizeof (icUInt16Number);
    00354                     if (((SINT) (lpMem - lpLineStart)) > MAX_LINELENG)
    00355                     {
    00356                         lpLineStart = lpMem;
    00357                         lpMem += WriteObject (lpMem, NewLine);
    00358                     }
    00359                 }
    00360             }
    00361             lpMem += WriteObject (lpMem, EndString);
    00362         } else
    00363         {                               // Output BINARY CRD
    00364             lpMem += WriteStringToken (lpMem, 143, nNumbers);
    00365             if (Tag == icSigLut8Type)
    00366                 lpMem += WriteByteString (lpMem, lpTable, nNumbers);
    00367             else
    00368                 lpMem += WriteInt2ByteString (lpMem, lpTable, nNumbers);
    00369         }
    00370     }
    00371
    00372     lpMem += WriteObject (lpMem, EndArray); // End array
    00373     lpMem += WriteInt (lpMem, nOutputCh);   // Send down m
    00374
    00375  //********** Send Output Table.
    00376     lpMem += SendCRDOutputTable(lpMem, PublicArrayName,
    00377         nOutputCh, Tag, FALSE, AllowBinary);
    00378
    00379     lpMem += WriteObject (lpMem, EndArray); // End array
    00380     lpMem += WriteObject (lpMem, EndDict);  // End dictionary definition
    00381
    00382     lpMem += WriteNewLineObject (lpMem, CRDEnd);
    00383
    00384 // Testing Convert binary to ascii
    00385 //    i = ConvertBinaryData2Ascii(lpOldMem, (SINT)(lpMem - lpOldMem), Ret);
    00386 //    lpMem = lpOldMem + i;
    00387 // Testing Convert binary to ascii
    00388
    00389     MemFree (hMem);
    00390     return ((SINT) ((unsigned long) (lpMem - lpOldMem)));
    00391 }
    00392 /***************************************************************************
    00393 *                               GetRevCurve
    00394 *  function:
    00395 *  prototype:
    00396 *       BOOL  GetRevCurve(
    00397 *                          MEMPTR       Buff,
    00398 *                          MEMPTR       lpRevCurve)
    00399 *  parameters:
    00400 *       Buff        --
    00401 *       lpRevCurve  --
    00402 *  returns:
    00403 *       BOOL        --  TRUE:  successful,
    00404 *                       FALSE: otherwise.
    00405 ***************************************************************************/
    00406
    00407 BOOL
    00408 GetRevCurve (MEMPTR lpBuff, MEMPTR lpCurve, MEMPTR lpRevCurve)
    00409 {
    00410     SINT i, j, nCount;
    00411     MEMPTR lpTable;
    00412     PUSHORT lpInput, lpOutput;
    00413     SFLOAT fTemp;
    00414     SINT iBegin, iEnd, iTemp;
    00415     nCount = ui32toSINT (((lpcpCurveType) lpBuff)->curve.count);
    00416     lpTable = (MEMPTR) (((lpcpCurveType) lpBuff)->curve.data);
    00417     lpOutput = (PUSHORT) lpRevCurve;
    00418     lpInput = (PUSHORT) lpCurve;
    00419
    00420     for (i = 0; i < nCount; i++)
    00421     {
    00422         lpInput[i] = (USHORT) (ui16toSINT (lpTable));
    00423         lpTable += sizeof (icUInt16Number);
    00424     }
    00425
    00426     j = nCount * REVCURVE_RATIO;
    00427     for (i = 0; i < j; i++)
    00428     {
    00429         fTemp = (SFLOAT) i *65535 / (j - 1);
    00430         lpOutput[i] = (fTemp < 65535) ? (USHORT) fTemp : (USHORT) 65535;
    00431     }
    00432
    00433     for (i = 0; i < j; i++)
    00434     {
    00435         iBegin = 0;
    00436         iEnd = nCount - 1;
    00437         for (;;)
    00438         {
    00439             if ((iEnd - iBegin) <= 1)
    00440                 break;
    00441             iTemp = (iEnd + iBegin) / 2;
    00442             if (lpOutput[i] < lpInput[iTemp])
    00443                 iEnd = iTemp;
    00444             else
    00445                 iBegin = iTemp;
    00446         }
    00447         if (lpOutput[i] <= lpInput[iBegin])
    00448             fTemp = (SFLOAT) iBegin;
    00449         else if (lpOutput[i] >= lpInput[iEnd])
    00450             fTemp = (SFLOAT) iEnd;
    00451         else
    00452         {
    00453             fTemp = ((SFLOAT) (lpInput[iEnd] - lpOutput[i])) /
    00454                 (lpOutput[i] - lpInput[iBegin]);
    00455             fTemp = (iBegin * fTemp + iEnd) / (fTemp + 1);
    00456         }
    00457         fTemp = (fTemp / (nCount - 1)) * 65535;
    00458         lpOutput[i] = (fTemp < 65535) ? (USHORT) fTemp : (USHORT) 65535;
    00459     }
    00460
    00461     return TRUE;
    00462 }
    00463 /***************************************************************************
    00464 *                               CreateMonoCRD
    00465 *  function:
    00466 *    this is the function which creates the Color Rendering Dictionary (CRD)
    00467 *    from the data supplied in the GrayTRC tag.
    00468 *  prototype:
    00469 *       BOOL EXTERN CreateMonoCRD(
    00470 *                          CHANDLE      cp,
    00471 *                          SINT         Index,
    00472 *                          MEMPTR       lpMem)
    00473 *  parameters:
    00474 *       cp          --  Color Profile handle
    00475 *       Index       --  Index of the tag
    00476 *       lpMem       --  Pointer to the memory block
    00477 *  returns:
    00478 *       SINT        --  !=0 if the function was successful,
    00479 *                         0 otherwise.
    00480 *                       Returns number of bytes required/transferred
    00481 ***************************************************************************/
    00482 //  According to the spec this tag-based function only converts from
    00483 //  Device to PCS, so we need to create an inverse function to perform
    00484 //  PCS->device conversion. By definition the CRD is only
    00485 //  for XYZ->DeviceRGB/CMYK conversion.
    00486 SINT EXTERN
    00487 CreateMonoCRD (CHANDLE cp, SINT Index, MEMPTR lpMem, DWORD InputIntent)
    00488 {
    00489     SINT nCount;
    00490     CSIG Tag, PCS;
    00491
    00492     MEMPTR Buff = NULL;
    00493     SINT MemSize = 0;
    00494     MEMPTR lpOldMem = lpMem;
    00495     MEMPTR lpCurve, lpRevCurve;
    00496     HGLOBAL hRevCurve;
    00497     SINT Ret = 0;
    00498     HGLOBAL hMem;
    00499     SINT i;
    00500     MEMPTR lpTable;
    00501     SFLOAT IlluminantWP[3];
    00502     SFLOAT MediaWP[3];
    00503     MEMPTR lpLineStart;
    00504  // Check if we can generate the CRD
    00505     if (!GetCPElementType (cp, Index, (LPCSIG) & Tag) ||
    00506         (Tag != icSigCurveType) ||
    00507         !GetCPConnSpace (cp, (LPCSIG) & PCS) ||
    00508         !GetCPElementSize (cp, Index, (LPSINT) & MemSize) ||
    00509         !MemAlloc (MemSize, (HGLOBAL FAR *)&hMem, (LPMEMPTR) & Buff) ||
    00510         !GetCPElement (cp, Index, Buff, MemSize))
    00511     {
    00512         if (NULL != Buff)
    00513         {
    00514             MemFree (hMem);
    00515         }
    00516         return (0);
    00517     }
    00518     nCount = ui32toSINT (((lpcpCurveType) Buff)->curve.count);
    00519
    00520  // Estimate the memory size required to hold CRD
    00521  // SRGB98
    00522     Ret = nCount * 6 * REVCURVE_RATIO + // Number of INT elements
    00523         2048;                           // + other PS stuff
    00524     if (lpMem == NULL)                  // This is a size request
    00525     {
    00526         MemFree (hMem);
    00527         return (Ret);
    00528     }
    00529     if (!MemAlloc (nCount * 2 * (REVCURVE_RATIO + 1),
    00530                    (HGLOBAL FAR *) &hRevCurve, (LPMEMPTR) & lpRevCurve))
    00531     {
    00532         MemFree (hMem);
    00533         return (FALSE);
    00534     }
    00535     lpCurve = lpRevCurve + 2 * REVCURVE_RATIO * nCount;
    00536     GetRevCurve (Buff, lpCurve, lpRevCurve);
    00537
    00538  //   GetCPCMMType (cp, (LPCSIG) & Intent);   // Get Intent
    00539     GetCPWhitePoint (cp, (LPSFLOAT) & IlluminantWP);          // .. Illuminant
    00540
    00541  // Support absolute whitePoint
    00542     if (InputIntent == icAbsoluteColorimetric)
    00543     {
    00544         if (!GetCPMediaWhitePoint (cp, (LPSFLOAT) & MediaWP)) // .. Media WhitePoint
    00545         {
    00546             MediaWP[0] = IlluminantWP[0];
    00547             MediaWP[1] = IlluminantWP[1];
    00548             MediaWP[2] = IlluminantWP[2];
    00549         }
    00550     }
    00551
    00552 //************* Start writing  CRD  ****************************
    00553     lpMem += WriteNewLineObject (lpMem, BeginDict);    // Begin dictionary
    00554     lpMem += WriteObject (lpMem, DictType); // Dictionary type
    00555
    00556     lpMem += WriteNewLineObject (lpMem, IntentType); // RenderingIntent
    00557     switch (InputIntent)
    00558     {
    00559         case icPerceptual:
    00560             lpMem += WriteObject (lpMem, IntentPer);
    00561             break;
    00562
    00563         case icSaturation:
    00564             lpMem += WriteObject (lpMem, IntentSat);
    00565             break;
    00566
    00567         case icRelativeColorimetric:
    00568             lpMem += WriteObject (lpMem, IntentRCol);
    00569             break;
    00570
    00571         case icAbsoluteColorimetric:
    00572             lpMem += WriteObject (lpMem, IntentACol);
    00573             break;
    00574     }
    00575
    00576  //********** Send Black/White Point.
    00577     lpMem += SendCRDBWPoint(lpMem, IlluminantWP);
    00578
    00579  //********** /TransformPQR
    00580     lpMem += SendCRDPQR(lpMem, InputIntent, IlluminantWP);
    00581
    00582  //********** /MatrixLMN
    00583     lpMem += SendCRDLMN(lpMem, InputIntent, IlluminantWP, MediaWP, PCS);
    00584
    00585  //********** /MatrixABC
    00586     if (PCS == icSigXYZData)
    00587     {   // Switch ABC to BAC, since we want to output B which is converted from Y.
    00588         lpMem += WriteNewLineObject (lpMem, MatrixABCTag);
    00589         lpMem += WriteObject (lpMem, MatrixABCXYZCRD);
    00590     }
    00591     else if (PCS == icSigLabData)
    00592     {
    00593         lpMem += WriteNewLineObject (lpMem, MatrixABCTag);
    00594         lpMem += WriteObject (lpMem, MatrixABCLabCRD);
    00595     }
    00596  //********** /EncodeABC
    00597     if (nCount != 0)
    00598     {
    00599         lpMem += WriteObject (lpMem, NewLine);
    00600         lpLineStart = lpMem;
    00601         lpMem += WriteObject (lpMem, EncodeABCTag);
    00602         lpMem += WriteObject (lpMem, BeginArray);
    00603         lpMem += WriteObject (lpMem, BeginFunction);
    00604         if (nCount == 1)                // Gamma supplied in ui16 format
    00605         {
    00606             lpTable = (MEMPTR) (((lpcpCurveType) Buff)->curve.data);
    00607             lpMem += WriteInt (lpMem, ui16toSINT (lpTable));
    00608             lpMem += WriteObject (lpMem, DecodeA3Rev);
    00609         } else
    00610         {
    00611             if (PCS == icSigLabData)
    00612             {
    00613                 lpMem += WriteObject (lpMem, EncodeABCLab1);
    00614             }
    00615             lpMem += WriteObject (lpMem, StartClip);
    00616             lpMem += WriteObject (lpMem, BeginArray);
    00617             for (i = 0; i < nCount * REVCURVE_RATIO; i++)
    00618             {
    00619                 lpMem += WriteInt (lpMem, (SINT) (*((PUSHORT) lpRevCurve)));
    00620                 lpRevCurve += sizeof (icUInt16Number);
    00621                 if (((SINT) (lpMem - lpLineStart)) > MAX_LINELENG)
    00622                 {
    00623                     lpLineStart = lpMem;
    00624                     lpMem += WriteObject (lpMem, NewLine);
    00625                 }
    00626             }
    00627             lpMem += WriteObject (lpMem, EndArray);
    00628             lpLineStart = lpMem;
    00629             lpMem += WriteNewLineObject (lpMem, IndexArray);
    00630             lpMem += WriteObject (lpMem, Scale16);
    00631             lpMem += WriteObject (lpMem, EndClip);
    00632         }
    00633         lpMem += WriteObject (lpMem, EndFunction);
    00634         lpMem += WriteObject (lpMem, DupOp);
    00635         lpMem += WriteObject (lpMem, DupOp);
    00636         lpMem += WriteObject (lpMem, EndArray);
    00637     }
    00638     lpMem += WriteObject (lpMem, EndDict);  // End dictionary definition
    00639
    00640     MemFree (hRevCurve);
    00641     MemFree (hMem);
    00642     return ((SINT) ((unsigned long) (lpMem - lpOldMem)));
    00643 }
    00644
    00645 // SRGB98 start
    00646 BOOL
    00647 GetTRCElementSize(CHANDLE cp, CSIG icSigXTRCTag, LPSINT pIndex, LPSINT pTRCSize)
    00648 {
    00649     CSIG Tag;
    00650
    00651     if (!GetCPTagIndex (cp, icSigXTRCTag, (LPSINT) pIndex) ||
    00652         !GetCPElementType (cp, *pIndex, (LPCSIG) & Tag) ||
    00653         !(Tag == icSigCurveType) ||
    00654         !GetCPElementSize (cp, *pIndex, (LPSINT) pTRCSize))
    00655     {
    00656         return FALSE;
    00657     }
    00658     return TRUE;
    00659 }
    00660
    00661 BOOL
    00662 DoesTRCAndColorantTagExist (CHANDLE cp)
    00663 {
    00664     if (DoesCPTagExist (cp, icSigRedColorantTag) &&
    00665         DoesCPTagExist (cp, icSigRedTRCTag ) &&
    00666         DoesCPTagExist (cp, icSigGreenColorantTag) &&
    00667         DoesCPTagExist (cp, icSigGreenTRCTag ) &&
    00668         DoesCPTagExist (cp, icSigBlueColorantTag) &&
    00669         DoesCPTagExist (cp, icSigBlueTRCTag ))
    00670     {
    00671         return TRUE;
    00672     }
    00673
    00674     return FALSE;
    00675 }
    00676
    00677 static SINT
    00678 CreateRevArray (CHANDLE cp, MEMPTR lpMem, MEMPTR lpBuff,
    00679                 MEMPTR lpRevCurve, CSIG CPTag, BOOL AllowBinary)
    00680 {
    00681     SINT i, nCount;
    00682     SINT MemSize = 0;
    00683     MEMPTR lpOldMem, lpLineStart;
    00684     MEMPTR lpCurve;
    00685
    00686     lpOldMem = lpMem;
    00687
    00688     lpLineStart = lpMem;
    00689     nCount = ui32toSINT (((lpcpCurveType) lpBuff)->curve.count);
    00690     if (nCount > 1)
    00691     {
    00692         lpMem += WriteNewLineObject (lpMem, Slash);
    00693         lpMem += WriteObject (lpMem, InputArray);
    00694         lpMem += WriteInt (lpMem, (SINT) CPTag);
    00695
    00696         lpCurve = lpRevCurve + 2 * REVCURVE_RATIO * nCount;
    00697         GetRevCurve (lpBuff, lpCurve, lpRevCurve);
    00698
    00699         if (!AllowBinary)           // Output ASCII DATA
    00700         {
    00701             lpMem += WriteObject (lpMem, BeginArray);
    00702             for (i = 0; i < nCount * REVCURVE_RATIO; i++)
    00703             {
    00704                 lpMem += WriteInt (lpMem, (SINT) (*((PUSHORT) lpRevCurve)));
    00705                 lpRevCurve += sizeof (icUInt16Number);
    00706                 if (((SINT) (lpMem - lpLineStart)) > MAX_LINELENG)
    00707                 {
    00708                     lpLineStart = lpMem;
    00709                     lpMem += WriteObject (lpMem, NewLine);
    00710                 }
    00711             }
    00712             lpMem += WriteObject (lpMem, EndArray);
    00713         } else
    00714         {                           // Output BINARY DATA
    00715             lpMem += WriteHNAToken (lpMem, 149, nCount);
    00716             lpMem += WriteIntStringU2S_L (lpMem, lpRevCurve, nCount);
    00717         }
    00718     }
    00719     lpMem += WriteObject (lpMem, DefOp);
    00720     return ((SINT) (lpMem - lpOldMem));
    00721 }
    00722
    00723 static SINT
    00724 SendRevArray (CHANDLE cp, MEMPTR lpMem, MEMPTR lpBuff,
    00725               CSIG CPTag, BOOL AllowBinary)
    00726 {
    00727     SINT nCount;
    00728     MEMPTR lpOldMem;
    00729     MEMPTR lpTable;
    00730
    00731     lpOldMem = lpMem;
    00732     lpMem += WriteObject (lpMem, BeginFunction);
    00733     nCount = ui32toSINT (((lpcpCurveType) lpBuff)->curve.count);
    00734     if (nCount != 0)
    00735     {
    00736         if (nCount == 1)            // Gamma supplied in ui16 format
    00737         {
    00738             lpTable = (MEMPTR) (((lpcpCurveType) lpBuff)->curve.data);
    00739             lpMem += WriteInt (lpMem, ui16toSINT (lpTable));
    00740             lpMem += WriteObject (lpMem, DecodeA3Rev);
    00741         } else
    00742         {
    00743             lpMem += WriteObject (lpMem, StartClip);
    00744             lpMem += WriteObject (lpMem, InputArray);
    00745             lpMem += WriteInt (lpMem, (SINT) CPTag);
    00746
    00747             if (!AllowBinary)       // Output ASCII CS
    00748             {
    00749                 lpMem += WriteObject (lpMem, IndexArray);
    00750             } else
    00751             {                       // Output BINARY CS
    00752                 lpMem += WriteObject (lpMem, IndexArray16b);
    00753             }
    00754             lpMem += WriteObject (lpMem, Scale16);
    00755             lpMem += WriteObject (lpMem, EndClip);
    00756         }
    00757     }
    00758     lpMem += WriteObject (lpMem, EndFunction);
    00759     return ((SINT) (lpMem - lpOldMem));
    00760 }
    00761
    00762 SINT
    00763 CreateColorantArray(CHANDLE cp, double FAR *lpArray, CSIG CPTag)
    00764 {
    00765     SINT i, Index;
    00766     MEMPTR lpTable;
    00767     MEMPTR Buff = NULL;
    00768     SINT MemSize = 0;
    00769     HGLOBAL hBuff;
    00770
    00771     if (GetCPTagIndex (cp, CPTag, (LPSINT) & Index) &&
    00772         GetCPElementSize (cp, Index, (LPSINT) & MemSize) &&
    00773         MemAlloc (MemSize, (HGLOBAL FAR *)&hBuff, (LPMEMPTR) & Buff) &&
    00774         GetCPElement (cp, Index, Buff, MemSize))
    00775     {
    00776         lpTable = (MEMPTR) & (((lpcpXYZType) Buff)->data);
    00777         for (i = 0; i < 3; i++)
    00778         {
    00779             *lpArray++ = (SFLOAT)si16f16toSFLOAT (lpTable);
    00780             lpTable += sizeof (icS15Fixed16Number);
    00781         }
    00782         MemFree (hBuff);
    00783     }
    00784     return ( TRUE );
    00785 }
    00786
    00787
    00788 /***************************************************************************
    00789 *                           IsSRGB
    00790 *  function: check if the profile is sRGB
    00791 *
    00792 *  parameters:
    00793 *       cp          --  Color Profile handle
    00794 *
    00795 *  returns:
    00796 *       BOOL        --  TRUE if the profile is sRGB
    00797 *                       FALSE otherwise.
    00798 ***************************************************************************/
    00799 BOOL FAR IsSRGB (CHANDLE cp)
    00800 {
    00801     BOOL    match = FALSE;
    00802     SINT    RedTRCIndex, GreenTRCIndex, BlueTRCIndex, RedCIndex, GreenCIndex, BlueCIndex;
    00803     SINT    MemSize;
    00804     SINT    RedTRCSize=0, GreenTRCSize=0, BlueTRCSize=0, RedCSize=0, GreenCSize=0, BlueCSize=0;
    00805     HGLOBAL hMem;
    00806     MEMPTR  lpRed = NULL,lpGreen, lpBlue, lpRedC, lpGreenC, lpBlueC;
    00807     DWORD   crc;
    00808
    00809     if (GetCPTagIndex (cp, icSigRedTRCTag, &RedTRCIndex) &&
    00810         GetCPElementSize (cp, RedTRCIndex, &RedTRCSize)  &&
    00811
    00812         GetCPTagIndex (cp, icSigGreenTRCTag, &GreenTRCIndex) &&
    00813         GetCPElementSize (cp, GreenTRCIndex, &GreenTRCSize)  &&
    00814
    00815         GetCPTagIndex (cp, icSigBlueTRCTag, &BlueTRCIndex) &&
    00816         GetCPElementSize (cp, BlueTRCIndex, &BlueTRCSize) &&
    00817
    00818         GetCPTagIndex (cp, icSigRedColorantTag, &RedCIndex) &&
    00819         GetCPElementSize (cp, RedCIndex, &RedCSize)  &&
    00820
    00821         GetCPTagIndex (cp, icSigGreenColorantTag, &GreenCIndex) &&
    00822         GetCPElementSize (cp, GreenCIndex, &GreenCSize)  &&
    00823
    00824         GetCPTagIndex (cp, icSigBlueColorantTag, &BlueCIndex) &&
    00825         GetCPElementSize (cp, BlueCIndex, &BlueCSize) )
    00826     {
    00827         MemSize = RedTRCSize + GreenTRCSize + BlueTRCSize + RedCSize + GreenCSize + BlueCSize;
    00828
    00829         if ( (MemSize == 6240) && // #bytes in sRGBColorTags
    00830              MemAlloc (MemSize, (HGLOBAL FAR *)&hMem, (LPMEMPTR)&lpRed) )
    00831         {
    00832             lpGreen = lpRed + RedTRCSize;
    00833             lpBlue = lpGreen + GreenTRCSize;
    00834             lpRedC = lpBlue + BlueTRCSize;
    00835             lpGreenC = lpRedC + RedCSize;
    00836             lpBlueC = lpGreenC + GreenCSize;
    00837
    00838             if (GetCPElement (cp, RedTRCIndex, lpRed, RedTRCSize) &&
    00839                 GetCPElement (cp, GreenTRCIndex, lpGreen, GreenTRCSize ) &&
    00840                 GetCPElement (cp, BlueTRCIndex, lpBlue, BlueTRCSize ) &&
    00841                 GetCPElement (cp, RedCIndex, lpRedC, RedCSize) &&
    00842                 GetCPElement (cp, GreenCIndex, lpGreenC, GreenCSize ) &&
    00843                 GetCPElement (cp, BlueCIndex, lpBlueC, BlueCSize ))
    00844             {
    00845                 crc = crc32( lpRed, 6240 );
    00846                 match = (crc == SRGBCRC);
    00847             }
    00848             MemFree(hMem);
    00849         }
    00850     }
    00851     return (match);
    00852 }
    00853
    00854 /***************************************************************************
    00855 *                           CreateMatrixCRD
    00856 *  function:
    00857 *    this is the function which creates the Color Rendering Dictionary (CRD)
    00858 *    from the data supplied in the redTRC, greenTRC, blueTRA, redColorant,
    00859 *    greenColorant and BlueColorant tags
    00860 *  prototype:
    00861 *       BOOL EXTERN CreateMatrixCRD(
    00862 *                          CHANDLE      cp,
    00863 *                          MEMPTR       lpMem,
    00864 *                          BOOL         AllowBinary)
    00865 *  parameters:
    00866 *       cp          --  Color Profile handle
    00867 *       lpMem       --  Pointer to the memory block
    00868 *       AllowBinary --
    00869 *  returns:
    00870 *       SINT        --  !=0 if the function was successful,
    00871 *                         0 otherwise.
    00872 *                       Returns number of bytes required/transferred
    00873 ***************************************************************************/
    00874 // With matrix/TRC model, only the CIEXYZ encoding of the PCS can be used.
    00875 // So, we don't need to worry about CIELAB.
    00876 SINT EXTERN
    00877 CreateMatrixCRD (CHANDLE cp, MEMPTR lpMem, DWORD InputIntent, BOOL AllowBinary)
    00878 {
    00879     SINT RedTRCIndex, GreenTRCIndex, BlueTRCIndex;
    00880     SINT i, MemSize;
    00881     SINT nRedCount, nGreenCount, nBlueCount;
    00882     MEMPTR lpRed = NULL,lpGreen, lpBlue;
    00883     SINT RedTRCSize = 0, GreenTRCSize = 0, BlueTRCSize = 0;
    00884     MEMPTR lpOldMem = lpMem;
    00885     MEMPTR lpRevCurve;
    00886     HGLOBAL hRevCurve;
    00887     SINT Ret = 0;
    00888     HGLOBAL hMem;
    00889     SFLOAT IlluminantWP[3];
    00890     double Colorant[9];
    00891     double RevColorant[9];
    00892
    00893  // Check if we can generate the CRD
    00894     if (!GetTRCElementSize(cp, icSigRedTRCTag, &RedTRCIndex, &RedTRCSize) ||
    00895         !GetTRCElementSize(cp, icSigGreenTRCTag, &GreenTRCIndex, &GreenTRCSize) ||
    00896         !GetTRCElementSize(cp, icSigBlueTRCTag, &BlueTRCIndex, &BlueTRCSize))
    00897     {
    00898         return 0;
    00899     }
    00900     MemSize = RedTRCSize + GreenTRCSize + BlueTRCSize;
    00901     if (!MemAlloc (MemSize, (HGLOBAL FAR *)&hMem, (LPMEMPTR) & lpRed))
    00902         return 0;
    00903
    00904     lpGreen = lpRed + RedTRCSize;
    00905     lpBlue = lpGreen + GreenTRCSize;
    00906     if (!GetCPElement (cp, RedTRCIndex, lpRed, RedTRCSize) ||
    00907         !GetCPElement (cp, GreenTRCIndex, lpGreen, GreenTRCSize ) ||
    00908         !GetCPElement (cp, BlueTRCIndex, lpBlue, BlueTRCSize ))
    00909     {
    00910         MemFree (hMem);
    00911         return (0);
    00912     }
    00913     nRedCount = ui32toSINT (((lpcpCurveType) lpRed)->curve.count);
    00914     nGreenCount = ui32toSINT (((lpcpCurveType) lpGreen)->curve.count);
    00915     nBlueCount = ui32toSINT (((lpcpCurveType) lpBlue)->curve.count);
    00916
    00917  // Estimate the memory size required to hold CRD
    00918     Ret = (nRedCount + nGreenCount + nBlueCount) * 6 * REVCURVE_RATIO +
    00919         2048;                // Number of INT elements + other PS stuff
    00920     if (lpMem == NULL)       // This is a size request
    00921     {
    00922         MemFree (hMem);
    00923         return (Ret);
    00924     }
    00925
    00926     if (!MemAlloc (nRedCount * 2 * (REVCURVE_RATIO + 1),
    00927                   (HGLOBAL FAR *) &hRevCurve, (LPMEMPTR) & lpRevCurve))
    00928     {
    00929         MemFree (hMem);
    00930         return (0);
    00931     }
    00932
    00933     if (IsSRGB(cp))
    00934     {
    00935        lpMem += WriteNewLineObject (lpMem, CRDBegin);
    00936        lpMem += WriteNewLineObject (lpMem, BeginDict);    // Begin dictionary
    00937        lpMem += WriteObject (lpMem, DictType); // Dictionary type
    00938        lpMem += WriteNewLineObject (lpMem, IntentType); // RenderingIntent
    00939        switch (InputIntent)
    00940        {
    00941            case icPerceptual:
    00942                lpMem += WriteObject (lpMem, IntentPer);
    00943                break;
    00944
    00945            case icSaturation:
    00946                lpMem += WriteObject (lpMem, IntentSat);
    00947                break;
    00948
    00949            case icRelativeColorimetric:
    00950                lpMem += WriteObject (lpMem, IntentRCol);
    00951                break;
    00952
    00953            case icAbsoluteColorimetric:
    00954                lpMem += WriteObject (lpMem, IntentACol);
    00955                break;
    00956        }
    00957        lpMem += WriteNewLineObject (lpMem, AdobeCRD);
    00958        lpMem += WriteNewLineObject (lpMem, CRDEnd);
    00959     }
    00960     else
    00961     {
    00962        lpMem += EnableGlobalDict(lpMem);
    00963        lpMem += BeginGlobalDict(lpMem);
    00964
    00965        lpMem += CreateRevArray (cp, lpMem, lpRed, lpRevCurve, icSigRedTRCTag, AllowBinary);
    00966        lpMem += CreateRevArray (cp, lpMem, lpGreen, lpRevCurve, icSigGreenTRCTag, AllowBinary);
    00967        lpMem += CreateRevArray (cp, lpMem, lpBlue, lpRevCurve, icSigBlueTRCTag, AllowBinary);
    00968
    00969        lpMem += EndGlobalDict(lpMem);
    00970
    00971     //   GetCPCMMType (cp, (LPCSIG) & Intent);   // Get Intent
    00972        GetCPWhitePoint (cp, (LPSFLOAT) & IlluminantWP);          // .. Illuminant
    00973
    00974     //************* Start writing  CRD  ****************************
    00975        lpMem += WriteNewLineObject (lpMem, CRDBegin);
    00976
    00977        lpMem += WriteNewLineObject (lpMem, BeginDict);    // Begin dictionary
    00978        lpMem += WriteObject (lpMem, DictType); // Dictionary type
    00979
    00980        lpMem += WriteNewLineObject (lpMem, IntentType); // RenderingIntent
    00981        switch (InputIntent)
    00982        {
    00983            case icPerceptual:
    00984                lpMem += WriteObject (lpMem, IntentPer);
    00985                break;
    00986
    00987            case icSaturation:
    00988                lpMem += WriteObject (lpMem, IntentSat);
    00989                break;
    00990
    00991            case icRelativeColorimetric:
    00992                lpMem += WriteObject (lpMem, IntentRCol);
    00993                break;
    00994
    00995            case icAbsoluteColorimetric:
    00996                lpMem += WriteObject (lpMem, IntentACol);
    00997                break;
    00998        }
    00999
    01000     //********** Send Black/White Point.
    01001        lpMem += SendCRDBWPoint(lpMem, IlluminantWP);
    01002
    01003     //********** /TransformPQR
    01004        lpMem += SendCRDPQR(lpMem, InputIntent, IlluminantWP);
    01005
    01006     //********** /MatrixLMN
    01007        CreateColorantArray(cp, &Colorant[0], icSigRedColorantTag);
    01008        CreateColorantArray(cp, &Colorant[3], icSigGreenColorantTag);
    01009        CreateColorantArray(cp, &Colorant[6], icSigBlueColorantTag);
    01010        InvertMatrix (Colorant, RevColorant);
    01011
    01012        lpMem += WriteNewLineObject (lpMem, MatrixLMNTag);
    01013
    01014        lpMem += WriteObject (lpMem, BeginArray);
    01015        for (i = 0; i < 9; i++)
    01016        {
    01017            lpMem += WriteFloat (lpMem, (SFLOAT)RevColorant[i]);
    01018        }
    01019        lpMem += WriteObject (lpMem, EndArray);
    01020
    01021     //********** /EncodeABC
    01022        lpMem += WriteNewLineObject (lpMem, EncodeABCTag);
    01023        lpMem += WriteObject (lpMem, BeginArray);
    01024
    01025        lpMem += WriteObject (lpMem, NewLine);
    01026        lpMem += SendRevArray (cp, lpMem, lpRed, icSigRedTRCTag, AllowBinary);
    01027        lpMem += WriteObject (lpMem, NewLine);
    01028        lpMem += SendRevArray (cp, lpMem, lpGreen, icSigGreenTRCTag, AllowBinary);
    01029        lpMem += WriteObject (lpMem, NewLine);
    01030        lpMem += SendRevArray (cp, lpMem, lpBlue, icSigBlueTRCTag, AllowBinary);
    01031        lpMem += WriteNewLineObject (lpMem, EndArray);
    01032
    01033        lpMem += WriteObject (lpMem, EndDict);  // End dictionary definition
    01034
    01035        lpMem += WriteNewLineObject (lpMem, CRDEnd);
    01036     }
    01037     MemFree (hRevCurve);
    01038     MemFree (hMem);
    01039     return ((SINT) ((unsigned long) (lpMem - lpOldMem)));
    01040 }
    01041 // SRGB98 End
    01042
    01043 BOOL EXTERN
    01044 GetPS2ColorRenderingDictionary (
    01045                                 CHANDLE cp,
    01046                                 DWORD Intent,
    01047                                 MEMPTR lpMem,
    01048                                 LPDWORD lpcbSize,
    01049                                 BOOL AllowBinary)
    01050 {
    01051     SINT Index;
    01052     SINT Ret, Size;
    01053     CSIG icSigPs2CRDx, icSigBToAx;
    01054
    01055     if (!cp)
    01056         return FALSE;
    01057
    01058     if ((lpMem == NULL) || (*lpcbSize == 0))
    01059     {
    01060         lpMem = NULL;
    01061         *lpcbSize = 0;
    01062     }
    01063     Ret = 0;
    01064     Size = (SINT) * lpcbSize;
    01065
    01066     switch (Intent)
    01067     {
    01068         case icPerceptual:
    01069             icSigPs2CRDx = icSigPs2CRD0Tag;
    01070             icSigBToAx = icSigBToA0Tag;
    01071             break;
    01072
    01073         case icRelativeColorimetric:
    01074             icSigPs2CRDx = icSigPs2CRD1Tag;
    01075             icSigBToAx = icSigBToA1Tag;
    01076             break;
    01077
    01078         case icSaturation:
    01079             icSigPs2CRDx = icSigPs2CRD2Tag;
    01080             icSigBToAx = icSigBToA2Tag;
    01081             break;
    01082
    01083         case icAbsoluteColorimetric:
    01084             icSigPs2CRDx = icSigPs2CRD3Tag;
    01085             icSigBToAx = icSigBToA1Tag;
    01086             break;
    01087
    01088         default:
    01089             *lpcbSize = (DWORD) Ret;
    01090             return (Ret > 0);
    01091     }
    01092
    01093     if (
    01094         (DoesCPTagExist (cp, icSigPs2CRDx) &&
    01095          GetCPTagIndex (cp, icSigPs2CRDx, (LPSINT) & Index) &&
    01096          GetCPElementDataSize (cp, Index, (LPSINT) & Ret) &&
    01097          ((Size == 0) ||
    01098           GetCPElementData (cp, Index, lpMem, Size)) &&
    01099          (Ret = Convert2Ascii (cp, Index, lpMem, Size, Ret, AllowBinary))
    01100         ) ||
    01101         (DoesCPTagExist (cp, icSigBToAx) &&
    01102          GetCPTagIndex (cp, icSigBToAx, (LPSINT) & Index) &&
    01103          (Ret = CreateLutCRD (cp, Index, lpMem, Intent, AllowBinary))
    01104         ) ||
    01105         // SRGB98 Support Windows 98 sRGB icc profile.
    01106         // Create CRD from TRC and Colorant Tags.
    01107         (DoesTRCAndColorantTagExist (cp) &&
    01108          (Ret = CreateMatrixCRD (cp, lpMem, Intent, AllowBinary))
    01109         ) ||
    01110         (DoesCPTagExist (cp, icSigGrayTRCTag) &&
    01111          GetCPTagIndex (cp, icSigGrayTRCTag, (LPSINT) & Index) &&
    01112          (Ret = CreateMonoCRD (cp, Index, lpMem, Intent))
    01113         )
    01114        )
    01115     {
    01116     }
    01117
    01118     *lpcbSize = (DWORD) Ret;
    01119     return (Ret > 0);
    01120 }