test: profcrd.c Source File

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

# profcrd.c

Go to the documentation of this file.

    00001 #include "generic.h"
    00002 #include "icmstr.h"
    00003
    00004 #pragma code_seg(_ICM3SEG)
    00005
    00006 #define MAXCOLOR8  255
    00007
    00008 #pragma optimize("", off)
    00009
    00010 static SINT
    00011 CreateHostInputOutputArray (MEMPTR lpMem, PMEMPTR ppArray,
    00012        SINT numChan, SINT tableSize, SINT Offset, CSIG Tag, MEMPTR Buff);
    00013 static BOOL
    00014 CheckInputOutputTable(LPHOSTCLUT lpHostClut, float far *fTemp, BOOL, BOOL);
    00015 BOOL
    00016 GetHostCSA_Intent (CHANDLE cp, MEMPTR lpBuffer, LPDWORD lpcbSize,
    00017        CSIG Intent, int Type);
    00018 static BOOL
    00019 CheckColorLookupTable(LPHOSTCLUT lpHostClut, float far *fTemp);
    00020 static BOOL
    00021 DoHostConversionCRD (LPHOSTCLUT lpHostCRD, LPHOSTCLUT lpHostCSA,
    00022        float far *Input, float far *Output,
    00023        CSIG ColorSpace, BOOL bCheckOutputTable);
    00024 static BOOL
    00025 DoHostConversionCSA (LPHOSTCLUT lpHostClut, float far *Input, float far *Output);
    00026 static BOOL
    00027 GetCRDInputOutputArraySize(CHANDLE cp, DWORD Intent,
    00028        LPSINT lpInTbSize, LPSINT lpOutTbSize,
    00029        LPCSIG lpIntentTag, LPSINT lpGrids);
    00030 static void
    00031 LabToXYZ(float far *Input, float far *Output, float far *whitePoint);
    00032
    00033 /***************************************************************************
    00034 *                           CreateHostInputOutputArray
    00035 *  function:
    00036 *    this is the function which creates the output array from the data
    00037 *    supplied in the ColorProfile's LUT8 or LUT16 tag.
    00038 *  parameters:
    00039 *    MEMPTR     lpMem        : The buffer to save output array.
    00040 *    LPHOSTCLUT lpHostClut   :
    00041 *    SINT       nOutputCh    : Number of input channel.
    00042 *    SINT       nOutputTable : The size of each input table.
    00043 *    SINT       Offset       : The position of source output data(in icc profile).
    00044 *    CSIG       Tag          : To determin the Output table is 8 or 16 bits.
    00045 *    MEMPTR     Buff         : The buffer that contains source data(copyed from icc profile)
    00046 *
    00047 *  returns:
    00048 *       SINT    Returns number of bytes of Output Array
    00049 *
    00050 ***************************************************************************/
    00051
    00052 static SINT
    00053 CreateHostInputOutputArray (MEMPTR lpMem, PMEMPTR ppArray,
    00054                             SINT numChan, SINT tableSize,
    00055                             SINT Offset, CSIG Tag, MEMPTR Buff)
    00056 {
    00057     SINT    i, j;
    00058     PUSHORT lpMemPtr16;
    00059     MEMPTR  lpMemPtr8;
    00060     MEMPTR  lpTable;
    00061
    00062     if (Tag == icSigLut8Type)
    00063         lpMemPtr8 = lpMem;
    00064     else
    00065         lpMemPtr16 = (PUSHORT)lpMem;
    00066
    00067     for (i = 0; i < numChan; i++)
    00068     {
    00069         if (Tag == icSigLut8Type)
    00070         {
    00071             ppArray[i] = lpMemPtr8;
    00072             lpTable = (MEMPTR) (((lpcpLut8Type) Buff)->lut.data) +
    00073                 Offset +
    00074                 tableSize * i;
    00075             MemCopy(lpMemPtr8, lpTable, tableSize);
    00076                 lpMemPtr8 += tableSize;
    00077         }
    00078         else
    00079         {
    00080             ppArray[i] = (MEMPTR)lpMemPtr16;
    00081             lpTable = (MEMPTR) (((lpcpLut16Type) Buff)->lut.data) +
    00082                 2 * Offset +
    00083                 2 * tableSize * i;
    00084             for (j = 0; j < tableSize; j++)
    00085             {
    00086                 *lpMemPtr16++ = (USHORT) ui16toSINT (lpTable);
    00087                 lpTable += sizeof (icUInt16Number);
    00088             }
    00089         }
    00090     }
    00091     if (Tag == icSigLut8Type)
    00092         return ((SINT) ((MEMPTR)lpMemPtr8 - lpMem));
    00093     else
    00094         return ((SINT) ((MEMPTR)lpMemPtr16 - lpMem));
    00095
    00096 }
    00097
    00098 VOID
    00099 GetCLUTinfo(CSIG LutTag, MEMPTR lpLut, LPSINT nInputCh, LPSINT nOutputCh,
    00100             LPSINT nGrids, LPSINT nInputTable, LPSINT nOutputTable, LPSINT size)
    00101 {
    00102     if (LutTag == icSigLut8Type)
    00103     {
    00104         *nInputCh = ui8toSINT (((lpcpLut8Type) lpLut)->lut.inputChan);
    00105         *nOutputCh = ui8toSINT (((lpcpLut8Type) lpLut)->lut.outputChan);
    00106         *nGrids = ui8toSINT (((lpcpLut8Type) lpLut)->lut.clutPoints);
    00107         *nInputTable = 256L;
    00108         *nOutputTable = 256L;
    00109         *size = 1;  // one byte for each input\output table entry
    00110     } else
    00111     {
    00112         *nInputCh = ui8toSINT (((lpcpLut16Type) lpLut)->lut.inputChan);
    00113         *nOutputCh = ui8toSINT (((lpcpLut16Type) lpLut)->lut.outputChan);
    00114         *nGrids = ui8toSINT (((lpcpLut16Type) lpLut)->lut.clutPoints);
    00115         *nInputTable = ui16toSINT (((lpcpLut16Type) lpLut)->lut.inputEnt);
    00116         *nOutputTable = ui16toSINT (((lpcpLut16Type) lpLut)->lut.outputEnt);
    00117         *size = 2;  // two bytes for each input\output table entry
    00118     }
    00119 }
    00120
    00121 /***************************************************************************
    00122 *                           GetHostCSA
    00123 *  function:
    00124 *    this is the function which creates a Host CSA
    00125 *  parameters:
    00126 *       CHANDLE cp       --  Color Profile handle
    00127 *       MEMPTR lpMem     --  Pointer to the memory block. If this point is NULL,
    00128 *                            require buffer size.
    00129 *       LPDWORD lpcbSize --  Size of the memory block
    00130 *       CSIG InputIntent --
    00131 *       SINT Index       --  to the icc profile tag that contains the data of Intent
    00132 *       int  Type        --  DEF or DEFG
    00133 *  returns:
    00134 *       BOOL        --  TRUE if the function was successful,
    00135 *                       FALSE otherwise.
    00136 ***************************************************************************/
    00137 static BOOL
    00138 GetHostCSA (CHANDLE cp, MEMPTR lpMem, LPDWORD lpcbSize,
    00139             CSIG InputIntent, SINT Index, int Type)
    00140 {
    00141     CSIG    PCS, LutTag;
    00142     CSIG    IntentSig;
    00143     SINT    nInputCh, nOutputCh, nGrids, SecondGrids;
    00144     SINT    nInputTable, nOutputTable, nNumbers;
    00145     SINT    i, j, k;
    00146     MEMPTR  lpTable;
    00147     MEMPTR  lpOldMem = lpMem;
    00148     MEMPTR  lpLut = NULL;
    00149     HGLOBAL hLut = 0;
    00150     SINT    LutSize;
    00151     LPHOSTCLUT lpHostClut;
    00152
    00153     // Check if we can generate the CS.
    00154     // If we cannot find the required tag - we will return false
    00155     if (!GetCPConnSpace (cp, (LPCSIG) & PCS) ||
    00156         (PCS != icSigLabData) && (PCS != icSigXYZData) ||
    00157         !GetCPTagSig (cp, Index, (LPCSIG) & IntentSig))
    00158     {
    00159         return (FALSE);
    00160     }
    00161     if (!GetCPElementType (cp, Index, (LPCSIG) & LutTag) ||
    00162         ((LutTag != icSigLut8Type) && (LutTag != icSigLut16Type)) ||
    00163         !GetCPElementSize (cp, Index, (LPSINT) & LutSize) ||
    00164         !MemAlloc (LutSize, (HGLOBAL FAR *) &hLut, (LPMEMPTR) & lpLut) ||
    00165         !GetCPElement (cp, Index, lpLut, LutSize))
    00166     {
    00167         if (0 != hLut)
    00168         {
    00169             MemFree (hLut);
    00170         }
    00171         return (FALSE);
    00172     }
    00173
    00174     // Estimate the memory size required to hold CS
    00175     GetCLUTinfo(LutTag, lpLut, &nInputCh, &nOutputCh,
    00176                 &nGrids, &nInputTable, &nOutputTable, &i);
    00177
    00178     if (!(nOutputCh == 3) ||
    00179         !((nInputCh == 3) && (Type == TYPE_CIEBASEDDEF)) &&
    00180         !((nInputCh == 4) && (Type == TYPE_CIEBASEDDEFG)))
    00181     {
    00182         SetCPLastError (CP_POSTSCRIPT_ERR);
    00183         MemFree (hLut);
    00184         return (FALSE);
    00185     }
    00186
    00187     // First Pass. This is a size request
    00188     if (lpMem == NULL)
    00189     {
    00190         if (Type == TYPE_CIEBASEDDEFG)
    00191             *lpcbSize = nOutputCh * nGrids * nGrids * nGrids * nGrids;
    00192         else
    00193             *lpcbSize = nOutputCh * nGrids * nGrids * nGrids;
    00194         *lpcbSize = *lpcbSize             +   // size of RenderTable 8-bits only
    00195             nInputCh * nInputTable * i    +   // size of input table 8/16-bits
    00196             nOutputCh * nOutputTable * i  +   // size of output table 8/16-bits
    00197             sizeof(HOSTCLUT) + 1024;          // data structure + extra safe space
    00198         MemFree (hLut);
    00199         return (TRUE);
    00200     }
    00201
    00202     // Second pass. constructure real HostCSA
    00203     lpHostClut = (LPHOSTCLUT)lpMem;
    00204     lpMem += sizeof(HOSTCLUT);
    00205     lpHostClut->size = sizeof(HOSTCLUT);
    00206     lpHostClut->pcs = PCS;
    00207     lpHostClut->intent = InputIntent;
    00208     lpHostClut->lutBits = (LutTag == icSigLut8Type)? 8:16;
    00209
    00210     // Get info about Illuminant White Point from the header
    00211     GetCPWhitePoint (cp, (LPSFLOAT)lpHostClut->whitePoint);          // .. Illuminant
    00212
    00213     lpHostClut->inputChan = (unsigned char)nInputCh;
    00214     lpHostClut->outputChan = (unsigned char)nOutputCh;
    00215     lpHostClut->clutPoints = (unsigned char)nGrids;
    00216     lpHostClut->inputEnt = (USHORT)nInputTable;
    00217     lpHostClut->outputEnt = (USHORT)nOutputTable;
    00218     // Input Array
    00219     lpMem += CreateHostInputOutputArray (lpMem, lpHostClut->inputArray,
    00220              nInputCh, nInputTable, 0, LutTag, lpLut);
    00221
    00222     if (Type == TYPE_CIEBASEDDEFG)
    00223     {
    00224         i = nInputTable * nInputCh +
    00225             nGrids * nGrids * nGrids * nGrids * nOutputCh;
    00226     } else
    00227     {
    00228         i = nInputTable * nInputCh +
    00229             nGrids * nGrids * nGrids * nOutputCh;
    00230     }
    00231     // ourput array
    00232     lpMem += CreateHostInputOutputArray (lpMem, lpHostClut->outputArray,
    00233              nOutputCh, nOutputTable, i, LutTag, lpLut);
    00234  //********** /Table
    00235
    00236     lpHostClut->clut = lpMem;
    00237     nNumbers = nGrids * nGrids * nOutputCh;
    00238     SecondGrids = 1;
    00239     if (Type == TYPE_CIEBASEDDEFG)
    00240     {
    00241         SecondGrids = nGrids;
    00242     }
    00243     for (i = 0; i < nGrids; i++)        // Nh strings should be sent
    00244     {
    00245         for (k = 0; k < SecondGrids; k++)
    00246         {
    00247             if (LutTag == icSigLut8Type)
    00248             {
    00249                 lpTable = (MEMPTR) (((lpcpLut8Type) lpLut)->lut.data) +
    00250                     nInputTable * nInputCh +
    00251                     nNumbers * (i * SecondGrids + k);
    00252             } else
    00253             {
    00254                 lpTable = (MEMPTR) (((lpcpLut16Type) lpLut)->lut.data) +
    00255                     2 * nInputTable * nInputCh +
    00256                     2 * nNumbers * (i * SecondGrids + k);
    00257             }
    00258
    00259             if (LutTag == icSigLut8Type)
    00260             {
    00261                 // Copy 8-bit data.
    00262                 MemCopy(lpMem, lpTable, nNumbers);
    00263                 lpMem += nNumbers;
    00264             }
    00265             else
    00266             {
    00267                 // convert 16 bit integer to right format. then copy only 8 bits.
    00268                 for (j = 0; j < nNumbers; j++)
    00269                 {
    00270                     *lpMem++ = (BYTE)(ui16toSINT (lpTable) / 256);
    00271                     lpTable += sizeof (icUInt16Number);
    00272                 }
    00273             }
    00274         }
    00275     }
    00276
    00277     *lpcbSize = (DWORD) (lpMem - lpOldMem);
    00278
    00279     MemFree (hLut);
    00280     return (TRUE);
    00281 }
    00282
    00283 // BUGBUG   -- MOVE to CSPROF.C
    00284 HGLOBAL GetTRCData(CHANDLE cp,
    00285         LPMEMPTR lpRed,  LPMEMPTR lpGreen,  LPMEMPTR lpBlue,
    00286         LPSINT   lpnRed, LPSINT   lpnGreen, LPSINT   lpnBlue)
    00287 {
    00288     SINT     RedTRCIndex, GreenTRCIndex, BlueTRCIndex;
    00289     SINT     RedTRCSize = 0, GreenTRCSize = 0, BlueTRCSize = 0;
    00290     SINT     MemSize;
    00291     HGLOBAL  hMem;
    00292
    00293  // Check if we can generate the CRD
    00294     if (!GetTRCElementSize(cp, icSigRedTRCTag, &RedTRCIndex, &RedTRCSize) ||
    00295         !GetTRCElementSize(cp, icSigGreenTRCTag, &GreenTRCIndex, &GreenTRCSize) ||
    00296         !GetTRCElementSize(cp, icSigBlueTRCTag, &BlueTRCIndex, &BlueTRCSize))
    00297     {
    00298          return 0;
    00299     }
    00300     MemSize = RedTRCSize + GreenTRCSize + BlueTRCSize;
    00301     if (!MemAlloc (MemSize, (HGLOBAL FAR *)&hMem, (LPMEMPTR) lpRed))
    00302         return 0;
    00303
    00304     *lpGreen = *lpRed + RedTRCSize;
    00305     *lpBlue = *lpGreen + GreenTRCSize;
    00306     if (!GetCPElement (cp, RedTRCIndex, *lpRed, RedTRCSize) ||
    00307         !GetCPElement (cp, GreenTRCIndex, *lpGreen, GreenTRCSize ) ||
    00308         !GetCPElement (cp, BlueTRCIndex, *lpBlue, BlueTRCSize ))
    00309     {
    00310         MemFree (hMem);
    00311         return (NULL);
    00312     }
    00313     *lpnRed = ui32toSINT (((lpcpCurveType) *lpRed)->curve.count);
    00314     *lpnGreen = ui32toSINT (((lpcpCurveType) *lpGreen)->curve.count);
    00315     *lpnBlue = ui32toSINT (((lpcpCurveType) *lpBlue)->curve.count);
    00316
    00317     return (hMem);
    00318 }
    00319
    00320
    00321 static SINT
    00322 CreateHostTRCInputTable(MEMPTR lpMem, LPHOSTCLUT lpHostClut,
    00323                         MEMPTR lpRed, MEMPTR lpGreen, MEMPTR lpBlue)
    00324 {
    00325     SINT    i;
    00326     PUSHORT lpPtr16;
    00327     MEMPTR  lpTable;
    00328
    00329     lpPtr16 = (PUSHORT)lpMem;
    00330
    00331     lpHostClut->inputArray[0] = (MEMPTR)lpPtr16;
    00332     lpTable = (MEMPTR)(((lpcpCurveType) lpRed)->curve.data);
    00333     for (i = 0; i < (SINT)(lpHostClut->inputEnt); i++)
    00334     {
    00335         *lpPtr16++ = (USHORT) ui16toSINT(lpTable);
    00336         lpTable += sizeof(icUInt16Number);
    00337     }
    00338
    00339     lpHostClut->inputArray[1] = (MEMPTR)lpPtr16;
    00340     lpTable = (MEMPTR)(((lpcpCurveType) lpGreen)->curve.data);
    00341     for (i = 0; i < (SINT)(lpHostClut->inputEnt); i++)
    00342     {
    00343         *lpPtr16++ = (USHORT) ui16toSINT(lpTable);
    00344         lpTable += sizeof(icUInt16Number);
    00345     }
    00346
    00347     lpHostClut->inputArray[2] = (MEMPTR)lpPtr16;
    00348     lpTable = (MEMPTR)(((lpcpCurveType) lpBlue)->curve.data);
    00349     for (i = 0; i < (SINT)(lpHostClut->inputEnt); i++)
    00350     {
    00351         *lpPtr16++ = (USHORT) ui16toSINT(lpTable);
    00352         lpTable += sizeof(icUInt16Number);
    00353     }
    00354     return ((MEMPTR)lpPtr16 - lpMem);
    00355 }
    00356
    00357 static SINT
    00358 CreateHostRevTRCInputTable(MEMPTR lpMem, LPHOSTCLUT lpHostClut,
    00359                            MEMPTR lpRed, MEMPTR lpGreen, MEMPTR lpBlue)
    00360 {
    00361     HGLOBAL   hTemp;
    00362     MEMPTR    lpTemp;
    00363
    00364     if (!MemAlloc (lpHostClut->outputEnt * (REVCURVE_RATIO + 1) * 2 ,
    00365                   (HGLOBAL FAR *) &hTemp, (LPMEMPTR) &lpTemp))
    00366     {
    00367         return (0);
    00368     }
    00369
    00370     lpHostClut->outputArray[0] = lpMem;
    00371     GetRevCurve (lpRed, lpTemp, lpHostClut->outputArray[0]);
    00372     lpHostClut->outputArray[1] = lpHostClut->outputArray[0] +
    00373                                 2 * REVCURVE_RATIO * lpHostClut->outputEnt;
    00374     GetRevCurve (lpGreen, lpTemp, lpHostClut->outputArray[1]);
    00375     lpHostClut->outputArray[2] = lpHostClut->outputArray[1] +
    00376                                 2 * REVCURVE_RATIO * lpHostClut->outputEnt;
    00377     GetRevCurve (lpBlue, lpTemp, lpHostClut->outputArray[2]);
    00378
    00379     MemFree (hTemp);
    00380     return ( 2 * REVCURVE_RATIO * lpHostClut->outputEnt * 3);
    00381 }
    00382
    00383 static BOOL
    00384 GetHostMatrixCSAorCRD(CHANDLE cp, MEMPTR lpMem, LPDWORD lpcbSize, BOOL bCSA)
    00385 {
    00386     SINT     nRedCount, nGreenCount, nBlueCount;
    00387     MEMPTR   lpRed = NULL,lpGreen, lpBlue;
    00388     HGLOBAL  hMem;
    00389     LPHOSTCLUT lpHostClut;
    00390     MEMPTR   lpOldMem = lpMem;
    00391     double   pArray[9], pRevArray[9], pTemp[9];
    00392     SINT     i;
    00393
    00394     hMem = GetTRCData(cp,
    00395         (LPMEMPTR)&lpRed, (LPMEMPTR)&lpGreen, (LPMEMPTR)&lpBlue,
    00396         (LPSINT)&nRedCount,(LPSINT)&nGreenCount, (LPSINT)&nBlueCount);
    00397
    00398     // Estimate the memory size required to hold CRD
    00399     *lpcbSize = (nRedCount + nGreenCount + nBlueCount) * 2 +
    00400            sizeof(HOSTCLUT) + 1024;      // data structure + extra safe space
    00401
    00402     if (lpMem == NULL)                   // This is a size request
    00403     {
    00404         MemFree (hMem);
    00405         return TRUE;
    00406     }
    00407
    00408     lpHostClut = (LPHOSTCLUT)lpMem;
    00409     lpMem += sizeof(HOSTCLUT);
    00410     lpHostClut->size = sizeof(HOSTCLUT);
    00411     lpHostClut->dataType = DATA_matrix;
    00412     lpHostClut->clutPoints = 2;
    00413     lpHostClut->pcs = icSigXYZData;
    00414     GetCPWhitePoint(cp, (LPSFLOAT)lpHostClut->whitePoint);
    00415
    00416     if (bCSA)
    00417     {
    00418         lpHostClut->inputEnt = (USHORT)nRedCount;
    00419         lpHostClut->inputChan = 3;
    00420         lpMem += CreateHostTRCInputTable(lpMem, lpHostClut,
    00421                                          lpRed, lpGreen, lpBlue);
    00422     }
    00423     else
    00424     {
    00425         lpHostClut->outputEnt = (USHORT)nRedCount;
    00426         lpHostClut->outputChan = 3;
    00427         lpMem += CreateHostRevTRCInputTable(lpMem, lpHostClut,
    00428                                             lpRed, lpGreen, lpBlue);
    00429     }
    00430
    00431     MemFree (hMem);
    00432     *lpcbSize = (DWORD) (lpMem - lpOldMem);
    00433
    00434     if (!CreateColorantArray(cp, &pTemp[0], icSigRedColorantTag) ||
    00435         !CreateColorantArray(cp, &pTemp[3], icSigGreenColorantTag) ||
    00436         !CreateColorantArray(cp, &pTemp[6], icSigBlueColorantTag))
    00437     {
    00438        return (FALSE);
    00439     }
    00440
    00441     for (i = 0; i < 9; i++)
    00442     {
    00443         pArray[i] = pTemp[i/8*8 + i*3%8];
    00444     }
    00445
    00446     if (bCSA)
    00447     {
    00448         for (i = 0; i < 9; i++)
    00449             lpHostClut->e[i] = (float)pArray[i];
    00450     }
    00451     else
    00452     {
    00453         InvertMatrix(pArray, pRevArray);
    00454         for (i = 0; i < 9; i++)
    00455             lpHostClut->e[i] = (float)pRevArray[i];
    00456     }
    00457
    00458     return TRUE;
    00459 }
    00460
    00461 /***************************************************************************
    00462 *                        GetHostCSA_Intent
    00463 *  function:
    00464 *       This is the function which creates the Host DEF or DEFGColorSpace array
    00465 *       based on Intent.
    00466 *  parameters:
    00467 *       cp          --  Color Profile handle
    00468 *       lpBuffer    --  Pointer to the memory block. If this point is NULL,
    00469 *                       require buffer size.
    00470 *       lpcbSize    --  Size of the memory block
    00471 *       Intent      --  Intent.
    00472 *       Type        --  CieBasedDEF or CieBasedDEF.
    00473 *  returns:
    00474 *       BOOL        --  TRUE if the function was successful,
    00475 *                       FALSE otherwise.
    00476 ***************************************************************************/
    00477
    00478 BOOL
    00479 GetHostCSA_Intent (CHANDLE cp, MEMPTR lpBuffer, LPDWORD lpcbSize,
    00480                    CSIG Intent, int Type)
    00481 {
    00482     SINT Index;
    00483     BOOL Success = FALSE;
    00484     CSIG AToBxTag;
    00485
    00486     switch (Intent)
    00487     {
    00488         case icPerceptual:
    00489             AToBxTag = icSigAToB0Tag;
    00490             break;
    00491         case icRelativeColorimetric:
    00492         case icAbsoluteColorimetric:
    00493             // use RelativeColorimetric data to build it.
    00494             AToBxTag = icSigAToB1Tag;
    00495             break;
    00496         case icSaturation:
    00497             AToBxTag = icSigAToB2Tag;
    00498             break;
    00499         default:
    00500             return FALSE;
    00501             break;
    00502     }
    00503     if (DoesCPTagExist (cp, AToBxTag) &&
    00504         GetCPTagIndex (cp, AToBxTag, (LPSINT) & Index))
    00505     {
    00506         Success = GetHostCSA(cp, lpBuffer, lpcbSize, Intent, Index, Type);
    00507     }
    00508     else if ((DoesTRCAndColorantTagExist(cp)) &&
    00509             (Type == TYPE_CIEBASEDDEF))
    00510     {
    00511         Success = GetHostMatrixCSAorCRD(cp, lpBuffer, lpcbSize, TRUE);
    00512     }
    00513
    00514     return Success;
    00515 }
    00516 /***************************************************************************
    00517 *                            GetHostColorSpaceArray
    00518 *  function:
    00519 *    This is the main function which creates the Host CSA
    00520 *    from the data supplied in the Profile.
    00521 *  parameters:
    00522 *       cp          --  Color Profile handle
    00523 *       InputIntent --  Intent.
    00524 *       lpBuffer    --  Pointer to the memory block. If this point is NULL,
    00525 *                       require buffer size.
    00526 *       lpcbSize    --  Size of the memory block
    00527 *  returns:
    00528 *       BOOL        --  TRUE if the function was successful,
    00529 *                       FALSE otherwise.
    00530 ***************************************************************************/
    00531 static BOOL
    00532 GetHostColorSpaceArray (CHANDLE cp, DWORD InputIntent,
    00533                        MEMPTR  lpBuffer, LPDWORD lpcbSize)
    00534 {
    00535     CSIG ColorSpace, Intent;
    00536     BOOL Success = FALSE;
    00537
    00538     if (!cp)
    00539         return Success;
    00540
    00541     if (!GetCPDevSpace (cp, (LPCSIG) & ColorSpace) ||
    00542         !GetCPRenderIntent (cp, (LPCSIG) & Intent))
    00543     {
    00544         return Success;
    00545     }
    00546     if (InputIntent == icUseRenderingIntent)
    00547         InputIntent = (DWORD)Intent;
    00548
    00549     if (!Success)
    00550     {
    00551         switch (ColorSpace)
    00552         {
    00553             case icSigRgbData:
    00554                 Success = GetHostCSA_Intent (cp, lpBuffer, lpcbSize,
    00555                           (CSIG) InputIntent, TYPE_CIEBASEDDEF);
    00556                 break;
    00557             case icSigCmykData:
    00558                 Success = GetHostCSA_Intent (cp, lpBuffer, lpcbSize,
    00559                           (CSIG) InputIntent, TYPE_CIEBASEDDEFG);
    00560                 break;
    00561             default:
    00562                 break;
    00563         }
    00564     }
    00565     return Success;
    00566 }
    00567
    00568 //===========================================================================
    00569
    00570 /***************************************************************************
    00571 *                             CreateHostLutCRD
    00572 *  function:
    00573 *    this is the function which creates the Host CRD
    00574 *    from the data supplied in the ColorProfile's LUT8 or LUT16 tag.
    00575 *  parameters:
    00576 *       cp          --  Color Profile handle
    00577 *       Index       --  Index of the tag
    00578 *       lpMem       --  Pointer to the memory block.If this point is NULL,
    00579 *                       require buffer size.
    00580 *       InputIntent --  Intent.
    00581 *
    00582 *  returns:
    00583 *       SINT        --  Size of Host CRD.
    00584 ***************************************************************************/
    00585
    00586 static SINT
    00587 CreateHostLutCRD (CHANDLE cp, SINT Index, MEMPTR lpMem, DWORD InputIntent)
    00588 {
    00589     SINT     nInputCh, nOutputCh, nGrids;
    00590     SINT     nInputTable, nOutputTable, nNumbers;
    00591     CSIG     Tag, PCS;
    00592     CSIG     IntentSig;
    00593
    00594     SINT     Ret;
    00595     SINT     i, j;
    00596     MEMPTR   lpTable;
    00597
    00598     MEMPTR   Buff = NULL;
    00599     SINT     MemSize = 0;
    00600     MEMPTR   lpOldMem = lpMem;
    00601     HGLOBAL  hMem;
    00602     LPHOSTCLUT  lpHostClut;
    00603
    00604     // Check if we can generate the CRD
    00605     if (!GetCPTagSig (cp, Index, (LPCSIG) & IntentSig) ||
    00606         !GetCPElementType (cp, Index, (LPCSIG) & Tag) ||
    00607         ((Tag != icSigLut8Type) && (Tag != icSigLut16Type)) ||
    00608         !GetCPConnSpace (cp, (LPCSIG) & PCS) ||
    00609         !GetCPElementSize (cp, Index, (LPSINT) & MemSize) ||
    00610         !MemAlloc (MemSize, (HGLOBAL FAR *)&hMem, (LPMEMPTR) & Buff) ||
    00611         !GetCPElement (cp, Index, Buff, MemSize))
    00612     {
    00613         if (NULL != Buff)
    00614         {
    00615             MemFree (hMem);
    00616         }
    00617         return (0);
    00618     }
    00619
    00620     GetCLUTinfo(Tag, Buff, &nInputCh, &nOutputCh,
    00621                 &nGrids, &nInputTable, &nOutputTable, &i);
    00622
    00623     if (((nOutputCh != 3) && (nOutputCh != 4)) ||
    00624         (nInputCh != 3))
    00625     {
    00626         SetCPLastError (CP_POSTSCRIPT_ERR);
    00627         MemFree (hMem);
    00628         return (0);
    00629     }
    00630
    00631     // First Pass. This is a size request
    00632     if (lpMem == NULL)
    00633     {
    00634         Ret = nInputCh * nInputTable * i         +  // Input table 8/16-bits
    00635             nOutputCh * nOutputTable * i         +  // Output table 8/16-bits
    00636             nOutputCh * nGrids * nGrids * nGrids +  // CLUT 8-bits only
    00637             sizeof(HOSTCLUT)                     +  // Data structure
    00638             1024;                                   // safe
    00639
    00640         MemFree (hMem);
    00641         return (Ret);
    00642     }
    00643
    00644     // Second Pass. Get a HostCRD
    00645     lpHostClut = (LPHOSTCLUT)lpMem;
    00646     lpMem += sizeof(HOSTCLUT);
    00647     lpHostClut->size = sizeof(HOSTCLUT);
    00648     lpHostClut->pcs = PCS;
    00649     lpHostClut->intent = InputIntent;
    00650     lpHostClut->lutBits = (Tag == icSigLut8Type)? 8:16;
    00651
    00652     GetCPWhitePoint (cp, (LPSFLOAT)lpHostClut->whitePoint);          // .. Illuminant
    00653
    00654     // Support absolute whitePoint
    00655     if (!GetCPMediaWhitePoint (cp, (LPSFLOAT)lpHostClut->mediaWP)) // .. Media WhitePoint
    00656     {
    00657         lpHostClut->mediaWP[0] = lpHostClut->whitePoint[0];
    00658         lpHostClut->mediaWP[1] = lpHostClut->whitePoint[1];
    00659         lpHostClut->mediaWP[2] = lpHostClut->whitePoint[2];
    00660     }
    00661     lpHostClut->inputChan = (unsigned char)nInputCh;
    00662     lpHostClut->outputChan = (unsigned char)nOutputCh;
    00663     lpHostClut->clutPoints = (unsigned char)nGrids;
    00664     lpHostClut->inputEnt = (USHORT)nInputTable;
    00665     lpHostClut->outputEnt = (USHORT)nOutputTable;
    00666
    00667 //******** Input array
    00668     lpMem += CreateHostInputOutputArray (lpMem, lpHostClut->inputArray,
    00669              nInputCh, nInputTable, 0, Tag, Buff);
    00670 //******** the offset to the position of output array.
    00671     i = nInputTable * nInputCh +
    00672         nGrids * nGrids * nGrids * nOutputCh;
    00673 //******** Output array
    00674     lpMem += CreateHostInputOutputArray (lpMem, lpHostClut->outputArray,
    00675              nOutputCh, nOutputTable, i, Tag, Buff);
    00676 //******** Matrix.
    00677     if (PCS == icSigXYZData)
    00678     {
    00679         if (Tag == icSigLut8Type)
    00680         {
    00681             lpTable = (MEMPTR) & ((lpcpLut8Type) Buff)->lut.e00;
    00682         } else
    00683         {
    00684             lpTable = (MEMPTR) & ((lpcpLut16Type) Buff)->lut.e00;
    00685         }
    00686         for (i = 0; i < 9; i++)
    00687         {
    00688             lpHostClut->e[i] = (float)((si16f16toSFLOAT (lpTable)) / CIEXYZRange);
    00689             lpTable += sizeof (icS15Fixed16Number);
    00690         }
    00691     }
    00692 //********** RenderTable
    00693     nNumbers = nGrids * nGrids * nOutputCh;
    00694     lpHostClut->clut = lpMem;
    00695     for (i = 0; i < nGrids; i++)        // Na strings should be sent
    00696     {
    00697         if (Tag == icSigLut8Type)
    00698         {
    00699             lpTable = (MEMPTR) (((lpcpLut8Type) Buff)->lut.data) +
    00700                 nInputTable * nInputCh +
    00701                 nNumbers * i;
    00702         } else
    00703         {
    00704             lpTable = (MEMPTR) (((lpcpLut16Type) Buff)->lut.data) +
    00705                 2 * nInputTable * nInputCh +
    00706                 2 * nNumbers * i;
    00707         }
    00708         if (Tag == icSigLut8Type)
    00709         {
    00710             MemCopy(lpMem, lpTable, nNumbers);
    00711             lpMem += nNumbers;
    00712         }
    00713         else
    00714         {
    00715             for (j = 0; j < nNumbers; j++)
    00716             {
    00717                 *lpMem++ = (BYTE)(ui16toSINT (lpTable) / 256);
    00718                 lpTable += sizeof (icUInt16Number);
    00719             }
    00720         }
    00721     }
    00722
    00723     MemFree (hMem);
    00724     return ((SINT) ((unsigned long) (lpMem - lpOldMem)));
    00725 }
    00726
    00727
    00728 /***************************************************************************
    00729 *                      GetHostColorRenderingDictionary
    00730 *  function:
    00731 *    this is the main function which creates the Host CRD
    00732 *  parameters:
    00733 *       cp          --  Color Profile handle
    00734 *       Intent      --  Intent.
    00735 *       lpMem       --  Pointer to the memory block.If this point is NULL,
    00736 *                       require buffer size.
    00737 *       lpcbSize    --  size of memory block.
    00738 *
    00739 *  returns:
    00740 *       SINT        --  !=0 if the function was successful,
    00741 *                         0 otherwise.
    00742 *                       Returns number of bytes required/transferred
    00743 ***************************************************************************/
    00744 static BOOL
    00745 GetHostColorRenderingDictionary (CHANDLE cp, DWORD Intent,
    00746                                 MEMPTR lpMem, LPDWORD lpcbSize)
    00747 {
    00748     SINT Index;
    00749     CSIG BToAxTag;
    00750
    00751     if (!cp)
    00752         return FALSE;
    00753
    00754     if ((lpMem == NULL) || (*lpcbSize == 0))
    00755     {
    00756         lpMem = NULL;
    00757         *lpcbSize = 0;
    00758     }
    00759
    00760     switch (Intent)
    00761     {
    00762         case icPerceptual:
    00763             BToAxTag = icSigBToA0Tag;
    00764             break;
    00765
    00766         case icRelativeColorimetric:
    00767         case icAbsoluteColorimetric:
    00768             // Use RelativeColorimetric to calculate this CRD.
    00769             BToAxTag = icSigBToA1Tag;
    00770             break;
    00771
    00772         case icSaturation:
    00773             BToAxTag = icSigBToA2Tag;
    00774             break;
    00775
    00776         default:
    00777            *lpcbSize = (DWORD) 0;
    00778             return FALSE;
    00779     }
    00780
    00781     if (DoesCPTagExist (cp, BToAxTag) &&
    00782         GetCPTagIndex (cp, BToAxTag, (LPSINT) & Index))
    00783     {
    00784         *lpcbSize = CreateHostLutCRD (cp, Index, lpMem, Intent);
    00785     }
    00786     else if(DoesTRCAndColorantTagExist(cp))
    00787     {
    00788         GetHostMatrixCSAorCRD(cp, lpMem, lpcbSize, FALSE);
    00789     }
    00790     return (*lpcbSize > 0);
    00791 }
    00792
    00793 //========================================================================
    00794 /***************************************************************************
    00795 *                               g
    00796 *  function:
    00797 *    Calculate function y = g(x). used in Lab->XYZ conversion
    00798 *    y = g(x):      g(x) = x*x*x             if x >= 6/29
    00799 *                   g(x) = 108/841*(x-4/29)  otherwise
    00800 *  parameters:
    00801 *       f           --  x
    00802 *  returns:
    00803 *       SINT        --  y
    00804 ***************************************************************************/
    00805
    00806 static float g(float f)
    00807 {
    00808     float frc;
    00809     if (f >= (6/29))
    00810     {
    00811         frc = f * f * f;
    00812     }
    00813     else
    00814     {
    00815         frc = f - (4.0f / 29.0f) * (108.0f / 841.0f);
    00816     }
    00817     return frc;
    00818 }
    00819
    00820 /***************************************************************************
    00821 *                          inverse_g
    00822 *  function:
    00823 *    Calculate inverse function y = g(x). used in XYZ->Lab conversion
    00824 *  parameters:
    00825 *       f           --  y
    00826 *  returns:
    00827 *       SINT        --  x
    00828 ***************************************************************************/
    00829 static float inverse_g(float f)
    00830 {
    00831     double frc;
    00832     if (f >= (6.0*6.0*6.0)/(29.0*29.0*29.0))
    00833     {
    00834         frc = pow(f, 1.0 / 3.0);
    00835     }
    00836     else
    00837     {
    00838         frc = f * (841.0 / 108.0) + (4.0 / 29.0);
    00839     }
    00840     return (float)frc;
    00841 }
    00842
    00843 //========================================================================
    00844
    00845 static BOOL
    00846 TableInterp3(LPHOSTCLUT lpHostClut, float far *fTemp)
    00847 {
    00848     int    tmpA, tmpBC;
    00849     int    cellA, cellB, cellC;
    00850     float  a, b, c;
    00851     short  Grids;
    00852     short  outputChan;
    00853     MEMPTR v000, v001, v010, v011;
    00854     MEMPTR v100, v101, v110, v111;
    00855     float  vx0x, vx1x;
    00856     float  v0xx, v1xx;
    00857     int    idx;
    00858
    00859     cellA = (int)(fTemp[0]);
    00860     a = fTemp[0] - cellA;
    00861
    00862     cellB = (int)(fTemp[1]);
    00863     b = fTemp[1] - cellB;
    00864
    00865     cellC = (int)(fTemp[2]);
    00866     c = fTemp[2] - cellC;
    00867
    00868     Grids = lpHostClut->clutPoints;
    00869     outputChan = lpHostClut->outputChan;
    00870     tmpA  = outputChan * Grids * Grids;
    00871     tmpBC = outputChan * (Grids * cellB + cellC);
    00872
    00873     // Calculate 8 surrounding cells.
    00874     v000 = lpHostClut->clut + tmpA * cellA + tmpBC;
    00875     v001 = (cellC < (Grids - 1))? v000 + outputChan : v000;
    00876     v010 = (cellB < (Grids - 1))? v000 + outputChan * Grids : v000;
    00877     v011 = (cellC < (Grids - 1))? v010 + outputChan : v010 ;
    00878
    00879     v100 = (cellA < (Grids - 1))? v000 + tmpA : v000;
    00880     v101 = (cellC < (Grids - 1))? v100 + outputChan : v100;
    00881     v110 = (cellB < (Grids - 1))? v100 + outputChan * Grids : v100;
    00882     v111 = (cellC < (Grids - 1))? v110 + outputChan : v110;
    00883
    00884     for (idx = 0; idx < outputChan; idx++)
    00885     {
    00886         // Calculate the average of 4 bottom cells.
    00887         vx0x = *v000 + c * (int)((int)*v001 - (int)*v000);
    00888         vx1x = *v010 + c * (int)((int)*v011 - (int)*v010);
    00889         v0xx = vx0x + b * (vx1x - vx0x);
    00890
    00891         // Calculate the average of 4 upper cells.
    00892         vx0x = *v100 + c * (int)((int)*v101 - (int)*v100);
    00893         vx1x = *v110 + c * (int)((int)*v111 - (int)*v110);
    00894         v1xx = vx0x + b * (vx1x - vx0x);
    00895
    00896         // Calculate the bottom and upper average.
    00897         fTemp[idx] = (v0xx + a * (v1xx - v0xx)) / MAXCOLOR8;
    00898
    00899         if ( idx < (outputChan - 1))
    00900         {
    00901             v000++;
    00902             v001++;
    00903             v010++;
    00904             v011++;
    00905             v100++;
    00906             v101++;
    00907             v110++;
    00908             v111++;
    00909         }
    00910     }
    00911
    00912     return TRUE;
    00913 }
    00914
    00915 static BOOL
    00916 TableInterp4(LPHOSTCLUT lpHostClut, float far *fTemp)
    00917 {
    00918     int    tmpH, tmpI, tmpJK;
    00919     int    cellH, cellI, cellJ, cellK;
    00920     float  h, i, j, k;
    00921     short  Grids;
    00922     short  outputChan;
    00923     MEMPTR v0000, v0001, v0010, v0011;
    00924     MEMPTR v0100, v0101, v0110, v0111;
    00925     MEMPTR v1000, v1001, v1010, v1011;
    00926     MEMPTR v1100, v1101, v1110, v1111;
    00927     float  vxx0x, vxx1x;
    00928     float  vx0xx, vx1xx;
    00929     float  v0xxx, v1xxx;
    00930     int    idx;
    00931
    00932     cellH = (int)(fTemp[0]);
    00933     h = fTemp[0] - cellH;
    00934
    00935     cellI = (int)(fTemp[1]);
    00936     i = fTemp[1] - cellI;
    00937
    00938     cellJ = (int)(fTemp[2]);
    00939     j = fTemp[2] - cellJ;
    00940
    00941     cellK = (int)(fTemp[3]);
    00942     k = fTemp[3] - cellK;
    00943
    00944     Grids = lpHostClut->clutPoints;
    00945     outputChan = lpHostClut->outputChan;
    00946     tmpI  = outputChan * Grids * Grids;
    00947     tmpH  = tmpI * Grids;
    00948     tmpJK = outputChan * (Grids * cellJ + cellK);
    00949
    00950     // Calculate 16 surrounding cells.
    00951     v0000 = lpHostClut->clut + tmpH * cellH + tmpI * cellI + tmpJK;
    00952     v0001 = (cellK < (Grids - 1))? v0000 + outputChan : v0000;
    00953     v0010 = (cellJ < (Grids - 1))? v0000 + outputChan * Grids : v0000;
    00954     v0011 = (cellK < (Grids - 1))? v0010 + outputChan : v0010;
    00955
    00956     v0100 = (cellI < (Grids - 1))? v0000 + tmpI : v0000;
    00957     v0101 = (cellK < (Grids - 1))? v0100 + outputChan : v0100;
    00958     v0110 = (cellJ < (Grids - 1))? v0100 + outputChan * Grids : v0100;
    00959     v0111 = (cellK < (Grids - 1))? v0110 + outputChan : v0110;
    00960
    00961     v1000 = (cellH < (Grids - 1))? v0000 + tmpH : v0000;
    00962     v1001 = (cellK < (Grids - 1))? v1000 + outputChan : v1000;
    00963     v1010 = (cellJ < (Grids - 1))? v1000 + outputChan * Grids : v1000;
    00964     v1011 = (cellK < (Grids - 1))? v1010 + outputChan : v1010;
    00965
    00966     v1100 = (cellI < (Grids - 1))? v1000 + tmpI : v1000;
    00967     v1101 = (cellK < (Grids - 1))? v1100 + outputChan : v1100;
    00968     v1110 = (cellJ < (Grids - 1))? v1100 + outputChan * Grids : v1100;
    00969     v1111 = (cellK < (Grids - 1))? v1110 + outputChan : v1110;
    00970
    00971     for (idx = 0; idx < outputChan; idx++)
    00972     {
    00973         // Calculate the average of 8 bottom cells.
    00974         vxx0x = *v0000 + k * (int)((int)*v0001 - (int)*v0000);
    00975         vxx1x = *v0010 + k * (int)((int)*v0011 - (int)*v0010);
    00976         vx0xx = vxx0x + j * (vxx1x - vxx0x);
    00977         vxx0x = *v0100 + k * (int)((int)*v0101 - (int)*v0100);
    00978         vxx1x = *v0110 + k * (int)((int)*v0111 - (int)*v0110);
    00979         vx1xx = vxx0x + j * (vxx1x - vxx0x);
    00980         v0xxx = vx0xx + i * (vx1xx - vx0xx);
    00981
    00982         // Calculate the average of 8 upper cells.
    00983         vxx0x = *v1000 + k * (int)((int)*v1001 - (int)*v1000);
    00984         vxx1x = *v1010 + k * (int)((int)*v1011 - (int)*v1010);
    00985         vx0xx = vxx0x + j * (vxx1x - vxx0x);
    00986         vxx0x = *v1100 + k * (int)((int)*v1101 - (int)*v1100);
    00987         vxx1x = *v1110 + k * (int)((int)*v1111 - (int)*v1110);
    00988         vx1xx = vxx0x + j * (vxx1x - vxx0x);
    00989         v1xxx = vx0xx + i * (vx1xx - vx0xx);
    00990
    00991         // Calculate the bottom and upper average.
    00992         fTemp[idx] = (v0xxx + h * (v1xxx - v0xxx)) / MAXCOLOR8;
    00993
    00994         if ( idx < (outputChan - 1))
    00995         {
    00996             v0000++;
    00997             v0001++;
    00998             v0010++;
    00999             v0011++;
    01000             v0100++;
    01001             v0101++;
    01002             v0110++;
    01003             v0111++;
    01004             v1000++;
    01005             v1001++;
    01006             v1010++;
    01007             v1011++;
    01008             v1100++;
    01009             v1101++;
    01010             v1110++;
    01011             v1111++;
    01012         }
    01013     }
    01014
    01015     return TRUE;
    01016 }
    01017
    01018
    01019 /***************************************************************************
    01020 *                         CheckColorLookupTable
    01021 *  function:
    01022 *    This function check RenderTable.
    01023 *  parameters:
    01024 *       LPHOSTCLUT lpHostClut --
    01025 *       float far  *fTemp     --  Input (in range [0 gred-1]) /
    01026 *                                 output(in range [0 1)
    01027 *  returns:
    01028 *       BOOL                  -- TRUE
    01029 ***************************************************************************/
    01030
    01031 static BOOL
    01032 CheckColorLookupTable(LPHOSTCLUT lpHostClut, float far *fTemp)
    01033 {
    01034     if (lpHostClut->inputChan == 3)
    01035     {
    01036         TableInterp3(lpHostClut, fTemp);
    01037     }
    01038     else if(lpHostClut->inputChan == 4)
    01039     {
    01040         TableInterp4(lpHostClut, fTemp);
    01041     }
    01042     return TRUE;
    01043 }
    01044
    01045 /***************************************************************************
    01046 *                         CheckInputOutputTable
    01047 *  function:
    01048 *    This function check inputTable.
    01049 *  parameters:
    01050 *       LPHOSTCLUT lpHostClut --
    01051 *       float far  *fTemp     --  Input / output data
    01052 *  returns:
    01053 *       BOOL                  -- TRUE
    01054 ***************************************************************************/
    01055 static BOOL
    01056 CheckInputOutputTable(LPHOSTCLUT lpHostClut, float far *fTemp,
    01057                       BOOL bCSA, BOOL bInputTable)
    01058 {
    01059     int     i;
    01060     short   Grids;
    01061     USHORT  floor1, ceiling1;
    01062     float   fIndex;
    01063     int     numChan;
    01064     int     numEnt;
    01065     PMEMPTR ppArray;
    01066
    01067     if (bInputTable)
    01068     {
    01069         numChan = lpHostClut->inputChan;
    01070         numEnt = lpHostClut->inputEnt - 1;
    01071         ppArray = lpHostClut->inputArray;
    01072     }
    01073     else
    01074     {
    01075         numChan = lpHostClut->outputChan;
    01076         numEnt = lpHostClut->outputEnt - 1;
    01077         ppArray = lpHostClut->outputArray;
    01078     }
    01079
    01080     Grids = lpHostClut->clutPoints;
    01081     for (i = 0; (i <= MAXCHANNELS) && (i < numChan); i++)
    01082     {
    01083         fTemp[i] = (fTemp[i] < 0)? 0: ((fTemp[i] > 1)? 1: fTemp[i]);
    01084         fIndex = fTemp[i] * numEnt;
    01085         if (lpHostClut->lutBits == 8)
    01086         {
    01087             floor1 = ppArray[i][(int)fIndex];
    01088             ceiling1 = ppArray[i][((int)fIndex) + 1];
    01089             fTemp[i] = (float)(floor1 + (ceiling1 - floor1) * (fIndex - floor(fIndex)));
    01090             if (bCSA && !bInputTable)
    01091                 fTemp[i] = (float)(fTemp[i] / 127.0);
    01092             else
    01093                 fTemp[i] = (float)(fTemp[i] / 255.0);
    01094         }
    01095         else
    01096         {
    01097             floor1 = ((PUSHORT)(ppArray[i]))[(int)fIndex];
    01098             ceiling1 = ((PUSHORT)(ppArray[i]))[((int)fIndex) + 1];
    01099             fTemp[i] = (float)(floor1 + (ceiling1 - floor1) * (fIndex - floor(fIndex)));
    01100             if (bCSA && !bInputTable)
    01101                 fTemp[i] = (float)(fTemp[i] / 32767.0);
    01102             else
    01103                 fTemp[i] = (float)(fTemp[i] / 65535.0);
    01104
    01105         }
    01106         if (bInputTable)
    01107         {
    01108             fTemp[i] *= (Grids - 1);
    01109             if (fTemp[i] > (Grids - 1))
    01110                 fTemp[i] = (float)(Grids - 1);
    01111         }
    01112     }
    01113     return TRUE;
    01114 }
    01115
    01116 static void
    01117 LabToXYZ(float far *Input, float far *Output, float far *whitePoint)
    01118 {
    01119     float   fL, fa, fb;
    01120
    01121     fL = (Input[0] * 50 + 16) / 116;
    01122     fa = (Input[1] * 128 - 128) / 500;
    01123     fb = (Input[2] * 128 - 128) / 200;
    01124     Output[0] = whitePoint[0] * g(fL + fa);
    01125     Output[1] = whitePoint[1] * g(fL);
    01126     Output[2] = whitePoint[2] * g(fL - fb);
    01127 }
    01128
    01129 static void
    01130 XYZToLab(float far *Input, float far *Output, float far *whitePoint)
    01131 {
    01132     float   fL, fa, fb;
    01133
    01134     fL = inverse_g(Input[0] / whitePoint[0]);
    01135     fa = inverse_g(Input[1] / whitePoint[1]);
    01136     fb = inverse_g(Input[2] / whitePoint[2]);
    01137     Output[0] = (fa * 116 - 16) / 100;
    01138     Output[1] = (fL * 500 - fa * 500 + 128) / 255;
    01139     Output[2] = (fa * 200 - fb * 200 + 128) / 255;
    01140 }
    01141
    01142 static void
    01143 ApplyMatrix(PFLOAT e, float far *Input, float far *Output)
    01144 {
    01145     SINT  i, j;
    01146
    01147     for (i = 0; i < 3; i++)
    01148     {
    01149         j = i*3;
    01150         Output[i] = e[j ]    * Input[0] +
    01151                     e[j + 1] * Input[1] +
    01152                     e[j + 2] * Input[2];
    01153     }
    01154 }
    01155
    01156 /***************************************************************************
    01157 *                         DoHostConversionCRD
    01158 *  function:
    01159 *    This function converts XYZ/Lab to RGB/CMYK by using HostCRD
    01160 *  parameters:
    01161 *       LPHOSTCLUT lpHostCRD  -- pointer to a HostCRD
    01162 *       LPHOSTCLUT lpHostCSA  -- pointer to a HostCSA
    01163 *       float far *Input      -- Input XYZ/Lab
    01164 *       float far *Output     -- Output RGB/CMYK
    01165 *  returns:
    01166 *       BOOL                  -- TRUE
    01167 ***************************************************************************/
    01168 static BOOL
    01169 DoHostConversionCRD (LPHOSTCLUT lpHostCRD, LPHOSTCLUT lpHostCSA,
    01170                      float far *Input, float far *Output,
    01171                      CSIG ColorSpace, BOOL bCheckOutputTable)
    01172 {
    01173     float   fTemp[MAXCHANNELS];
    01174     float   fTemp1[MAXCHANNELS];
    01175     int     i;
    01176
    01180     // When sampling the deviceCRD, skip the input table.
    01181     // If lpHostCSA is not NULL, the current CRD is targetCRD, we
    01182     // need to do input table conversion
    01183     if (lpHostCSA)
    01184     {
    01185         // Convert Lab to XYZ  in range [ 0 whitePoint ]
    01186         if ((lpHostCRD->pcs == icSigXYZData) &&
    01187             (lpHostCSA->pcs == icSigLabData))
    01188         {
    01189             LabToXYZ(Input, fTemp1, lpHostCRD->whitePoint);
    01190         }
    01191         // Convert XYZ to Lab in range [ 0 1]
    01192         else if ((lpHostCRD->pcs == icSigLabData) &&
    01193                  (lpHostCSA->pcs == icSigXYZData))
    01194         {
    01195             XYZToLab(Input, fTemp, lpHostCSA->whitePoint);
    01196         }
    01197         // Convert Lab to range [ 0 1]
    01198         else if ((lpHostCRD->pcs == icSigLabData) &&
    01199                  (lpHostCSA->pcs == icSigLabData))
    01200         {
    01201             for (i = 0; i < 3; i++)
    01202                 fTemp[i] = Input[i] / 2;
    01203         }
    01204         // Convert XYZ to XYZ (based on white point) to range [0 1]
    01205         else
    01206         {   // TODO: different intents using different conversion.
    01207             // icRelativeColorimetric: using Bradford transform.
    01208             // icAbsoluteColorimetric: using scaling.
    01209             for (i = 0; i < 3; i++)
    01210                 fTemp1[i] = Input[i] * lpHostCRD->whitePoint[i] / lpHostCSA->whitePoint[i];
    01211         }
    01212
    01213         // Matrix, used for XYZ data only or Matrix icc profile only
    01214         if (lpHostCRD->pcs == icSigXYZData)
    01215         {
    01216             ApplyMatrix(lpHostCRD->e, fTemp1, fTemp);
    01217         }
    01218
    01219         if (lpHostCRD->dataType != DATA_matrix)
    01220         {
    01221             //Search input Table
    01222             CheckInputOutputTable(lpHostCRD, fTemp, 0, 1);
    01223         }
    01224     }
    01225     // If the current CRD is device CRD, we do not need to do input
    01226     // table conversion.
    01227     else
    01228     {
    01229         short   Grids;
    01230         Grids = lpHostCRD->clutPoints;
    01231         // Sample data may be XYZ or Lab. It depends on Target icc profile.
    01232         // If the PCS of the target icc profile is XYZ, input data will be XYZ.
    01233         // If the PCS of the target icc profile is Lab, input data will be Lab.
    01234
    01235         if (lpHostCRD->dataType == DATA_matrix)
    01236         {
    01237             for (i = 0; i < 3; i++)
    01238             {
    01239                 fTemp[i] = Input[i];
    01240             }
    01241         }
    01242         else
    01243         {
    01244             for (i = 0; i < 3; i++)
    01245             {
    01246                 fTemp[i] = Input[i]* (Grids - 1);
    01247                 if (fTemp[i] > (Grids - 1))
    01248                     fTemp[i] = (float)(Grids - 1);
    01249             }
    01250         }
    01251     }   // bCheckInputTable
    01252
    01253     if (lpHostCRD->dataType != DATA_matrix)
    01254     {
    01255         // Rendering table
    01256         CheckColorLookupTable(lpHostCRD, fTemp);
    01257
    01261     }
    01262     if (bCheckOutputTable)
    01263     {
    01264         //Output Table
    01265         CheckInputOutputTable(lpHostCRD, fTemp, 0, 0);
    01266     }
    01267     for (i = 0; (i <= MAXCHANNELS) && (i < lpHostCRD->outputChan); i++)
    01268     {
    01269         Output[i] = fTemp[i];
    01270     }
    01271
    01272    return TRUE;
    01273 }
    01274
    01275 /***************************************************************************
    01276 *                         DoHostConversionCSA
    01277 *  function:
    01278 *    This function converts RGB/CMYK to XYZ/Lab by using HostCSA
    01279 *  parameters:
    01280 *       LPHOSTCLUT lpHostCLUT -- pointer to a HostCSA
    01281 *       float far *Input      -- Input XYZ/Lab
    01282 *       float far *Output     -- Output RGB/CMYK
    01283 *  returns:
    01284 *       BOOL                  -- TRUE
    01285 ***************************************************************************/
    01286
    01287 static BOOL
    01288 DoHostConversionCSA (LPHOSTCLUT lpHostClut, float far *Input, float far *Output)
    01289 {
    01290     float   fTemp[MAXCHANNELS];
    01291     int     i;
    01292
    01296     for (i = 0; (i <= MAXCHANNELS) && (i < lpHostClut->inputChan); i++)
    01297     {
    01298         fTemp[i] = Input[i];
    01299     }
    01300
    01301     if (lpHostClut->dataType == DATA_matrix)
    01302     {
    01303         //Search input Table
    01304         CheckInputOutputTable(lpHostClut, fTemp, 1, 1);
    01305         ApplyMatrix(lpHostClut->e, fTemp, Output);
    01306     }
    01307     else
    01308     {
    01309         //Search input Table
    01310         CheckInputOutputTable(lpHostClut, fTemp, 1, 1);
    01311
    01312         // Rendering table
    01313         CheckColorLookupTable(lpHostClut, fTemp);
    01314
    01315         //Output Table
    01316         CheckInputOutputTable(lpHostClut, fTemp, 1, 0 );
    01317
    01321         for (i = 0; (i <= MAXCHANNELS) && (i < lpHostClut->outputChan); i++)
    01322         {
    01323             Output[i] = fTemp[i];
    01324         }
    01325     }
    01326
    01327     return TRUE;
    01328 }
    01329
    01330 static BOOL
    01331 GetCRDInputOutputArraySize(CHANDLE cp, DWORD Intent,
    01332     LPSINT lpInTbSize, LPSINT lpOutTbSize,
    01333     LPCSIG lpIntentTag, LPSINT lpGrids)
    01334 {
    01335     CSIG    Tag;
    01336     SINT    Index;
    01337     SINT    Ret = 0;
    01338     MEMPTR  Buff = NULL;
    01339     SINT    MemSize = 0;
    01340     HGLOBAL hMem;
    01341     SINT    outputChan, outputEnt;
    01342     SINT    inputChan, inputEnt;
    01343     SINT    Grids;
    01344     SINT    i;
    01345
    01346     switch (Intent)
    01347     {
    01348         case icPerceptual:
    01349             *lpIntentTag = icSigBToA0Tag;
    01350             break;
    01351
    01352         case icRelativeColorimetric:
    01353         case icAbsoluteColorimetric:
    01354             *lpIntentTag = icSigBToA1Tag;
    01355             break;
    01356
    01357         case icSaturation:
    01358             *lpIntentTag = icSigBToA2Tag;
    01359             break;
    01360
    01361         default:
    01362             return FALSE;
    01363     }
    01364     if (!DoesCPTagExist (cp, *lpIntentTag) ||
    01365         !GetCPTagIndex (cp, *lpIntentTag, (LPSINT) & Index) ||
    01366         !GetCPElementType (cp, Index, (LPCSIG) & Tag) ||
    01367         ((Tag != icSigLut8Type) && (Tag != icSigLut16Type)) ||
    01368         !GetCPElementSize (cp, Index, (LPSINT) & MemSize) ||
    01369         !MemAlloc (MemSize, (HGLOBAL FAR *)&hMem, (LPMEMPTR) & Buff) ||
    01370         !GetCPElement (cp, Index, Buff, MemSize))
    01371     {
    01372         BOOL retVal = FALSE;
    01373
    01374         if (NULL != Buff)
    01375         {
    01376             MemFree (hMem);
    01377         }
    01378
    01379         // Matrix icc profile.
    01380
    01381         *lpGrids = 2;
    01382         if (lpInTbSize)
    01383         {
    01384             retVal = GetHostCSA_Intent (cp, NULL, lpInTbSize,
    01385                           (CSIG) Intent, TYPE_CIEBASEDDEF);
    01386             *lpInTbSize = *lpInTbSize * 3;
    01387         }
    01388         if (lpOutTbSize)
    01389         {
    01390             retVal = GetHostCSA_Intent (cp, NULL, lpOutTbSize,
    01391                           (CSIG) Intent, TYPE_CIEBASEDDEF);
    01392             *lpOutTbSize = *lpOutTbSize * 3;
    01393         }
    01394         return retVal;
    01395     }
    01396
    01397     if (lpInTbSize)
    01398     {
    01399         GetCLUTinfo(Tag, Buff, &inputChan, &outputChan,
    01400                 &Grids, &inputEnt, &outputEnt, &i);
    01401
    01402         if (inputChan != 3)
    01403         {
    01404             MemFree (hMem);
    01405             return FALSE;
    01406         }
    01407
    01408         *lpInTbSize = inputChan * inputEnt * 6;  // Number of INT bytes
    01409         *lpGrids = Grids;
    01410     }
    01411
    01412     if (lpOutTbSize)
    01413     {
    01414         GetCLUTinfo(Tag, Buff, &inputChan, &outputChan,
    01415                 &Grids, &inputEnt, &outputEnt, &i);
    01416
    01417         if ((outputChan != 3) && (outputChan != 4))
    01418         {
    01419             MemFree (hMem);
    01420             return FALSE;
    01421         }
    01422         *lpOutTbSize = outputChan * outputEnt * 6; // Number of INT bytes
    01423         *lpGrids = Grids;
    01424     }
    01425
    01426     MemFree (hMem);
    01427     return TRUE;
    01428 }
    01429
    01430 /***************************************************************************
    01431 *                         CreateOutputArray
    01432 *  function:
    01433 *       Create CSA/CRD output arrays from the data supplied in icc profile's
    01434 *       LUT8 or LUT16 tags.
    01435 *  parameters:
    01436 *       MEMPTR  lpMem        -- a pointer to a buffer which will contain the arrays.
    01437 *       SINT    nOutputCh    -- Number of output channel. if lpHostClut, no meaning.
    01438 *       SINT    nOutputTable -- saze of each array.  if lpHostClut, no meaning.
    01439 *       SINT    Offset       -- offset of Buff, point to the 1st byte of output array in CLUT.
    01440 *                               if lpHostClut, no meaning.
    01441 *       MEMPTR  Intent       --
    01442 *       CSIG    Tag          -- LUT8 or LUT16
    01443 *       MEMPTR  Buff         -- point to a buffer which contain LUT8 or LUT16.
    01444 *                               if NULL, use lpHostClut.
    01445 *       BOOL    AllowBinary  --
    01446 *       MEMPTR  lpHostClut   -- point to host CSA/CRD. if NULL, use Buff.
    01447 *  returns:
    01448 *       SINT                 -- The size of output array created.
    01449 ***************************************************************************/
    01450
    01451 SINT
    01452 CreateOutputArray (MEMPTR lpMem, SINT nOutputCh,
    01453     SINT nOutputTable, SINT Offset, MEMPTR Intent,
    01454     CSIG Tag, MEMPTR Buff, BOOL AllowBinary, MEMPTR lpHostClut)
    01455 {
    01456     SINT i, j;
    01457     MEMPTR lpOldMem;
    01458     MEMPTR lpTable;
    01459     MEMPTR lpLineStart;
    01460     lpOldMem = lpMem;
    01461
    01462     if (lpHostClut)
    01463     {
    01464         nOutputCh = (SINT)(((LPHOSTCLUT)lpHostClut)->outputChan);
    01465         nOutputTable = (SINT)(((LPHOSTCLUT)lpHostClut)->outputEnt);
    01466         Tag = (((LPHOSTCLUT)lpHostClut)->lutBits == 8)?
    01467               icSigLut8Type : icSigLut16Type;
    01468     }
    01469
    01470     for (i = 0; i < nOutputCh; i++)
    01471     {
    01472         lpLineStart = lpMem;
    01473         lpMem += WriteNewLineObject (lpMem, Slash);
    01474         if (lpHostClut)
    01475             lpMem += WriteObject (lpMem, PreViewOutArray);
    01476         else
    01477             lpMem += WriteObject (lpMem, OutputArray);
    01478         lpMem += WriteObjectN (lpMem, Intent, lstrlen (Intent));
    01479         lpMem += WriteInt (lpMem, i);
    01480
    01481         if (lpHostClut)
    01482             lpTable = ((LPHOSTCLUT)lpHostClut)->outputArray[i];
    01483         else
    01484         {
    01485             if (Tag == icSigLut8Type)
    01486                 lpTable = (MEMPTR) (((lpcpLut8Type) Buff)->lut.data) +
    01487                     Offset +
    01488                     nOutputTable * i;
    01489             else
    01490                 lpTable = (MEMPTR) (((lpcpLut16Type) Buff)->lut.data) +
    01491                     2 * Offset +
    01492                     2 * nOutputTable * i;
    01493         }
    01494
    01495         if (!AllowBinary)               // Output ASCII CRD
    01496         {
    01497             if (Tag == icSigLut8Type)
    01498             {
    01499                 lpMem += WriteObject (lpMem, BeginString);
    01500                 lpMem += WriteHexBuffer (lpMem, lpTable, lpLineStart, nOutputTable);
    01501                 lpMem += WriteObject (lpMem, EndString);
    01502             } else
    01503             {
    01504                 lpMem += WriteObject (lpMem, BeginArray);
    01505                 for (j = 0; j < nOutputTable; j++)
    01506                 {
    01507                     if (lpHostClut)
    01508                         lpMem += WriteInt (lpMem, *((PUSHORT)lpTable));
    01509                     else
    01510                         lpMem += WriteInt (lpMem, ui16toSINT (lpTable));
    01511                     lpTable += sizeof (icUInt16Number);
    01512                     if (((SINT) (lpMem - lpLineStart)) > MAX_LINELENG)
    01513                     {
    01514                         lpLineStart = lpMem;
    01515                         lpMem += WriteObject (lpMem, NewLine);
    01516                     }
    01517                 }
    01518                 lpMem += WriteObject (lpMem, EndArray);
    01519             }
    01520         } else
    01521         {                               // Output BINARY CRD
    01522             if (Tag == icSigLut8Type)
    01523             {
    01524                 lpMem += WriteStringToken (lpMem, 143, 256);
    01525                 lpMem += WriteByteString (lpMem, lpTable, 256L);
    01526             } else
    01527             {
    01528                 lpMem += WriteHNAToken (lpMem, 149, nOutputTable);
    01529                 if (lpHostClut)
    01530                     lpMem += WriteIntStringU2S_L (lpMem, lpTable, nOutputTable);
    01531                 else
    01532                     lpMem += WriteIntStringU2S (lpMem, lpTable, nOutputTable);
    01533             }
    01534         }
    01535         lpMem += WriteObject (lpMem, DefOp);
    01536     }
    01537
    01538     return ((SINT) (lpMem - lpOldMem));
    01539 }
    01540
    01541 /***************************************************************************
    01542 *                         CreateInputArray
    01543 *  function:
    01544 *       Create CSA/CRD Input arrays from the data supplied in icc profile's
    01545 *       LUT8 or LUT16 tags.
    01546 *  parameters:
    01547 *       MEMPTR  lpMem        -- a pointer to the buffer which will contain the arrays.
    01548 *       SINT    nInputCh     -- Number of input channel. if lpHostClut, no meaning.
    01549 *       SINT    nInputTable  -- saze of each array.  if lpHostClut, no meaning.
    01550 *       SINT    Offset       -- offset of Buff, point to the 1st byte of output array in CLUT.
    01551 *                               if lpHostClut, no meaning.
    01552 *       MEMPTR  Intent       --
    01553 *       CSIG    Tag          -- LUT8 or LUT16
    01554 *       MEMPTR  Buff         -- point to a buffer which contains LUT8 or LUT16.
    01555 *                               if NULL, use lpHostClut.
    01556 *       BOOL    AllowBinary  --
    01557 *       MEMPTR  lpHostClut   -- point to host CSA/CRD. if NULL, use Buff.
    01558 *  returns:
    01559 *       SINT                 -- The size of inpput array created.
    01560 ***************************************************************************/
    01561
    01562 SINT
    01563 CreateInputArray (MEMPTR lpMem, SINT nInputCh,
    01564     SINT nInputTable, MEMPTR Intent, CSIG Tag,
    01565     MEMPTR Buff, BOOL bAllowBinary, MEMPTR lpHostClut)
    01566 {
    01567     SINT i, j;
    01568     MEMPTR lpOldMem;
    01569     MEMPTR lpTable;
    01570     MEMPTR lpLineStart;
    01571     lpOldMem = lpMem;
    01572
    01573     if (lpHostClut)
    01574     {
    01575         nInputCh = (SINT)(((LPHOSTCLUT)lpHostClut)->inputChan);
    01576         nInputTable = (SINT)(((LPHOSTCLUT)lpHostClut)->inputEnt);
    01577         Tag = (((LPHOSTCLUT)lpHostClut)->lutBits == 8)?
    01578                icSigLut8Type : icSigLut16Type;
    01579     }
    01580
    01581     for (i = 0; i < nInputCh; i++)
    01582     {
    01583         lpLineStart = lpMem;
    01584         lpMem += WriteNewLineObject (lpMem, Slash);
    01585         if (lpHostClut)
    01586             lpMem += WriteObject (lpMem, PreViewInArray);
    01587         else
    01588             lpMem += WriteObject (lpMem, InputArray);
    01589         lpMem += WriteObjectN (lpMem, Intent, lstrlen (Intent));
    01590         lpMem += WriteInt (lpMem, i);
    01591
    01592         if (lpHostClut)
    01593         {
    01594             lpTable = ((LPHOSTCLUT)lpHostClut)->inputArray[i];
    01595         }
    01596         else
    01597         {
    01598             if (Tag == icSigLut8Type)
    01599                 lpTable = (MEMPTR) (((lpcpLut8Type) Buff)->lut.data) + nInputTable * i;
    01600             else
    01601                 lpTable = (MEMPTR) (((lpcpLut16Type) Buff)->lut.data) + 2 * nInputTable * i;
    01602         }
    01603         if (!bAllowBinary)               // Output ASCII CRD
    01604         {
    01605             if (Tag == icSigLut8Type)
    01606             {
    01607                 lpMem += WriteObject (lpMem, BeginString);
    01608                 lpMem += WriteHexBuffer (lpMem, lpTable,lpLineStart, nInputTable);
    01609                 lpMem += WriteObject (lpMem, EndString);
    01610             } else
    01611             {
    01612                 lpMem += WriteObject (lpMem, BeginArray);
    01613                 for (j = 0; j < nInputTable; j++)
    01614                 {
    01615                     if(lpHostClut)
    01616                         lpMem += WriteInt (lpMem, *((PUSHORT)lpTable));
    01617                     else
    01618                         lpMem += WriteInt (lpMem, ui16toSINT (lpTable));
    01619                     lpTable += sizeof (icUInt16Number);
    01620                     if (((SINT) (lpMem - lpLineStart)) > MAX_LINELENG)
    01621                     {
    01622                         lpLineStart = lpMem;
    01623                         lpMem += WriteObject (lpMem, NewLine);
    01624                     }
    01625                 }
    01626                 lpMem += WriteObject (lpMem, EndArray);
    01627             }
    01628         } else
    01629         {                               // Output BINARY CRD
    01630             if (Tag == icSigLut8Type)
    01631             {
    01632                 lpMem += WriteStringToken (lpMem, 143, 256);
    01633                 lpMem += WriteByteString (lpMem, lpTable, 256L);
    01634             } else
    01635             {
    01636                 lpMem += WriteHNAToken (lpMem, 149, nInputTable);
    01637                 if (lpHostClut)
    01638                     lpMem += WriteIntStringU2S_L (lpMem, lpTable, nInputTable);
    01639                 else
    01640                     lpMem += WriteIntStringU2S (lpMem, lpTable, nInputTable);
    01641             }
    01642         }
    01643         lpMem += WriteObject (lpMem, DefOp);
    01644     }
    01645
    01646     return ((SINT) (lpMem - lpOldMem));
    01647 }
    01648
    01649 SINT
    01650 SendCRDLMN(MEMPTR lpMem, CSIG Intent, LPSFLOAT whitePoint, LPSFLOAT mediaWP, CSIG pcs)
    01651 {
    01652     MEMPTR  lpOldMem;
    01653     SINT    i, j;
    01654
    01655     lpOldMem = lpMem;
    01656
    01657 //********** /MatrixLMN
    01658     if (icAbsoluteColorimetric == Intent)
    01659     {
    01660         lpMem += WriteNewLineObject (lpMem, MatrixLMNTag);
    01661
    01662         lpMem += WriteObject (lpMem, BeginArray);
    01663         for (i = 0; i < 3; i++)
    01664         {
    01665             for (j = 0; j < 3; j++)
    01666                 lpMem += WriteFloat (lpMem,
    01667                     (double) (i == j) ? whitePoint[i] / mediaWP[i] : 0.0);
    01668         }
    01669         lpMem += WriteObject (lpMem, EndArray);
    01670     }
    01671  //********** /RangeLMN
    01672     lpMem += WriteNewLineObject (lpMem, RangeLMNTag);
    01673     if (pcs == icSigXYZData)
    01674     {
    01675         lpMem += WriteObject (lpMem, BeginArray);
    01676         for (i = 0; i < 3; i++)
    01677         {
    01678             lpMem += WriteFloat (lpMem, (double) 0);
    01679             lpMem += WriteFloat (lpMem, (double) whitePoint[i]);
    01680         }
    01681         lpMem += WriteObject (lpMem, EndArray);
    01682     } else
    01683     {
    01684         lpMem += WriteObject (lpMem, RangeLMNLab);
    01685     }
    01686
    01687  //********** /EncodeLMN
    01688     lpMem += WriteNewLineObject (lpMem, EncodeLMNTag);
    01689     lpMem += WriteObject (lpMem, BeginArray);
    01690     for (i = 0; i < 3; i++)
    01691     {
    01692         lpMem += WriteObject (lpMem, BeginFunction);
    01693         if (pcs != icSigXYZData)
    01694         {
    01695             lpMem += WriteFloat (lpMem, (double)whitePoint[i]);
    01696             lpMem += WriteObject (lpMem, DivOp);
    01697             lpMem += WriteObject (lpMem, EncodeLMNLab);
    01698         }
    01699         lpMem += WriteObject (lpMem, EndFunction);
    01700     }
    01701     lpMem += WriteObject (lpMem, EndArray);
    01702
    01703     return (SINT)(lpMem - lpOldMem);
    01704 }
    01705
    01706
    01707 SINT
    01708 SendCRDPQR(MEMPTR lpMem, CSIG Intent, LPSFLOAT whitePoint)
    01709 {
    01710     MEMPTR  lpOldMem;
    01711     SINT    i;
    01712
    01713     lpOldMem = lpMem;
    01714
    01715     if (icAbsoluteColorimetric != Intent)
    01716     {
    01717      //********** /RangePQR
    01718         lpMem += WriteNewLineObject (lpMem, RangePQRTag);
    01719         lpMem += WriteObject (lpMem, RangePQR);
    01720
    01721      //********** /MatrixPQR
    01722         lpMem += WriteNewLineObject (lpMem, MatrixPQRTag);
    01723         lpMem += WriteObject (lpMem, MatrixPQR);
    01724     }
    01725     else
    01726     {
    01727     //********** /RangePQR
    01728         lpMem += WriteNewLineObject (lpMem, RangePQRTag);
    01729         lpMem += WriteObject (lpMem, BeginArray);
    01730         for (i = 0; i < 3; i++)
    01731         {
    01732             lpMem += WriteFloat (lpMem, (double) 0);
    01733             lpMem += WriteFloat (lpMem, (double)(whitePoint[i]));
    01734         }
    01735         lpMem += WriteObject (lpMem, EndArray);
    01736     //********** /MatrixPQR
    01737         lpMem += WriteNewLineObject (lpMem, MatrixPQRTag);
    01738         lpMem += WriteObject (lpMem, Identity);
    01739     }
    01740 //********** /TransformPQR
    01741     lpMem += WriteNewLineObject (lpMem, TransformPQRTag);
    01742     lpMem += WriteObject (lpMem, BeginArray);
    01743     for (i = 0; i < 3; i++)
    01744     {
    01745         lpMem += WriteObject (lpMem, BeginFunction);
    01746         lpMem += WriteObject (lpMem,
    01747             (icAbsoluteColorimetric != Intent) ? TransformPQR[i] : NullOp);
    01748         lpMem += WriteObject (lpMem, EndFunction);
    01749     }
    01750     lpMem += WriteObject (lpMem, EndArray);
    01751
    01752     return (SINT)(lpMem - lpOldMem);
    01753 }
    01754
    01755 SINT
    01756 SendCRDABC(MEMPTR lpMem, MEMPTR PublicArrayName, CSIG pcs, SINT nInputCh,
    01757            MEMPTR Buff, LPSFLOAT e, CSIG LutTag, BOOL bAllowBinary)
    01758 {
    01759     MEMPTR  lpOldMem;
    01760     SINT    i, j;
    01761     double TempMatrixABC[9];
    01762     MEMPTR lpTable;
    01763     MEMPTR lpLineStart;
    01764     lpOldMem = lpMem;
    01765
    01766  //********** /RangeABC
    01767     lpMem += WriteNewLineObject (lpMem, RangeABCTag);
    01768     lpMem += WriteObject (lpMem, RangeABC);
    01769  //********** /MatrixABC
    01770     lpMem += WriteNewLineObject (lpMem, MatrixABCTag);
    01771     if (pcs == icSigXYZData)
    01772     {
    01773         lpMem += WriteObject (lpMem, BeginArray);
    01774         if (e)
    01775         {
    01776             for (i = 0; i < 3; i++)
    01777             {
    01778                 for (j = 0; j < 3; j++)
    01779                 {
    01780                     lpMem += WriteFloat (lpMem, e[i + j * 3]);
    01781                 }
    01782             }
    01783         }
    01784         else
    01785         {
    01786             if (LutTag == icSigLut8Type)
    01787             {
    01788                 lpTable = (MEMPTR) & ((lpcpLut8Type) Buff)->lut.e00;
    01789             } else
    01790             {
    01791                 lpTable = (MEMPTR) & ((lpcpLut16Type) Buff)->lut.e00;
    01792             }
    01793             for (i = 0; i < 9; i++)
    01794             {
    01795                 TempMatrixABC[i] = ((double) si16f16toSFLOAT (lpTable)) / CIEXYZRange;
    01796                 lpTable += sizeof (icS15Fixed16Number);
    01797             }
    01798             for (i = 0; i < 3; i++)
    01799             {
    01800                 for (j = 0; j < 3; j++)
    01801                 {
    01802                     lpMem += WriteFloat (lpMem, TempMatrixABC[i + j * 3]);
    01803                 }
    01804             }
    01805         }
    01806         lpMem += WriteObject (lpMem, EndArray);
    01807     } else
    01808     {
    01809         lpMem += WriteObject (lpMem, MatrixABCLabCRD);
    01810     }
    01811  //********** /EncodeABC
    01812     if (nInputCh == 0)
    01813         return (SINT)(lpMem - lpOldMem);
    01814
    01815     lpLineStart = lpMem;
    01816     lpMem += WriteNewLineObject (lpMem, EncodeABCTag);
    01817     lpMem += WriteObject (lpMem, BeginArray);
    01818     for (i = 0; i < nInputCh; i++)
    01819     {
    01820         lpLineStart = lpMem;
    01821         lpMem += WriteNewLineObject (lpMem, BeginFunction);
    01822         if (pcs == icSigLabData)
    01823         {
    01824             lpMem += WriteObject (lpMem,
    01825                                   (0 == i) ? EncodeABCLab1 : EncodeABCLab2);
    01826         }
    01827         lpMem += WriteObject (lpMem, StartClip);
    01828         if (e)
    01829             lpMem += WriteObject (lpMem, PreViewInArray);
    01830         else
    01831             lpMem += WriteObject (lpMem, InputArray);
    01832         lpMem += WriteObjectN (lpMem, (MEMPTR) PublicArrayName, lstrlen (PublicArrayName));
    01833         lpMem += WriteInt (lpMem, i);
    01834
    01835         if (!bAllowBinary)              // Output ASCII CRD
    01836         {
    01837             lpMem += WriteNewLineObject (lpMem, IndexArray);
    01838         } else
    01839         {                               // Output BINARY CRD
    01840             if (LutTag == icSigLut8Type)
    01841             {
    01842                 lpMem += WriteObject (lpMem, IndexArray);
    01843             } else
    01844             {
    01845                 lpMem += WriteObject (lpMem, IndexArray16b);
    01846             }
    01847         }
    01848         lpMem += WriteObject (lpMem, (LutTag == icSigLut8Type) ?
    01849                               Scale8 : Scale16);
    01850         lpMem += WriteObject (lpMem, EndClip);
    01851         lpMem += WriteObject (lpMem, EndFunction);
    01852     }
    01853     lpMem += WriteObject (lpMem, EndArray);
    01854     return (SINT)(lpMem - lpOldMem);
    01855 }
    01856
    01857 SINT
    01858 SendCRDBWPoint(MEMPTR lpMem, LPSFLOAT whitePoint)
    01859 {
    01860     MEMPTR  lpOldMem;
    01861     SINT    i;
    01862
    01863     lpOldMem = lpMem;
    01864
    01865 //********** /BlackPoint
    01866     lpMem += WriteNewLineObject (lpMem, BlackPointTag);
    01867     lpMem += WriteObject (lpMem, BlackPoint);
    01868
    01869 //********** /WhitePoint
    01870     lpMem += WriteNewLineObject (lpMem, WhitePointTag);
    01871     lpMem += WriteObject (lpMem, BeginArray);
    01872     for (i = 0; i < 3; i++)
    01873     {
    01874         lpMem += WriteFloat (lpMem, (double)(whitePoint[i]));
    01875     }
    01876     lpMem += WriteObject (lpMem, EndArray);
    01877     return (SINT)(lpMem - lpOldMem);
    01878 }
    01879
    01880 SINT SendCRDOutputTable(MEMPTR lpMem, MEMPTR PublicArrayName,
    01881         SINT nOutputCh, CSIG LutTag, BOOL bHost, BOOL bAllowBinary)
    01882 {
    01883     MEMPTR  lpOldMem;
    01884     SINT    i;
    01885
    01886     lpOldMem = lpMem;
    01887
    01888     for (i = 0; i < nOutputCh; i++)
    01889     {
    01890         lpMem += WriteNewLineObject (lpMem, BeginFunction);
    01891         lpMem += WriteObject (lpMem, Clip01);
    01892         if (bHost)
    01893             lpMem += WriteObject (lpMem, PreViewOutArray);
    01894         else
    01895             lpMem += WriteObject (lpMem, OutputArray);
    01896         lpMem += WriteObjectN (lpMem, (MEMPTR) PublicArrayName, lstrlen (PublicArrayName));
    01897         lpMem += WriteInt (lpMem, i);
    01898
    01899         if (!bAllowBinary)               // Output ASCII CRD
    01900         {
    01901             lpMem += WriteObject (lpMem, NewLine);
    01902             if (LutTag == icSigLut8Type)
    01903             {
    01904                 lpMem += WriteObject (lpMem, TFunction8);
    01905             } else
    01906             {
    01907                 lpMem += WriteObject (lpMem, IndexArray);
    01908                 lpMem += WriteObject (lpMem, Scale16);
    01909             }
    01910         } else
    01911         {                               // Output BINARY CRD
    01912             if (LutTag == icSigLut8Type)
    01913             {
    01914                 lpMem += WriteObject (lpMem, TFunction8);
    01915             } else
    01916             {
    01917                 lpMem += WriteObject (lpMem, IndexArray16b);
    01918                 lpMem += WriteObject (lpMem, Scale16);
    01919             }
    01920         }
    01921
    01922         lpMem += WriteObject (lpMem, EndFunction);
    01923     }
    01924     return (SINT)(lpMem - lpOldMem);
    01925 }
    01926
    01927 //========================================================================
    01928 /***************************************************************************
    01929 *                  GetPS2PreviewColorRenderingDictionary
    01930 *  function:
    01931 *    This is the main function that creates proofing CRD.
    01932 *    It does the following:
    01933 *       1) Creates host TargetCRD, TargetCSA and DevCRD.
    01934 *       2) Create proofing CRD by sampling TargetCRD TargetCSA and DevCRD.
    01935 *       3) Uses TargetCRD's input table as proofingCRD's input table.
    01936 *       4) Uses DevCRD's output table as proofingCRD's output table.
    01937 *       5) Sample data is XYZ or Lab, depends on PCS of TargetCRD.
    01938 *
    01939 *  parameters:
    01940 *       CHANDLE  cpDev        -- handle to Target icc profile.
    01941 *       CHANDLE  cpTarget     -- handle to Dev icc profile.
    01942 *       DWORD    Intent       -- intent
    01943 *       MEMPTR   lpMem        -- pointer to buffer for proofCRD,
    01944 *                                NULL means query buffer size.
    01945 *       LPDWORD  lpcbSize     -- as input: current buffer size
    01946 *                             -- as output: real proofCRD size.
    01947 *       BOOL     bAllowBinary -- create a ascii or binary proofCRD.
    01948 *
    01949 *  returns:
    01950 *       BOOL                  -- TRUE/FALSE
    01951 ***************************************************************************/
    01952
    01953 BOOL EXTERN
    01954 GetPS2PreviewColorRenderingDictionary (CHANDLE cpDev,
    01955                                 CHANDLE cpTarget,
    01956                                 DWORD Intent,
    01957                                 MEMPTR lpMem,
    01958                                 LPDWORD lpcbSize,
    01959                                 BOOL bAllowBinary)
    01960 {
    01961     MEMPTR    lpTargetCRD, lpTargetCSA, lpDevCRD;
    01962     DWORD     cbTargetCRD, cbTargetCSA, cbDevCRD;
    01963     HGLOBAL   hTargetCRD, hTargetCSA, hDevCRD;
    01964     BOOL      Success = FALSE;
    01965     float     Input[MAXCHANNELS];
    01966     float     Output[MAXCHANNELS];
    01967     float     Temp[MAXCHANNELS];
    01968     int       i, j, k, l;
    01969     MEMPTR    lpLineStart;
    01970     MEMPTR    lpOldMem;
    01971     CSIG      ColorSpace;
    01972     CSIG      DevColorSpace;
    01973     static CSIG      IntentTag;
    01974     static SINT      PreviewCRDGrid;
    01975     SINT      OutArraySize, InArraySize;
    01976     char      PublicArrayName[TempBfSize];
    01977     SINT      TargetGrids, DevGrids;
    01978
    01979     // First pass, return the size of Previewind CRD.
    01980     if (lpMem == NULL)
    01981     {
    01982         SINT   dwOutArraySizr = 0;
    01983
    01984         i = 3;      // Default output channal;
    01985         if ((GetCPDevSpace (cpDev, (LPCSIG) & DevColorSpace)) &&
    01986                           (DevColorSpace == icSigCmykData))
    01987         {
    01988             i = 4;
    01989         }
    01990
    01991         // Get the input array size IntentTag and Grid of the Target icc profile.
    01992         if (!GetCRDInputOutputArraySize(cpTarget, Intent,
    01993             &InArraySize, NULL, &IntentTag, &TargetGrids ))
    01994             return FALSE;
    01995
    01996         // Get the output array size IntentTag and Grid of the Dev icc profile.
    01997         if (!GetCRDInputOutputArraySize(cpDev, Intent,
    01998             NULL, &OutArraySize, &IntentTag, &DevGrids ))
    01999             return FALSE;
    02000
    02001         PreviewCRDGrid = (TargetGrids > DevGrids)? TargetGrids: DevGrids;
    02002
    02003         // Min proofing CRD grid will be PREVIEWCRDGRID
    02004         if (PreviewCRDGrid < PREVIEWCRDGRID)
    02005             PreviewCRDGrid = PREVIEWCRDGRID;
    02006         *lpcbSize = PreviewCRDGrid * PreviewCRDGrid * PreviewCRDGrid *
    02007                     i * 2 +           // CLUT size (Hex output)
    02008                     OutArraySize +    // Output Array size
    02009                     InArraySize  +    // Input Array size
    02010                     4096;             // Extra PostScript staff.
    02011          return (TRUE);
    02012     }
    02013
    02014     // Second pass, return the Previewind CRD.
    02015     lpOldMem = lpMem;
    02016
    02017     //Query the sizes of Host TargetCRD, TargetCSA and DevCRD.
    02018     if (!(GetHostColorRenderingDictionary (cpTarget, Intent, NULL, &cbTargetCRD)) ||
    02019         !(GetHostColorSpaceArray (cpTarget, Intent, NULL, &cbTargetCSA)) ||
    02020         !(GetHostColorRenderingDictionary (cpDev, Intent, NULL, &cbDevCRD)))
    02021     {
    02022         return (Success);
    02023     }
    02024
    02025     //Alloc the buffers for Host TargetCRD, TargetCSA and DevCRD.
    02026     hTargetCRD = hTargetCSA = hDevCRD = 0;
    02027     if (!MemAlloc (cbTargetCRD, (HGLOBAL FAR *)&hTargetCRD, (LPMEMPTR)&lpTargetCRD) ||
    02028         !MemAlloc (cbTargetCSA, (HGLOBAL FAR *)&hTargetCSA, (LPMEMPTR)&lpTargetCSA) ||
    02029         !MemAlloc (cbDevCRD, (HGLOBAL FAR *)&hDevCRD, (LPMEMPTR)&lpDevCRD))
    02030     {
    02031         goto Done;
    02032     }
    02033
    02034     //Build Host TargetCRD, TargetCSA and DevCRD.
    02035     if (!(GetHostColorRenderingDictionary (cpTarget, Intent, lpTargetCRD, &cbTargetCRD)) ||
    02036         !(GetHostColorSpaceArray (cpTarget, Intent, lpTargetCSA, &cbTargetCSA)) ||
    02037         !(GetHostColorRenderingDictionary (cpDev, Intent, lpDevCRD, &cbDevCRD)))
    02038     {
    02039         goto Done;
    02040     }
    02041
    02042 //  Build Proofing CRD based on Host TargetCRD TargetCSA and DevCRD.
    02043 //  We use TargetCRD input tables and matrix as the
    02044 //  input tables and matrix of the ProofCRD.
    02045 //  We use DevCRD output tables as the output tables of the ProofCRD.
    02046
    02047 //******** Define golbal array used in EncodeABC and RenderTaber
    02048     GetPublicArrayName (cpDev, IntentTag, PublicArrayName);
    02049     lpMem += WriteNewLineObject (lpMem, CRDBegin);
    02050
    02051     lpMem += EnableGlobalDict(lpMem);
    02052     lpMem += BeginGlobalDict(lpMem);
    02053
    02054     lpMem += CreateInputArray (lpMem, (SINT)0, (SINT)0, (MEMPTR)PublicArrayName,
    02055              (CSIG)0, NULL, bAllowBinary, lpTargetCRD);
    02056
    02057     lpMem += CreateOutputArray (lpMem, (SINT)0, (SINT)0, (SINT)0,
    02058              (MEMPTR)PublicArrayName, (CSIG)0, NULL, bAllowBinary, lpDevCRD);
    02059
    02060     lpMem += EndGlobalDict(lpMem);
    02061
    02062 //************* Start writing  CRD  ****************************
    02063     lpMem += WriteNewLineObject (lpMem, BeginDict);    // Begin dictionary
    02064     lpMem += WriteObject (lpMem, DictType); // Dictionary type
    02065
    02066     lpMem += WriteNewLineObject (lpMem, IntentType); // RenderingIntent
    02067     switch (Intent)
    02068     {
    02069         case icPerceptual:
    02070             lpMem += WriteObject (lpMem, IntentPer);
    02071             break;
    02072
    02073         case icSaturation:
    02074             lpMem += WriteObject (lpMem, IntentSat);
    02075             break;
    02076
    02077         case icRelativeColorimetric:
    02078             lpMem += WriteObject (lpMem, IntentRCol);
    02079             break;
    02080
    02081         case icAbsoluteColorimetric:
    02082             lpMem += WriteObject (lpMem, IntentACol);
    02083             break;
    02084     }
    02085
    02086 //********** Send Black/White Point.
    02087     lpMem += SendCRDBWPoint(lpMem,
    02088         ((LPHOSTCLUT)lpTargetCRD)->whitePoint);
    02089
    02090 //********** Send PQR - For White Point correction
    02091     lpMem += SendCRDPQR(lpMem, Intent,
    02092         ((LPHOSTCLUT)lpTargetCRD)->whitePoint);
    02093
    02094 //********** Send LMN - For Absolute Colorimetric use WhitePoint's XYZs
    02095     lpMem += SendCRDLMN(lpMem, Intent,
    02096         ((LPHOSTCLUT)lpTargetCRD)->whitePoint,
    02097         ((LPHOSTCLUT)lpTargetCRD)->mediaWP,
    02098         ((LPHOSTCLUT)lpTargetCRD)->pcs);
    02099
    02100 //********** Create MatrixABC and  EncodeABC  stuff
    02101     lpMem += SendCRDABC(lpMem, PublicArrayName,
    02102         ((LPHOSTCLUT)lpTargetCRD)->pcs,
    02103         ((LPHOSTCLUT)lpTargetCRD)->inputChan,
    02104         NULL,
    02105         ((LPHOSTCLUT)lpTargetCRD)->e,
    02106         (((LPHOSTCLUT)lpTargetCRD)->lutBits == 8)? icSigLut8Type:icSigLut16Type,
    02107         bAllowBinary);
    02108
    02109 //********** /RenderTable
    02110     lpMem += WriteNewLineObject (lpMem, RenderTableTag);
    02111     lpMem += WriteObject (lpMem, BeginArray);
    02112
    02113     lpMem += WriteInt (lpMem, PreviewCRDGrid);  // Send down Na
    02114     lpMem += WriteInt (lpMem, PreviewCRDGrid);  // Send down Nb
    02115     lpMem += WriteInt (lpMem, PreviewCRDGrid);  // Send down Nc
    02116
    02117     lpLineStart = lpMem;
    02118     lpMem += WriteNewLineObject (lpMem, BeginArray);
    02119     ColorSpace = ((LPHOSTCLUT)lpDevCRD)->pcs;
    02120     for (i = 0; i < PreviewCRDGrid; i++)        // Na strings should be sent
    02121     {
    02122         lpMem += WriteObject (lpMem, NewLine);
    02123         lpLineStart = lpMem;
    02124         if (bAllowBinary)
    02125         {
    02126             lpMem += WriteStringToken (lpMem, 143,
    02127                 PreviewCRDGrid * PreviewCRDGrid * ((LPHOSTCLUT)lpDevCRD)->outputChan);
    02128         }
    02129         else
    02130         {
    02131             lpMem += WriteObject (lpMem, BeginString);
    02132         }
    02133         Input[0] = ((float)i) / (PreviewCRDGrid - 1);
    02134         for (j = 0; j < PreviewCRDGrid; j++)
    02135         {
    02136             Input[1] = ((float)j) / (PreviewCRDGrid - 1);
    02137             for (k = 0; k < PreviewCRDGrid; k++)
    02138             {
    02139                 Input[2] = ((float)k) / (PreviewCRDGrid - 1);
    02140
    02141                 DoHostConversionCRD ((LPHOSTCLUT)lpTargetCRD, NULL, Input, Output, ColorSpace, 1);
    02142                 DoHostConversionCSA ((LPHOSTCLUT)lpTargetCSA, Output, Temp);
    02143                 DoHostConversionCRD ((LPHOSTCLUT)lpDevCRD, (LPHOSTCLUT)lpTargetCSA,
    02144                                      Temp, Output, 0, 0);
    02145                 for (l = 0; l < ((LPHOSTCLUT)lpDevCRD)->outputChan; l++)
    02146                 {
    02147                     if (bAllowBinary)
    02148                     {
    02149                         *lpMem++ = (BYTES)(Output[l]*255);
    02150                     }
    02151                     else
    02152                     {
    02153                         lpMem += WriteHex (lpMem, (USHORT)(Output[l]*255));
    02154                         if (((SINT) (lpMem - lpLineStart)) > MAX_LINELENG)
    02155                         {
    02156                             lpLineStart = lpMem;
    02157                             lpMem += WriteObject (lpMem, NewLine);
    02158                         }
    02159                     }
    02160                 }
    02161             }
    02162         }
    02163         if (!bAllowBinary)
    02164             lpMem += WriteObject (lpMem, EndString);
    02165     }
    02166     lpMem += WriteNewLineObject (lpMem, EndArray);
    02167     lpMem += WriteInt (lpMem, ((LPHOSTCLUT)lpDevCRD)->outputChan);
    02168
    02169 //********** Send Output Table.
    02170     lpMem += SendCRDOutputTable(lpMem, PublicArrayName,
    02171         ((LPHOSTCLUT)lpDevCRD)->outputChan,
    02172         (((LPHOSTCLUT)lpDevCRD)->lutBits == 8)? icSigLut8Type:icSigLut16Type,
    02173         TRUE,
    02174         bAllowBinary);
    02175
    02176
    02177     lpMem += WriteNewLineObject (lpMem, EndArray);
    02178     lpMem += WriteObject (lpMem, EndDict); // End dictionary definition
    02179     lpMem += WriteNewLineObject (lpMem, CRDEnd);
    02180     Success = TRUE;
    02181
    02182 Done:
    02183     *lpcbSize = (DWORD)(lpMem - lpOldMem);
    02184
    02185     if (hTargetCRD)
    02186          MemFree(hTargetCRD);
    02187     if (hTargetCSA)
    02188          MemFree(hTargetCSA);
    02189     if (hDevCRD)
    02190          MemFree(hDevCRD);
    02191     return (Success);
    02192 }