test: ps2.c Source File

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

# ps2.c

Go to the documentation of this file.

    00001 /****************************Module*Header******************************\
    00002 * Module Name: PS2.C
    00003 *
    00004 * Module Descripton: Functions for retrieving or creating PostScript
    00005 *    Level 2 operators from a profile. It is shared by mscms & pscript5
    00006 *
    00007 * Warnings:
    00008 *
    00009 * Issues:
    00010 *
    00011 * Public Routines:
    00012 *
    00013 * Created:  13 May 1996
    00014 * Author:   Srinivasan Chandrasekar    [srinivac]
    00015 *
    00016 * Copyright (c) 1996, 1997  Microsoft Corporation
    00017 \***********************************************************************/
    00018
    00019 #include <math.h>
    00020
    00021 #define MAX_LINELEN             240
    00022 #define REVCURVE_RATIO          1
    00023 #define CIEXYZRange             0x1FFEC       // 1.9997 in 16.16 notation
    00024 #define ALIGN_DWORD(nBytes)     (((nBytes) + 3) & ~3)
    00025
    00026 #define FIX_16_16_SHIFT         16
    00027 #define FIX_16_16_SCALE         (1 << (FIX_16_16_SHIFT))
    00028
    00029 #define TO_FIX(x)               ((x) << FIX_16_16_SHIFT)
    00030 #define TO_INT(x)               ((x) >> FIX_16_16_SHIFT)
    00031 #define FIX_MUL(x, y)           MulDiv((x), (y), FIX_16_16_SCALE)
    00032 #define FIX_DIV(x, y)           MulDiv((x), FIX_16_16_SCALE, (y))
    00033
    00034 #define FLOOR(x)                ((x) >> FIX_16_16_SHIFT << FIX_16_16_SHIFT)
    00035
    00036 #define TYPE_CIEBASEDDEF        1
    00037 #define TYPE_CIEBASEDDEFG       2
    00038
    00039 #define TAG_PS2CSA              'ps2s'
    00040 #define TAG_REDCOLORANT         'rXYZ'
    00041 #define TAG_GREENCOLORANT       'gXYZ'
    00042 #define TAG_BLUECOLORANT        'bXYZ'
    00043 #define TAG_REDTRC              'rTRC'
    00044 #define TAG_GREENTRC            'gTRC'
    00045 #define TAG_BLUETRC             'bTRC'
    00046 #define TAG_GRAYTRC             'kTRC'
    00047 #define TAG_MEDIAWHITEPOINT     'wtpt'
    00048 #define TAG_AToB0               'A2B0'
    00049 #define TAG_AToB1               'A2B1'
    00050 #define TAG_AToB2               'A2B2'
    00051 #define TAG_PS2INTENT0          'psi0'
    00052 #define TAG_PS2INTENT1          'psi1'
    00053 #define TAG_PS2INTENT2          'psi2'
    00054 #define TAG_PS2INTENT3          'psi3'
    00055 #define TAG_CRDINTENT0          'psd0'
    00056 #define TAG_CRDINTENT1          'psd1'
    00057 #define TAG_CRDINTENT2          'psd2'
    00058 #define TAG_CRDINTENT3          'psd3'
    00059 #define TAG_BToA0               'B2A0'
    00060 #define TAG_BToA1               'B2A1'
    00061 #define TAG_BToA2               'B2A2'
    00062 #define TAG_BToA3               'B2A3'
    00063
    00064 #define LUT8_TYPE               'mft1'
    00065 #define LUT16_TYPE              'mft2'
    00066
    00067 #define SIG_CURVE_TYPE          'curv'
    00068
    00069 #define GetCPConnSpace(pProfile)     (FIX_ENDIAN(((PPROFILEHEADER)pProfile)->phConnectionSpace))
    00070 #define GetCPDevSpace(pProfile)      (FIX_ENDIAN(((PPROFILEHEADER)pProfile)->phDataColorSpace))
    00071 #define GetCPRenderIntent(pProfile)  (FIX_ENDIAN(((PPROFILEHEADER)pProfile)->phRenderingIntent))
    00072 #define WriteObject(pBuf, pStr)      (STRCPY(pBuf, pStr), STRLEN(pStr))
    00073
    00074 #ifdef KERNEL_MODE
    00075 #define WriteInt(pBuf, i)            OPSprintf(pBuf, "%l ", (i))
    00076 #define WriteHex(pBuf, x)            OPSprintf(pBuf, "%x", ((x) & 0x00FF))
    00077 #define STRLEN                       strlen
    00078 #define STRCPY                       strcpy
    00079 #else
    00080 #define WriteInt(pBuf, i)            wsprintfA(pBuf, "%lu ", (i))
    00081 #define WriteHex(pBuf, x)            wsprintfA(pBuf, "%2.2x", ((x) & 0x00FF))
    00082 #define STRLEN                       lstrlenA
    00083 #define STRCPY                       lstrcpyA
    00084 #endif
    00085
    00086 #define MAXCHANNELS             4
    00087 #define PREVIEWCRDGRID          16
    00088 #define MAXCOLOR8               255
    00089
    00090 #define DATATYPE_LUT            0
    00091 #define DATATYPE_MATRIX         1
    00092
    00093 #define sRGB_CRC                0xa3d777b4L
    00094 #define sRGB_TAGSIZE            6168
    00095
    00096 //
    00097 // Local typedefs
    00098 //
    00099
    00100 typedef DWORD FIX_16_16, *PFIX_16_16;
    00101
    00102 typedef struct tagCURVETYPE {
    00103     DWORD dwSignature;
    00104     DWORD dwReserved;
    00105     DWORD nCount;
    00106     WORD  data[0];
    00107 } CURVETYPE, *PCURVETYPE;
    00108
    00109 typedef struct tagXYZTYPE {
    00110     DWORD     dwSignature;
    00111     DWORD     dwReserved;
    00112     FIX_16_16 afxData[0];
    00113 } XYZTYPE, *PXYZTYPE;
    00114
    00115 typedef struct tagLUT8TYPE {
    00116     DWORD     dwSignature;
    00117     DWORD     dwReserved;
    00118     BYTE      nInputChannels;
    00119     BYTE      nOutputChannels;
    00120     BYTE      nClutPoints;
    00121     BYTE      padding;
    00122     FIX_16_16 e00;
    00123     FIX_16_16 e01;
    00124     FIX_16_16 e02;
    00125     FIX_16_16 e10;
    00126     FIX_16_16 e11;
    00127     FIX_16_16 e12;
    00128     FIX_16_16 e20;
    00129     FIX_16_16 e21;
    00130     FIX_16_16 e22;
    00131     BYTE      data[0];
    00132 } LUT8TYPE, *PLUT8TYPE;
    00133
    00134 typedef struct tagLUT16TYPE {
    00135     DWORD     dwSignature;
    00136     DWORD     dwReserved;
    00137     BYTE      nInputChannels;
    00138     BYTE      nOutputChannels;
    00139     BYTE      nClutPoints;
    00140     BYTE      padding;
    00141     FIX_16_16 e00;
    00142     FIX_16_16 e01;
    00143     FIX_16_16 e02;
    00144     FIX_16_16 e10;
    00145     FIX_16_16 e11;
    00146     FIX_16_16 e12;
    00147     FIX_16_16 e20;
    00148     FIX_16_16 e21;
    00149     FIX_16_16 e22;
    00150     WORD      wInputEntries;
    00151     WORD      wOutputEntries;
    00152     WORD      data[0];
    00153 } LUT16TYPE, *PLUT16TYPE;
    00154
    00155 typedef struct tagHOSTCLUT {
    00156     WORD        wSize;
    00157     WORD        wDataType;
    00158     DWORD       dwDev;
    00159     DWORD       dwPCS;
    00160     DWORD       dwIntent;
    00161     FIX_16_16   afxIlluminantWP[3];
    00162     FIX_16_16   afxMediaWP[3];
    00163     BYTE        nInputCh;
    00164     BYTE        nOutputCh;
    00165     BYTE        nClutPoints;
    00166     BYTE        nLutBits;
    00167     FIX_16_16   e[9];
    00168     WORD        nInputEntries;
    00169     WORD        nOutputEntries;
    00170     PBYTE       inputArray[MAXCHANNELS];
    00171     PBYTE       outputArray[MAXCHANNELS];
    00172     PBYTE       clut;
    00173 } HOSTCLUT, *PHOSTCLUT;
    00174
    00175 //
    00176 // Internal functions
    00177 //
    00178
    00179 BOOL  IsSRGBColorProfile(PBYTE);
    00180
    00181 BOOL  GetCSAFromProfile (PBYTE, DWORD, DWORD, PBYTE, PDWORD, PBOOL);
    00182 BOOL  GetPS2CSA_MONO_A(PBYTE, PBYTE, PDWORD, DWORD, PBOOL);
    00183 BOOL  GetPS2CSA_ABC(PBYTE, PBYTE, PDWORD, DWORD, PBOOL, BOOL);
    00184 BOOL  GetPS2CSA_ABC_Lab(PBYTE, PBYTE, PDWORD, DWORD, PBOOL);
    00185 BOOL  GetPS2CSA_DEFG(PBYTE, PBYTE, PDWORD, DWORD, DWORD, PBOOL);
    00186
    00187 BOOL  CreateMonoCRD(PBYTE, DWORD, PBYTE, PDWORD, DWORD);
    00188 BOOL  CreateLutCRD(PBYTE, DWORD, PBYTE, PDWORD, DWORD, BOOL);
    00189
    00190 BOOL  DoesCPTagExist(PBYTE, DWORD, PDWORD);
    00191 BOOL  DoesTRCAndColorantTagExist(PBYTE);
    00192 BOOL  GetCPWhitePoint(PBYTE, PFIX_16_16);
    00193 BOOL  GetCPMediaWhitePoint(PBYTE, PFIX_16_16);
    00194 BOOL  GetCPElementDataSize(PBYTE, DWORD, PDWORD);
    00195 BOOL  GetCPElementSize(PBYTE, DWORD, PDWORD);
    00196 BOOL  GetCPElementDataType(PBYTE, DWORD, PDWORD);
    00197 BOOL  GetCPElementData(PBYTE, DWORD, PBYTE, PDWORD);
    00198 BOOL  GetTRCElementSize(PBYTE, DWORD, PDWORD, PDWORD);
    00199
    00200 DWORD Ascii85Encode(PBYTE, DWORD, DWORD);
    00201
    00202 BOOL  GetCRDInputOutputArraySize(PBYTE, DWORD, PDWORD, PDWORD, PDWORD, PDWORD);
    00203 BOOL  GetHostCSA(PBYTE, PBYTE, PDWORD, DWORD, DWORD);
    00204 BOOL  GetHostColorRenderingDictionary(PBYTE, DWORD, PBYTE, PDWORD);
    00205 BOOL  GetHostColorSpaceArray(PBYTE, DWORD, PBYTE, PDWORD);
    00206
    00207 DWORD SendCRDBWPoint(PBYTE, PFIX_16_16);
    00208 DWORD SendCRDPQR(PBYTE, DWORD, PFIX_16_16);
    00209 DWORD SendCRDLMN(PBYTE, DWORD, PFIX_16_16, PFIX_16_16, DWORD);
    00210 DWORD SendCRDABC(PBYTE, PBYTE, DWORD, DWORD, PBYTE, PFIX_16_16, DWORD, BOOL);
    00211 DWORD SendCRDOutputTable(PBYTE, PBYTE, DWORD, DWORD, BOOL, BOOL);
    00212
    00213 DWORD SendCSABWPoint(PBYTE, DWORD, PFIX_16_16, PFIX_16_16);
    00214 VOID  GetMediaWP(PBYTE, DWORD, PFIX_16_16, PFIX_16_16);
    00215
    00216 DWORD CreateCRDRevArray(PBYTE, PBYTE, PCURVETYPE, PWORD, DWORD, BOOL);
    00217 DWORD SendCRDRevArray(PBYTE, PBYTE, PCURVETYPE, DWORD, BOOL);
    00218
    00219 DWORD CreateColSpArray(PBYTE, PBYTE, DWORD, BOOL);
    00220 DWORD CreateColSpProc(PBYTE, PBYTE, DWORD, BOOL);
    00221 DWORD CreateFloatString(PBYTE, PBYTE, DWORD);
    00222 DWORD CreateInputArray(PBYTE, DWORD, DWORD, PBYTE, DWORD, PBYTE, BOOL, PBYTE);
    00223 DWORD CreateOutputArray(PBYTE, DWORD, DWORD, DWORD, PBYTE, DWORD, PBYTE, BOOL, PBYTE);
    00224
    00225 DWORD GetPublicArrayName(DWORD, PBYTE);
    00226 BOOL  GetRevCurve(PCURVETYPE, PWORD, PWORD);
    00227 VOID  GetCLUTInfo(DWORD, PBYTE, PDWORD, PDWORD, PDWORD, PDWORD, PDWORD, PDWORD);
    00228 DWORD EnableGlobalDict(PBYTE);
    00229 DWORD BeginGlobalDict(PBYTE);
    00230 DWORD EndGlobalDict(PBYTE);
    00231
    00232 DWORD WriteNewLineObject(PBYTE, const char *);
    00233 DWORD WriteHNAToken(PBYTE, BYTE, DWORD);
    00234 DWORD WriteIntStringU2S(PBYTE, PBYTE, DWORD);
    00235 DWORD WriteIntStringU2S_L(PBYTE, PBYTE, DWORD);
    00236 DWORD WriteHexBuffer(PBYTE, PBYTE, PBYTE, DWORD);
    00237 DWORD WriteStringToken(PBYTE, BYTE, DWORD);
    00238 DWORD WriteByteString(PBYTE, PBYTE, DWORD);
    00239 DWORD WriteInt2ByteString(PBYTE, PBYTE, DWORD);
    00240 DWORD WriteFixed(PBYTE, FIX_16_16);
    00241 DWORD WriteFixed2dot30(PBYTE, DWORD);
    00242 #if !defined(KERNEL_MODE) || defined(USERMODE_DRIVER)
    00243 DWORD WriteDouble(PBYTE, double);
    00244
    00245 BOOL  CreateMatrixCRD(PBYTE, PBYTE, PDWORD, DWORD, BOOL);
    00246 DWORD CreateHostLutCRD(PBYTE, DWORD, PBYTE, DWORD);
    00247 DWORD CreateHostMatrixCSAorCRD(PBYTE, PBYTE, PDWORD, DWORD, BOOL);
    00248 DWORD CreateHostInputOutputArray(PBYTE, PBYTE*, DWORD, DWORD, DWORD, DWORD, PBYTE);
    00249 DWORD CreateHostTRCInputTable(PBYTE, PHOSTCLUT, PCURVETYPE, PCURVETYPE, PCURVETYPE);
    00250 DWORD CreateHostRevTRCInputTable(PBYTE, PHOSTCLUT, PCURVETYPE, PCURVETYPE, PCURVETYPE);
    00251
    00252 BOOL  CheckInputOutputTable(PHOSTCLUT, float*, BOOL, BOOL);
    00253 BOOL  CheckColorLookupTable(PHOSTCLUT, float*);
    00254
    00255 BOOL  DoHostConversionCSA(PHOSTCLUT, float*, float*);
    00256 BOOL  DoHostConversionCRD(PHOSTCLUT, PHOSTCLUT, float*, float*, BOOL);
    00257
    00258 float g(float);
    00259 float inverse_g(float);
    00260 BOOL  TableInterp3(PHOSTCLUT, float*);
    00261 BOOL  TableInterp4(PHOSTCLUT, float*);
    00262 void  LabToXYZ(float*, float*, PFIX_16_16);
    00263 void  XYZToLab(float*, float*, PFIX_16_16);
    00264 VOID  ApplyMatrix(FIX_16_16 *e, float *Input, float *Output);
    00265
    00266 BOOL  CreateColorantArray(PBYTE, double *, DWORD);
    00267 BOOL  InvertColorantArray(double *, double *);
    00268 #endif
    00269
    00270 DWORD crc32(PBYTE buff, DWORD length);
    00271
    00272 //
    00273 // Global variables
    00274 //
    00275
    00276 const char  ASCII85DecodeBegin[] = "<~";
    00277 const char  ASCII85DecodeEnd[]   = "~> cvx exec ";
    00278 const char  TestingDEFG[]       = "/SupportDEFG? {/CIEBasedDEFG \
    00279  /ColorSpaceFamily resourcestatus { pop pop languagelevel 3 ge}{false} ifelse} def";
    00280 const char  SupportDEFG_S[]     = "SupportDEFG? { ";
    00281 const char  NotSupportDEFG_S[]  = "SupportDEFG? not { ";
    00282 const char  SupportDEFG_E[]     = "}if ";
    00283 const char  IndexArray16b[]     = " dup length 1 sub 3 -1 roll mul dup dup floor cvi\
    00284  exch ceiling cvi 3 index exch get 32768 add 4 -1 roll 3 -1 roll get 32768 add\
    00285  dup 3 1 roll sub 3 -1 roll dup floor cvi sub mul add ";
    00286
    00287 const char  IndexArray[]        = " dup length 1 sub 3 -1 roll mul dup dup floor cvi\
    00288  exch ceiling cvi 3 index exch get 4 -1 roll 3 -1 roll get\
    00289  dup 3 1 roll sub 3 -1 roll dup floor cvi sub mul add ";
    00290 const char  StartClip[]         = "dup 1.0 le{dup 0.0 ge{" ;
    00291 const char  EndClip[]           = "}if}if " ;
    00292 const char  BeginString[]       = "<";
    00293 const char  EndString[]         = ">";
    00294 const char  BeginArray[]        = "[";
    00295 const char  EndArray[]          = "]";
    00296 const char  BeginFunction[]     = "{";
    00297 const char  EndFunction[]       = "}bind ";
    00298 const char  BeginDict[]         = "<<" ;
    00299 const char  EndDict[]           = ">>" ;
    00300 const char  BlackPoint[]        = "[0 0 0]" ;
    00301 const char  DictType[]          = "/ColorRenderingType 1 ";
    00302 const char  IntentType[]        = "/RenderingIntent ";
    00303 const char  IntentPer[]         = "/Perceptual";
    00304 const char  IntentSat[]         = "/Saturation";
    00305 const char  IntentACol[]        = "/AbsoluteColorimetric";
    00306 const char  IntentRCol[]        = "/RelativeColorimetric";
    00307
    00308 const char  WhitePointTag[]     = "/WhitePoint " ;
    00309 const char  BlackPointTag[]     = "/BlackPoint " ;
    00310 const char  RangePQRTag[]       = "/RangePQR " ;
    00311 const char  TransformPQRTag[]   = "/TransformPQR " ;
    00312 const char  MatrixPQRTag[]      = "/MatrixPQR " ;
    00313 const char  RangePQR[]          = "[ -0.07 2.2 -0.02 1.4 -0.2 4.8 ]";
    00314 const char  MatrixPQR[]         = "[0.8951 -0.7502 0.0389 0.2664 1.7135 -0.0685 -0.1614 0.0367 1.0296]";
    00315 #ifdef BARDFORD_TRANSFORM
    00316 const char  *TransformPQR[3]    = {"exch pop exch 3 get mul exch pop exch 3 get div ",
    00317                                    "exch pop exch 4 get mul exch pop exch 4 get div ",
    00318                                    "exch pop exch 5 get mul exch pop exch 5 get div " };
    00319 #else
    00320 const char  *TransformPQR[3]    = {"4 index 0 get div 2 index 0 get mul 4 {exch pop} repeat ",
    00321                                    "4 index 1 get div 2 index 1 get mul 4 {exch pop} repeat ",
    00322                                    "4 index 2 get div 2 index 2 get mul 4 {exch pop} repeat " };
    00323 #endif
    00324 const char  RangeABCTag[]       = "/RangeABC " ;
    00325 const char  MatrixATag[]        = "/MatrixA ";
    00326 const char  MatrixABCTag[]      = "/MatrixABC ";
    00327 const char  EncodeABCTag[]      = "/EncodeABC " ;
    00328 const char  RangeLMNTag[]       = "/RangeLMN " ;
    00329 const char  MatrixLMNTag[]      = "/MatrixLMN " ;
    00330 const char  EncodeLMNTag[]      = "/EncodeLMN " ;
    00331 const char  RenderTableTag[]    = "/RenderTable " ;
    00332 const char  CIEBasedATag[]      = "/CIEBasedA " ;
    00333 const char  CIEBasedABCTag[]    = "/CIEBasedABC " ;
    00334 const char  CIEBasedDEFGTag[]   = "/CIEBasedDEFG " ;
    00335 const char  CIEBasedDEFTag[]    = "/CIEBasedDEF " ;
    00336 const char  DecodeATag[]        = "/DecodeA " ;
    00337 const char  DecodeABCTag[]      = "/DecodeABC " ;
    00338 const char  DecodeLMNTag[]      = "/DecodeLMN " ;
    00339 const char  DeviceRGBTag[]      = "/DeviceRGB " ;
    00340 const char  DeviceCMYKTag[]     = "/DeviceCMYK " ;
    00341 const char  DeviceGrayTag[]     = "/DeviceGray " ;
    00342 const char  TableTag[]          = "/Table " ;
    00343 const char  DecodeDEFGTag[]     = "/DecodeDEFG " ;
    00344 const char  DecodeDEFTag[]      = "/DecodeDEF " ;
    00345
    00346 const char  NullOp[]            = "";
    00347 const char  DupOp[]             = "dup ";
    00348 const char  UserDictOp[]        = "userdict ";
    00349 const char  GlobalDictOp[]      = "globaldict ";
    00350 const char  CurrentGlobalOp[]   = "currentglobal ";
    00351 const char  SetGlobalOp[]       = "setglobal ";
    00352 const char  DefOp[]             = "def ";
    00353 const char  BeginOp[]           = "begin ";
    00354 const char  EndOp[]             = "end ";
    00355 const char  TrueOp[]            = "true ";
    00356 const char  FalseOp[]           = "false ";
    00357 const char  MulOp[]             = "mul ";
    00358 const char  DivOp[]             = "div ";
    00359
    00360 const char  NewLine[]           = "\r\n" ;
    00361 const char  Slash[]             = "/" ;
    00362 const char  Space[]             = " " ;
    00363 const char  CRDBegin[]          = "%** CRD Begin ";
    00364 const char  CRDEnd[]            = "%** CRD End ";
    00365 const char  CieBasedDEFGBegin[] = "%** CieBasedDEFG CSA Begin ";
    00366 const char  CieBasedDEFBegin[]  = "%** CieBasedDEF CSA Begin ";
    00367 const char  CieBasedABCBegin[]  = "%** CieBasedABC CSA Begin ";
    00368 const char  CieBasedABegin[]    = "%** CieBasedA CSA Begin ";
    00369 const char  CieBasedDEFGEnd[]   = "%** CieBasedDEFG CSA End ";
    00370 const char  CieBasedDEFEnd[]    = "%** CieBasedDEF CSA End ";
    00371 const char  CieBasedABCEnd[]    = "%** CieBasedABC CSA End ";
    00372 const char  CieBasedAEnd[]      = "%** CieBasedA CSA End ";
    00373 const char  RangeABC[]          = "[ 0 1 0 1 0 1 ] ";
    00374 const char  RangeLMN[]          = "[ 0 2 0 2 0 2 ] ";
    00375 const char  Identity[]          = "[1 0 0 0 1 0 0 0 1]";
    00376 const char  RangeABC_Lab[]      = "[0 100 -128 127 -128 127]";
    00377 const char  Clip01[]            = "dup 1.0 ge{pop 1.0}{dup 0.0 lt{pop 0.0}if}ifelse " ;
    00378 const char  DecodeA3[]          = "256 div exp ";
    00379 const char  DecodeA3Rev[]       = "256 div 1.0 exch div exp ";
    00380 const char  DecodeABCArray[]    = "DecodeABC_";
    00381 const char  InputArray[]        = "Inp_";
    00382 const char  OutputArray[]       = "Out_";
    00383 const char  Scale8[]            = "255 div " ;
    00384 const char  Scale16[]           = "65535 div " ;
    00385 const char  Scale16XYZ[]        = "32768 div " ;
    00386 const char  TFunction8[]        = "exch 255 mul round cvi get 255 div " ;
    00387 const char  TFunction8XYZ[]     = "exch 255 mul round cvi get 128 div " ;
    00388 const char  MatrixABCLab[]      = "[1 1 1 1 0 0 0 0 -1]" ;
    00389 const char  DecodeABCLab1[]     = "[{16 add 116 div} bind {500 div} bind {200 div} bind]";
    00390 const char  DecodeALab[]        = " 50 mul 16 add 116 div ";
    00391 const char  DecodeLMNLab[]      = "dup 0.206897 ge{dup dup mul mul}{0.137931 sub 0.128419 mul} ifelse ";
    00392
    00393 const char  RangeLMNLab[]       = "[0 1 0 1 0 1]" ;
    00394 const char  EncodeLMNLab[]      = "dup 0.008856 le{7.787 mul 0.13793 add}{0.3333 exp}ifelse " ;
    00395
    00396 const char  MatrixABCLabCRD[]   = "[0 500 0 116 -500 200 0 0 -200]" ;
    00397 const char  MatrixABCXYZCRD[]   = "[0 1 0 1 0 0 0 0 1]" ;
    00398 const char  EncodeABCLab1[]     = "16 sub 100 div " ;
    00399 const char  EncodeABCLab2[]     = "128 add 255 div " ;
    00400 const char  *DecodeABCLab[]     = {"50 mul 16 add 116 div ",
    00401                                    "128 mul 128 sub 500 div",
    00402                                    "128 mul 128 sub 200 div"};
    00403
    00404 const char ColorSpace1[]        = "/CIEBasedABC << /DecodeLMN ";
    00405 const char ColorSpace3[]        = " exp} bind ";
    00406 const char ColorSpace5[]        = "/WhitePoint [0.9642 1 0.8249] ";
    00407
    00408 const char PreViewInArray[]     = "IPV_";
    00409 const char PreViewOutArray[]    = "OPV_";
    00410
    00411 const char sRGBColorSpaceArray[] = "[/CIEBasedABC << \r\n\
    00412 /DecodeLMN [{dup 0.03928 le {12.92321 div}{0.055 add 1.055 div 2.4 exp}ifelse} bind dup dup ] \r\n\
    00413 /MatrixLMN [0.412457 0.212673 0.019334 0.357576 0.715152 0.119192 0.180437 0.072175 0.950301] \r\n\
    00414 /WhitePoint [ 0.9505 1 1.0890 ] >> ]";
    00415
    00416 #ifdef BRADFORD_TRANSFORM
    00417 const char sRGBColorRenderingDictionary[] = "\
    00418 /RangePQR [ -0.5 2 -0.5 2 -0.5 2 ] \r\n\
    00419 /MatrixPQR [0.8951 -0.7502  0.0389 0.2664  1.7135 -0.0685 -0.1614  0.0367  1.0296] \r\n\
    00420 /TransformPQR [\
    00421 {exch pop exch 3 get mul exch pop exch 3 get div} bind \
    00422 {exch pop exch 4 get mul exch pop exch 4 get div} bind \
    00423 {exch pop exch 5 get mul exch pop exch 5 get div} bind] \r\n\
    00424 /MatrixLMN [3.240449 -0.969265  0.055643 -1.537136  1.876011 -0.204026 -0.498531  0.041556  1.057229] \r\n\
    00425 /EncodeABC [{dup 0.00304 le {12.92321 mul}{1 2.4 div exp 1.055 mul 0.055 sub}ifelse} bind dup dup] \r\n\
    00426 /WhitePoint[0.9505 1 1.0890] >>";
    00427 #else
    00428 const char sRGBColorRenderingDictionary[] = "\
    00429 /RangePQR [ -0.5 2 -0.5 2 -0.5 2 ] \r\n\
    00430 /MatrixPQR [0.8951 -0.7502  0.0389 0.2664  1.7135 -0.0685 -0.1614  0.0367  1.0296] \r\n\
    00431 /TransformPQR [\
    00432 {4 index 0 get div 2 index 0 get mul 4 {exch pop} repeat} \
    00433 {4 index 1 get div 2 index 1 get mul 4 {exch pop} repeat} \
    00434 {4 index 2 get div 2 index 2 get mul 4 {exch pop} repeat}] \r\n\
    00435 /MatrixLMN [3.240449 -0.969265  0.055643 -1.537136  1.876011 -0.204026 -0.498531  0.041556  1.057229] \r\n\
    00436 /EncodeABC [{dup 0.00304 le {12.92321 mul}{1 2.4 div exp 1.055 mul 0.055 sub}ifelse} bind dup dup] \r\n\
    00437 /WhitePoint[0.9505 1 1.0890] >>";
    00438 #endif
    00439
    00440 /******************************************************************************
    00441  *
    00442  *                       InternalGetPS2ColorSpaceArray
    00443  *
    00444  *  Function:
    00445  *       This functions retrieves the PostScript Level 2 CSA from the profile,
    00446  *       or creates it if the profile tag is not present
    00447  *
    00448  *  Arguments:
    00449  *       hProfile  - handle identifing the profile object
    00450  *       dwIntent  - rendering intent of CSA
    00451  *       dwCSAType - type of CSA
    00452  *       pbuffer   - pointer to receive the CSA
    00453  *       pcbSize   - pointer to size of buffer. If function fails because
    00454  *                   buffer is not big enough, it is filled with required size.
    00455  *       pcbBinary - TRUE if binary data is requested. On return it is set to
    00456  *                   reflect the data returned
    00457  *
    00458  *  Returns:
    00459  *       TRUE if successful, FALSE otherwise
    00460  *
    00461  ******************************************************************************/
    00462
    00463 BOOL
    00464 InternalGetPS2ColorSpaceArray (
    00465     PBYTE     pProfile,
    00466     DWORD     dwIntent,
    00467     DWORD     dwCSAType,
    00468     PBYTE     pBuffer,
    00469     PDWORD    pcbSize,
    00470     LPBOOL    pbBinary
    00471     )
    00472 {
    00473     DWORD dwInpBufSize;
    00474     BOOL  bRc;
    00475
    00476     //
    00477     // If profile has a CSA tag, get it directly
    00478     //
    00479
    00480     bRc = GetCSAFromProfile(pProfile, dwIntent, dwCSAType, pBuffer,
    00481               pcbSize, pbBinary);
    00482
    00483     if (! bRc && (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
    00484     {
    00485         //
    00486         // Create a CSA from the profile data
    00487         //
    00488
    00489         switch (dwCSAType)
    00490         {
    00491         case CSA_ABC:
    00492             bRc = GetPS2CSA_ABC(pProfile, pBuffer, pcbSize,
    00493                       dwIntent, pbBinary, FALSE);
    00494             break;
    00495
    00496         case CSA_DEF:
    00497             bRc = GetPS2CSA_DEFG(pProfile, pBuffer, pcbSize, dwIntent,
    00498                       TYPE_CIEBASEDDEF, pbBinary);
    00499             break;
    00500
    00501         case CSA_RGB:
    00502         case CSA_Lab:
    00503
    00504             dwInpBufSize = *pcbSize;
    00505
    00506             //
    00507             // We get a DEF CSA followed by an ABC CSA and set it up so that
    00508             // on PS interpreters that do not support the DEF CSA, the ABC one
    00509             // is active
    00510             //
    00511
    00512             bRc = GetPS2CSA_DEFG(pProfile, pBuffer, pcbSize, dwIntent,
    00513                       TYPE_CIEBASEDDEF, pbBinary);
    00514
    00515             if (bRc)
    00516             {
    00517                 //
    00518                 // Create CieBasedABC for printers that do not support CieBasedDEF
    00519                 //
    00520
    00521                 DWORD cbNewSize = 0;
    00522                 PBYTE pNewBuffer;
    00523                 PBYTE pOldBuffer;
    00524
    00525                 if (pBuffer)
    00526                 {
    00527                     pNewBuffer = pBuffer + *pcbSize;
    00528                     pOldBuffer = pNewBuffer;
    00529                     pNewBuffer += WriteObject(pNewBuffer, NewLine);
    00530                     if (dwCSAType == CSA_Lab)
    00531                     {
    00532                         pNewBuffer += WriteNewLineObject(pNewBuffer, NotSupportDEFG_S);
    00533                     }
    00534                     cbNewSize = dwInpBufSize - (DWORD)(pNewBuffer - pBuffer);
    00535                 }
    00536                 else
    00537                 {
    00538                     pNewBuffer = NULL;
    00539                 }
    00540
    00541                 bRc = GetPS2CSA_ABC(pProfile, pNewBuffer, &cbNewSize,
    00542                           dwIntent, pbBinary, TRUE);
    00543
    00544                 if (pBuffer)
    00545                 {
    00546                     pNewBuffer += cbNewSize;
    00547                     if (dwCSAType == CSA_Lab)
    00548                     {
    00549                         pNewBuffer += WriteNewLineObject(pNewBuffer, SupportDEFG_E);
    00550                     }
    00551                     *pcbSize += (DWORD) (pNewBuffer - pOldBuffer);
    00552                 }
    00553                 else
    00554                 {
    00555                     *pcbSize += cbNewSize;
    00556                 }
    00557
    00558             }
    00559             else
    00560             {
    00561                 *pcbSize = dwInpBufSize;
    00562
    00563                 bRc = GetPS2CSA_ABC(pProfile, pBuffer, pcbSize, dwIntent, pbBinary, FALSE);
    00564             }
    00565
    00566             break;
    00567
    00568         case CSA_CMYK:
    00569         case CSA_DEFG:
    00570             bRc = GetPS2CSA_DEFG(pProfile, pBuffer, pcbSize, dwIntent,
    00571                       TYPE_CIEBASEDDEFG, pbBinary);
    00572             break;
    00573
    00574         case CSA_GRAY:
    00575         case CSA_A:
    00576             bRc = GetPS2CSA_MONO_A(pProfile, pBuffer, pcbSize, dwIntent, pbBinary);
    00577             break;
    00578
    00579         default:
    00580             WARNING((__TEXT("Invalid CSA type passed to GetPS2ColorSpaceArray: %d\n"), dwCSAType));
    00581             SetLastError(ERROR_INVALID_PARAMETER);
    00582             return FALSE;
    00583         }
    00584     }
    00585
    00586     return bRc;
    00587 }
    00588
    00589
    00590 /******************************************************************************
    00591  *
    00592  *                       InternalGetPS2ColorRenderingIntent
    00593  *
    00594  *  Function:
    00595  *       This functions retrieves the PostScript Level 2 color rendering intent
    00596  *       from the profile, or creates it if the profile tag is not present
    00597  *
    00598  *  Arguments:
    00599  *       hProfile  - handle identifing the profile object
    00600  *       pbuffer   - pointer to receive the color rendering intent
    00601  *       pcbSize   - pointer to size of buffer. If function fails because
    00602  *                   buffer is not big enough, it is filled with required size.
    00603  *       pcbBinary - TRUE if binary data is requested. On return it is set to
    00604  *                   reflect the data returned
    00605  *
    00606  *  Returns:
    00607  *       TRUE if successful, FALSE otherwise
    00608  *
    00609  ******************************************************************************/
    00610
    00611 BOOL
    00612 InternalGetPS2ColorRenderingIntent(
    00613     PBYTE     pProfile,
    00614     DWORD     dwIntent,
    00615     PBYTE     pBuffer,
    00616     PDWORD    pcbSize
    00617     )
    00618 {
    00619     DWORD dwIndex, dwTag, dwSize;
    00620     BOOL  bRc = FALSE;
    00621
    00622     switch (dwIntent)
    00623     {
    00624     case INTENT_PERCEPTUAL:
    00625         dwTag = TAG_PS2INTENT0;
    00626         break;
    00627
    00628     case INTENT_RELATIVE_COLORIMETRIC:
    00629         dwTag = TAG_PS2INTENT1;
    00630         break;
    00631
    00632     case INTENT_SATURATION:
    00633         dwTag = TAG_PS2INTENT2;
    00634         break;
    00635
    00636     case INTENT_ABSOLUTE_COLORIMETRIC:
    00637         dwTag = TAG_PS2INTENT3;
    00638         break;
    00639
    00640     default:
    00641         WARNING((__TEXT("Invalid intent passed to GetPS2ColorRenderingIntent: %d\n"), dwIntent));
    00642         SetLastError(ERROR_INVALID_PARAMETER);
    00643         return FALSE;
    00644     }
    00645
    00646     if (DoesCPTagExist(pProfile, dwTag, &dwIndex))
    00647     {
    00648         (void)GetCPElementDataSize(pProfile, dwIndex, &dwSize);
    00649
    00650         if (pBuffer)
    00651         {
    00652             if (*pcbSize >= dwSize + 1) // for NULL terminating
    00653             {
    00654                 bRc = GetCPElementData(pProfile, dwIndex, pBuffer, &dwSize);
    00655             }
    00656             else
    00657             {
    00658                 WARNING((__TEXT("Buffer too small to get CRI\n")));
    00659                 SetLastError(ERROR_INSUFFICIENT_BUFFER);
    00660             }
    00661         }
    00662         else
    00663             bRc = TRUE;
    00664
    00665         *pcbSize = dwSize;
    00666     }
    00667     else
    00668     {
    00669         WARNING((__TEXT("psi tag not present for intent %d in profile\n"), dwIntent));
    00670         SetLastError(ERROR_TAG_NOT_PRESENT);
    00671     }
    00672
    00673     //
    00674     // NULL terminate
    00675     //
    00676
    00677     if (bRc)
    00678     {
    00679         if (pBuffer)
    00680         {
    00681             pBuffer[*pcbSize] = '\0';
    00682         }
    00683         (*pcbSize)++;
    00684     }
    00685
    00686     return bRc;
    00687 }
    00688
    00689
    00690 /******************************************************************************
    00691  *
    00692  *                       InternalGetPS2ColorRenderingDictionary
    00693  *
    00694  *  Function:
    00695  *       This functions retrieves the PostScript Level 2 CRD from the profile,
    00696  *       or creates it if the profile tag is not preesnt
    00697  *
    00698  *  Arguments:
    00699  *       hProfile  - handle identifing the profile object
    00700  *       dwIntent  - intent whose CRD is required
    00701  *       pbuffer   - pointer to receive the CSA
    00702  *       pcbSize   - pointer to size of buffer. If function fails because
    00703  *                   buffer is not big enough, it is filled with required size.
    00704  *       pcbBinary - TRUE if binary data is requested. On return it is set to
    00705  *                   reflect the data returned
    00706  *
    00707  *  Returns:
    00708  *       TRUE if successful, FALSE otherwise
    00709  *
    00710  ******************************************************************************/
    00711
    00712 BOOL
    00713 InternalGetPS2ColorRenderingDictionary(
    00714     PBYTE     pProfile,
    00715     DWORD     dwIntent,
    00716     PBYTE     pBuffer,
    00717     PDWORD    pcbSize,
    00718     PBOOL     pbBinary
    00719     )
    00720 {
    00721     DWORD dwIndex, dwSize, dwDataType;
    00722     DWORD dwCRDTag, dwBToATag;
    00723     BOOL  bRc = FALSE;
    00724
    00725     switch (dwIntent)
    00726     {
    00727     case INTENT_PERCEPTUAL:
    00728         dwCRDTag = TAG_CRDINTENT0;
    00729         dwBToATag = TAG_BToA0;
    00730         break;
    00731
    00732     case INTENT_RELATIVE_COLORIMETRIC:
    00733         dwCRDTag = TAG_CRDINTENT1;
    00734         dwBToATag = TAG_BToA1;
    00735         break;
    00736
    00737     case INTENT_SATURATION:
    00738         dwCRDTag = TAG_CRDINTENT2;
    00739         dwBToATag = TAG_BToA2;
    00740         break;
    00741
    00742     case INTENT_ABSOLUTE_COLORIMETRIC:
    00743         dwCRDTag = TAG_CRDINTENT3;
    00744         dwBToATag = TAG_BToA1;
    00745         break;
    00746
    00747     default:
    00748         WARNING((__TEXT("Invalid intent passed to GetPS2ColorRenderingDictionary: %d\n"), dwIntent));
    00749         SetLastError(ERROR_INVALID_PARAMETER);
    00750         return bRc;
    00751     }
    00752
    00753     if (DoesCPTagExist(pProfile, dwCRDTag, &dwIndex))
    00754     {
    00755         (void)GetCPElementDataSize(pProfile, dwIndex, &dwSize);
    00756
    00757         (void)GetCPElementDataType(pProfile, dwIndex, &dwDataType);
    00758
    00759         if (! *pbBinary && dwDataType == 1)
    00760         {
    00761             //
    00762             // Profile has binary data, user asked for ASCII, so we have to
    00763             // ASCII 85 encode it
    00764             //
    00765
    00766             dwSize = dwSize * 5 / 4 + sizeof(ASCII85DecodeBegin) + sizeof(ASCII85DecodeEnd) + 2048;
    00767         }
    00768
    00769         if (pBuffer)
    00770         {
    00771             if (*pcbSize >= dwSize)
    00772             {
    00773                 (void)GetCPElementData(pProfile, dwIndex, pBuffer, &dwSize);
    00774
    00775                 if (! *pbBinary && dwDataType == 1)
    00776                 {
    00777                     dwSize = Ascii85Encode(pBuffer, dwSize, *pcbSize);
    00778                 }
    00779                 bRc = TRUE;
    00780             }
    00781             else
    00782             {
    00783                 WARNING((__TEXT("Buffer too small to get CRD\n")));
    00784                 SetLastError(ERROR_INSUFFICIENT_BUFFER);
    00785             }
    00786         }
    00787         else
    00788             bRc = TRUE;
    00789
    00790         *pcbSize = dwSize;
    00791     }
    00792     else if (DoesCPTagExist(pProfile, dwBToATag, &dwIndex))
    00793     {
    00794         bRc = CreateLutCRD(pProfile, dwIndex, pBuffer, pcbSize, dwIntent, *pbBinary);
    00795     }
    00796     else if (DoesCPTagExist(pProfile, TAG_GRAYTRC, &dwIndex))
    00797     {
    00798         bRc = CreateMonoCRD(pProfile, dwIndex, pBuffer, pcbSize, dwIntent);
    00799     }
    00800 #if !defined(KERNEL_MODE) || defined(USERMODE_DRIVER)
    00801     else if (DoesTRCAndColorantTagExist(pProfile))
    00802     {
    00803         bRc = CreateMatrixCRD(pProfile, pBuffer, pcbSize, dwIntent, *pbBinary);
    00804     }
    00805 #endif // !defined(KERNEL_MODE) || defined(USERMODE_DRIVER)
    00806     else
    00807     {
    00808         WARNING((__TEXT("Profile doesn't have tags to create CRD\n")));
    00809         SetLastError(ERROR_INVALID_PROFILE);
    00810     }
    00811
    00812     return bRc;
    00813 }
    00814
    00815 #if !defined(KERNEL_MODE) || defined(USERMODE_DRIVER)
    00816
    00817 /******************************************************************************
    00818  *
    00819  *                    InternalGetPS2PreviewCRD
    00820  *
    00821  *  Function:
    00822  *       This functions creates a preview PostScript Level 2 CRD from the
    00823  *       specified destination and target profiles
    00824  *       To do this, it does the following:
    00825  *           1) Creates host deviceCRD deviceCSA targetCRD.
    00826  *           2) Creates proofing CRD by sampling deviceCRD deviceCSA and targetCRD.
    00827  *           3) Uses deviceCRD's input table as proofingCRD's input table.
    00828  *           4) Uses targetCRD's output table as proofingCRD's output table.
    00829  *           5) Sample data is XYZ or Lab, depends on PCS of targetCRD.
    00830  *
    00831  *  Arguments:
    00832  *       pDestProf    - memory mapped pointer to destination profile
    00833  *       pTargetProf  - memory mapped pointer to target profile
    00834  *       dwIntent     - intent whose CRD is required
    00835  *       pbuffer      - pointer to receive the CSA
    00836  *       pcbSize      - pointer to size of buffer. If function fails because
    00837  *                      buffer is not big enough, it is filled with required size.
    00838  *       pcbBinary    - TRUE if binary data is requested. On return it is set to
    00839  *                      reflect the data returned
    00840  *
    00841  *  Returns:
    00842  *       TRUE if successful, FALSE otherwise
    00843  *
    00844  ******************************************************************************/
    00845
    00846 BOOL
    00847 InternalGetPS2PreviewCRD(
    00848     PBYTE   pDestProf,
    00849     PBYTE   pTargetProf,
    00850     DWORD   dwIntent,
    00851     PBYTE   pBuffer,
    00852     PDWORD  pcbSize,
    00853     PBOOL   pbBinary
    00854     )
    00855 {
    00856     DWORD      i, j, k, l, dwDev, dwTag, dwPCS;
    00857     DWORD      dwInArraySize, dwOutArraySize;
    00858     DWORD      nDevGrids, nTargetGrids, nPreviewCRDGrids;
    00859     DWORD      cbDevCRD, cbTargetCSA, cbTargetCRD;
    00860     float      fInput[MAXCHANNELS];
    00861     float      fOutput[MAXCHANNELS];
    00862     float      fTemp[MAXCHANNELS];
    00863     PBYTE      pLineStart, pStart = pBuffer;
    00864     PBYTE      lpDevCRD = NULL, lpTargetCSA = NULL, lpTargetCRD = NULL;
    00865     char       pPublicArrayName[5];
    00866     BOOL       bRc = FALSE;
    00867
    00868     dwDev = GetCPDevSpace(pTargetProf);
    00869     i = (dwDev == SPACE_CMYK) ? 4 : 3;
    00870
    00871     //
    00872     // Get the input array size IntentTag and Grid of the destination profile
    00873     //
    00874
    00875     if (!GetCRDInputOutputArraySize(
    00876             pTargetProf,
    00877             dwIntent,
    00878             &dwInArraySize,
    00879             NULL,
    00880             &dwTag,
    00881             &nTargetGrids))
    00882         return FALSE;
    00883
    00884     //
    00885     // Get the output array size IntentTag and Grid of the target profile
    00886     //
    00887
    00888     if (!GetCRDInputOutputArraySize(
    00889             pDestProf,
    00890             dwIntent,
    00891             NULL,
    00892             &dwOutArraySize,
    00893             &dwTag,
    00894             &nDevGrids))
    00895         return FALSE;
    00896
    00897     nPreviewCRDGrids = (nTargetGrids > nDevGrids) ? nTargetGrids : nDevGrids;
    00898
    00899     //
    00900     // Min proofing CRD grid will be PREVIEWCRDGRID
    00901     //
    00902
    00903     if (nPreviewCRDGrids < PREVIEWCRDGRID)
    00904         nPreviewCRDGrids = PREVIEWCRDGRID;
    00905
    00906     if (pBuffer == NULL)
    00907     {
    00908         //
    00909         // Return size of buffer needed
    00910         //
    00911
    00912         *pcbSize = nPreviewCRDGrids * nPreviewCRDGrids * nPreviewCRDGrids *
    00913                    i * 2        +    // CLUT size (Hex output)
    00914                    dwOutArraySize +  // Output Array size
    00915                    dwInArraySize  +  // Input Array size
    00916                    4096;             // Extra PostScript stuff
    00917
    00918         //
    00919         // Add space for new line.
    00920         //
    00921
    00922         *pcbSize += (((*pcbSize) / MAX_LINELEN) + 1) * STRLEN(NewLine);
    00923
    00924         return TRUE;
    00925     }
    00926
    00927     //
    00928     // Query the sizes of host target CRD, target CSA and device CRD
    00929     //
    00930
    00931     if (!GetHostColorRenderingDictionary(pTargetProf, dwIntent, NULL, &cbTargetCRD) ||
    00932         !GetHostColorSpaceArray(pTargetProf, dwIntent, NULL, &cbTargetCSA) ||
    00933         !GetHostColorRenderingDictionary(pDestProf, dwIntent, NULL, &cbDevCRD))
    00934     {
    00935         return FALSE;
    00936     }
    00937
    00938     //
    00939     // Allocate buffers for host target CRD, target CSA and device CRD
    00940     //
    00941
    00942     if (((lpTargetCRD = MemAlloc(cbTargetCRD)) == NULL) ||
    00943         ((lpTargetCSA = MemAlloc(cbTargetCSA)) == NULL) ||
    00944         ((lpDevCRD = MemAlloc(cbDevCRD)) == NULL))
    00945     {
    00946         goto Done;
    00947     }
    00948
    00949     //
    00950     // Build host target CRD, target CSA and device CRD
    00951     //
    00952
    00953     if (!GetHostColorRenderingDictionary(pTargetProf, dwIntent, lpTargetCRD, &cbTargetCRD) ||
    00954         !GetHostColorSpaceArray(pTargetProf, dwIntent, lpTargetCSA, &cbTargetCSA) ||
    00955         !GetHostColorRenderingDictionary(pDestProf, dwIntent, lpDevCRD, &cbDevCRD))
    00956     {
    00957         goto Done;
    00958     }
    00959
    00960     //
    00961     // Create global data
    00962     //
    00963
    00964     GetPublicArrayName(dwTag, pPublicArrayName);
    00965
    00966     //
    00967     // Build Proofing CRD based on Host target CRD, target CSA and dest CRD.
    00968     // We use target CRD input tables and matrix as the input tables and
    00969     // matrix of the ProofCRD. We use dest CRD output tables as the
    00970     // output tables of the ProofCRD.
    00971     //
    00972
    00973     pBuffer += WriteNewLineObject(pBuffer, CRDBegin);
    00974
    00975     pBuffer += EnableGlobalDict(pBuffer);
    00976     pBuffer += BeginGlobalDict(pBuffer);
    00977
    00978     pBuffer += CreateInputArray(pBuffer, 0, 0, pPublicArrayName,
    00979                     0, NULL, *pbBinary, lpTargetCRD);
    00980
    00981     pBuffer += CreateOutputArray(pBuffer, 0, 0, 0,
    00982                     pPublicArrayName, 0, NULL, *pbBinary, lpDevCRD);
    00983
    00984     pBuffer += EndGlobalDict(pBuffer);
    00985
    00986     //
    00987     // Start writing the CRD
    00988     //
    00989
    00990     pBuffer += WriteNewLineObject(pBuffer, BeginDict);     // Begin dictionary
    00991     pBuffer += WriteObject(pBuffer, DictType);      // Dictionary type
    00992
    00993     //
    00994     // Send /RenderingIntent
    00995     //
    00996
    00997     switch (dwIntent)
    00998     {
    00999         case INTENT_PERCEPTUAL:
    01000             pBuffer += WriteNewLineObject(pBuffer, IntentType);
    01001             pBuffer += WriteObject(pBuffer, IntentPer);
    01002             break;
    01003
    01004         case INTENT_SATURATION:
    01005             pBuffer += WriteNewLineObject(pBuffer, IntentType);
    01006             pBuffer += WriteObject(pBuffer, IntentSat);
    01007             break;
    01008
    01009         case INTENT_RELATIVE_COLORIMETRIC:
    01010             pBuffer += WriteNewLineObject(pBuffer, IntentType);
    01011             pBuffer += WriteObject(pBuffer, IntentRCol);
    01012             break;
    01013
    01014         case INTENT_ABSOLUTE_COLORIMETRIC:
    01015             pBuffer += WriteNewLineObject(pBuffer, IntentType);
    01016             pBuffer += WriteObject(pBuffer, IntentACol);
    01017             break;
    01018     }
    01019
    01020     //
    01021     // /BlackPoint & /WhitePoint
    01022     //
    01023
    01024     pBuffer += SendCRDBWPoint(pBuffer, ((PHOSTCLUT)lpTargetCRD)->afxIlluminantWP);
    01025
    01026     //
    01027     // Send PQR - used for Absolute Colorimetric
    01028     //
    01029
    01030     pBuffer += SendCRDPQR(pBuffer, dwIntent, ((PHOSTCLUT)lpTargetCRD)->afxIlluminantWP);
    01031
    01032     //
    01033     // Send LMN - For Absolute Colorimetric use WhitePoint's XYZs
    01034     //
    01035
    01036     pBuffer += SendCRDLMN(pBuffer, dwIntent,
    01037                    ((PHOSTCLUT)lpTargetCRD)->afxIlluminantWP,
    01038                    ((PHOSTCLUT)lpTargetCRD)->afxMediaWP,
    01039                    ((PHOSTCLUT)lpTargetCRD)->dwPCS);
    01040
    01041     //
    01042     // Send ABC
    01043     //
    01044
    01045     pBuffer += SendCRDABC(pBuffer, pPublicArrayName,
    01046                    ((PHOSTCLUT)lpTargetCRD)->dwPCS,
    01047                    ((PHOSTCLUT)lpTargetCRD)->nInputCh,
    01048                    NULL,
    01049                    ((PHOSTCLUT)lpTargetCRD)->e,
    01050                    (((PHOSTCLUT)lpTargetCRD)->nLutBits == 8)? LUT8_TYPE : LUT16_TYPE,
    01051                    *pbBinary);
    01052
    01053     //
    01054     // /RenderTable
    01055     //
    01056
    01057     pBuffer += WriteNewLineObject(pBuffer, RenderTableTag);
    01058     pBuffer += WriteObject(pBuffer, BeginArray);
    01059
    01060     pBuffer += WriteInt(pBuffer, nPreviewCRDGrids);  // Send down Na
    01061     pBuffer += WriteInt(pBuffer, nPreviewCRDGrids);  // Send down Nb
    01062     pBuffer += WriteInt(pBuffer, nPreviewCRDGrids);  // Send down Nc
    01063
    01064     pLineStart = pBuffer;
    01065     pBuffer += WriteNewLineObject(pBuffer, BeginArray);
    01066     dwPCS = ((PHOSTCLUT)lpDevCRD)->dwPCS;
    01067
    01068     for (i=0; i<nPreviewCRDGrids; i++)        // Na strings should be sent
    01069     {
    01070         pBuffer += WriteObject(pBuffer, NewLine);
    01071         pLineStart = pBuffer;
    01072         if (*pbBinary)
    01073         {
    01074             pBuffer += WriteStringToken(pBuffer, 143,
    01075                 nPreviewCRDGrids * nPreviewCRDGrids * ((PHOSTCLUT)lpDevCRD)->nOutputCh);
    01076         }
    01077         else
    01078         {
    01079             pBuffer += WriteObject(pBuffer, BeginString);
    01080         }
    01081         fInput[0] = ((float)i) / (nPreviewCRDGrids - 1);
    01082         for (j=0; j<nPreviewCRDGrids; j++)
    01083         {
    01084             fInput[1] = ((float)j) / (nPreviewCRDGrids - 1);
    01085             for (k=0; k<nPreviewCRDGrids; k++)
    01086             {
    01087                 fInput[2] = ((float)k) / (nPreviewCRDGrids - 1);
    01088
    01089                 DoHostConversionCRD((PHOSTCLUT)lpTargetCRD, NULL, fInput, fOutput, 1);
    01090                 DoHostConversionCSA((PHOSTCLUT)lpTargetCSA, fOutput, fTemp);
    01091                 DoHostConversionCRD((PHOSTCLUT)lpDevCRD, (PHOSTCLUT)lpTargetCSA,
    01092                                      fTemp, fOutput, 0);
    01093                 for (l=0; l<((PHOSTCLUT)lpDevCRD)->nOutputCh; l++)
    01094                 {
    01095                     if (*pbBinary)
    01096                     {
    01097                         *pBuffer++ = (BYTE)(fOutput[l] * 255);
    01098                     }
    01099                     else
    01100                     {
    01101                         pBuffer += WriteHex(pBuffer, (USHORT)(fOutput[l] * 255));
    01102                         if ((pBuffer - pLineStart) > MAX_LINELEN)
    01103                         {
    01104                             pLineStart = pBuffer;
    01105                             pBuffer += WriteObject(pBuffer, NewLine);
    01106                         }
    01107                     }
    01108                 }
    01109             }
    01110         }
    01111         if (!*pbBinary)
    01112             pBuffer += WriteObject(pBuffer, EndString);
    01113     }
    01114     pBuffer += WriteNewLineObject(pBuffer, EndArray);
    01115     pBuffer += WriteInt(pBuffer, ((PHOSTCLUT)lpDevCRD)->nOutputCh);
    01116
    01117     //
    01118     // Send output table
    01119     //
    01120
    01121     pBuffer += SendCRDOutputTable(pBuffer, pPublicArrayName,
    01122                     ((PHOSTCLUT)lpDevCRD)->nOutputCh,
    01123                     (((PHOSTCLUT)lpDevCRD)->nLutBits == 8)? LUT8_TYPE : LUT16_TYPE,
    01124                     TRUE,
    01125                     *pbBinary);
    01126
    01127     pBuffer += WriteNewLineObject(pBuffer, EndArray);
    01128     pBuffer += WriteObject(pBuffer, EndDict); // End dictionary definition
    01129     pBuffer += WriteNewLineObject(pBuffer, CRDEnd);
    01130     bRc = TRUE;
    01131
    01132 Done:
    01133     *pcbSize = (DWORD)(pBuffer - pStart);
    01134
    01135     if (lpTargetCRD)
    01136          MemFree(lpTargetCRD);
    01137     if (lpTargetCSA)
    01138          MemFree(lpTargetCSA);
    01139     if (lpDevCRD)
    01140          MemFree(lpDevCRD);
    01141
    01142     return bRc;
    01143 }
    01144
    01145 #endif //  !defined(KERNEL_MODE) || defined(USERMODE_DRIVER)
    01146
    01147
    01148 /******************************************************************************
    01149  *
    01150  *                               GetCSAFromProfile
    01151  *
    01152  *  Function:
    01153  *       This function gets the Color Space Array from the profile if the
    01154  *       tag is present
    01155  *
    01156  *  Arguments:
    01157  *       pProfile  - pointer to the memory mapped  profile
    01158  *       dwIntent  - rendering intent of CSA requested
    01159  *       dwCSAType - type of CSA requested
    01160  *       pBuffer   - pointer to receive the CSA
    01161  *       pcbSize   - pointer to size of buffer. If function fails because
    01162  *                   buffer is not big enough, it is filled with required size.
    01163  *       pcbBinary - TRUE if binary data is requested. On return it is set to
    01164  *                   reflect the data returned
    01165  *
    01166  *  Returns:
    01167  *       TRUE if successful, FALSE otherwise
    01168  *
    01169  ******************************************************************************/
    01170
    01171 BOOL
    01172 GetCSAFromProfile (
    01173     PBYTE  pProfile,
    01174     DWORD  dwIntent,
    01175     DWORD  dwCSAType,
    01176     PBYTE  pBuffer,
    01177     PDWORD pcbSize,
    01178     PBOOL  pbBinary
    01179     )
    01180 {
    01181     DWORD dwDev, dwProfileIntent;
    01182     DWORD dwIndex, dwSize, dwDataType;
    01183     BOOL  bRc = FALSE;
    01184
    01185     //
    01186     // This function can fail without setting an error, so reset error
    01187     // here to prevent confusion later
    01188     //
    01189
    01190     SetLastError(0);
    01191
    01192     //
    01193     // Get the profile's color space and rendering intent
    01194     //
    01195
    01196     dwDev = GetCPDevSpace(pProfile);
    01197     dwProfileIntent = GetCPRenderIntent(pProfile);
    01198
    01199     //
    01200     // If the rendering intents don't match, or the profile's color space
    01201     // is incompatible with requested CSA type, fail
    01202     //
    01203
    01204     if  ((dwIntent != dwProfileIntent) ||
    01205          ((dwDev == SPACE_GRAY) &&
    01206          ((dwCSAType != CSA_GRAY) && (dwCSAType != CSA_A))))
    01207     {
    01208         WARNING((__TEXT("Can't use profile's CSA tag due to different rendering intents\n")));
    01209         return FALSE;
    01210     }
    01211
    01212     if (DoesCPTagExist(pProfile, TAG_PS2CSA, &dwIndex))
    01213     {
    01214         (void)GetCPElementDataSize(pProfile, dwIndex, &dwSize);
    01215
    01216         (void)GetCPElementDataType(pProfile, dwIndex, &dwDataType);
    01217
    01218         if (! *pbBinary && dwDataType == 1)
    01219         {
    01220             //
    01221             // Profile has binary data, user asked for ASCII, so we have to
    01222             // ASCII 85 encode it
    01223             //
    01224
    01225             dwSize = dwSize * 5 / 4 + sizeof(ASCII85DecodeBegin) + sizeof(ASCII85DecodeEnd) + 2048;
    01226         }
    01227
    01228         if (pBuffer)
    01229         {
    01230             if (*pcbSize >= dwSize)
    01231             {
    01232                 (void)GetCPElementData(pProfile, dwIndex, pBuffer, &dwSize);
    01233
    01234                 if (! *pbBinary && dwDataType == 1)
    01235                 {
    01236                     dwSize = Ascii85Encode(pBuffer, dwSize, *pcbSize);
    01237                 }
    01238                 bRc = TRUE;
    01239             }
    01240             else
    01241             {
    01242                 WARNING((__TEXT("Buffer too small to get CSA\n")));
    01243                 SetLastError(ERROR_INSUFFICIENT_BUFFER);
    01244             }
    01245         }
    01246         else
    01247             bRc = TRUE;
    01248
    01249         *pcbSize = dwSize;
    01250     }
    01251
    01252     return bRc;
    01253 }
    01254
    01255
    01256 /******************************************************************************
    01257  *
    01258  *                              GetPS2CSA_MONO_A
    01259  *
    01260  *  Function:
    01261  *       This function creates a CIEBasedA colorspace array from an input
    01262  *       GRAY profile
    01263  *
    01264  *  Arguments:
    01265  *       pProfile  - pointer to the memory mapped profile
    01266  *       pBuffer   - pointer to receive the CSA
    01267  *       pcbSize   - pointer to size of buffer. If function fails because
    01268  *                   buffer is not big enough, it is filled with required size.
    01269  *       dwIntent  - rendering intent of CSA requested
    01270  *       pcbBinary - TRUE if binary data is requested. On return it is set to
    01271  *                   reflect the data returned
    01272  *
    01273  *  Returns:
    01274  *       TRUE if successful, FALSE otherwise
    01275  *
    01276  ******************************************************************************/
    01277
    01278 BOOL
    01279 GetPS2CSA_MONO_A(
    01280     PBYTE  pProfile,
    01281     PBYTE  pBuffer,
    01282     PDWORD pcbSize,
    01283     DWORD  dwIntent,
    01284     PBOOL  pbBinary
    01285     )
    01286 {
    01287     PCURVETYPE pData;
    01288     PTAGDATA   pTagData;
    01289     PBYTE      pLineStart, pStart = pBuffer;
    01290     PBYTE      pTable;
    01291     DWORD      i, dwPCS, nCount;
    01292     DWORD      dwIndex, dwSize;
    01293     DWORD      afxIlluminantWP[3];
    01294     DWORD      afxMediaWP[3];
    01295
    01296     //
    01297     // Check if we can generate the CSA
    01298     // Required tag is gray TRC
    01299     //
    01300
    01301     if (! DoesCPTagExist(pProfile, TAG_GRAYTRC, &dwIndex))
    01302     {
    01303         WARNING((__TEXT("Gray TRC tag not present to create MONO_A CSA\n")));
    01304         SetLastError(ERROR_TAG_NOT_PRESENT);
    01305         return FALSE;
    01306     }
    01307
    01308     dwPCS = GetCPConnSpace(pProfile);
    01309
    01310     (void)GetCPElementSize(pProfile, dwIndex, &dwSize);
    01311
    01312     pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
    01313                dwIndex * sizeof(TAGDATA));
    01314
    01315     pData = (PCURVETYPE)(pProfile + FIX_ENDIAN(pTagData->dwOffset));
    01316
    01317     nCount = FIX_ENDIAN(pData->nCount);
    01318
    01319     //
    01320     // Estimate size required to hold the CSA
    01321     //
    01322
    01323     dwSize = nCount * 6 +               // Number of INT elements
    01324         3 * (STRLEN(IndexArray) +
    01325              STRLEN(StartClip) +
    01326              STRLEN(EndClip)) +
    01327         2048;                           // + other PS stuff
    01328
    01329     //
    01330     // Add space for new line.
    01331     //
    01332
    01333     dwSize += (((dwSize) / MAX_LINELEN) + 1) * STRLEN(NewLine);
    01334
    01335     if (! pBuffer)
    01336     {
    01337         *pcbSize = dwSize;
    01338         return TRUE;
    01339     }
    01340     else if (*pcbSize < dwSize)
    01341     {
    01342         WARNING((__TEXT("Buffer too small to get MONO_A CSA\n")));
    01343         SetLastError(ERROR_INSUFFICIENT_BUFFER);
    01344         return FALSE;
    01345     }
    01346
    01347     //
    01348     // Get info about Illuminant White Point from the header
    01349     //
    01350
    01351     (void)GetCPWhitePoint(pProfile, afxIlluminantWP);
    01352
    01353     //
    01354     // Support absolute whitePoint
    01355     //
    01356
    01357     (void)GetMediaWP(pProfile, dwIntent, afxIlluminantWP, afxMediaWP);
    01358
    01359     //
    01360     // Start creating the ColorSpace
    01361     //
    01362
    01363     pBuffer += WriteNewLineObject(pBuffer, CieBasedABegin);
    01364
    01365     pBuffer += WriteNewLineObject(pBuffer, BeginArray);   // Begin array
    01366
    01367     //
    01368     // /CIEBasedA
    01369     //
    01370
    01371     pBuffer += WriteObject(pBuffer, CIEBasedATag); // Create entry
    01372     pBuffer += WriteObject(pBuffer, BeginDict);    // Begin dictionary
    01373
    01374     //
    01375     // Send /BlackPoint & /WhitePoint
    01376     //
    01377
    01378     pBuffer += SendCSABWPoint(pBuffer, dwIntent, afxIlluminantWP, afxMediaWP);
    01379
    01380     //
    01381     // /DecodeA
    01382     //
    01383
    01384     pBuffer += WriteObject(pBuffer, NewLine);
    01385     pLineStart = pBuffer;
    01386
    01387     if (nCount != 0)
    01388     {
    01389         pBuffer += WriteObject(pBuffer, DecodeATag);
    01390         pBuffer += WriteObject(pBuffer, BeginArray);
    01391
    01392         pBuffer += WriteObject(pBuffer, BeginFunction);
    01393
    01394         pTable = (PBYTE)(pData->data);
    01395
    01396         if (nCount == 1)                // Gamma supplied in ui16 format
    01397         {
    01398             pBuffer += WriteInt(pBuffer, FIX_ENDIAN16(*((PWORD)pTable)));
    01399             pBuffer += WriteObject(pBuffer, DecodeA3);
    01400
    01401             //
    01402             // If the PCS is Lab, we need to convert Lab to XYZ
    01403             // Now, the range is from 0 --> 0.99997.
    01404             // Actually, the conversion from Lab to XYZ is not needed
    01405             //
    01406
    01407             if (dwPCS == SPACE_Lab)
    01408             {
    01409                 pBuffer += WriteObject(pBuffer, DecodeALab);
    01410                 pBuffer += WriteObject(pBuffer, DecodeLMNLab);
    01411             }
    01412         }
    01413         else
    01414         {
    01415             pBuffer += WriteObject(pBuffer, StartClip);
    01416             pBuffer += WriteObject(pBuffer, BeginArray);
    01417             for (i=0; i<nCount; i++)
    01418             {
    01419                 pBuffer += WriteInt(pBuffer, FIX_ENDIAN16(*((PWORD)pTable)));
    01420                 pTable += sizeof(WORD);
    01421                 if (((DWORD) (pBuffer - pLineStart)) > MAX_LINELEN)
    01422                 {
    01423                     pLineStart = pBuffer;
    01424                     pBuffer += WriteObject (pBuffer, NewLine);
    01425                 }
    01426             }
    01427             pBuffer += WriteObject(pBuffer, EndArray);
    01428             pLineStart = pBuffer;
    01429             pBuffer += WriteObject(pBuffer, NewLine);
    01430
    01431             pBuffer += WriteObject(pBuffer, IndexArray);
    01432             pBuffer += WriteObject(pBuffer, Scale16);
    01433
    01434             //
    01435             // If the PCS is Lab, we need to convert Lab to XYZ
    01436             // Now, the range is from 0 --> .99997.
    01437             // Actually, the conversion from Lab to XYZ is not needed.
    01438             //
    01439
    01440             if (dwPCS == SPACE_Lab)
    01441             {
    01442                 pBuffer += WriteObject(pBuffer, DecodeALab);
    01443                 pBuffer += WriteObject(pBuffer, DecodeLMNLab);
    01444             }
    01445             pBuffer += WriteObject(pBuffer, EndClip);
    01446         }
    01447
    01448         pBuffer += WriteObject(pBuffer, EndFunction);
    01449         pBuffer += WriteObject(pBuffer, EndArray);
    01450     }
    01451
    01452     //
    01453     // /MatrixA
    01454     //
    01455
    01456     pBuffer += WriteNewLineObject(pBuffer, MatrixATag);
    01457     pBuffer += WriteObject(pBuffer, BeginArray);
    01458     for (i=0; i<3; i++)
    01459     {
    01460         if (dwIntent == INTENT_ABSOLUTE_COLORIMETRIC)
    01461         {
    01462             pBuffer += WriteFixed(pBuffer, afxMediaWP[i]);
    01463         }
    01464         else
    01465         {
    01466             pBuffer += WriteFixed(pBuffer, afxIlluminantWP[i]);
    01467         }
    01468     }
    01469     pBuffer += WriteObject(pBuffer, EndArray);
    01470
    01471     //
    01472     // /RangeLMN
    01473     //
    01474
    01475     pBuffer += WriteNewLineObject(pBuffer, RangeLMNTag);
    01476     pBuffer += WriteObject(pBuffer, RangeLMN);
    01477
    01478     //
    01479     // /End dictionary
    01480     //
    01481
    01482     pBuffer += WriteObject(pBuffer, EndDict);  // End dictionary definition
    01483     pBuffer += WriteObject(pBuffer, EndArray);
    01484
    01485     pBuffer += WriteNewLineObject(pBuffer, CieBasedAEnd);
    01486
    01487     *pcbSize = (DWORD) (pBuffer - pStart);
    01488
    01489     return TRUE;
    01490 }
    01491
    01492
    01493 /******************************************************************************
    01494  *
    01495  *                              GetPS2CSA_ABC
    01496  *
    01497  *  Function:
    01498  *       This function creates a CIEBasedABC colorspace array from an input
    01499  *       RGB profile
    01500  *
    01501  *  Arguments:
    01502  *       pProfile  - pointer to the memory mapped profile
    01503  *       pBuffer   - pointer to receive the CSA
    01504  *       pcbSize   - pointer to size of buffer. If function fails because
    01505  *                   buffer is not big enough, it is filled with required size.
    01506  *       dwIntent  - rendering intent of CSA requested
    01507  *       pcbBinary - TRUE if binary data is requested. On return it is set to
    01508  *                   reflect the data returned
    01509  *       bBackup   - TRUE: A CIEBasedDEF has been created, this CSA is a backup
    01510  *                          in case some old printer can not support CIEBasedDEF.
    01511  *                   FALSE: No CIEBasedDEF. This is the only CSA.
    01512  *
    01513  *  Returns:
    01514  *       TRUE if successful, FALSE otherwise
    01515  *
    01516  ******************************************************************************/
    01517
    01518 BOOL
    01519 GetPS2CSA_ABC(
    01520     PBYTE  pProfile,
    01521     PBYTE  pBuffer,
    01522     PDWORD pcbSize,
    01523     DWORD  dwIntent,
    01524     PBOOL  pbBinary,
    01525     BOOL   bBackup
    01526     )
    01527 {
    01528     PBYTE     pStart = pBuffer;
    01529     DWORD     i, dwPCS, dwDev, dwSize;
    01530     FIX_16_16 afxIlluminantWP[3];
    01531     FIX_16_16 afxMediaWP[3];
    01532
    01533     //
    01534     // Check if we can generate the CSA:
    01535     // Required  tags are red, green and blue Colorants & TRCs
    01536     //
    01537
    01538     dwPCS = GetCPConnSpace(pProfile);
    01539     dwDev = GetCPDevSpace(pProfile);
    01540
    01541     //
    01542     // Call another function to handle Lab profiles
    01543     //
    01544
    01545     if (dwDev == SPACE_Lab)
    01546     {
    01547         return GetPS2CSA_ABC_Lab(pProfile, pBuffer, pcbSize, dwIntent, pbBinary);
    01548     }
    01549
    01550     //
    01551     // We only handle RGB profiles in this function
    01552     //
    01553
    01554     if ((dwDev != SPACE_RGB)                   ||
    01555         !DoesTRCAndColorantTagExist(pProfile))
    01556     {
    01557         WARNING((__TEXT("Colorant or TRC tag not present to create ABC CSA\n")));
    01558         SetLastError(ERROR_TAG_NOT_PRESENT);
    01559         return FALSE;
    01560     }
    01561
    01562     //
    01563     // Estimate size required to hold the CSA
    01564     //
    01565
    01566     dwSize = 65530;
    01567
    01568     if (! pBuffer)
    01569     {
    01570         *pcbSize = dwSize;
    01571         return TRUE;
    01572     }
    01573     else if (*pcbSize < dwSize)
    01574     {
    01575         WARNING((__TEXT("Buffer too small to get ABC CSA\n")));
    01576         SetLastError(ERROR_INSUFFICIENT_BUFFER);
    01577         return FALSE;
    01578     }
    01579
    01580     //
    01581     // Get info about Illuminant White Point from the header
    01582     //
    01583
    01584     (void)GetCPWhitePoint(pProfile, afxIlluminantWP);
    01585
    01586     //
    01587     // Support absolute whitePoint
    01588     //
    01589
    01590     (void)GetMediaWP(pProfile, dwIntent, afxIlluminantWP, afxMediaWP);
    01591
    01592     //
    01593     // Create global data
    01594     //
    01595
    01596     pBuffer += WriteNewLineObject(pBuffer, CieBasedABCBegin);
    01597
    01598     if (IsSRGBColorProfile(pProfile))
    01599     {
    01600         pBuffer += WriteNewLineObject(pBuffer, sRGBColorSpaceArray);
    01601     }
    01602     else
    01603     {
    01604         pBuffer += EnableGlobalDict(pBuffer);
    01605
    01606         if (bBackup)
    01607         {
    01608             pBuffer += WriteNewLineObject(pBuffer, NotSupportDEFG_S);
    01609         }
    01610
    01611         pBuffer += BeginGlobalDict(pBuffer);
    01612
    01613         pBuffer += CreateColSpArray(pProfile, pBuffer, TAG_REDTRC, *pbBinary);
    01614         pBuffer += CreateColSpArray(pProfile, pBuffer, TAG_GREENTRC, *pbBinary);
    01615         pBuffer += CreateColSpArray(pProfile, pBuffer, TAG_BLUETRC, *pbBinary);
    01616
    01617         pBuffer += WriteNewLineObject(pBuffer, EndOp);
    01618
    01619         if (bBackup)
    01620         {
    01621             pBuffer += WriteNewLineObject(pBuffer, SupportDEFG_E);
    01622         }
    01623
    01624         pBuffer += WriteNewLineObject(pBuffer, SetGlobalOp);
    01625
    01626         if (bBackup)
    01627         {
    01628             pBuffer += WriteNewLineObject(pBuffer, NotSupportDEFG_S);
    01629         }
    01630
    01631         //
    01632         // Start creating the ColorSpace
    01633         //
    01634
    01635         pBuffer += WriteNewLineObject(pBuffer, BeginArray);       // Begin array
    01636
    01637         //
    01638         // /CIEBasedABC
    01639         //
    01640
    01641         pBuffer += WriteObject(pBuffer, CIEBasedABCTag);   // Create entry
    01642         pBuffer += WriteObject(pBuffer, BeginDict);        // Begin dictionary
    01643
    01644         //
    01645         // /BlackPoint & /WhitePoint
    01646         //
    01647
    01648         pBuffer += SendCSABWPoint(pBuffer, dwIntent, afxIlluminantWP, afxMediaWP);
    01649
    01650         //
    01651         // /DecodeABC
    01652         //
    01653
    01654         pBuffer += WriteNewLineObject(pBuffer, DecodeABCTag);
    01655         pBuffer += WriteObject(pBuffer, BeginArray);
    01656
    01657         pBuffer += WriteObject(pBuffer, NewLine);
    01658         pBuffer += CreateColSpProc(pProfile, pBuffer, TAG_REDTRC, *pbBinary);
    01659         pBuffer += WriteObject(pBuffer, NewLine);
    01660         pBuffer += CreateColSpProc(pProfile, pBuffer, TAG_GREENTRC, *pbBinary);
    01661         pBuffer += WriteObject(pBuffer, NewLine);
    01662         pBuffer += CreateColSpProc(pProfile, pBuffer, TAG_BLUETRC, *pbBinary);
    01663         pBuffer += WriteObject(pBuffer, EndArray);
    01664
    01665         //
    01666         // /MatrixABC
    01667         //
    01668
    01669         pBuffer += WriteNewLineObject(pBuffer, MatrixABCTag);
    01670         pBuffer += WriteObject(pBuffer, BeginArray);
    01671
    01672         pBuffer += CreateFloatString(pProfile, pBuffer, TAG_REDCOLORANT);
    01673         pBuffer += CreateFloatString(pProfile, pBuffer, TAG_GREENCOLORANT);
    01674         pBuffer += CreateFloatString(pProfile, pBuffer, TAG_BLUECOLORANT);
    01675
    01676         pBuffer += WriteObject(pBuffer, EndArray);
    01677
    01678         //
    01679         // /RangeLMN
    01680         //
    01681
    01682         pBuffer += WriteObject(pBuffer, NewLine);
    01683         pBuffer += WriteObject(pBuffer, RangeLMNTag);
    01684         pBuffer += WriteObject(pBuffer, RangeLMN);
    01685
    01686         //
    01687         // /DecodeLMN
    01688         //
    01689
    01690         if (dwIntent == INTENT_ABSOLUTE_COLORIMETRIC)
    01691         {
    01692             //
    01693             // Support absolute whitePoint
    01694             //
    01695
    01696             pBuffer += WriteNewLineObject(pBuffer, DecodeLMNTag);
    01697             pBuffer += WriteObject(pBuffer, BeginArray);
    01698             for (i=0; i<3; i++)
    01699             {
    01700                 pBuffer += WriteObject(pBuffer, BeginFunction);
    01701                 pBuffer += WriteFixed(pBuffer, FIX_DIV(afxMediaWP[i], afxIlluminantWP[i]));
    01702                 pBuffer += WriteObject(pBuffer, MulOp);
    01703                 pBuffer += WriteObject(pBuffer, EndFunction);
    01704             }
    01705             pBuffer += WriteObject (pBuffer, EndArray);
    01706         }
    01707
    01708         //
    01709         // End dictionary definition
    01710         //
    01711
    01712         pBuffer += WriteNewLineObject(pBuffer, EndDict);
    01713         pBuffer += WriteObject(pBuffer, EndArray);
    01714
    01715         pBuffer += WriteNewLineObject(pBuffer, CieBasedABCEnd);
    01716     }
    01717
    01718     *pcbSize = (DWORD) (pBuffer - pStart);
    01719
    01720     return TRUE;
    01721 }
    01722
    01723
    01724 /******************************************************************************
    01725  *
    01726  *                              GetPS2CSA_ABC_Lab
    01727  *
    01728  *  Function:
    01729  *       This function creates a CIEBasedABC colorspace array from an input
    01730  *       Lab profile
    01731  *
    01732  *  Arguments:
    01733  *       pProfile  - pointer to the memory mapped profile
    01734  *       pBuffer   - pointer to receive the CSA
    01735  *       pcbSize   - pointer to size of buffer. If function fails because
    01736  *                   buffer is not big enough, it is filled with required size.
    01737  *       dwIntent  - rendering intent of CSA requested
    01738  *       pcbBinary - TRUE if binary data is requested. On return it is set to
    01739  *                   reflect the data returned
    01740  *
    01741  *  Returns:
    01742  *       TRUE if successful, FALSE otherwise
    01743  *
    01744  ******************************************************************************/
    01745
    01746 BOOL
    01747 GetPS2CSA_ABC_Lab(
    01748     PBYTE  pProfile,
    01749     PBYTE  pBuffer,
    01750     PDWORD pcbSize,
    01751     DWORD  dwIntent,
    01752     PBOOL  pbBinary
    01753     )
    01754 {
    01755     PBYTE     pStart = pBuffer;
    01756     DWORD     i, dwSize;
    01757     FIX_16_16 afxIlluminantWP[3];
    01758     FIX_16_16 afxMediaWP[3];
    01759
    01760     //
    01761     // Estimate size required to hold the CSA
    01762     //
    01763
    01764     dwSize = 65530;
    01765
    01766     if (! pBuffer)
    01767     {
    01768         *pcbSize = dwSize;
    01769         return TRUE;
    01770     }
    01771     else if (*pcbSize < dwSize)
    01772     {
    01773         WARNING((__TEXT("Buffer too small to get ABC_Lab CSA\n")));
    01774         SetLastError(ERROR_INSUFFICIENT_BUFFER);
    01775         return FALSE;
    01776     }
    01777
    01778     //
    01779     // Get info about Illuminant White Point from the header
    01780     //
    01781
    01782     (void)GetCPWhitePoint(pProfile, afxIlluminantWP);
    01783
    01784     //
    01785     // Support absolute whitePoint
    01786     //
    01787
    01788     GetMediaWP(pProfile, dwIntent, afxIlluminantWP, afxMediaWP);
    01789
    01790     //
    01791     // Start creating the ColorSpace
    01792     //
    01793
    01794     pBuffer += WriteNewLineObject(pBuffer, BeginArray);       // Begin array
    01795
    01796     //
    01797     // /CIEBasedABC
    01798     //
    01799
    01800     pBuffer += WriteObject(pBuffer, CIEBasedABCTag);   // Create entry
    01801     pBuffer += WriteObject(pBuffer, BeginDict);        // Begin dictionary
    01802
    01803     //
    01804     // /BlackPoint & /WhitePoint
    01805     //
    01806
    01807     pBuffer += SendCSABWPoint(pBuffer, dwIntent, afxIlluminantWP, afxMediaWP);
    01808
    01809     //
    01810     // /RangeABC
    01811     //
    01812
    01813     pBuffer += WriteNewLineObject(pBuffer, RangeABCTag);
    01814     pBuffer += WriteObject(pBuffer, RangeABC_Lab);
    01815
    01816     //
    01817     // /DecodeABC
    01818     //
    01819
    01820     pBuffer += WriteNewLineObject(pBuffer, DecodeABCTag);
    01821     pBuffer += WriteObject(pBuffer, DecodeABCLab1);
    01822
    01823     //
    01824     // /MatrixABC
    01825     //
    01826
    01827     pBuffer += WriteNewLineObject(pBuffer, MatrixABCTag);
    01828     pBuffer += WriteObject(pBuffer, MatrixABCLab);
    01829
    01830     //
    01831     // /DecodeLMN
    01832     //
    01833
    01834     pBuffer += WriteNewLineObject(pBuffer, DecodeLMNTag);
    01835     pBuffer += WriteObject(pBuffer, BeginArray);
    01836     for (i=0; i<3; i++)
    01837     {
    01838         pBuffer += WriteObject(pBuffer, BeginFunction);
    01839         pBuffer += WriteObject(pBuffer, DecodeLMNLab);
    01840
    01841         if (dwIntent == INTENT_ABSOLUTE_COLORIMETRIC)
    01842         {
    01843             pBuffer += WriteFixed(pBuffer, afxMediaWP[i]);
    01844         }
    01845         else
    01846         {
    01847             pBuffer += WriteFixed(pBuffer, afxIlluminantWP[i]);
    01848         }
    01849         pBuffer += WriteObject(pBuffer, MulOp);
    01850         pBuffer += WriteObject(pBuffer, EndFunction);
    01851         pBuffer += WriteObject(pBuffer, NewLine);
    01852     }
    01853     pBuffer += WriteObject(pBuffer, EndArray);
    01854
    01855
    01856     //
    01857     // End dictionary definition
    01858     //
    01859
    01860     pBuffer += WriteNewLineObject(pBuffer, EndDict);
    01861     pBuffer += WriteObject(pBuffer, EndArray);
    01862
    01863     pBuffer += WriteNewLineObject(pBuffer, CieBasedABCEnd);
    01864
    01865     *pcbSize = (DWORD) (pBuffer - pStart);
    01866
    01867     return TRUE;
    01868 }
    01869
    01870
    01871 /******************************************************************************
    01872  *
    01873  *                           GetPS2CSA_DEFG
    01874  *
    01875  *  Function:
    01876  *       This function creates DEF and DEFG based CSAs from the data supplied
    01877  *       in the RGB or CMYK profiles respectively
    01878  *
    01879  *  Arguments:
    01880  *       pProfile  - pointer to the memory mapped profile
    01881  *       pBuffer   - pointer to receive the CSA
    01882  *       pcbSize   - pointer to size of buffer. If function fails because
    01883  *                   buffer is not big enough, it is filled with required size.
    01884  *       dwIntent  - rendering intent of CSA requested
    01885  *       dwType    - whether DEF CSA or DEFG CSA is required
    01886  *       pcbBinary - TRUE if binary data is requested. On return it is set to
    01887  *                   reflect the data returned
    01888  *
    01889  *  Returns:
    01890  *       TRUE if successful, FALSE otherwise
    01891  *
    01892  ******************************************************************************/
    01893
    01894 BOOL
    01895 GetPS2CSA_DEFG(
    01896     PBYTE  pProfile,
    01897     PBYTE  pBuffer,
    01898     PDWORD pcbSize,
    01899     DWORD  dwIntent,
    01900     DWORD  dwType,
    01901     PBOOL  pbBinary
    01902     )
    01903 {
    01904     PLUT16TYPE pLut;
    01905     PTAGDATA   pTagData;
    01906     PBYTE      pLineStart, pStart = pBuffer;
    01907     PBYTE      pTable;
    01908     DWORD      i, j, k, dwPCS, dwDev, dwIndex, dwTag, dwLutSig, SecondGrids, dwSize;
    01909     DWORD      nInputCh, nOutputCh, nGrids, nInputTable, nOutputTable, nNumbers;
    01910     FIX_16_16  afxIlluminantWP[3];
    01911     FIX_16_16  afxMediaWP[3];
    01912     char       pPublicArrayName[5];
    01913
    01914     //
    01915     // Make sure required tags exist
    01916     //
    01917
    01918     switch (dwIntent)
    01919     {
    01920     case INTENT_PERCEPTUAL:
    01921         dwTag = TAG_AToB0;
    01922         break;
    01923
    01924     case INTENT_RELATIVE_COLORIMETRIC:
    01925         dwTag = TAG_AToB1;
    01926         break;
    01927
    01928     case INTENT_SATURATION:
    01929         dwTag = TAG_AToB2;
    01930         break;
    01931
    01932     case INTENT_ABSOLUTE_COLORIMETRIC:
    01933         dwTag = TAG_AToB1;
    01934         break;
    01935
    01936     default:
    01937         WARNING((__TEXT("Invalid intent passed to GetPS2CSA_DEFG: %d\n"), dwIntent));
    01938         SetLastError(ERROR_INVALID_PARAMETER);
    01939         return FALSE;
    01940     }
    01941
    01942     if (! DoesCPTagExist(pProfile, dwTag, &dwIndex))
    01943     {
    01944         WARNING((__TEXT("AToB%d tag not present to create DEF(G) CSA\n"), dwIntent));
    01945         SetLastError(ERROR_TAG_NOT_PRESENT);
    01946         return FALSE;
    01947     }
    01948
    01949     //
    01950     // Check if we can generate the CSA
    01951     // Required  tags is AToBi, where i is the rendering intent
    01952     //
    01953
    01954     dwPCS = GetCPConnSpace(pProfile);
    01955     dwDev = GetCPDevSpace(pProfile);
    01956
    01957     if ((dwType == TYPE_CIEBASEDDEF  && dwDev != SPACE_RGB) ||
    01958         (dwType == TYPE_CIEBASEDDEFG && dwDev != SPACE_CMYK))
    01959     {
    01960         WARNING((__TEXT("RGB profile & requesting CMYK CSA or vice versa\n")));
    01961         SetLastError(ERROR_TAG_NOT_PRESENT);
    01962         return FALSE;
    01963     }
    01964
    01965     pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
    01966                dwIndex * sizeof(TAGDATA));
    01967
    01968     pLut = (PLUT16TYPE)(pProfile + FIX_ENDIAN(pTagData->dwOffset));
    01969
    01970     dwLutSig = FIX_ENDIAN(pLut->dwSignature);
    01971
    01972     if (((dwPCS != SPACE_Lab) && (dwPCS != SPACE_XYZ)) ||
    01973         ((dwLutSig != LUT8_TYPE) && (dwLutSig != LUT16_TYPE)))
    01974     {
    01975         WARNING((__TEXT("Invalid color space - unable to create DEF(G) CSA\n")));
    01976         SetLastError(ERROR_INVALID_PROFILE);
    01977         return FALSE;
    01978     }
    01979
    01980     //
    01981     // Estimate size required to hold the CSA
    01982     //
    01983
    01984     (void)GetCLUTInfo(dwLutSig, (PBYTE)pLut, &nInputCh, &nOutputCh, &nGrids,
    01985                 &nInputTable, &nOutputTable, NULL);
    01986
    01987     //
    01988     // Calculate size of buffer needed
    01989     //
    01990
    01991     if (dwType == TYPE_CIEBASEDDEFG)
    01992     {
    01993         dwSize = nOutputCh * nGrids * nGrids * nGrids * nGrids * 2;
    01994     }
    01995     else
    01996     {
    01997         dwSize = nOutputCh * nGrids * nGrids * nGrids * 2;
    01998     }
    01999
    02000     dwSize = dwSize +
    02001         nInputCh * nInputTable * 6 +
    02002         nOutputCh * nOutputTable * 6 +      // Number of INT bytes
    02003         nInputCh * (STRLEN(IndexArray) +
    02004                     STRLEN(StartClip) +
    02005                     STRLEN(EndClip)) +
    02006         nOutputCh * (STRLEN(IndexArray) +
    02007                      STRLEN(StartClip) +
    02008                      STRLEN(EndClip)) +
    02009         4096;                               // + other PS stuff
    02010
    02011     //
    02012     // Add space for new line.
    02013     //
    02014
    02015     dwSize += (((dwSize) / MAX_LINELEN) + 1) * STRLEN(NewLine);
    02016
    02017     if (! pBuffer)
    02018     {
    02019         *pcbSize = dwSize;
    02020         return TRUE;
    02021     }
    02022     else if (*pcbSize < dwSize)
    02023     {
    02024         WARNING((__TEXT("Buffer too small to get DEFG CSA\n")));
    02025         SetLastError(ERROR_INSUFFICIENT_BUFFER);
    02026         return FALSE;
    02027     }
    02028
    02029     //
    02030     // Get info about Illuminant White Point from the header
    02031     //
    02032
    02033     (void)GetCPWhitePoint(pProfile, afxIlluminantWP);
    02034
    02035     //
    02036     // Support absolute whitePoint
    02037     //
    02038
    02039     (void)GetMediaWP(pProfile, dwIntent, afxIlluminantWP, afxMediaWP);
    02040
    02041     //
    02042     // Testing CieBasedDEFG support
    02043     //
    02044
    02045     pBuffer += WriteNewLineObject(pBuffer, TestingDEFG);
    02046
    02047     //
    02048     // Create global data
    02049     //
    02050
    02051     GetPublicArrayName(dwTag, pPublicArrayName);
    02052
    02053     if (dwType == TYPE_CIEBASEDDEFG)
    02054     {
    02055         pBuffer += WriteNewLineObject(pBuffer, CieBasedDEFGBegin);
    02056     }
    02057     else
    02058     {
    02059         pBuffer += WriteNewLineObject(pBuffer, CieBasedDEFBegin);
    02060     }
    02061
    02062     pBuffer += EnableGlobalDict(pBuffer);
    02063     pBuffer += WriteNewLineObject(pBuffer, SupportDEFG_S);
    02064     pBuffer += BeginGlobalDict(pBuffer);
    02065
    02066     pBuffer += CreateInputArray(pBuffer, nInputCh, nInputTable,
    02067                  pPublicArrayName, dwLutSig, (PBYTE)pLut, *pbBinary, NULL);
    02068
    02069     if (dwType == TYPE_CIEBASEDDEFG)
    02070     {
    02071         i = nInputTable * nInputCh +
    02072             nGrids * nGrids * nGrids * nGrids * nOutputCh;
    02073     }
    02074     else
    02075     {
    02076         i = nInputTable * nInputCh +
    02077             nGrids * nGrids * nGrids * nOutputCh;
    02078     }
    02079     pBuffer += CreateOutputArray(pBuffer, nOutputCh, nOutputTable, i,
    02080                  pPublicArrayName, dwLutSig, (PBYTE)pLut, *pbBinary, NULL);
    02081
    02082     pBuffer += WriteNewLineObject(pBuffer, EndOp);
    02083     pBuffer += WriteNewLineObject(pBuffer, SupportDEFG_E);
    02084     pBuffer += WriteNewLineObject(pBuffer, SetGlobalOp);
    02085     pBuffer += WriteNewLineObject(pBuffer, SupportDEFG_S);
    02086
    02087     //
    02088     // Start creating the ColorSpace
    02089     //
    02090
    02091     pBuffer += WriteNewLineObject(pBuffer, BeginArray);   // Begin array
    02092
    02093     //
    02094     // /CIEBasedDEF(G)
    02095     //
    02096
    02097     if (dwType == TYPE_CIEBASEDDEFG)
    02098     {
    02099         pBuffer += WriteObject(pBuffer, CIEBasedDEFGTag);
    02100     }
    02101     else
    02102     {
    02103         pBuffer += WriteObject(pBuffer, CIEBasedDEFTag);
    02104     }
    02105
    02106     pBuffer += WriteObject(pBuffer, BeginDict);    // Begin dictionary
    02107
    02108     //
    02109     // /BlackPoint & /WhitePoint
    02110     //
    02111
    02112     pBuffer += SendCSABWPoint(pBuffer, dwIntent, afxIlluminantWP, afxMediaWP);
    02113
    02114     //
    02115     // /DecodeDEF(G)
    02116     //
    02117
    02118     pLineStart = pBuffer;
    02119
    02120     if (dwType == TYPE_CIEBASEDDEFG)
    02121     {
    02122         pBuffer += WriteNewLineObject(pBuffer, DecodeDEFGTag);
    02123     }
    02124     else
    02125     {
    02126         pBuffer += WriteNewLineObject(pBuffer, DecodeDEFTag);
    02127     }
    02128
    02129     pBuffer += WriteObject(pBuffer, BeginArray);
    02130     for (i=0; i<nInputCh; i++)
    02131     {
    02132         pLineStart = pBuffer;
    02133
    02134         pBuffer += WriteNewLineObject(pBuffer, BeginFunction);
    02135         pBuffer += WriteObject(pBuffer, StartClip);
    02136         pBuffer += WriteObject(pBuffer, InputArray);
    02137         pBuffer += WriteObject(pBuffer, pPublicArrayName);
    02138         pBuffer += WriteInt(pBuffer, i);
    02139
    02140         if (! *pbBinary)               // Output ASCII
    02141         {
    02142             pBuffer += WriteObject(pBuffer, IndexArray);
    02143         }
    02144         else
    02145         {                               // Output BINARY
    02146             if (dwLutSig == LUT8_TYPE)
    02147             {
    02148                 pBuffer += WriteObject(pBuffer, IndexArray);
    02149             }
    02150             else
    02151             {
    02152                 pBuffer += WriteObject(pBuffer, IndexArray16b);
    02153             }
    02154         }
    02155         pBuffer += WriteObject(pBuffer, (dwLutSig == LUT8_TYPE) ? Scale8 : Scale16);
    02156         pBuffer += WriteObject(pBuffer, EndClip);
    02157         pBuffer += WriteObject(pBuffer, EndFunction);
    02158     }
    02159     pBuffer += WriteObject(pBuffer, EndArray);
    02160
    02161     //
    02162     // /Table
    02163     //
    02164
    02165     pBuffer += WriteNewLineObject(pBuffer, TableTag);
    02166     pBuffer += WriteObject(pBuffer, BeginArray);
    02167
    02168     pBuffer += WriteInt(pBuffer, nGrids);  // Send down Nh
    02169     pBuffer += WriteInt(pBuffer, nGrids);  // Send down Ni
    02170     pBuffer += WriteInt(pBuffer, nGrids);  // Send down Nj
    02171     nNumbers = nGrids * nGrids * nOutputCh;
    02172     SecondGrids = 1;
    02173
    02174     if (dwType == TYPE_CIEBASEDDEFG)
    02175     {
    02176         pBuffer += WriteInt (pBuffer, nGrids);  // Send down Nk
    02177         SecondGrids = nGrids;
    02178     }
    02179     pBuffer += WriteNewLineObject(pBuffer, BeginArray);
    02180
    02181     for (i=0; i<nGrids; i++)        // Nh strings should be sent
    02182     {
    02183         if (dwType == TYPE_CIEBASEDDEFG)
    02184         {
    02185             pBuffer += WriteNewLineObject(pBuffer, BeginArray);
    02186         }
    02187         for (k=0; k<SecondGrids; k++)
    02188         {
    02189             pLineStart = pBuffer;
    02190             pBuffer += WriteObject(pBuffer, NewLine);
    02191             if (dwLutSig == LUT8_TYPE)
    02192             {
    02193                 pTable = (PBYTE)(((PLUT8TYPE)pLut)->data) +
    02194                     nInputTable * nInputCh +
    02195                     nNumbers * (i * SecondGrids + k);
    02196             }
    02197             else
    02198             {
    02199                 pTable = (PBYTE)(((PLUT16TYPE)pLut)->data) +
    02200                     2 * nInputTable * nInputCh +
    02201                     2 * nNumbers * (i * SecondGrids + k);
    02202             }
    02203
    02204             if (! *pbBinary)           // Output ASCII
    02205             {
    02206                 pBuffer += WriteObject(pBuffer, BeginString);
    02207                 if (dwLutSig == LUT8_TYPE)
    02208                 {
    02209                     pBuffer += WriteHexBuffer(pBuffer, pTable, pLineStart, nNumbers);
    02210                 }
    02211                 else
    02212                 {
    02213                     for (j=0; j<nNumbers; j++)
    02214                     {
    02215                         pBuffer += WriteHex(pBuffer, FIX_ENDIAN16(*((PWORD)pTable)) / 256);
    02216                         pTable += sizeof(WORD);
    02217
    02218                         if (((DWORD) (pBuffer - pLineStart)) > MAX_LINELEN)
    02219                         {
    02220                             pLineStart = pBuffer;
    02221                             pBuffer += WriteObject(pBuffer, NewLine);
    02222                         }
    02223                     }
    02224                 }
    02225                 pBuffer += WriteObject(pBuffer, EndString);
    02226             }
    02227             else
    02228             {                           // Output BINARY
    02229                 pBuffer += WriteStringToken(pBuffer, 143, nNumbers);
    02230                 if (dwLutSig == LUT8_TYPE)
    02231                     pBuffer += WriteByteString(pBuffer, pTable, nNumbers);
    02232                 else
    02233                     pBuffer += WriteInt2ByteString(pBuffer, pTable, nNumbers);
    02234             }
    02235             pBuffer += WriteObject (pBuffer, NewLine);
    02236         }
    02237         if (dwType == TYPE_CIEBASEDDEFG)
    02238         {
    02239             pBuffer += WriteObject(pBuffer, EndArray);
    02240         }
    02241     }
    02242     pBuffer += WriteObject(pBuffer, EndArray);
    02243     pBuffer += WriteObject(pBuffer, EndArray); // End array
    02244
    02245     //
    02246     // /DecodeABC
    02247     //
    02248
    02249     pLineStart = pBuffer;
    02250     pBuffer += WriteNewLineObject(pBuffer, DecodeABCTag);
    02251     pBuffer += WriteObject(pBuffer, BeginArray);
    02252     for (i=0; i<nOutputCh; i++)
    02253     {
    02254         pLineStart = pBuffer;
    02255
    02256         pBuffer += WriteNewLineObject(pBuffer, BeginFunction);
    02257         pBuffer += WriteObject(pBuffer, Clip01);
    02258         pBuffer += WriteObject(pBuffer, OutputArray);
    02259         pBuffer += WriteObject(pBuffer, pPublicArrayName);
    02260         pBuffer += WriteInt(pBuffer, i);
    02261
    02262         if (! *pbBinary)
    02263         {
    02264             pBuffer += WriteObject(pBuffer, NewLine);
    02265
    02266             if (dwLutSig == LUT8_TYPE)
    02267             {
    02268                 pBuffer += WriteObject(pBuffer, TFunction8XYZ);
    02269             }
    02270             else
    02271             {
    02272                 pBuffer += WriteObject(pBuffer, IndexArray);
    02273                 pBuffer += WriteObject(pBuffer, Scale16XYZ);
    02274             }
    02275         }
    02276         else
    02277         {
    02278             if (dwLutSig == LUT8_TYPE)
    02279             {
    02280                 pBuffer += WriteObject(pBuffer, TFunction8XYZ);
    02281             }
    02282             else
    02283             {
    02284                 pBuffer += WriteObject(pBuffer, IndexArray16b);
    02285                 pBuffer += WriteObject(pBuffer, Scale16XYZ);
    02286             }
    02287         }
    02288
    02289         //
    02290         // Now, We get CieBasedXYZ output. Output range 0 --> 1.99997
    02291         // If the connection space is absolute XYZ, We need to convert
    02292         // from relative XYZ to absolute XYZ.
    02293         //
    02294
    02295         if ((dwPCS == SPACE_XYZ) && (dwIntent == INTENT_ABSOLUTE_COLORIMETRIC))
    02296         {
    02297             pBuffer += WriteFixed(pBuffer, FIX_DIV(afxMediaWP[i], afxIlluminantWP[i]));
    02298             pBuffer += WriteObject(pBuffer, MulOp);
    02299         }
    02300         else if (dwPCS == SPACE_Lab)
    02301         {
    02302             //
    02303             // If the connection space is Lab, We need to convert XYZ to Lab
    02304             //
    02305
    02306             pBuffer += WriteObject(pBuffer, DecodeABCLab[i]);
    02307         }
    02308         pBuffer += WriteObject(pBuffer, EndFunction);
    02309     }
    02310     pBuffer += WriteObject(pBuffer, EndArray);
    02311
    02312     if (dwPCS == SPACE_Lab)
    02313     {
    02314         //
    02315         // /MatrixABC
    02316         //
    02317
    02318         pBuffer += WriteNewLineObject(pBuffer, MatrixABCTag);
    02319         pBuffer += WriteObject(pBuffer, MatrixABCLab);
    02320
    02321         //
    02322         // /DecodeLMN
    02323         //
    02324
    02325         pLineStart = pBuffer;
    02326         pBuffer += WriteNewLineObject(pBuffer, DecodeLMNTag);
    02327         pBuffer += WriteObject(pBuffer, BeginArray);
    02328         for (i=0; i<3; i++)
    02329         {
    02330             pLineStart = pBuffer;
    02331
    02332             pBuffer += WriteNewLineObject(pBuffer, BeginFunction);
    02333             pBuffer += WriteObject(pBuffer, DecodeLMNLab);
    02334             if (dwIntent == INTENT_ABSOLUTE_COLORIMETRIC)
    02335             {
    02336                 pBuffer += WriteFixed(pBuffer, afxMediaWP[i]);
    02337             }
    02338             else
    02339             {
    02340                 pBuffer += WriteFixed(pBuffer, afxIlluminantWP[i]);
    02341             }
    02342             pBuffer += WriteObject(pBuffer, MulOp);
    02343             pBuffer += WriteObject(pBuffer, EndFunction);
    02344         }
    02345         pBuffer += WriteObject(pBuffer, EndArray);
    02346     }
    02347     else
    02348     {
    02349         //
    02350         // /RangeLMN
    02351         //
    02352
    02353         pBuffer += WriteNewLineObject(pBuffer, RangeLMNTag);
    02354         pBuffer += WriteObject(pBuffer, RangeLMN);
    02355     }
    02356
    02357     //
    02358     // End dictionary definition
    02359     //
    02360
    02361     pBuffer += WriteNewLineObject(pBuffer, EndDict);
    02362     pBuffer += WriteObject(pBuffer, EndArray);
    02363
    02364     if (dwType == TYPE_CIEBASEDDEFG)
    02365     {
    02366         pBuffer += WriteNewLineObject(pBuffer, CieBasedDEFGEnd);
    02367     }
    02368     else
    02369     {
    02370         pBuffer += WriteNewLineObject(pBuffer, CieBasedDEFEnd);
    02371     }
    02372
    02373     pBuffer += WriteNewLineObject(pBuffer, SupportDEFG_E);
    02374
    02375     *pcbSize = (DWORD) (pBuffer - pStart);
    02376
    02377     return TRUE;
    02378 }
    02379
    02380
    02381 BOOL
    02382 InternalGetPS2CSAFromLCS(
    02383     LPLOGCOLORSPACE pLogColorSpace,
    02384     PBYTE           pBuffer,
    02385     PDWORD          pcbSize,
    02386     PBOOL           pbBinary
    02387     )
    02388 {
    02389     PBYTE  pStart = pBuffer;
    02390     DWORD  dwSize = 1024*2; // same value as in pscript/icm.c
    02391
    02392     if (! pBuffer)
    02393     {
    02394         *pcbSize = dwSize;
    02395
    02396         return TRUE;
    02397     }
    02398
    02399     if (*pcbSize < dwSize)
    02400     {
    02401         WARNING((__TEXT("Buffer too small to get CSA from LCS\n")));
    02402         SetLastError(ERROR_INSUFFICIENT_BUFFER);
    02403         return FALSE;
    02404     }
    02405
    02406     pBuffer += WriteObject(pBuffer, NewLine);
    02407     pBuffer += WriteObject(pBuffer, BeginArray);    // Begin array
    02408
    02409     pBuffer += WriteObject(pBuffer, ColorSpace1);
    02410     pBuffer += WriteObject(pBuffer, BeginArray);    // [
    02411
    02412     //
    02413     // Red gamma
    02414     //
    02415
    02416     pBuffer += WriteObject(pBuffer, BeginFunction);
    02417     pBuffer += WriteFixed(pBuffer, pLogColorSpace->lcsGammaRed);
    02418     pBuffer += WriteObject(pBuffer, ColorSpace3);
    02419
    02420     //
    02421     // Green gamma
    02422     //
    02423
    02424     pBuffer += WriteObject(pBuffer, BeginFunction);
    02425     pBuffer += WriteFixed(pBuffer, pLogColorSpace->lcsGammaGreen);
    02426     pBuffer += WriteObject(pBuffer, ColorSpace3);
    02427
    02428     //
    02429     // Blue Gamma
    02430     //
    02431
    02432     pBuffer += WriteObject(pBuffer, BeginFunction);
    02433     pBuffer += WriteFixed(pBuffer, pLogColorSpace->lcsGammaBlue);
    02434     pBuffer += WriteObject(pBuffer, ColorSpace3);
    02435
    02436     pBuffer += WriteObject(pBuffer, EndArray);      // ]
    02437
    02438     pBuffer += WriteObject(pBuffer, ColorSpace5);   // /WhitePoint
    02439
    02440     //
    02441     // Matrix LMN
    02442     //
    02443
    02444     pBuffer += WriteObject(pBuffer, MatrixLMNTag);
    02445     pBuffer += WriteObject(pBuffer, BeginArray);
    02446
    02447     //
    02448     // Red Value
    02449     //
    02450
    02451     pBuffer += WriteFixed2dot30(pBuffer, pLogColorSpace->lcsEndpoints.ciexyzRed.ciexyzX);
    02452     pBuffer += WriteFixed2dot30(pBuffer, pLogColorSpace->lcsEndpoints.ciexyzRed.ciexyzY);
    02453     pBuffer += WriteFixed2dot30(pBuffer, pLogColorSpace->lcsEndpoints.ciexyzRed.ciexyzZ);
    02454
    02455     //
    02456     // Green Value
    02457     //
    02458
    02459     pBuffer += WriteFixed2dot30(pBuffer, pLogColorSpace->lcsEndpoints.ciexyzGreen.ciexyzX);
    02460     pBuffer += WriteFixed2dot30(pBuffer, pLogColorSpace->lcsEndpoints.ciexyzGreen.ciexyzY);
    02461     pBuffer += WriteFixed2dot30(pBuffer, pLogColorSpace->lcsEndpoints.ciexyzGreen.ciexyzZ);
    02462
    02463     //
    02464     // Blue Value
    02465     //
    02466
    02467     pBuffer += WriteFixed2dot30(pBuffer, pLogColorSpace->lcsEndpoints.ciexyzBlue.ciexyzX);
    02468     pBuffer += WriteFixed2dot30(pBuffer, pLogColorSpace->lcsEndpoints.ciexyzBlue.ciexyzY);
    02469     pBuffer += WriteFixed2dot30(pBuffer, pLogColorSpace->lcsEndpoints.ciexyzBlue.ciexyzZ);
    02470
    02471     pBuffer += WriteObject(pBuffer, EndArray);      // ]
    02472     pBuffer += WriteObject(pBuffer, EndDict);       // End dictionary
    02473
    02474     pBuffer += WriteObject(pBuffer, EndArray);      // ]
    02475
    02476     *pcbSize = (DWORD) (pBuffer - pStart);
    02477
    02478     return TRUE;
    02479 }
    02480
    02481
    02482 /******************************************************************************
    02483  *
    02484  *                           CreateColorSpArray
    02485  *
    02486  *  Function:
    02487  *       This function creates an array that is used in /DecodeABC
    02488  *
    02489  *  Arguments:
    02490  *       pProfile  - pointer to the memory mapped profile
    02491  *       pBuffer   - pointer to receive the array
    02492  *       dwCPTag   - Channel TRC tag
    02493  *       bBinary   - TRUE if binary data is requested
    02494  *
    02495  *  Returns:
    02496  *       Length of the data created in bytes
    02497  *
    02498  ******************************************************************************/
    02499
    02500 DWORD
    02501 CreateColSpArray(
    02502     PBYTE pProfile,
    02503     PBYTE pBuffer,
    02504     DWORD dwCPTag,
    02505     BOOL  bBinary
    02506     )
    02507 {
    02508     PCURVETYPE pData;
    02509     PTAGDATA   pTagData;
    02510     PBYTE      pLineStart, pStart = pBuffer;
    02511     PBYTE      pTable;
    02512     DWORD      i, nCount, dwIndex;
    02513
    02514     pLineStart = pBuffer;
    02515
    02516     if (DoesCPTagExist(pProfile, dwCPTag, &dwIndex))
    02517     {
    02518         pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
    02519                    dwIndex * sizeof(TAGDATA));
    02520
    02521         pData = (PCURVETYPE)(pProfile + FIX_ENDIAN(pTagData->dwOffset));
    02522
    02523         nCount = FIX_ENDIAN(pData->nCount);
    02524
    02525         if (nCount > 1)
    02526         {
    02527             pBuffer += WriteNewLineObject(pBuffer, Slash);
    02528             pBuffer += WriteObject(pBuffer, DecodeABCArray);
    02529             pBuffer += WriteInt(pBuffer, dwCPTag);
    02530
    02531             pTable = (PBYTE)(pData->data);
    02532
    02533             if (! bBinary)           // Output ASCII CS
    02534             {
    02535                 pBuffer += WriteObject(pBuffer, BeginArray);
    02536                 for (i=0; i<nCount; i++)
    02537                 {
    02538                     pBuffer += WriteInt(pBuffer, FIX_ENDIAN16(*((PWORD)pTable)));
    02539                     pTable += sizeof(WORD);
    02540
    02541                     if (((DWORD) (pBuffer - pLineStart)) > MAX_LINELEN)
    02542                     {
    02543                         pLineStart = pBuffer;
    02544                         pBuffer += WriteObject(pBuffer, NewLine);
    02545                     }
    02546                 }
    02547                 pBuffer += WriteObject(pBuffer, EndArray);
    02548             }
    02549             else
    02550             {                           // Output BINARY CS
    02551                 pBuffer += WriteHNAToken(pBuffer, 149, nCount);
    02552                 pBuffer += WriteIntStringU2S(pBuffer, pTable, nCount);
    02553             }
    02554
    02555             pBuffer += WriteObject(pBuffer, DefOp);
    02556         }
    02557     }
    02558     return (DWORD) (pBuffer - pStart);
    02559 }
    02560
    02561
    02562 /******************************************************************************
    02563  *
    02564  *                           CreateColorSpProc
    02565  *
    02566  *  Function:
    02567  *       This function creates a PostScript procedure for the color space
    02568  *
    02569  *  Arguments:
    02570  *       pProfile  - pointer to the memory mapped profile
    02571  *       pBuffer   - pointer to receive the procedure
    02572  *       dwCPTag   - Channel TRC tag
    02573  *       bBinary   - TRUE if binary data is requested
    02574  *
    02575  *  Returns:
    02576  *       Length of the data created in bytes
    02577  *
    02578  ******************************************************************************/
    02579
    02580 DWORD
    02581 CreateColSpProc(
    02582     PBYTE pProfile,
    02583     PBYTE pBuffer,
    02584     DWORD dwCPTag,
    02585     BOOL  bBinary
    02586     )
    02587 {
    02588     PCURVETYPE pData;
    02589     PTAGDATA   pTagData;
    02590     PBYTE      pStart = pBuffer;
    02591     PBYTE      pTable;
    02592     DWORD      nCount, dwIndex;
    02593
    02594     pBuffer += WriteObject(pBuffer, BeginFunction);
    02595
    02596     if (DoesCPTagExist(pProfile, dwCPTag, &dwIndex))
    02597     {
    02598         pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
    02599                    dwIndex * sizeof(TAGDATA));
    02600
    02601         pData = (PCURVETYPE)(pProfile + FIX_ENDIAN(pTagData->dwOffset));
    02602
    02603         nCount = FIX_ENDIAN(pData->nCount);
    02604
    02605         if (nCount != 0)
    02606         {
    02607             if (nCount == 1)            // Gamma supplied in ui16 format
    02608             {
    02609                 pTable = (PBYTE)(pData->data);
    02610                 pBuffer += WriteInt(pBuffer, FIX_ENDIAN16(*((PWORD)pTable)));
    02611                 pBuffer += WriteObject(pBuffer, DecodeA3);
    02612             }
    02613             else
    02614             {
    02615                 pBuffer += WriteObject(pBuffer, StartClip);
    02616                 pBuffer += WriteObject(pBuffer, DecodeABCArray);
    02617                 pBuffer += WriteInt(pBuffer, dwCPTag);
    02618
    02619                 if (! bBinary)       // Output ASCII CS
    02620                 {
    02621                     pBuffer += WriteObject(pBuffer, IndexArray);
    02622                 }
    02623                 else
    02624                 {                    // Output BINARY CS
    02625                     pBuffer += WriteObject(pBuffer, IndexArray16b);
    02626                 }
    02627                 pBuffer += WriteObject(pBuffer, Scale16);
    02628                 pBuffer += WriteObject(pBuffer, EndClip);
    02629             }
    02630         }
    02631     }
    02632     pBuffer += WriteObject(pBuffer, EndFunction);
    02633
    02634     return (DWORD) (pBuffer - pStart);
    02635 }
    02636
    02637
    02638 /******************************************************************************
    02639  *
    02640  *                           CreateFloatString
    02641  *
    02642  *  Function:
    02643  *       This function creates a string of floating point numbers for
    02644  *       the X, Y and Z values of the specified colorant.
    02645  *
    02646  *  Arguments:
    02647  *       pProfile  - pointer to the memory mapped profile
    02648  *       pBuffer   - pointer to receive the string
    02649  *       dwCPTag   - Colorant tag
    02650  *
    02651  *  Returns:
    02652  *       Length of the data created in bytes
    02653  *
    02654  ******************************************************************************/
    02655
    02656 DWORD
    02657 CreateFloatString(
    02658     PBYTE pProfile,
    02659     PBYTE pBuffer,
    02660     DWORD dwCPTag
    02661     )
    02662 {
    02663     PTAGDATA   pTagData;
    02664     PBYTE      pStart = pBuffer;
    02665     PDWORD     pTable;
    02666     DWORD      i, dwIndex;
    02667
    02668     if (DoesCPTagExist(pProfile, dwCPTag, &dwIndex))
    02669     {
    02670         pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
    02671                    dwIndex * sizeof(TAGDATA));
    02672
    02673         pTable = (PDWORD)(pProfile + FIX_ENDIAN(pTagData->dwOffset)) + 2;
    02674
    02675         for (i=0; i<3; i++)
    02676         {
    02677             pBuffer += WriteFixed(pBuffer, FIX_ENDIAN(*pTable));
    02678             pTable ++;
    02679         }
    02680     }
    02681
    02682     return (DWORD) (pBuffer - pStart);
    02683 }
    02684
    02685
    02686 /******************************************************************************
    02687  *
    02688  *                           CreateInputArray
    02689  *
    02690  *  Function:
    02691  *       This function creates the Color Rendering Dictionary (CRD)
    02692  *       from the data supplied in the ColorProfile's LUT8 or LUT16 tag.
    02693  *
    02694  *  Arguments:
    02695  *       pBuffer        - pointer to receive the data
    02696  *       nInputChannels - number of input channels
    02697  *       nInputTable    - size of input table
    02698  *       pIntent        - rendering intent signature (eg. A2B0)
    02699  *       dwTag          - signature of the look up table (8 or 16 bits)
    02700  *       pLut           - pointer to the look up table
    02701  *       bBinary        - TRUE if binary data is requested
    02702  *
    02703  *  Returns:
    02704  *       Length of the data created in bytes
    02705  *
    02706  ******************************************************************************/
    02707
    02708 DWORD
    02709 CreateInputArray(
    02710     PBYTE pBuffer,
    02711     DWORD nInputChannels,
    02712     DWORD nInputTable,
    02713     PBYTE pIntent,
    02714     DWORD dwTag,
    02715     PBYTE pLut,
    02716     BOOL  bBinary,
    02717     PBYTE pHostClut
    02718     )
    02719 {
    02720     DWORD i, j;
    02721     PBYTE pLineStart, pStart = pBuffer;
    02722     PBYTE pTable;
    02723
    02724     if (pHostClut)
    02725     {
    02726         nInputChannels = ((PHOSTCLUT)pHostClut)->nInputCh;
    02727         nInputTable = ((PHOSTCLUT)pHostClut)->nInputEntries;
    02728         dwTag = ((PHOSTCLUT)pHostClut)->nLutBits == 8 ? LUT8_TYPE : LUT16_TYPE;
    02729     }
    02730
    02731     for (i=0; i<nInputChannels; i++)
    02732     {
    02733         pLineStart = pBuffer;
    02734         pBuffer += WriteNewLineObject(pBuffer, Slash);
    02735         if (pHostClut)
    02736             pBuffer += WriteObject(pBuffer, PreViewInArray);
    02737         else
    02738             pBuffer += WriteObject(pBuffer, InputArray);
    02739
    02740         pBuffer += WriteObject(pBuffer, pIntent);
    02741         pBuffer += WriteInt(pBuffer, i);
    02742
    02743         if (pHostClut)
    02744         {
    02745             pTable = ((PHOSTCLUT)pHostClut)->inputArray[i];
    02746         }
    02747         else
    02748         {
    02749             if (dwTag == LUT8_TYPE)
    02750             {
    02751                 pTable = (PBYTE)(((PLUT8TYPE)pLut)->data) + nInputTable * i;
    02752             }
    02753             else
    02754             {
    02755                 pTable = (PBYTE)(((PLUT16TYPE)pLut)->data) + 2 * nInputTable * i;
    02756             }
    02757         }
    02758
    02759         if (! bBinary)
    02760         {
    02761             if (dwTag == LUT8_TYPE)
    02762             {
    02763                 pBuffer += WriteObject(pBuffer, BeginString);
    02764                 pBuffer += WriteHexBuffer(pBuffer, pTable, pLineStart, nInputTable);
    02765                 pBuffer += WriteObject(pBuffer, EndString);
    02766             }
    02767             else
    02768             {
    02769                 pBuffer += WriteObject(pBuffer, BeginArray);
    02770                 for (j=0; j<nInputTable; j++)
    02771                 {
    02772                     if (pHostClut)
    02773                         pBuffer += WriteInt(pBuffer, *((PWORD)pTable));
    02774                     else
    02775                         pBuffer += WriteInt(pBuffer, FIX_ENDIAN16(*((PWORD)pTable)));
    02776                     pTable += sizeof(WORD);
    02777                     if (((DWORD) (pBuffer - pLineStart)) > MAX_LINELEN)
    02778                     {
    02779                         pLineStart = pBuffer;
    02780                         pBuffer += WriteObject(pBuffer, NewLine);
    02781                     }
    02782                 }
    02783                 pBuffer += WriteObject(pBuffer, EndArray);
    02784             }
    02785         }
    02786         else
    02787         {
    02788             if (dwTag == LUT8_TYPE)
    02789             {
    02790                 pBuffer += WriteStringToken(pBuffer, 143, nInputTable);
    02791                 pBuffer += WriteByteString(pBuffer, pTable, nInputTable);
    02792             }
    02793             else
    02794             {
    02795                 pBuffer += WriteHNAToken(pBuffer, 149, nInputTable);
    02796                 if (pHostClut)
    02797                     pBuffer += WriteIntStringU2S_L(pBuffer, pTable, nInputTable);
    02798                 else
    02799                     pBuffer += WriteIntStringU2S(pBuffer, pTable, nInputTable);
    02800             }
    02801         }
    02802         pBuffer += WriteObject(pBuffer, DefOp);
    02803     }
    02804
    02805     return (DWORD) (pBuffer - pStart);
    02806 }
    02807
    02808
    02809
    02810 /******************************************************************************
    02811  *
    02812  *                           CreateOutputArray
    02813  *
    02814  *  Function:
    02815  *       This function creates the Color Rendering Dictionary (CRD)
    02816  *       from the data supplied in the ColorProfile's LUT8 or LUT16 tag.
    02817  *
    02818  *  Arguments:
    02819  *       pBuffer        - pointer to receive the data
    02820  *       nOutputChannels- number of output channels
    02821  *       nOutputTable   - size of output table
    02822  *       dwOffset       - offset into the output table
    02823  *       pIntent        - rendering intent signature (eg. A2B0)
    02824  *       dwTag          - signature of the look up table (8 or 16 bits)
    02825  *       pLut           - pointer to the look up table
    02826  *       bBinary        - TRUE if binary data is requested
    02827  *
    02828  *  Returns:
    02829  *       Length of the data created in bytes
    02830  *
    02831  ******************************************************************************/
    02832
    02833 DWORD
    02834 CreateOutputArray(
    02835     PBYTE pBuffer,
    02836     DWORD nOutputChannels,
    02837     DWORD nOutputTable,
    02838     DWORD dwOffset,
    02839     PBYTE pIntent,
    02840     DWORD dwTag,
    02841     PBYTE pLut,
    02842     BOOL  bBinary,
    02843     PBYTE pHostClut
    02844     )
    02845 {
    02846     DWORD i, j;
    02847     PBYTE pLineStart, pStart = pBuffer;
    02848     PBYTE pTable;
    02849
    02850     if (pHostClut)
    02851     {
    02852         nOutputChannels = ((PHOSTCLUT)pHostClut)->nOutputCh;
    02853         nOutputTable = ((PHOSTCLUT)pHostClut)->nOutputEntries;
    02854         dwTag = ((PHOSTCLUT)pHostClut)->nLutBits == 8 ? LUT8_TYPE : LUT16_TYPE;
    02855     }
    02856
    02857     for (i=0; i<nOutputChannels; i++)
    02858     {
    02859         pLineStart = pBuffer;
    02860         pBuffer += WriteNewLineObject(pBuffer, Slash);
    02861         if (pHostClut)
    02862             pBuffer += WriteObject(pBuffer, PreViewOutArray);
    02863         else
    02864             pBuffer += WriteObject(pBuffer, OutputArray);
    02865         pBuffer += WriteObject(pBuffer, pIntent);
    02866         pBuffer += WriteInt(pBuffer, i);
    02867
    02868         if (pHostClut)
    02869         {
    02870             pTable = ((PHOSTCLUT)pHostClut)->outputArray[i];
    02871         }
    02872         else
    02873         {
    02874             if (dwTag == LUT8_TYPE)
    02875             {
    02876                 pTable = (PBYTE)(((PLUT8TYPE)pLut)->data) +
    02877                     dwOffset + nOutputTable * i;
    02878             }
    02879             else
    02880             {
    02881                 pTable = (PBYTE)(((PLUT16TYPE)pLut)->data) +
    02882                     2 * dwOffset + 2 * nOutputTable * i;
    02883             }
    02884         }
    02885
    02886         if (! bBinary)
    02887         {
    02888             if (dwTag == LUT8_TYPE)
    02889             {
    02890                 pBuffer += WriteObject(pBuffer, BeginString);
    02891                 pBuffer += WriteHexBuffer(pBuffer, pTable, pLineStart, nOutputTable);
    02892                 pBuffer += WriteObject(pBuffer, EndString);
    02893             }
    02894             else
    02895             {
    02896                 pBuffer += WriteObject(pBuffer, BeginArray);
    02897                 for (j=0; j<nOutputTable; j++)
    02898                 {
    02899                     if (pHostClut)
    02900                         pBuffer += WriteInt(pBuffer, *((PWORD)pTable));
    02901                     else
    02902                         pBuffer += WriteInt(pBuffer, FIX_ENDIAN16(*((PWORD)pTable)));
    02903                     pTable += sizeof(WORD);
    02904                     if (((DWORD) (pBuffer - pLineStart)) > MAX_LINELEN)
    02905                     {
    02906                         pLineStart = pBuffer;
    02907                         pBuffer += WriteObject(pBuffer, NewLine);
    02908                     }
    02909                 }
    02910                 pBuffer += WriteObject(pBuffer, EndArray);
    02911             }
    02912         }
    02913         else
    02914         {
    02915             if (dwTag == LUT8_TYPE)
    02916             {
    02917                 pBuffer += WriteStringToken(pBuffer, 143, 256);
    02918                 pBuffer += WriteByteString(pBuffer, pTable, 256L);
    02919             }
    02920             else
    02921             {
    02922                 pBuffer += WriteHNAToken(pBuffer, 149, nOutputTable);
    02923                 if (pHostClut)
    02924                     pBuffer += WriteIntStringU2S_L(pBuffer, pTable, nOutputTable);
    02925                 else
    02926                     pBuffer += WriteIntStringU2S(pBuffer, pTable, nOutputTable);
    02927             }
    02928         }
    02929         pBuffer += WriteObject(pBuffer, DefOp);
    02930     }
    02931
    02932     return (DWORD)(pBuffer - pStart);
    02933 }
    02934
    02935
    02936 /******************************************************************************
    02937  *
    02938  *                           GetPublicArrayName
    02939  *
    02940  *  Function:
    02941  *       This function creates a string with the lookup table's signature
    02942  *
    02943  *  Arguments:
    02944  *       dwIntentSig      - the look up table signature
    02945  *       pPublicArrayName - pointer to buffer
    02946  *
    02947  *  Returns:
    02948  *       Length of the data created in bytes
    02949  *
    02950  ******************************************************************************/
    02951
    02952 DWORD
    02953 GetPublicArrayName(
    02954     DWORD   dwIntentSig,
    02955     PBYTE   pPublicArrayName
    02956     )
    02957 {
    02958     *((DWORD *)pPublicArrayName) = dwIntentSig;
    02959     pPublicArrayName[sizeof(DWORD)] = '\0';
    02960
    02961     return sizeof(DWORD) + 1;
    02962 }
    02963
    02964
    02965 /***************************************************************************
    02966 *                               CreateMonoCRD
    02967 *  function:
    02968 *    this is the function which creates the Color Rendering Dictionary (CRD)
    02969 *    from the data supplied in the GrayTRC tag.
    02970 *
    02971 *  returns:
    02972 *       BOOL        --  !=0 if the function was successful,
    02973 *                         0 otherwise.
    02974 *                       Returns number of bytes required/transferred
    02975 ***************************************************************************/
    02976
    02977 BOOL
    02978 CreateMonoCRD(
    02979     PBYTE  pProfile,
    02980     DWORD  dwIndex,
    02981     PBYTE  pBuffer,
    02982     PDWORD pcbSize,
    02983     DWORD  dwIntent
    02984     )
    02985 {
    02986     PTAGDATA   pTagData;
    02987     PCURVETYPE pData;
    02988     PBYTE      pLineStart, pStart = pBuffer;
    02989     PWORD      pCurve, pRevCurve, pRevCurveStart;
    02990     DWORD      dwPCS, dwSize, nCount, i;
    02991     FIX_16_16  afxIlluminantWP[3];
    02992     FIX_16_16  afxMediaWP[3];
    02993
    02994     dwPCS = GetCPConnSpace(pProfile);
    02995
    02996     pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
    02997                dwIndex * sizeof(TAGDATA));
    02998
    02999     pData = (PCURVETYPE)(pProfile + FIX_ENDIAN(pTagData->dwOffset));
    03000
    03001     nCount = FIX_ENDIAN(pData->nCount);
    03002
    03003     //
    03004     // Estimate size required to hold the CRD
    03005     //
    03006
    03007     dwSize = nCount * 6 * REVCURVE_RATIO + // Number of INT elements
    03008         2048;                              // + other PS stuff
    03009
    03010     //
    03011     // Add space for new line.
    03012     //
    03013
    03014     dwSize += (((dwSize) / MAX_LINELEN) + 1) * STRLEN(NewLine);
    03015
    03016     if (! pBuffer)
    03017     {
    03018         *pcbSize = dwSize;
    03019         return TRUE;
    03020     }
    03021     else if (*pcbSize < dwSize)
    03022     {
    03023         WARNING((__TEXT("Buffer too small to get Mono CRD\n")));
    03024         SetLastError(ERROR_INSUFFICIENT_BUFFER);
    03025         return FALSE;
    03026     }
    03027
    03028     //
    03029     // Allocate memory, each entry occupy 2 bytes (1 word),
    03030     //
    03031     // input buffer  = (nCount * sizeof(WORD)
    03032     // output buffer = (nCount * sizeof(WORD) * REVCURVE_RATIO)
    03033     //
    03034
    03035     if ((pRevCurveStart = MemAlloc(nCount * sizeof(WORD) * (REVCURVE_RATIO + 1))) == NULL)
    03036     {
    03037         WARNING((__TEXT("Unable to allocate memory for reverse curve\n")));
    03038         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
    03039         return FALSE;
    03040     }
    03041
    03042     //
    03043     // pCurve will points input buffer (which used in GetRevCurve)
    03044     //
    03045
    03046     pCurve    = pRevCurveStart + nCount * REVCURVE_RATIO;
    03047     pRevCurve = pRevCurveStart;
    03048
    03049     (void)GetRevCurve(pData, pCurve, pRevCurve);
    03050
    03051     //
    03052     // Get info about Illuminant White Point from the header
    03053     //
    03054
    03055     (void)GetCPWhitePoint(pProfile, afxIlluminantWP);
    03056
    03057     //
    03058     // Support absolute whitePoint
    03059     //
    03060
    03061     if (dwIntent == INTENT_ABSOLUTE_COLORIMETRIC)
    03062     {
    03063         if (! GetCPMediaWhitePoint(pProfile, afxMediaWP))
    03064         {
    03065             afxMediaWP[0] = afxIlluminantWP[0];
    03066             afxMediaWP[1] = afxIlluminantWP[1];
    03067             afxMediaWP[2] = afxIlluminantWP[2];
    03068         }
    03069     }
    03070
    03071     //
    03072     // Start writing the CRD
    03073     //
    03074
    03075     pBuffer += WriteNewLineObject(pBuffer, BeginDict); // Begin dictionary
    03076     pBuffer += WriteObject(pBuffer, DictType); // Dictionary type
    03077
    03078     //
    03079     // Send /RenderingIntent
    03080     //
    03081
    03082     switch (dwIntent)
    03083     {
    03084         case INTENT_PERCEPTUAL:
    03085             pBuffer += WriteNewLineObject(pBuffer, IntentType);
    03086             pBuffer += WriteObject(pBuffer, IntentPer);
    03087             break;
    03088
    03089         case INTENT_SATURATION:
    03090             pBuffer += WriteNewLineObject(pBuffer, IntentType);
    03091             pBuffer += WriteObject(pBuffer, IntentSat);
    03092             break;
    03093
    03094         case INTENT_RELATIVE_COLORIMETRIC:
    03095             pBuffer += WriteNewLineObject(pBuffer, IntentType);
    03096             pBuffer += WriteObject(pBuffer, IntentRCol);
    03097             break;
    03098
    03099         case INTENT_ABSOLUTE_COLORIMETRIC:
    03100             pBuffer += WriteNewLineObject(pBuffer, IntentType);
    03101             pBuffer += WriteObject(pBuffer, IntentACol);
    03102             break;
    03103     }
    03104
    03105     //
    03106     // Send /BlackPoint & /WhitePoint
    03107     //
    03108
    03109     pBuffer += SendCRDBWPoint(pBuffer, afxIlluminantWP);
    03110
    03111     //
    03112     // Send PQR
    03113     //
    03114
    03115     pBuffer += SendCRDPQR(pBuffer, dwIntent, afxIlluminantWP);
    03116
    03117     //
    03118     // Send LMN
    03119     //
    03120
    03121     pBuffer += SendCRDLMN(pBuffer, dwIntent, afxIlluminantWP, afxMediaWP, dwPCS);
    03122
    03123     //
    03124     // /MatrixABC
    03125     //
    03126
    03127     if (dwPCS == SPACE_XYZ)
    03128     {
    03129         //
    03130         // Switch ABC to BAC, since we want to output B
    03131         // which is converted from Y
    03132         //
    03133
    03134         pBuffer += WriteNewLineObject(pBuffer, MatrixABCTag);
    03135         pBuffer += WriteObject(pBuffer, MatrixABCXYZCRD);
    03136     }
    03137     else if (dwPCS == SPACE_Lab)
    03138     {
    03139         pBuffer += WriteNewLineObject(pBuffer, MatrixABCTag);
    03140         pBuffer += WriteObject(pBuffer, MatrixABCLabCRD);
    03141     }
    03142
    03143     //
    03144     // /EncodeABC
    03145     //
    03146
    03147     if (nCount != 0)
    03148     {
    03149         pBuffer += WriteObject(pBuffer, NewLine);
    03150         pLineStart = pBuffer;
    03151         pBuffer += WriteObject(pBuffer, EncodeABCTag);
    03152         pBuffer += WriteObject(pBuffer, BeginArray);
    03153         pBuffer += WriteObject(pBuffer, BeginFunction);
    03154         if (nCount == 1)                // Gamma supplied in ui16 format
    03155         {
    03156             PBYTE pTable;
    03157
    03158             pTable = (PBYTE) (pData->data);
    03159             pBuffer += WriteInt(pBuffer, FIX_ENDIAN16(*((PWORD)pTable)));
    03160             pBuffer += WriteObject(pBuffer, DecodeA3Rev);
    03161         }
    03162         else
    03163         {
    03164             if (dwPCS == SPACE_Lab)
    03165             {
    03166                 pBuffer += WriteObject(pBuffer, EncodeABCLab1);
    03167             }
    03168             pBuffer += WriteObject(pBuffer, StartClip);
    03169             pBuffer += WriteObject(pBuffer, BeginArray);
    03170             for (i=0; i<nCount * REVCURVE_RATIO; i++)
    03171             {
    03172                 pBuffer += WriteInt(pBuffer, *((WORD *)pRevCurve));
    03173                 pRevCurve++;
    03174                 if (((DWORD) (pBuffer - pLineStart)) > MAX_LINELEN)
    03175                 {
    03176                     pLineStart = pBuffer;
    03177                     pBuffer += WriteObject(pBuffer, NewLine);
    03178                 }
    03179             }
    03180             pBuffer += WriteObject(pBuffer, EndArray);
    03181             pLineStart = pBuffer;
    03182
    03183             pBuffer += WriteNewLineObject(pBuffer, IndexArray);
    03184             pBuffer += WriteObject(pBuffer, Scale16);
    03185             pBuffer += WriteObject(pBuffer, EndClip);
    03186         }
    03187         pBuffer += WriteObject (pBuffer, EndFunction);
    03188         pBuffer += WriteObject (pBuffer, DupOp);
    03189         pBuffer += WriteObject (pBuffer, DupOp);
    03190         pBuffer += WriteObject (pBuffer, EndArray);
    03191     }
    03192     pBuffer += WriteObject(pBuffer, EndDict);  // End dictionary definition
    03193
    03194     MemFree(pRevCurveStart);
    03195
    03196     *pcbSize = (DWORD) (pBuffer - pStart);
    03197
    03198     return TRUE;
    03199 }
    03200
    03201
    03202 /***************************************************************************
    03203 *                               CreateLutCRD
    03204 *  function:
    03205 *    this is the function which creates the Color Rendering Dictionary (CRD)
    03206 *    from the data supplied in the ColorProfile's LUT8 or LUT16 tag.
    03207 *
    03208 *  returns:
    03209 *       BOOL        --  !=0 if the function was successful,
    03210 *                         0 otherwise.
    03211 *                       Returns number of bytes required/transferred
    03212 ***************************************************************************/
    03213
    03214 BOOL
    03215 CreateLutCRD(
    03216     PBYTE  pProfile,
    03217     DWORD  dwIndex,
    03218     PBYTE  pBuffer,
    03219     PDWORD pcbSize,
    03220     DWORD  dwIntent,
    03221     BOOL   bBinary
    03222     )
    03223 {
    03224     PTAGDATA   pTagData;
    03225     PLUT16TYPE pLut;
    03226     PBYTE      pTable;
    03227     PBYTE      pLineStart, pStart = pBuffer;
    03228     DWORD      dwPCS, dwSize, dwLutSig, dwTag, i, j;
    03229     DWORD      nInputCh, nOutputCh, nGrids, nInputTable, nOutputTable, nNumbers;
    03230     FIX_16_16  afxIlluminantWP[3];
    03231     FIX_16_16  afxMediaWP[3];
    03232     char       pPublicArrayName[5];
    03233
    03234     //
    03235     // Check if we can generate the CSA
    03236     // Required  tags is AToBi, where i is the rendering intent
    03237     //
    03238
    03239     dwPCS = GetCPConnSpace(pProfile);
    03240
    03241     pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
    03242                dwIndex * sizeof(TAGDATA));
    03243
    03244     dwTag = FIX_ENDIAN(pTagData->tagType);
    03245
    03246     pLut = (PLUT16TYPE)(pProfile + FIX_ENDIAN(pTagData->dwOffset));
    03247
    03248     dwLutSig = FIX_ENDIAN(pLut->dwSignature);
    03249
    03250     if ((dwLutSig != LUT8_TYPE) && (dwLutSig != LUT16_TYPE))
    03251     {
    03252         WARNING((__TEXT("Invalid profile - unable to create Lut CRD\n")));
    03253         SetLastError(ERROR_INVALID_PROFILE);
    03254         return FALSE;
    03255     }
    03256
    03257     //
    03258     // Estimate size required to hold the CSA
    03259     //
    03260
    03261     (void)GetCLUTInfo(dwLutSig, (PBYTE)pLut, &nInputCh, &nOutputCh, &nGrids,
    03262                 &nInputTable, &nOutputTable, NULL);
    03263
    03264     //
    03265     // Calculate size of buffer needed
    03266     //
    03267
    03268     dwSize = nInputCh * nInputTable * 6 +
    03269         nOutputCh * nOutputTable * 6 +               // Number of INT bytes
    03270         nOutputCh * nGrids * nGrids * nGrids * 2 +   // LUT HEX bytes
    03271         nInputCh * (STRLEN(IndexArray) +
    03272                     STRLEN(StartClip) +
    03273                     STRLEN(EndClip)) +
    03274         nOutputCh * (STRLEN(IndexArray) +
    03275                      STRLEN(StartClip) +
    03276                      STRLEN(EndClip)) +
    03277         2048;                                        // + other PS stuff
    03278
    03279     //
    03280     // Add space for new line.
    03281     //
    03282
    03283     dwSize += (((dwSize) / MAX_LINELEN) + 1) * STRLEN(NewLine);
    03284
    03285     if (! pBuffer)
    03286     {
    03287         *pcbSize = dwSize;
    03288         return TRUE;
    03289     }
    03290     else if (*pcbSize < dwSize)
    03291     {
    03292         WARNING((__TEXT("Buffer too small to get DEFG CSA\n")));
    03293         SetLastError(ERROR_INSUFFICIENT_BUFFER);
    03294         return FALSE;
    03295     }
    03296
    03297     //
    03298     // Get info about Illuminant White Point from the header
    03299     //
    03300
    03301     (void)GetCPWhitePoint(pProfile, afxIlluminantWP);
    03302
    03303     //
    03304     // Support absolute whitePoint
    03305     //
    03306
    03307     if (dwIntent == INTENT_ABSOLUTE_COLORIMETRIC)
    03308     {
    03309         if (! GetCPMediaWhitePoint(pProfile, afxMediaWP))
    03310         {
    03311             afxMediaWP[0] = afxIlluminantWP[0];
    03312             afxMediaWP[1] = afxIlluminantWP[1];
    03313             afxMediaWP[2] = afxIlluminantWP[2];
    03314         }
    03315     }
    03316
    03317     //
    03318     // Define global array used in EncodeABC and RenderTable
    03319     //
    03320
    03321     GetPublicArrayName(dwTag, pPublicArrayName);
    03322     pBuffer += WriteNewLineObject(pBuffer, CRDBegin);
    03323
    03324     pBuffer += EnableGlobalDict(pBuffer);
    03325     pBuffer += BeginGlobalDict(pBuffer);
    03326
    03327     pBuffer += CreateInputArray(pBuffer, nInputCh, nInputTable,
    03328                  pPublicArrayName, dwLutSig, (PBYTE)pLut, bBinary, NULL);
    03329
    03330     i = nInputTable * nInputCh +
    03331         nGrids * nGrids * nGrids * nOutputCh;
    03332     pBuffer += CreateOutputArray(pBuffer, nOutputCh, nOutputTable, i,
    03333                  pPublicArrayName, dwLutSig, (PBYTE)pLut, bBinary, NULL);
    03334
    03335     pBuffer += EndGlobalDict(pBuffer);
    03336
    03337     //
    03338     // Start writing the CRD
    03339     //
    03340
    03341     pBuffer += WriteNewLineObject(pBuffer, BeginDict); // Begin dictionary
    03342     pBuffer += WriteObject(pBuffer, DictType); // Dictionary type
    03343
    03344     //
    03345     // Send /RenderingIntent
    03346     //
    03347
    03348     switch (dwIntent)
    03349     {
    03350         case INTENT_PERCEPTUAL:
    03351             pBuffer += WriteNewLineObject(pBuffer, IntentType);
    03352             pBuffer += WriteObject(pBuffer, IntentPer);
    03353             break;
    03354
    03355         case INTENT_SATURATION:
    03356             pBuffer += WriteNewLineObject(pBuffer, IntentType);
    03357             pBuffer += WriteObject(pBuffer, IntentSat);
    03358             break;
    03359
    03360         case INTENT_RELATIVE_COLORIMETRIC:
    03361             pBuffer += WriteNewLineObject(pBuffer, IntentType);
    03362             pBuffer += WriteObject(pBuffer, IntentRCol);
    03363             break;
    03364
    03365         case INTENT_ABSOLUTE_COLORIMETRIC:
    03366             pBuffer += WriteNewLineObject(pBuffer, IntentType);
    03367             pBuffer += WriteObject(pBuffer, IntentACol);
    03368             break;
    03369     }
    03370
    03371     //
    03372     // Send /BlackPoint & /WhitePoint
    03373     //
    03374
    03375     pBuffer += SendCRDBWPoint(pBuffer, afxIlluminantWP);
    03376
    03377     //
    03378     // Send PQR
    03379     //
    03380
    03381     pBuffer += SendCRDPQR(pBuffer, dwIntent, afxIlluminantWP);
    03382
    03383     //
    03384     // Send LMN
    03385     //
    03386
    03387     pBuffer += SendCRDLMN(pBuffer, dwIntent, afxIlluminantWP, afxMediaWP, dwPCS);
    03388
    03389     //
    03390     // Send ABC
    03391     //
    03392
    03393     pBuffer += SendCRDABC(pBuffer, pPublicArrayName, dwPCS, nInputCh,
    03394                     (PBYTE)pLut, NULL, dwLutSig, bBinary);
    03395
    03396     //
    03397     // /RenderTable
    03398     //
    03399
    03400     pBuffer += WriteNewLineObject(pBuffer, RenderTableTag);
    03401     pBuffer += WriteObject(pBuffer, BeginArray);
    03402
    03403     pBuffer += WriteInt(pBuffer, nGrids);  // Send down Na
    03404     pBuffer += WriteInt(pBuffer, nGrids);  // Send down Nb
    03405     pBuffer += WriteInt(pBuffer, nGrids);  // Send down Nc
    03406
    03407     pLineStart = pBuffer;
    03408     pBuffer += WriteNewLineObject(pBuffer, BeginArray);
    03409     nNumbers = nGrids * nGrids * nOutputCh;
    03410
    03411     for (i=0; i<nGrids; i++)        // Na strings should be sent
    03412     {
    03413         pBuffer += WriteObject(pBuffer, NewLine);
    03414         pLineStart = pBuffer;
    03415         if (dwLutSig == LUT8_TYPE)
    03416         {
    03417             pTable = (PBYTE)(((PLUT8TYPE)pLut)->data) + nInputTable * nInputCh + nNumbers * i;
    03418         }
    03419         else
    03420         {
    03421             pTable = (PBYTE)(((PLUT16TYPE)pLut)->data) + 2 * nInputTable * nInputCh + 2 * nNumbers * i;
    03422         }
    03423
    03424         if (! bBinary)
    03425         {
    03426             pBuffer += WriteObject(pBuffer, BeginString);
    03427             if (dwLutSig == LUT8_TYPE)
    03428             {
    03429                 pBuffer += WriteHexBuffer(pBuffer, pTable, pLineStart, nNumbers);
    03430             }
    03431             else
    03432             {
    03433                 for (j=0; j<nNumbers; j++)
    03434                 {
    03435                     pBuffer += WriteHex(pBuffer, FIX_ENDIAN16(*((PWORD)pTable)) / 256);
    03436                     pTable += sizeof(WORD);
    03437                     if (((DWORD) (pBuffer - pLineStart)) > MAX_LINELEN)
    03438                     {
    03439                         pLineStart = pBuffer;
    03440                         pBuffer += WriteObject(pBuffer, NewLine);
    03441                     }
    03442                 }
    03443             }
    03444             pBuffer += WriteObject(pBuffer, EndString);
    03445         }
    03446         else
    03447         {
    03448             pBuffer += WriteStringToken(pBuffer, 143, nNumbers);
    03449             if (dwLutSig == LUT8_TYPE)
    03450             {
    03451                 pBuffer += WriteByteString(pBuffer, pTable, nNumbers);
    03452             }
    03453             else
    03454             {
    03455                 pBuffer += WriteInt2ByteString(pBuffer, pTable, nNumbers);
    03456             }
    03457         }
    03458     }
    03459
    03460     pBuffer += WriteObject(pBuffer, EndArray); // End array
    03461     pBuffer += WriteInt(pBuffer, nOutputCh);   // Send down m
    03462
    03463     pBuffer += SendCRDOutputTable(pBuffer, pPublicArrayName,
    03464                     nOutputCh, dwLutSig, FALSE, bBinary);
    03465
    03466     pBuffer += WriteObject(pBuffer, EndArray); // End array
    03467     pBuffer += WriteObject(pBuffer, EndDict);  // End dictionary definition
    03468
    03469     pBuffer += WriteNewLineObject(pBuffer, CRDEnd);
    03470
    03471     *pcbSize = (DWORD) (pBuffer - pStart);
    03472
    03473     return TRUE;
    03474 }
    03475
    03476 #if !defined(KERNEL_MODE) || defined(USERMODE_DRIVER)
    03477
    03478 /***************************************************************************
    03479 *                           CreateMatrixCRD
    03480 *  function:
    03481 *    this is the function which creates the Color Rendering Dictionary (CRD)
    03482 *    from the data supplied in the redTRC, greenTRC, blueTRA, redColorant,
    03483 *    greenColorant and BlueColorant tags
    03484 *
    03485 *  returns:
    03486 *       BOOL        --  !=0 if the function was successful,
    03487 *                         0 otherwise.
    03488 *                       Returns number of bytes required/transferred
    03489 ***************************************************************************/
    03490
    03491 // With matrix/TRC model, only the CIEXYZ encoding of the PCS can be used.
    03492 // So, we don't need to worry about CIELAB.
    03493
    03494 BOOL
    03495 CreateMatrixCRD(
    03496     PBYTE  pProfile,
    03497     PBYTE  pBuffer,
    03498     PDWORD pcbSize,
    03499     DWORD  dwIntent,
    03500     BOOL   bBinary
    03501     )
    03502 {
    03503     PTAGDATA   pTagData;
    03504     DWORD      dwRedTRCIndex, dwGreenTRCIndex, dwBlueTRCIndex;
    03505     DWORD      dwRedCount, dwGreenCount, dwBlueCount;
    03506     PBYTE      pMem = NULL;
    03507     PCURVETYPE pRed, pGreen, pBlue;
    03508     DWORD      i, dwSize;
    03509     PBYTE      pStart = pBuffer;
    03510     PWORD      pRevCurve;
    03511     FIX_16_16  afxIlluminantWP[3];
    03512     double     adColorant[9];
    03513     double     adRevColorant[9];
    03514
    03515     //
    03516     // Check this is sRGB color profile or not.
    03517     //
    03518
    03519     if (IsSRGBColorProfile(pProfile))
    03520     {
    03521         dwSize = 4096; // hack - approx.
    03522
    03523         //
    03524         // Return buffer size, if this is a size request
    03525         //
    03526
    03527         if (! pBuffer)
    03528         {
    03529             *pcbSize = dwSize;
    03530             return TRUE;
    03531         }
    03532
    03533         //
    03534         // Check buffer size.
    03535         //
    03536
    03537         if (*pcbSize < dwSize)
    03538         {
    03539             WARNING((__TEXT("Buffer too small to get sRGB CRD\n")));
    03540             SetLastError(ERROR_INSUFFICIENT_BUFFER);
    03541             return FALSE;
    03542         }
    03543
    03544         //
    03545         // Start writing the CRD
    03546         //
    03547
    03548         pBuffer += WriteNewLineObject(pBuffer, CRDBegin);
    03549         pBuffer += WriteNewLineObject(pBuffer, BeginDict);  // Begin dictionary
    03550         pBuffer += WriteObject(pBuffer, DictType);          // Dictionary type
    03551
    03552         //
    03553         // Send /RenderingIntent
    03554         //
    03555
    03556         switch (dwIntent)
    03557         {
    03558             case INTENT_PERCEPTUAL:
    03559                 pBuffer += WriteNewLineObject(pBuffer, IntentType);
    03560                 pBuffer += WriteObject(pBuffer, IntentPer);
    03561                 break;
    03562
    03563             case INTENT_SATURATION:
    03564                 pBuffer += WriteNewLineObject(pBuffer, IntentType);
    03565                 pBuffer += WriteObject(pBuffer, IntentSat);
    03566                 break;
    03567
    03568             case INTENT_RELATIVE_COLORIMETRIC:
    03569                 pBuffer += WriteNewLineObject(pBuffer, IntentType);
    03570                 pBuffer += WriteObject(pBuffer, IntentRCol);
    03571                 break;
    03572
    03573             case INTENT_ABSOLUTE_COLORIMETRIC:
    03574                 pBuffer += WriteNewLineObject(pBuffer, IntentType);
    03575                 pBuffer += WriteObject(pBuffer, IntentACol);
    03576                 break;
    03577         }
    03578
    03579         //
    03580         // Write prepaired sRGB CRD.
    03581         //
    03582
    03583         pBuffer += WriteNewLineObject(pBuffer, sRGBColorRenderingDictionary);
    03584
    03585         //
    03586         // End CRD.
    03587         //
    03588
    03589         pBuffer += WriteNewLineObject(pBuffer, CRDEnd);
    03590     }
    03591     else
    03592     {
    03593         //
    03594         // Get each TRC index for Red, Green and Blue.
    03595         //
    03596
    03597         if (!DoesCPTagExist(pProfile, TAG_REDTRC, &dwRedTRCIndex) ||
    03598             !DoesCPTagExist(pProfile, TAG_GREENTRC, &dwGreenTRCIndex) ||
    03599             !DoesCPTagExist(pProfile, TAG_BLUETRC, &dwBlueTRCIndex))
    03600         {
    03601             return FALSE;
    03602         }
    03603
    03604         //
    03605         // Get CURVETYPE data for each Red, Green and Blue
    03606         //
    03607
    03608         pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
    03609                    dwRedTRCIndex * sizeof(TAGDATA));
    03610
    03611         pRed = (PCURVETYPE)(pProfile + FIX_ENDIAN(pTagData->dwOffset));
    03612
    03613         pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
    03614                    dwGreenTRCIndex * sizeof(TAGDATA));
    03615
    03616         pGreen = (PCURVETYPE)(pProfile + FIX_ENDIAN(pTagData->dwOffset));
    03617
    03618         pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
    03619                    dwBlueTRCIndex * sizeof(TAGDATA));
    03620
    03621         pBlue = (PCURVETYPE)(pProfile + FIX_ENDIAN(pTagData->dwOffset));
    03622
    03623         //
    03624         // Get curve count for each Red, Green and Blue.
    03625         //
    03626
    03627         dwRedCount   = FIX_ENDIAN(pRed->nCount);
    03628         dwGreenCount = FIX_ENDIAN(pGreen->nCount);
    03629         dwBlueCount  = FIX_ENDIAN(pBlue->nCount);
    03630
    03631         //
    03632         // Estimate the memory size required to hold CRD
    03633         //
    03634
    03635         dwSize = (dwRedCount + dwGreenCount + dwBlueCount) * 6 * REVCURVE_RATIO +
    03636                  4096;  // Number of INT elements + other PS stuff
    03637
    03638         //
    03639         // Add space for new line.
    03640         //
    03641
    03642         dwSize += (((dwSize) / MAX_LINELEN) + 1) * STRLEN(NewLine);
    03643
    03644         if (pBuffer == NULL)     // This is a size request
    03645         {
    03646             *pcbSize = dwSize;
    03647             return TRUE;
    03648         }
    03649
    03650         //
    03651         // Check buffer size.
    03652         //
    03653
    03654         if (*pcbSize < dwSize)
    03655         {
    03656             WARNING((__TEXT("Buffer too small to get sRGB CRD\n")));
    03657             SetLastError(ERROR_INSUFFICIENT_BUFFER);
    03658             return FALSE;
    03659         }
    03660
    03661         //
    03662         // Allocate buffer for curves
    03663         //
    03664
    03665         if ((pRevCurve = MemAlloc(dwRedCount * sizeof(WORD) * (REVCURVE_RATIO + 1))) == NULL)
    03666         {
    03667             WARNING((__TEXT("Unable to allocate memory for reserved curve\n")));
    03668             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
    03669             MemFree(pMem);
    03670             return FALSE;
    03671         }
    03672
    03673         //
    03674         // Get info about Illuminant White Point from the header
    03675         //
    03676
    03677         (void)GetCPWhitePoint(pProfile, afxIlluminantWP);
    03678
    03679         //
    03680         // Start writing the CRD
    03681         //
    03682
    03683         pBuffer += EnableGlobalDict(pBuffer);
    03684         pBuffer += BeginGlobalDict(pBuffer);
    03685
    03686         pBuffer += CreateCRDRevArray(pProfile, pBuffer, pRed, pRevCurve, TAG_REDTRC, bBinary);
    03687         pBuffer += CreateCRDRevArray(pProfile, pBuffer, pGreen, pRevCurve, TAG_GREENTRC, bBinary);
    03688         pBuffer += CreateCRDRevArray(pProfile, pBuffer, pBlue, pRevCurve, TAG_BLUETRC, bBinary);
    03689
    03690         pBuffer += EndGlobalDict(pBuffer);
    03691
    03692         //
    03693         // Start writing the CRD
    03694         //
    03695
    03696         pBuffer += WriteNewLineObject(pBuffer, CRDBegin);
    03697         pBuffer += WriteNewLineObject(pBuffer, BeginDict);  // Begin dictionary
    03698         pBuffer += WriteObject(pBuffer, DictType);          // Dictionary type
    03699
    03700         //
    03701         // Send /RenderingIntent
    03702         //
    03703
    03704         switch (dwIntent)
    03705         {
    03706             case INTENT_PERCEPTUAL:
    03707                 pBuffer += WriteNewLineObject(pBuffer, IntentType);
    03708                 pBuffer += WriteObject(pBuffer, IntentPer);
    03709                 break;
    03710
    03711             case INTENT_SATURATION:
    03712                 pBuffer += WriteNewLineObject(pBuffer, IntentType);
    03713                 pBuffer += WriteObject(pBuffer, IntentSat);
    03714                 break;
    03715
    03716             case INTENT_RELATIVE_COLORIMETRIC:
    03717                 pBuffer += WriteNewLineObject(pBuffer, IntentType);
    03718                 pBuffer += WriteObject(pBuffer, IntentRCol);
    03719                 break;
    03720
    03721             case INTENT_ABSOLUTE_COLORIMETRIC:
    03722                 pBuffer += WriteNewLineObject(pBuffer, IntentType);
    03723                 pBuffer += WriteObject(pBuffer, IntentACol);
    03724                 break;
    03725         }
    03726
    03727         //
    03728         // Send /BlackPoint & /WhitePoint
    03729         //
    03730
    03731         pBuffer += SendCRDBWPoint(pBuffer, afxIlluminantWP);
    03732
    03733         //
    03734         // Send PQR
    03735         //
    03736
    03737         pBuffer += SendCRDPQR(pBuffer, dwIntent, afxIlluminantWP);
    03738
    03739         //
    03740         // Send LMN
    03741         //
    03742
    03743         CreateColorantArray(pProfile, &adColorant[0], TAG_REDCOLORANT);
    03744         CreateColorantArray(pProfile, &adColorant[3], TAG_GREENCOLORANT);
    03745         CreateColorantArray(pProfile, &adColorant[6], TAG_BLUECOLORANT);
    03746         InvertColorantArray(adColorant, adRevColorant);
    03747
    03748         pBuffer += WriteNewLineObject(pBuffer, MatrixLMNTag);
    03749
    03750         pBuffer += WriteObject(pBuffer, BeginArray);
    03751         for (i = 0; i < 9; i++)
    03752         {
    03753             pBuffer += WriteDouble(pBuffer, adRevColorant[i]);
    03754         }
    03755         pBuffer += WriteObject(pBuffer, EndArray);
    03756
    03757         //
    03758         // /EncodeABC
    03759         //
    03760
    03761         pBuffer += WriteNewLineObject(pBuffer, EncodeABCTag);
    03762         pBuffer += WriteObject(pBuffer, BeginArray);
    03763
    03764         pBuffer += WriteObject(pBuffer, NewLine);
    03765         pBuffer += SendCRDRevArray(pProfile, pBuffer, pRed, TAG_REDTRC, bBinary);
    03766
    03767         pBuffer += WriteObject(pBuffer, NewLine);
    03768         pBuffer += SendCRDRevArray(pProfile, pBuffer, pGreen, TAG_GREENTRC, bBinary);
    03769
    03770         pBuffer += WriteObject(pBuffer, NewLine);
    03771         pBuffer += SendCRDRevArray(pProfile, pBuffer, pBlue, TAG_BLUETRC, bBinary);
    03772
    03773         pBuffer += WriteNewLineObject(pBuffer, EndArray);
    03774         pBuffer += WriteObject(pBuffer, EndDict);  // End dictionary definition
    03775
    03776         pBuffer += WriteNewLineObject(pBuffer, CRDEnd);
    03777
    03778         MemFree (pRevCurve);
    03779     }
    03780
    03781     *pcbSize = (DWORD)(pBuffer - pStart);
    03782
    03783     return TRUE;
    03784 }
    03785
    03786
    03787 DWORD
    03788 CreateCRDRevArray(
    03789     PBYTE      pProfile,
    03790     PBYTE      pBuffer,
    03791     PCURVETYPE pData,
    03792     PWORD      pRevCurve,
    03793     DWORD      dwTag,
    03794     BOOL       bBinary
    03795     )
    03796 {
    03797     DWORD i, nCount;
    03798     PBYTE pStart, pLineStart;
    03799     PWORD pCurve;
    03800
    03801     pStart = pBuffer;
    03802     pLineStart = pBuffer;
    03803
    03804     nCount = FIX_ENDIAN(pData->nCount);
    03805     if (nCount > 1)
    03806     {
    03807         pBuffer += WriteNewLineObject(pBuffer, Slash);
    03808         pBuffer += WriteObject(pBuffer, InputArray);
    03809         pBuffer += WriteInt(pBuffer, (INT) dwTag);
    03810
    03811         pCurve = pRevCurve + (REVCURVE_RATIO * nCount);
    03812
    03813         GetRevCurve (pData, pCurve, pRevCurve);
    03814
    03815         if (!bBinary)  // Output ASCII DATA
    03816         {
    03817             pBuffer += WriteObject(pBuffer, BeginArray);
    03818             for (i = 0; i < nCount * REVCURVE_RATIO; i++)
    03819             {
    03820                 pBuffer += WriteInt(pBuffer, *pRevCurve);
    03821                 pRevCurve++;
    03822                 if (((DWORD) (pBuffer - pLineStart)) > MAX_LINELEN)
    03823                 {
    03824                     pLineStart = pBuffer;
    03825                     pBuffer += WriteObject(pBuffer, NewLine);
    03826                 }
    03827             }
    03828             pBuffer += WriteObject(pBuffer, EndArray);
    03829         }
    03830         else // Output BINARY DATA
    03831         {
    03832             pBuffer += WriteHNAToken(pBuffer, 149, nCount);
    03833             pBuffer += WriteIntStringU2S_L(pBuffer, (PBYTE) pRevCurve, nCount);
    03834         }
    03835         pBuffer += WriteObject(pBuffer, DefOp);
    03836     }
    03837
    03838     return (DWORD)(pBuffer - pStart);
    03839 }
    03840
    03841
    03842 DWORD
    03843 SendCRDRevArray(
    03844     PBYTE pProfile,
    03845     PBYTE pBuffer,
    03846     PCURVETYPE pData,
    03847     DWORD dwTag,
    03848     BOOL  bBinary
    03849     )
    03850 {
    03851     DWORD nCount;
    03852     PBYTE pStart;
    03853     PWORD pTable;
    03854
    03855     pStart = pBuffer;
    03856
    03857     pBuffer += WriteObject(pBuffer, BeginFunction);
    03858     nCount = FIX_ENDIAN(pData->nCount);
    03859     if (nCount != 0)
    03860     {
    03861         if (nCount == 1)            // Gamma supplied in ui16 format
    03862         {
    03863             pTable = pData->data;
    03864             pBuffer += WriteInt(pBuffer, FIX_ENDIAN16(*pTable));
    03865             pBuffer += WriteObject(pBuffer, DecodeA3Rev);
    03866         }
    03867         else
    03868         {
    03869             pBuffer += WriteObject(pBuffer, StartClip);
    03870             pBuffer += WriteObject(pBuffer, InputArray);
    03871             pBuffer += WriteInt(pBuffer, dwTag);
    03872
    03873             if (!bBinary)       // Output ASCII CS
    03874             {
    03875                 pBuffer += WriteObject(pBuffer, IndexArray);
    03876             }
    03877             else                // Output BINARY CS
    03878             {
    03879                 pBuffer += WriteObject(pBuffer, IndexArray16b);
    03880             }
    03881
    03882             pBuffer += WriteObject(pBuffer, Scale16);
    03883             pBuffer += WriteObject(pBuffer, EndClip);
    03884         }
    03885     }
    03886     pBuffer += WriteObject(pBuffer, EndFunction);
    03887
    03888     return (DWORD)(pBuffer - pStart);
    03889 }
    03890
    03891
    03892 BOOL
    03893 CreateColorantArray(
    03894     PBYTE pProfile,
    03895     double *lpArray,
    03896     DWORD dwTag
    03897     )
    03898 {
    03899     PTAGDATA pTagData;
    03900     PXYZTYPE pData;
    03901     PFIX_16_16 pTable;
    03902     DWORD i, dwIndex;
    03903     BYTE buffer[1000];
    03904
    03905     if (DoesCPTagExist(pProfile, dwTag, &dwIndex))
    03906     {
    03907         pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
    03908                    dwIndex * sizeof(TAGDATA));
    03909
    03910         pData = (PXYZTYPE)(pProfile + FIX_ENDIAN(pTagData->dwOffset));
    03911
    03912         pTable = pData->afxData;
    03913
    03914         for (i = 0; i < 3; i++)
    03915         {
    03916             FIX_16_16 afxData = FIX_ENDIAN(*pTable);
    03917
    03918             //
    03919             // Convert Fix 16.16 to double.
    03920             //
    03921
    03922             *lpArray = ((double) afxData) / ((double) FIX_16_16_SCALE);
    03923
    03924             pTable++; lpArray++;
    03925         }
    03926
    03927         return (TRUE);
    03928     }
    03929
    03930     return (FALSE);
    03931 }
    03932
    03933 #endif // !defined(KERNEL_MODE) || defined(USERMODE_DRIVER)
    03934
    03935 /***************************************************************************
    03936 *                               GetRevCurve
    03937 *  function:
    03938 *  returns:
    03939 *       BOOL        --  TRUE:  successful,
    03940 *                       FALSE: otherwise.
    03941 ***************************************************************************/
    03942
    03943 BOOL
    03944 GetRevCurve(
    03945     PCURVETYPE pData,
    03946     PWORD      pInput,
    03947     PWORD      pOutput
    03948     )
    03949 {
    03950     PBYTE       pTable;
    03951     DWORD       nCount, dwStore, i, j;
    03952     DWORD       dwBegin, dwEnd, dwTemp;
    03953
    03954     nCount = FIX_ENDIAN(pData->nCount);
    03955     pTable = (PBYTE)pData->data;
    03956
    03957     for (i=0; i<nCount; i++)
    03958     {
    03959         pInput[i] = FIX_ENDIAN16(*((PWORD)pTable));
    03960         pTable += sizeof(WORD);
    03961     }
    03962
    03963     j = nCount * REVCURVE_RATIO;
    03964     for (i=0; i<j; i++)
    03965     {
    03966         dwStore = i * 65535 / (j - 1);
    03967         pOutput[i] = (dwStore < 65535) ? (WORD) dwStore : 65535;
    03968     }
    03969
    03970     for (i=0; i<j; i++)
    03971     {
    03972         dwBegin = 0;
    03973         dwEnd = nCount - 1;
    03974         for (;;)
    03975         {
    03976             if ((dwEnd - dwBegin) <= 1)
    03977                 break;
    03978             dwTemp = (dwEnd + dwBegin) / 2;
    03979             if (pOutput[i] < pInput[dwTemp])
    03980                 dwEnd = dwTemp;
    03981             else
    03982                 dwBegin = dwTemp;
    03983         }
    03984         if (pOutput[i] <= pInput[dwBegin])
    03985         {
    03986             dwStore = dwBegin;
    03987         }
    03988         else if (pOutput[i] >= pInput[dwEnd])
    03989         {
    03990             dwStore = dwEnd;
    03991         }
    03992         else
    03993         {
    03994             dwStore = (pInput[dwEnd] - pOutput[i]) / (pOutput[i] - pInput[dwBegin]);
    03995             dwStore = (dwBegin * dwStore + dwEnd) / (dwStore + 1);
    03996         }
    03997
    03998         dwStore = dwStore * 65535 / (nCount - 1);
    03999         pOutput[i] = (dwStore < 65535) ? (WORD) dwStore : 65535;
    04000     }
    04001
    04002     return TRUE;
    04003 }
    04004
    04005
    04006 BOOL
    04007 DoesCPTagExist(
    04008     PBYTE     pProfile,
    04009     DWORD     dwTag,
    04010     PDWORD    pdwIndex
    04011     )
    04012 {
    04013     DWORD    i, dwCount;
    04014     PTAGDATA pTagData;
    04015     BOOL     bRc;
    04016
    04017     //
    04018     // Get count of tag items - it is right after the profile header
    04019     //
    04020
    04021     dwCount = FIX_ENDIAN(*((DWORD *)(pProfile + sizeof(PROFILEHEADER))));
    04022
    04023     //
    04024     // Tag data records follow the count.
    04025     //
    04026
    04027     pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD));
    04028
    04029     //
    04030     // Check if any of these records match the tag passed in.
    04031     //
    04032
    04033     bRc = FALSE;
    04034     dwTag = FIX_ENDIAN(dwTag);      // to match tags in profile
    04035     for (i=0; i<dwCount; i++)
    04036     {
    04037         if (pTagData->tagType == dwTag)
    04038         {
    04039             if (pdwIndex)
    04040             {
    04041                 *pdwIndex = i;
    04042             }
    04043
    04044             bRc = TRUE;
    04045             break;
    04046         }
    04047         pTagData++;                     // Next record
    04048     }
    04049
    04050     return bRc;
    04051 }
    04052
    04053
    04054 BOOL
    04055 DoesTRCAndColorantTagExist(
    04056     PBYTE pProfile
    04057     )
    04058 {
    04059     if (DoesCPTagExist(pProfile,TAG_REDCOLORANT,NULL) &&
    04060         DoesCPTagExist(pProfile,TAG_REDTRC,NULL) &&
    04061         DoesCPTagExist(pProfile,TAG_GREENCOLORANT,NULL) &&
    04062         DoesCPTagExist(pProfile,TAG_GREENTRC,NULL) &&
    04063         DoesCPTagExist(pProfile,TAG_BLUECOLORANT,NULL) &&
    04064         DoesCPTagExist(pProfile,TAG_BLUETRC,NULL))
    04065     {
    04066         return TRUE;
    04067     }
    04068
    04069     return FALSE;
    04070 }
    04071
    04072
    04073 BOOL
    04074 GetCPWhitePoint(
    04075     PBYTE      pProfile,
    04076     PFIX_16_16 pafxWP
    04077     )
    04078 {
    04079     pafxWP[0]  = FIX_ENDIAN(((PPROFILEHEADER)pProfile)->phIlluminant.ciexyzX);
    04080     pafxWP[1]  = FIX_ENDIAN(((PPROFILEHEADER)pProfile)->phIlluminant.ciexyzY);
    04081     pafxWP[2]  = FIX_ENDIAN(((PPROFILEHEADER)pProfile)->phIlluminant.ciexyzZ);
    04082
    04083     return TRUE;
    04084 }
    04085
    04086 BOOL
    04087 GetCPMediaWhitePoint(
    04088     PBYTE      pProfile,
    04089     PFIX_16_16 pafxMediaWP
    04090     )
    04091 {
    04092     PTAGDATA pTagData;
    04093     PDWORD   pTable;
    04094     DWORD    dwIndex, i;
    04095
    04096     if (DoesCPTagExist (pProfile, TAG_MEDIAWHITEPOINT, &dwIndex))
    04097     {
    04098         pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
    04099                dwIndex * sizeof(TAGDATA));
    04100
    04101         //
    04102         // Skip the first 2 DWORDs to get to the real data
    04103         //
    04104
    04105         pTable = (PDWORD)(pProfile + FIX_ENDIAN(pTagData->dwOffset)) + 2;
    04106
    04107         for (i=0; i<3; i++)
    04108         {
    04109             pafxMediaWP[i] = FIX_ENDIAN(*pTable);
    04110             pTable++;
    04111         }
    04112
    04113         return TRUE;
    04114     }
    04115
    04116     return FALSE;
    04117 }
    04118
    04119
    04120 BOOL
    04121 GetCPElementDataSize(
    04122     PBYTE  pProfile,
    04123     DWORD  dwIndex,
    04124     PDWORD pcbSize)
    04125 {
    04126     PTAGDATA pTagData;
    04127
    04128     pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
    04129                dwIndex * sizeof(TAGDATA));
    04130
    04131     //
    04132     // Actual data Size of elements of type 'dataType' is 3 DWORDs less than the
    04133     // total tag data size
    04134     //
    04135
    04136     *pcbSize = FIX_ENDIAN(pTagData->cbSize) - 3 * sizeof(DWORD);
    04137
    04138     return TRUE;
    04139 }
    04140
    04141
    04142 BOOL
    04143 GetCPElementSize(
    04144     PBYTE  pProfile,
    04145     DWORD  dwIndex,
    04146     PDWORD pcbSize)
    04147 {
    04148     PTAGDATA pTagData;
    04149
    04150     pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
    04151                dwIndex * sizeof(TAGDATA));
    04152
    04153     *pcbSize = FIX_ENDIAN(pTagData->cbSize);
    04154
    04155     return TRUE;
    04156 }
    04157
    04158
    04159 BOOL
    04160 GetCPElementDataType(
    04161     PBYTE  pProfile,
    04162     DWORD  dwIndex,
    04163     PDWORD pdwDataType)
    04164 {
    04165     PTAGDATA pTagData;
    04166     PBYTE    pData;
    04167
    04168     pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
    04169                dwIndex * sizeof(TAGDATA));
    04170
    04171     pData = pProfile + FIX_ENDIAN(pTagData->dwOffset);
    04172
    04173     *pdwDataType = FIX_ENDIAN(*((DWORD *)(pData + 2 * sizeof(DWORD))));
    04174
    04175     return TRUE;
    04176 }
    04177
    04178
    04179 BOOL
    04180 GetCPElementData(
    04181     PBYTE  pProfile,
    04182     DWORD  dwIndex,
    04183     PBYTE  pBuffer,
    04184     PDWORD pdwSize
    04185     )
    04186 {
    04187     PTAGDATA pTagData;
    04188     PBYTE    pData;
    04189
    04190     pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
    04191                dwIndex * sizeof(TAGDATA));
    04192
    04193     pData = pProfile + FIX_ENDIAN(pTagData->dwOffset);
    04194
    04195     //
    04196     // Actual data Size of elements of type 'dataType' is 3 DWORDs less than the
    04197     // total tag data size
    04198     //
    04199
    04200     *pdwSize = FIX_ENDIAN(pTagData->cbSize) - 3 * sizeof(DWORD);
    04201
    04202     if (pBuffer)
    04203     {
    04204         CopyMemory(pBuffer, (pData + 3*sizeof(DWORD)), *pdwSize);
    04205     }
    04206
    04207     return TRUE;
    04208 }
    04209
    04210
    04211 BOOL
    04212 GetTRCElementSize(
    04213     PBYTE  pProfile,
    04214     DWORD  dwTag,
    04215     PDWORD pdwIndex,
    04216     PDWORD pdwSize
    04217     )
    04218 {
    04219     DWORD dwDataType;
    04220
    04221     if (!DoesCPTagExist(pProfile, dwTag, pdwIndex) ||
    04222         !GetCPElementDataType(pProfile, *pdwIndex, &dwDataType) ||
    04223         !(dwDataType != SIG_CURVE_TYPE) ||
    04224         !GetCPElementSize(pProfile, *pdwIndex, pdwSize))
    04225     {
    04226         return FALSE;
    04227     }
    04228
    04229     return TRUE;
    04230 }
    04231
    04232
    04233 DWORD
    04234 Ascii85Encode(
    04235     PBYTE pBuffer,
    04236     DWORD dwDataSize,
    04237     DWORD dwBufSize
    04238     )
    04239 {
    04240     // BUGBUG - To be done
    04241
    04242 #if 0
    04243     PBYTE     pTempBuf, pPtr;
    04244     DWORD     dwASCII85Size = 0;
    04245     DWORD     dwBufSize = DataSize * 5 / 4 + sizeof(ASCII85DecodeBegin)+sizeof(ASCII85DecodeEnd) + 2048;
    04246
    04247     if ((pTempBuf = (PBYTE)MemAlloc(dwBufSize)))
    04248     {
    04249         pPtr = pTempBuf;
    04250         pPtr += WriteObject(pPtr,  NewLine);
    04251         pPtr += WriteObject(pPtr,  ASCII85DecodeBegin);
    04252         pPtr += WriteObject(pPtr,  NewLine);
    04253         pPtr += WriteASCII85Cont(pPtr, dwBufSize, pBuffer, dwDataSize);
    04254         pPtr += WriteObject(pPtr,  ASCII85DecodeEnd);
    04255         dwAscii85Size = (DWORD)(pPtr - pTempBuf);
    04256         lstrcpyn(pBuffer, pTempBuf, dwAscii85Size);
    04257
    04258         MemFree(pTempBuf);
    04259     }
    04260
    04261     return dwAscii85Size;
    04262 #else
    04263     return 0;
    04264 #endif
    04265 }
    04266
    04267 /***************************************************************************
    04268 *
    04269 *   Function to write the Homogeneous Number Array token into the buffer
    04270 *
    04271 ***************************************************************************/
    04272
    04273 DWORD
    04274 WriteHNAToken(
    04275     PBYTE pBuffer,
    04276     BYTE  token,
    04277     DWORD dwNum
    04278     )
    04279 {
    04280     *pBuffer++ = token;
    04281     *pBuffer++ = 32;       // 16-bit fixed integer, high-order byte first
    04282     *pBuffer++ = (BYTE)((dwNum & 0xFF00) >> 8);
    04283     *pBuffer++ = (BYTE)(dwNum & 0x00FF);
    04284
    04285     return 4;
    04286 }
    04287
    04288 /***************************************************************************
    04289 *
    04290 *   Function to convert 2-bytes unsigned integer to 2-bytes signed
    04291 *   integer(-32768) and write them to the buffer. High byte first.
    04292 *
    04293 ***************************************************************************/
    04294
    04295 DWORD
    04296 WriteIntStringU2S(
    04297     PBYTE pBuffer,
    04298     PBYTE pData,
    04299     DWORD dwNum
    04300     )
    04301 {
    04302     DWORD i, dwTemp;
    04303
    04304     for (i=0; i<dwNum; i++)
    04305     {
    04306         dwTemp = FIX_ENDIAN16(*((PWORD)pData)) - 32768;
    04307         *pBuffer++ = (BYTE)((dwTemp & 0xFF00) >> 8);
    04308         *pBuffer++ = (BYTE)(dwTemp & 0x00FF);
    04309         pData += sizeof(WORD);
    04310     }
    04311
    04312     return dwNum * 2;
    04313 }
    04314
    04315
    04316 /***************************************************************************
    04317 *
    04318 *   Function to convert 2-bytes unsigned integer to 2-bytes signed
    04319 *   integer(-32768) and write them to the buffer. Low-order byte first.
    04320 *
    04321 ***************************************************************************/
    04322
    04323 DWORD
    04324 WriteIntStringU2S_L(
    04325     PBYTE pBuffer,
    04326     PBYTE pData,
    04327     DWORD dwNum
    04328     )
    04329 {
    04330     DWORD i, dwTemp;
    04331
    04332     for (i=0; i<dwNum; i++)
    04333     {
    04334         dwTemp = *((PWORD)pData) - 32768;
    04335         *pBuffer++ = (BYTE)((dwTemp & 0xFF00) >> 8);
    04336         *pBuffer++ = (BYTE)(dwTemp & 0x00FF);
    04337         pData += sizeof(WORD);
    04338     }
    04339
    04340     return dwNum * 2;
    04341 }
    04342
    04343
    04344 /***************************************************************************
    04345 *
    04346 *   Function to put the chunk of memory as string of Hex
    04347 *
    04348 ***************************************************************************/
    04349
    04350 DWORD
    04351 WriteHexBuffer(
    04352     PBYTE pBuffer,
    04353     PBYTE pData,
    04354     PBYTE pLineStart,
    04355     DWORD dwBytes
    04356     )
    04357 {
    04358     PBYTE  pStart = pBuffer;
    04359
    04360     for ( ; dwBytes ; dwBytes-- )
    04361     {
    04362         WriteHex(pBuffer, *pData);
    04363         pBuffer += 2;
    04364         pData++;
    04365         if (((DWORD)(pBuffer - pLineStart)) > MAX_LINELEN)
    04366         {
    04367             pLineStart = pBuffer;
    04368             pBuffer += WriteObject(pBuffer,  NewLine);
    04369         }
    04370     }
    04371     return( (DWORD)(pBuffer - pStart));
    04372 }
    04373
    04374 /***************************************************************************
    04375 *
    04376 *   Function to write the string token into the buffer
    04377 *
    04378 ***************************************************************************/
    04379
    04380 DWORD
    04381 WriteStringToken(
    04382     PBYTE pBuffer,
    04383     BYTE  token,
    04384     DWORD dwNum
    04385     )
    04386 {
    04387     *pBuffer++ = token;
    04388     *pBuffer++ = (BYTE)((dwNum & 0xFF00) >> 8);
    04389     *pBuffer++ = (BYTE)(dwNum & 0x00FF);
    04390
    04391     return 3;
    04392 }
    04393
    04394 /***************************************************************************
    04395 *
    04396 *   Function to put the chunk of memory into buffer
    04397 *
    04398 ***************************************************************************/
    04399
    04400 DWORD
    04401 WriteByteString(
    04402     PBYTE pBuffer,
    04403     PBYTE pData,
    04404     DWORD dwBytes
    04405     )
    04406 {
    04407     DWORD  i;
    04408
    04409     for (i=0; i<dwBytes; i++)
    04410         *pBuffer++ = *pData++;
    04411
    04412     return dwBytes;
    04413 }
    04414
    04415 /***************************************************************************
    04416 *
    04417 *   Function to put the chunk of memory into buffer
    04418 *
    04419 ***************************************************************************/
    04420
    04421 DWORD
    04422 WriteInt2ByteString(
    04423     PBYTE pBuffer,
    04424     PBYTE pData,
    04425     DWORD dwBytes
    04426     )
    04427 {
    04428     DWORD  i;
    04429
    04430     for (i=0; i<dwBytes ; i++)
    04431     {
    04432         *pBuffer++ = (BYTE)(FIX_ENDIAN16(*((PWORD)pData))/256);
    04433         pData += sizeof(WORD);
    04434     }
    04435
    04436     return dwBytes;
    04437 }
    04438
    04439 #ifndef KERNEL_MODE
    04440 DWORD
    04441 WriteFixed(
    04442     PBYTE     pBuffer,
    04443     FIX_16_16 fxNum
    04444     )
    04445 {
    04446     double dFloat = (double) ((long) fxNum) / (double) FIX_16_16_SCALE;
    04447
    04448     return (WriteDouble(pBuffer,dFloat));
    04449 }
    04450 #else
    04451 DWORD
    04452 WriteFixed(
    04453     PBYTE     pBuffer,
    04454     FIX_16_16 fxNum
    04455     )
    04456 {
    04457     PBYTE pStart = pBuffer;
    04458     DWORD i;
    04459
    04460     //
    04461     // Integer portion
    04462     //
    04463
    04464     #ifndef KERNEL_MODE
    04465     pBuffer += wsprintfA(pBuffer, "%lu", fxNum >> FIX_16_16_SHIFT);
    04466     #else
    04467     pBuffer += OPSprintf(pBuffer, "%l", fxNum >> FIX_16_16_SHIFT);
    04468     #endif
    04469
    04470     //
    04471     // Fractional part
    04472     //
    04473
    04474     fxNum &= 0xffff;
    04475     if (fxNum != 0)
    04476     {
    04477         //
    04478         // We output a maximum of 6 digits after the
    04479         // decimal point
    04480         //
    04481
    04482         *pBuffer++ = '.';
    04483
    04484         i = 0;
    04485         while (fxNum && i++ < 6)
    04486         {
    04487             fxNum *= 10;
    04488             *pBuffer++ = (BYTE)(fxNum >> FIX_16_16_SHIFT) + '0';  // quotient + '0'
    04489             fxNum -= FLOOR(fxNum);          // remainder
    04490         }
    04491     }
    04492
    04493     *pBuffer++ = ' ';
    04494
    04495     return (DWORD) (pBuffer - pStart);
    04496 }
    04497 #endif
    04498
    04499 DWORD
    04500 WriteFixed2dot30(
    04501     PBYTE pBuffer,
    04502     DWORD fxNum
    04503     )
    04504 {
    04505     PBYTE pStart = pBuffer;
    04506     DWORD i;
    04507
    04508     //
    04509     // Integer portion
    04510     //
    04511
    04512     #ifndef KERNEL_MODE
    04513     pBuffer += wsprintfA(pBuffer, "%lu", fxNum >> 30);
    04514     #else
    04515     pBuffer += OPSprintf(pBuffer, "%l", fxNum >> 30);
    04516     #endif
    04517
    04518     //
    04519     // Fractional part
    04520     //
    04521
    04522     fxNum &= 0x3fffffffL;
    04523     if (fxNum != 0)
    04524     {
    04525         //
    04526         // We output a maximum of 10 digits after the
    04527         // decimal point
    04528         //
    04529
    04530         *pBuffer++ = '.';
    04531
    04532         i = 0;
    04533         while (fxNum && i++ < 10)
    04534         {
    04535             fxNum *= 10;
    04536             *pBuffer++ = (BYTE)(fxNum >> 30) + '0';  // quotient + '0'
    04537             fxNum -= ((fxNum >> 30) << 30);          // remainder
    04538         }
    04539     }
    04540
    04541     *pBuffer++ = ' ';
    04542
    04543     return (DWORD) (pBuffer - pStart);
    04544 }
    04545
    04546 #if !defined(KERNEL_MODE) || defined(USERMODE_DRIVER)
    04547
    04548 /***************************************************************************
    04549 *
    04550 *   Function to write the float into the buffer
    04551 *
    04552 ***************************************************************************/
    04553
    04554 DWORD WriteDouble(PBYTE pBuffer, double dFloat)
    04555 {
    04556     LONG   lFloat  = (LONG) floor(dFloat * 10000.0 + 0.5);
    04557     double dFloat1 = lFloat  / 10000.0 ;
    04558     double dInt    = floor(fabs(dFloat1));
    04559     double dFract =  fabs(dFloat1) - dInt ;
    04560     char   cSign  = ' ' ;
    04561
    04562     if (dFloat1 < 0)
    04563     {
    04564         cSign = '-' ;
    04565     }
    04566
    04567     return (wsprintfA(pBuffer, (LPSTR) "%c%d.%0.4lu ",
    04568                         cSign, (WORD) dInt , (DWORD) (dFract * 10000.0)));
    04569 }
    04570
    04571 #endif // !defined(KERNEL_MODE) || defined(USERMODE_DRIVER)
    04572
    04573 DWORD WriteNewLineObject(
    04574     PBYTE       pBuffer,
    04575     const char *pData)
    04576 {
    04577     PBYTE pStart = pBuffer;
    04578
    04579     pBuffer += WriteObject(pBuffer, NewLine);
    04580     pBuffer += WriteObject(pBuffer, pData);
    04581
    04582     return (DWORD)(pBuffer - pStart);
    04583 }
    04584
    04585
    04586 DWORD
    04587 SendCRDBWPoint(
    04588     PBYTE      pBuffer,
    04589     PFIX_16_16 pafxWP
    04590     )
    04591 {
    04592     PBYTE pStart = pBuffer;
    04593     int   i;
    04594
    04595     //
    04596     // /BlackPoint
    04597     //
    04598
    04599     pBuffer += WriteObject(pBuffer, NewLine);
    04600     pBuffer += WriteObject(pBuffer, BlackPointTag);
    04601     pBuffer += WriteObject(pBuffer, BlackPoint);
    04602
    04603     //
    04604     // /WhitePoint
    04605     //
    04606
    04607     pBuffer += WriteObject(pBuffer, NewLine);
    04608     pBuffer += WriteObject(pBuffer, WhitePointTag);
    04609     pBuffer += WriteObject(pBuffer, BeginArray);
    04610     for (i=0; i<3; i++)
    04611     {
    04612         pBuffer += WriteFixed(pBuffer, pafxWP[i]);
    04613     }
    04614     pBuffer += WriteObject(pBuffer, EndArray);
    04615
    04616     return (DWORD)(pBuffer - pStart);
    04617 }
    04618
    04619
    04620 DWORD
    04621 SendCRDPQR(
    04622     PBYTE      pBuffer,
    04623     DWORD      dwIntent,
    04624     PFIX_16_16 pafxWP
    04625     )
    04626 {
    04627     PBYTE pStart = pBuffer;
    04628     int   i;
    04629
    04630     if (dwIntent != INTENT_ABSOLUTE_COLORIMETRIC)
    04631     {
    04632         //
    04633         // /RangePQR
    04634         //
    04635
    04636         pBuffer += WriteNewLineObject(pBuffer, RangePQRTag);
    04637         pBuffer += WriteObject(pBuffer, RangePQR);
    04638
    04639         //
    04640         // /MatrixPQR
    04641         //
    04642
    04643         pBuffer += WriteNewLineObject(pBuffer, MatrixPQRTag);
    04644         pBuffer += WriteObject(pBuffer, MatrixPQR);
    04645     }
    04646     else
    04647     {
    04648         //
    04649         // /RangePQR
    04650         //
    04651
    04652         pBuffer += WriteNewLineObject(pBuffer, RangePQRTag);
    04653         pBuffer += WriteObject(pBuffer, BeginArray);
    04654         for (i=0; i<3; i++)
    04655         {
    04656             pBuffer += WriteFixed(pBuffer, 0);
    04657             pBuffer += WriteFixed(pBuffer, pafxWP[i]);
    04658         }
    04659         pBuffer += WriteObject(pBuffer, EndArray);
    04660
    04661         //
    04662         // /MatrixPQR
    04663         //
    04664
    04665         pBuffer += WriteNewLineObject(pBuffer, MatrixPQRTag);
    04666         pBuffer += WriteObject(pBuffer, Identity);
    04667     }
    04668
    04669     //
    04670     // /TransformPQR
    04671     //
    04672
    04673     pBuffer += WriteNewLineObject(pBuffer, TransformPQRTag);
    04674     pBuffer += WriteObject(pBuffer, BeginArray);
    04675     for (i=0; i<3; i++)
    04676     {
    04677         pBuffer += WriteObject(pBuffer, BeginFunction);
    04678         pBuffer += WriteObject(pBuffer,
    04679             (dwIntent != INTENT_ABSOLUTE_COLORIMETRIC) ? TransformPQR[i] : NullOp);
    04680         pBuffer += WriteObject(pBuffer, EndFunction);
    04681     }
    04682     pBuffer += WriteObject(pBuffer, EndArray);
    04683
    04684     return (DWORD)(pBuffer - pStart);
    04685 }
    04686
    04687
    04688 DWORD
    04689 SendCRDLMN(
    04690     PBYTE      pBuffer,
    04691     DWORD      dwIntent,
    04692     PFIX_16_16 pafxIlluminantWP,
    04693     PFIX_16_16 pafxMediaWP,
    04694     DWORD      dwPCS
    04695     )
    04696 {
    04697     PBYTE pStart = pBuffer;
    04698     DWORD i, j;
    04699
    04700     //
    04701     // /MatrixLMN
    04702     //
    04703
    04704     if (dwIntent == INTENT_ABSOLUTE_COLORIMETRIC)
    04705     {
    04706         pBuffer += WriteNewLineObject(pBuffer, MatrixLMNTag);
    04707
    04708         pBuffer += WriteObject(pBuffer, BeginArray);
    04709         for (i=0; i<3; i++)
    04710         {
    04711             for (j=0; j<3; j++)
    04712                 pBuffer += WriteFixed(pBuffer,
    04713                     (i == j) ? FIX_DIV(pafxIlluminantWP[i], pafxMediaWP[i]) : 0);
    04714         }
    04715         pBuffer += WriteObject(pBuffer, EndArray);
    04716     }
    04717
    04718     //
    04719     // /RangeLMN
    04720     //
    04721
    04722     pBuffer += WriteNewLineObject(pBuffer, RangeLMNTag);
    04723     if (dwPCS == SPACE_XYZ)
    04724     {
    04725         pBuffer += WriteObject(pBuffer, BeginArray);
    04726         for (i=0; i<3; i++)
    04727         {
    04728             pBuffer += WriteFixed(pBuffer, 0);
    04729             pBuffer += WriteFixed(pBuffer, pafxIlluminantWP[i]);
    04730         }
    04731         pBuffer += WriteObject(pBuffer, EndArray);
    04732     }
    04733     else
    04734     {
    04735         pBuffer += WriteObject(pBuffer, RangeLMNLab);
    04736     }
    04737
    04738     //
    04739     // /EncodeLMN
    04740     //
    04741
    04742     pBuffer += WriteNewLineObject(pBuffer, EncodeLMNTag);
    04743     pBuffer += WriteObject(pBuffer, BeginArray);
    04744     for (i=0; i<3; i++)
    04745     {
    04746         pBuffer += WriteObject(pBuffer, BeginFunction);
    04747         if (dwPCS != SPACE_XYZ)
    04748         {
    04749             pBuffer += WriteFixed(pBuffer, pafxIlluminantWP[i]);
    04750             pBuffer += WriteObject(pBuffer, DivOp);
    04751             pBuffer += WriteObject(pBuffer, EncodeLMNLab);
    04752         }
    04753         pBuffer += WriteObject(pBuffer, EndFunction);
    04754     }
    04755     pBuffer += WriteObject(pBuffer, EndArray);
    04756
    04757     return (DWORD)(pBuffer - pStart);
    04758 }
    04759
    04760
    04761 DWORD
    04762 SendCRDABC(
    04763     PBYTE       pBuffer,
    04764     PBYTE       pPublicArrayName,
    04765     DWORD       dwPCS,
    04766     DWORD       nInputCh,
    04767     PBYTE       pLut,
    04768     PFIX_16_16  e,
    04769     DWORD       dwLutSig,
    04770     BOOL        bBinary
    04771     )
    04772 {
    04773     PBYTE      pLineStart, pStart = pBuffer;
    04774     PBYTE      pTable;
    04775     DWORD      i, j;
    04776     FIX_16_16  fxTempMatrixABC[9];
    04777
    04778     //
    04779     // /RangeABC
    04780     //
    04781
    04782     pBuffer += WriteNewLineObject(pBuffer, RangeABCTag);
    04783     pBuffer += WriteObject(pBuffer, RangeABC);
    04784
    04785     //
    04786     // /MatrixABC
    04787     //
    04788
    04789     pBuffer += WriteNewLineObject(pBuffer, MatrixABCTag);
    04790     if (dwPCS == SPACE_XYZ)
    04791     {
    04792         pBuffer += WriteObject(pBuffer, BeginArray);
    04793         if (e)
    04794         {
    04795             for (i=0; i<3; i++)
    04796             {
    04797                 for (j=0; j<3; j++)
    04798                 {
    04799                     pBuffer += WriteFixed(pBuffer, e[i + j * 3]);
    04800                 }
    04801             }
    04802         }
    04803         else
    04804         {
    04805             if (dwLutSig == LUT8_TYPE)
    04806             {
    04807                 pTable = (PBYTE) &((PLUT8TYPE)pLut)->e00;
    04808             }
    04809             else
    04810             {
    04811                 pTable = (PBYTE) &((PLUT16TYPE)pLut)->e00;
    04812             }
    04813
    04814             for (i=0; i<9; i++)
    04815             {
    04816                 fxTempMatrixABC[i] = FIX_DIV(FIX_ENDIAN(*((PDWORD)pTable)), CIEXYZRange);
    04817                 pTable += sizeof(DWORD);
    04818             }
    04819             for (i=0; i<3; i++)
    04820             {
    04821                 for (j=0; j<3; j++)
    04822                 {
    04823                     pBuffer += WriteFixed(pBuffer, fxTempMatrixABC[i + j * 3]);
    04824                 }
    04825             }
    04826         }
    04827         pBuffer += WriteObject(pBuffer, EndArray);
    04828     }
    04829     else
    04830     {
    04831         pBuffer += WriteObject(pBuffer, MatrixABCLabCRD);
    04832     }
    04833
    04834     //
    04835     // /EncodeABC
    04836     //
    04837
    04838     if (nInputCh == 0)
    04839     {
    04840         return (DWORD)(pBuffer - pStart);
    04841     }
    04842
    04843     pLineStart = pBuffer;
    04844     pBuffer += WriteNewLineObject(pBuffer, EncodeABCTag);
    04845     pBuffer += WriteObject(pBuffer, BeginArray);
    04846     for (i=0; i<nInputCh; i++)
    04847     {
    04848         pLineStart = pBuffer;
    04849
    04850         pBuffer += WriteNewLineObject(pBuffer, BeginFunction);
    04851         if (dwPCS == SPACE_Lab)
    04852         {
    04853             pBuffer += WriteObject(pBuffer, (i == 0) ? EncodeABCLab1 : EncodeABCLab2);
    04854         }
    04855
    04856         pBuffer += WriteObject(pBuffer, StartClip);
    04857         if (e)
    04858             pBuffer += WriteObject(pBuffer, PreViewInArray);
    04859         else
    04860             pBuffer += WriteObject(pBuffer, InputArray);
    04861
    04862         pBuffer += WriteObject(pBuffer, pPublicArrayName);
    04863         pBuffer += WriteInt(pBuffer, i);
    04864
    04865         if (!bBinary)              // Output ASCII CRD
    04866         {
    04867             pBuffer += WriteNewLineObject(pBuffer, IndexArray);
    04868         }
    04869         else
    04870         {                               // Output BINARY CRD
    04871             if (dwLutSig == LUT8_TYPE)
    04872             {
    04873                 pBuffer += WriteObject(pBuffer, IndexArray);
    04874             }
    04875             else
    04876             {
    04877                 pBuffer += WriteObject(pBuffer, IndexArray16b);
    04878             }
    04879         }
    04880
    04881         pBuffer += WriteObject(pBuffer, (dwLutSig == LUT8_TYPE) ?
    04882                          Scale8 : Scale16);
    04883         pBuffer += WriteObject(pBuffer, EndClip);
    04884         pBuffer += WriteObject(pBuffer, EndFunction);
    04885     }
    04886     pBuffer += WriteObject(pBuffer, EndArray);
    04887
    04888     return (DWORD)(pBuffer - pStart);
    04889 }
    04890
    04891
    04892 DWORD
    04893 SendCRDOutputTable(
    04894     PBYTE pBuffer,
    04895     PBYTE pPublicArrayName,
    04896     DWORD nOutputCh,
    04897     DWORD dwLutSig,
    04898     BOOL  bHost,
    04899     BOOL  bBinary
    04900     )
    04901 {
    04902     PBYTE pStart = pBuffer;
    04903     DWORD i;
    04904
    04905     for (i=0; i<nOutputCh; i++)
    04906     {
    04907         pBuffer += WriteNewLineObject(pBuffer, BeginFunction);
    04908         pBuffer += WriteObject(pBuffer, Clip01);
    04909         if (bHost)
    04910             pBuffer += WriteObject(pBuffer, PreViewOutArray);
    04911         else
    04912             pBuffer += WriteObject(pBuffer, OutputArray);
    04913
    04914         pBuffer += WriteObject(pBuffer, pPublicArrayName);
    04915         pBuffer += WriteInt(pBuffer, i);
    04916
    04917         if (! bBinary)
    04918         {
    04919             pBuffer += WriteObject(pBuffer, NewLine);
    04920             if (dwLutSig == LUT8_TYPE)
    04921             {
    04922                 pBuffer += WriteObject(pBuffer, TFunction8);
    04923             }
    04924             else
    04925             {
    04926                 pBuffer += WriteObject(pBuffer, IndexArray);
    04927                 pBuffer += WriteObject(pBuffer, Scale16);
    04928             }
    04929         }
    04930         else
    04931         {
    04932             if (dwLutSig == LUT8_TYPE)
    04933             {
    04934                 pBuffer += WriteObject(pBuffer, TFunction8);
    04935             }
    04936             else
    04937             {
    04938                 pBuffer += WriteObject(pBuffer, IndexArray16b);
    04939                 pBuffer += WriteObject(pBuffer, Scale16);
    04940             }
    04941         }
    04942
    04943         pBuffer += WriteObject(pBuffer, EndFunction);
    04944     }
    04945
    04946     return (DWORD)(pBuffer - pStart);
    04947 }
    04948
    04949
    04950 VOID
    04951 GetCLUTInfo(
    04952     DWORD  dwLutSig,
    04953     PBYTE  pLut,
    04954     PDWORD pnInputCh,
    04955     PDWORD pnOutputCh,
    04956     PDWORD pnGrids,
    04957     PDWORD pnInputTable,
    04958     PDWORD pnOutputTable,
    04959     PDWORD pdwSize
    04960     )
    04961 {
    04962     if (dwLutSig == LUT8_TYPE)
    04963     {
    04964         *pnInputCh = ((PLUT8TYPE)pLut)->nInputChannels;
    04965         *pnOutputCh = ((PLUT8TYPE)pLut)->nOutputChannels;
    04966         *pnGrids = ((PLUT8TYPE)pLut)->nClutPoints;
    04967         *pnInputTable = 256L;
    04968         *pnOutputTable = 256L;
    04969         if (pdwSize)
    04970             *pdwSize = 1;
    04971     }
    04972     else
    04973     {
    04974         *pnInputCh = ((PLUT16TYPE)pLut)->nInputChannels;
    04975         *pnOutputCh = ((PLUT16TYPE)pLut)->nOutputChannels;
    04976         *pnGrids =  ((PLUT16TYPE)pLut)->nClutPoints;
    04977         *pnInputTable = FIX_ENDIAN16(((PLUT16TYPE)pLut)->wInputEntries);
    04978         *pnOutputTable = FIX_ENDIAN16(((PLUT16TYPE)pLut)->wOutputEntries);
    04979         if (pdwSize)
    04980             *pdwSize = 2;
    04981     }
    04982
    04983     return;
    04984 }
    04985
    04986 DWORD
    04987 EnableGlobalDict(
    04988     PBYTE pBuffer
    04989     )
    04990 {
    04991     PBYTE pStart = pBuffer;
    04992
    04993     pBuffer += WriteNewLineObject(pBuffer, CurrentGlobalOp);
    04994     pBuffer += WriteObject(pBuffer, TrueOp);
    04995     pBuffer += WriteObject(pBuffer, SetGlobalOp);
    04996
    04997     return (DWORD)(pBuffer - pStart);
    04998 }
    04999
    05000 DWORD
    05001 BeginGlobalDict(
    05002     PBYTE pBuffer
    05003     )
    05004 {
    05005     PBYTE pStart = pBuffer;
    05006
    05007     pBuffer += WriteNewLineObject(pBuffer, GlobalDictOp);
    05008     pBuffer += WriteObject(pBuffer, BeginOp);
    05009
    05010     return (DWORD)(pBuffer - pStart);
    05011 }
    05012
    05013 DWORD
    05014 EndGlobalDict(
    05015     PBYTE pBuffer
    05016     )
    05017 {
    05018     PBYTE pStart = pBuffer;
    05019
    05020     pBuffer += WriteNewLineObject(pBuffer, EndOp);
    05021     pBuffer += WriteObject(pBuffer, SetGlobalOp);
    05022
    05023     return (DWORD)(pBuffer - pStart);
    05024 }
    05025
    05026 DWORD
    05027 SendCSABWPoint(
    05028     PBYTE      pBuffer,
    05029     DWORD      dwIntent,
    05030     PFIX_16_16 pafxIlluminantWP,
    05031     PFIX_16_16 pafxMediaWP
    05032     )
    05033 {
    05034     PBYTE pStart = pBuffer;
    05035     int   i;
    05036
    05037     //
    05038     // /BlackPoint
    05039     //
    05040
    05041     pBuffer += WriteNewLineObject(pBuffer, BlackPointTag);
    05042     pBuffer += WriteObject(pBuffer, BlackPoint);
    05043
    05044     //
    05045     // /WhitePoint
    05046     //
    05047
    05048     pBuffer += WriteNewLineObject(pBuffer, WhitePointTag);
    05049     pBuffer += WriteObject(pBuffer, BeginArray);
    05050     for (i=0; i<3; i++)
    05051     {
    05052         if (dwIntent == INTENT_ABSOLUTE_COLORIMETRIC)
    05053         {
    05054             pBuffer += WriteFixed(pBuffer, pafxMediaWP[i]);
    05055         }
    05056         else
    05057         {
    05058             pBuffer += WriteFixed(pBuffer, pafxIlluminantWP[i]);
    05059         }
    05060     }
    05061     pBuffer += WriteObject(pBuffer, EndArray);
    05062
    05063     return (DWORD)(pBuffer - pStart);
    05064 }
    05065
    05066
    05067 VOID
    05068 GetMediaWP(
    05069     PBYTE      pProfile,
    05070     DWORD      dwIntent,
    05071     PFIX_16_16 pafxIlluminantWP,
    05072     PFIX_16_16 pafxMediaWP
    05073     )
    05074 {
    05075     if (dwIntent == INTENT_ABSOLUTE_COLORIMETRIC)
    05076     {
    05077         if (! GetCPMediaWhitePoint(pProfile, pafxMediaWP))
    05078         {
    05079             pafxMediaWP[0] = pafxIlluminantWP[0];
    05080             pafxMediaWP[1] = pafxIlluminantWP[1];
    05081             pafxMediaWP[2] = pafxIlluminantWP[2];
    05082         }
    05083     }
    05084
    05085     return;
    05086 }
    05087
    05088
    05089 BOOL
    05090 GetCRDInputOutputArraySize(
    05091     PBYTE  pProfile,
    05092     DWORD  dwIntent,
    05093     PDWORD pdwInTblSize,
    05094     PDWORD pdwOutTblSize,
    05095     PDWORD pdwTag,
    05096     PDWORD pnGrids
    05097     )
    05098 {
    05099     PTAGDATA   pTagData;
    05100     PLUT16TYPE pLut;
    05101     DWORD      dwIndex, dwLutSig;
    05102     DWORD      nInputEntries, nOutputEntries;
    05103     DWORD      nInputCh, nOutputCh, nGrids;
    05104     BOOL       bRet;
    05105
    05106     //
    05107     // Make sure required tags exist
    05108     //
    05109
    05110     switch (dwIntent)
    05111     {
    05112     case INTENT_PERCEPTUAL:
    05113         *pdwTag = TAG_BToA0;
    05114         break;
    05115
    05116     case INTENT_RELATIVE_COLORIMETRIC:
    05117     case INTENT_ABSOLUTE_COLORIMETRIC:
    05118         *pdwTag = TAG_BToA1;
    05119         break;
    05120
    05121     case INTENT_SATURATION:
    05122         *pdwTag = TAG_BToA2;
    05123         break;
    05124
    05125     default:
    05126         WARNING((__TEXT("Invalid intent passed to GetCRDInputOutputArraySize: %d\n"), dwIntent));
    05127         SetLastError(ERROR_INVALID_PARAMETER);
    05128         return FALSE;
    05129     }
    05130
    05131     if (DoesCPTagExist(pProfile, *pdwTag, &dwIndex))
    05132     {
    05133         pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
    05134                    dwIndex * sizeof(TAGDATA));
    05135
    05136         pLut = (PLUT16TYPE)(pProfile + FIX_ENDIAN(pTagData->dwOffset));
    05137
    05138         dwLutSig = FIX_ENDIAN(pLut->dwSignature);
    05139
    05140         if ((dwLutSig != LUT8_TYPE) && (dwLutSig != LUT16_TYPE))
    05141         {
    05142             WARNING((__TEXT("Invalid Lut type - unable to create proofing CRD\n")));
    05143             SetLastError(ERROR_INVALID_PROFILE);
    05144             return FALSE;
    05145         }
    05146
    05147         (void)GetCLUTInfo(dwLutSig, (PBYTE)pLut, &nInputCh, &nOutputCh,
    05148                 &nGrids, &nInputEntries, &nOutputEntries, NULL);
    05149
    05150         if (pdwInTblSize)
    05151         {
    05152             if (nInputCh != 3)
    05153             {
    05154                 return FALSE;
    05155             }
    05156
    05157             *pdwInTblSize = nInputCh * nInputEntries * 6;  // Number of INT bytes
    05158             *pnGrids = nGrids;
    05159         }
    05160
    05161         if (pdwOutTblSize)
    05162         {
    05163             if ((nOutputCh != 3) && (nOutputCh != 4))
    05164             {
    05165                 return FALSE;
    05166             }
    05167
    05168             *pdwOutTblSize = nOutputCh * nOutputEntries * 6; // Number of INT bytes
    05169             *pnGrids = nGrids;
    05170         }
    05171
    05172         return TRUE;
    05173     }
    05174     else
    05175     {
    05176         //
    05177         // Matrix icc profile.
    05178         //
    05179
    05180         *pnGrids = 2;
    05181
    05182         if (pdwInTblSize)
    05183         {
    05184             bRet = GetHostCSA(pProfile, NULL, pdwInTblSize,
    05185                               dwIntent, TYPE_CIEBASEDDEF);
    05186             *pdwInTblSize = *pdwInTblSize * 3;
    05187         }
    05188
    05189         if (bRet && pdwOutTblSize)
    05190         {
    05191             bRet = GetHostCSA(pProfile, NULL, pdwInTblSize,
    05192                               dwIntent, TYPE_CIEBASEDDEF);
    05193             *pdwOutTblSize = *pdwOutTblSize * 3;
    05194         }
    05195
    05196         return bRet;
    05197     }
    05198 }
    05199
    05200 #if !defined(KERNEL_MODE) || defined(USERMODE_DRIVER)
    05201
    05202 DWORD
    05203 CreateHostLutCRD(
    05204     PBYTE  pProfile,
    05205     DWORD  dwIndex,
    05206     PBYTE  pBuffer,
    05207     DWORD  dwIntent
    05208     )
    05209 {
    05210     PLUT16TYPE pLut;
    05211     PHOSTCLUT  pHostClut;
    05212     PTAGDATA   pTagData;
    05213     PBYTE      pTable;
    05214     DWORD      nInputCh, nOutputCh, nGrids;
    05215     DWORD      nInputEntries, nOutputEntries, nNumbers;
    05216     DWORD      dwPCS, dwLutSig;
    05217     DWORD      dwSize, i, j;
    05218     PBYTE      pStart = pBuffer;
    05219
    05220     //
    05221     // Check if we can generate the CSA
    05222     // Required  tags is AToBi, where i is the rendering intent
    05223     //
    05224
    05225     dwPCS = GetCPConnSpace(pProfile);
    05226
    05227     pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
    05228                dwIndex * sizeof(TAGDATA));
    05229
    05230     pLut = (PLUT16TYPE)(pProfile + FIX_ENDIAN(pTagData->dwOffset));
    05231
    05232     dwLutSig = FIX_ENDIAN(pLut->dwSignature);
    05233
    05234     if ((dwLutSig != LUT8_TYPE) && (dwLutSig != LUT16_TYPE))
    05235     {
    05236         WARNING((__TEXT("Invalid profile - unable to create Lut CRD\n")));
    05237         SetLastError(ERROR_INVALID_PROFILE);
    05238         return 0;
    05239     }
    05240
    05241     (void)GetCLUTInfo(dwLutSig, (PBYTE)pLut, &nInputCh, &nOutputCh,
    05242             &nGrids, &nInputEntries, &nOutputEntries, &i);
    05243
    05244     if (((nOutputCh != 3) && (nOutputCh != 4)) ||  (nInputCh != 3))
    05245     {
    05246         return 0;
    05247     }
    05248
    05249     if (pBuffer == NULL)
    05250     {
    05251         //
    05252         // Return size
    05253         //
    05254
    05255         dwSize = nInputCh * nInputEntries * i    +  // Input table 8/16-bits
    05256             nOutputCh * nOutputEntries * i       +  // Output table 8/16-bits
    05257             nOutputCh * nGrids * nGrids * nGrids +  // CLUT 8-bits only
    05258             sizeof(HOSTCLUT)                     +  // Data structure
    05259             2048;                                   // Other PS stuff
    05260
    05261         //
    05262         // Add space for new line.
    05263         //
    05264
    05265         dwSize += (((dwSize) / MAX_LINELEN) + 1) * STRLEN(NewLine);
    05266
    05267         return dwSize;
    05268     }
    05269
    05270     pHostClut = (PHOSTCLUT)pBuffer;
    05271     pBuffer += sizeof(HOSTCLUT);
    05272     pHostClut->wSize = sizeof(HOSTCLUT);
    05273     pHostClut->wDataType = DATATYPE_LUT;
    05274     pHostClut->dwPCS = dwPCS;
    05275     pHostClut->dwIntent = dwIntent;
    05276     pHostClut->nLutBits = (dwLutSig == LUT8_TYPE) ? 8 : 16;
    05277
    05278     (void)GetCPWhitePoint(pProfile, pHostClut->afxIlluminantWP);
    05279
    05280     //
    05281     // Support absolute whitePoint
    05282     //
    05283
    05284     if (!GetCPMediaWhitePoint(pProfile, pHostClut->afxMediaWP))
    05285     {
    05286         pHostClut->afxMediaWP[0] = pHostClut->afxIlluminantWP[0];
    05287         pHostClut->afxMediaWP[1] = pHostClut->afxIlluminantWP[1];
    05288         pHostClut->afxMediaWP[2] = pHostClut->afxIlluminantWP[2];
    05289     }
    05290
    05291     pHostClut->nInputCh = (BYTE)nInputCh;
    05292     pHostClut->nOutputCh = (BYTE)nOutputCh;
    05293     pHostClut->nClutPoints = (BYTE)nGrids;
    05294     pHostClut->nInputEntries = (WORD)nInputEntries;
    05295     pHostClut->nOutputEntries = (WORD)nOutputEntries;
    05296
    05297     //
    05298     // Input array
    05299     //
    05300
    05301     pBuffer += CreateHostInputOutputArray(
    05302                         pBuffer,
    05303                         pHostClut->inputArray,
    05304                         nInputCh,
    05305                         nInputEntries,
    05306                         0,
    05307                         dwLutSig,
    05308                         (PBYTE)pLut);
    05309
    05310     //
    05311     // The offset to the position of output array.
    05312     //
    05313
    05314     i = nInputEntries * nInputCh +
    05315         nGrids * nGrids * nGrids * nOutputCh;
    05316
    05317     //
    05318     // Output array
    05319     //
    05320
    05321     pBuffer += CreateHostInputOutputArray(
    05322                         pBuffer,
    05323                         pHostClut->outputArray,
    05324                         nOutputCh,
    05325                         nOutputEntries,
    05326                         i,
    05327                         dwLutSig,
    05328                         (PBYTE)pLut);
    05329
    05330     //
    05331     // Matrix
    05332     //
    05333
    05334     if (dwPCS == SPACE_XYZ)
    05335     {
    05336         if (dwLutSig == LUT8_TYPE)
    05337         {
    05338             pTable = (PBYTE) &((PLUT8TYPE)pLut)->e00;
    05339         } else
    05340         {
    05341             pTable = (PBYTE) &((PLUT16TYPE)pLut)->e00;
    05342         }
    05343
    05344         for (i=0; i<9; i++)
    05345         {
    05346             pHostClut->e[i] = FIX_DIV(FIX_ENDIAN(*((PDWORD)pTable)), CIEXYZRange);
    05347             pTable += sizeof(DWORD);
    05348         }
    05349     }
    05350
    05351     //
    05352     // RenderTable
    05353     //
    05354
    05355     nNumbers = nGrids * nGrids * nOutputCh;
    05356     pHostClut->clut = pBuffer;
    05357
    05358     for (i=0; i<nGrids; i++)        // Na strings should be sent
    05359     {
    05360         if (dwLutSig == LUT8_TYPE)
    05361         {
    05362             pTable = (PBYTE)(((PLUT8TYPE)pLut)->data) +
    05363                 nInputEntries * nInputCh +
    05364                 nNumbers * i;
    05365         }
    05366         else
    05367         {
    05368             pTable = (PBYTE)(((PLUT16TYPE)pLut)->data) +
    05369                 2 * nInputEntries * nInputCh +
    05370                 2 * nNumbers * i;
    05371         }
    05372
    05373         if (dwLutSig == LUT8_TYPE)
    05374         {
    05375             CopyMemory(pBuffer, pTable, nNumbers);
    05376             pBuffer += nNumbers;
    05377         }
    05378         else
    05379         {
    05380             for (j=0; j<nNumbers; j++)
    05381             {
    05382                 *pBuffer++ = (BYTE)(FIX_ENDIAN16(*((PWORD)pTable)) / 256);
    05383                 pTable += sizeof(WORD);
    05384             }
    05385         }
    05386     }
    05387
    05388     return (DWORD)(pBuffer - pStart);
    05389 }
    05390
    05391
    05392 DWORD
    05393 CreateHostMatrixCSAorCRD(
    05394     PBYTE pProfile,
    05395     PBYTE pBuffer,
    05396     PDWORD pcbSize,
    05397     DWORD dwIntent,
    05398     BOOL bCSA
    05399     )
    05400 {
    05401     PTAGDATA   pTagData;
    05402     DWORD      dwRedTRCIndex, dwGreenTRCIndex, dwBlueTRCIndex;
    05403     DWORD      dwRedCount, dwGreenCount, dwBlueCount;
    05404     PCURVETYPE pRed, pGreen, pBlue;
    05405     PHOSTCLUT  pHostClut;
    05406     PBYTE      pStart = pBuffer;
    05407     DWORD      i, dwSize;
    05408     double     adArray[9], adRevArray[9], adTemp[9];
    05409
    05410     //
    05411     // Get each TRC index for Red, Green and Blue.
    05412     //
    05413
    05414     if (!DoesCPTagExist(pProfile, TAG_REDTRC, &dwRedTRCIndex) ||
    05415         !DoesCPTagExist(pProfile, TAG_GREENTRC, &dwGreenTRCIndex) ||
    05416         !DoesCPTagExist(pProfile, TAG_BLUETRC, &dwBlueTRCIndex))
    05417     {
    05418         return FALSE;
    05419     }
    05420
    05421     //
    05422     // Get CURVETYPE data for each Red, Green and Blue
    05423     //
    05424
    05425     pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
    05426                dwRedTRCIndex * sizeof(TAGDATA));
    05427
    05428     pRed = (PCURVETYPE)(pProfile + FIX_ENDIAN(pTagData->dwOffset));
    05429
    05430     pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
    05431                dwGreenTRCIndex * sizeof(TAGDATA));
    05432
    05433     pGreen = (PCURVETYPE)(pProfile + FIX_ENDIAN(pTagData->dwOffset));
    05434
    05435     pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
    05436                dwBlueTRCIndex * sizeof(TAGDATA));
    05437
    05438     pBlue = (PCURVETYPE)(pProfile + FIX_ENDIAN(pTagData->dwOffset));
    05439
    05440     //
    05441     // Get curve count for each Red, Green and Blue.
    05442     //
    05443
    05444     dwRedCount   = FIX_ENDIAN(pRed->nCount);
    05445     dwGreenCount = FIX_ENDIAN(pGreen->nCount);
    05446     dwBlueCount  = FIX_ENDIAN(pBlue->nCount);
    05447
    05448     //
    05449     // Estimate the memory size required to hold CRD
    05450     //
    05451
    05452     dwSize = (dwRedCount + dwGreenCount + dwBlueCount) * 2 +
    05453              sizeof(HOSTCLUT) + 2048;   // data structure + extra safe space
    05454
    05455     //
    05456     // Add space for new line.
    05457     //
    05458
    05459     dwSize += (((dwSize) / MAX_LINELEN) + 1) * STRLEN(NewLine);
    05460
    05461     if (pBuffer == NULL)     // This is a size request
    05462     {
    05463         *pcbSize = dwSize;
    05464         return TRUE;
    05465     }
    05466
    05467     //
    05468     // Check buffer size.
    05469     //
    05470
    05471     if (*pcbSize < dwSize)
    05472     {
    05473         WARNING((__TEXT("Buffer too small to get Host Matrix CSA/CRD\n")));
    05474         SetLastError(ERROR_INSUFFICIENT_BUFFER);
    05475         return FALSE;
    05476     }
    05477
    05478     pHostClut = (PHOSTCLUT)pBuffer;
    05479     pBuffer += sizeof(HOSTCLUT);
    05480     pHostClut->wSize = sizeof(HOSTCLUT);
    05481     pHostClut->wDataType = DATATYPE_MATRIX;
    05482     pHostClut->dwPCS = SPACE_XYZ;
    05483     pHostClut->dwIntent = dwIntent;
    05484     pHostClut->nClutPoints = 2;
    05485
    05486     (void)GetCPWhitePoint(pProfile, pHostClut->afxIlluminantWP);
    05487
    05488     if (bCSA)
    05489     {
    05490         pHostClut->nInputEntries = (USHORT) dwRedCount;
    05491         pHostClut->nInputCh      = 3;
    05492
    05493         pBuffer += CreateHostTRCInputTable(pBuffer, pHostClut,
    05494                                            pRed, pGreen, pBlue);
    05495     }
    05496     else
    05497     {
    05498         pHostClut->nOutputEntries = (USHORT) dwRedCount;
    05499         pHostClut->nOutputCh = 3;
    05500
    05501         pBuffer += CreateHostRevTRCInputTable(pBuffer, pHostClut,
    05502                                               pRed, pGreen, pBlue);
    05503     }
    05504
    05505     if (!CreateColorantArray(pProfile, &adTemp[0], TAG_REDCOLORANT) ||
    05506         !CreateColorantArray(pProfile, &adTemp[3], TAG_GREENCOLORANT) ||
    05507         !CreateColorantArray(pProfile, &adTemp[6], TAG_BLUECOLORANT))
    05508     {
    05509         WARNING((__TEXT("Fail to create colorant array for Host Matrix CSA/CRD\n")));
    05510         return FALSE;
    05511     }
    05512
    05513     for (i = 0; i < 9; i++)
    05514     {
    05515         adArray[i] = adTemp[i/8*8 + i*3%8];
    05516     }
    05517
    05518     if (bCSA)
    05519     {
    05520         for (i = 0; i < 9; i++)
    05521         {
    05522             //
    05523             // Convert double to Fix 16.16
    05524             //
    05525
    05526             pHostClut->e[i] = (FIX_16_16)(adArray[i] * (double)FIX_16_16_SCALE);
    05527         }
    05528     }
    05529     else
    05530     {
    05531         InvertColorantArray(adArray, adRevArray);
    05532         for (i = 0; i < 9; i++)
    05533         {
    05534             //
    05535             // Convert double to Fix 16.16
    05536             //
    05537
    05538             pHostClut->e[i] = (FIX_16_16)(adRevArray[i] * (double)FIX_16_16_SCALE);
    05539         }
    05540     }
    05541
    05542     *pcbSize = (DWORD)(pBuffer - pStart);
    05543
    05544     return TRUE;
    05545 }
    05546
    05547
    05548 DWORD
    05549 CreateHostTRCInputTable(
    05550     PBYTE pBuffer,
    05551     PHOSTCLUT pHostClut,
    05552     PCURVETYPE pRed,
    05553     PCURVETYPE pGreen,
    05554     PCURVETYPE pBlue
    05555     )
    05556 {
    05557     DWORD i;
    05558     PWORD pBuffer16 = (PWORD) pBuffer;
    05559     PWORD pTable;
    05560
    05561     //
    05562     // Red
    05563     //
    05564
    05565     pHostClut->inputArray[0] = (PBYTE) pBuffer16;
    05566     pTable = pRed->data;
    05567     for (i = 0; i < pHostClut->nInputEntries; i++)
    05568     {
    05569         *pBuffer16++ = FIX_ENDIAN16(*pTable);
    05570         pTable++;
    05571     }
    05572
    05573     //
    05574     // Green
    05575     //
    05576
    05577     pHostClut->inputArray[1] = (PBYTE) pBuffer16;
    05578     pTable = pGreen->data;
    05579     for (i = 0; i < pHostClut->nInputEntries; i++)
    05580     {
    05581         *pBuffer16++ = FIX_ENDIAN16(*pTable);
    05582         pTable++;
    05583     }
    05584
    05585     //
    05586     // Blue
    05587     //
    05588
    05589     pHostClut->inputArray[2] = (PBYTE) pBuffer16;
    05590     pTable = pBlue->data;
    05591     for (i = 0; i < pHostClut->nInputEntries; i++)
    05592     {
    05593         *pBuffer16++ = FIX_ENDIAN16(*pTable);
    05594         pTable++;
    05595     }
    05596
    05597     return (DWORD)((PBYTE)pBuffer16 - pBuffer);
    05598 }
    05599
    05600 DWORD
    05601 CreateHostRevTRCInputTable(
    05602     PBYTE pBuffer,
    05603     PHOSTCLUT pHostClut,
    05604     PCURVETYPE pRed,
    05605     PCURVETYPE pGreen,
    05606     PCURVETYPE pBlue
    05607     )
    05608 {
    05609     PWORD pTemp = MemAlloc(pHostClut->nOutputEntries * (REVCURVE_RATIO + 1) * 2);
    05610
    05611     if (! pTemp)
    05612     {
    05613         return 0;
    05614     }
    05615
    05616     //
    05617     // Red
    05618     //
    05619
    05620     pHostClut->outputArray[0] = pBuffer;
    05621     GetRevCurve(pRed, pTemp, (PWORD) pHostClut->outputArray[0]);
    05622
    05623     //
    05624     // Green
    05625     //
    05626
    05627     pHostClut->outputArray[1] = pHostClut->outputArray[0] +
    05628                                 2 * REVCURVE_RATIO * pHostClut->nOutputEntries;
    05629     GetRevCurve(pGreen, pTemp, (PWORD) pHostClut->outputArray[1]);
    05630
    05631     //
    05632     // Blue
    05633     //
    05634
    05635     pHostClut->outputArray[2] = pHostClut->outputArray[1] +
    05636                                 2 * REVCURVE_RATIO * pHostClut->nOutputEntries;
    05637     GetRevCurve(pBlue, pTemp, (PWORD) pHostClut->outputArray[2]);
    05638
    05639     MemFree(pTemp);
    05640
    05641     return (DWORD)(2 * REVCURVE_RATIO * pHostClut->nOutputEntries * 3);
    05642 }
    05643
    05644 /***************************************************************************
    05645 *                      GetHostColorRenderingDictionary
    05646 *  function:
    05647 *    this is the main function which creates the Host CRD
    05648 *  parameters:
    05649 *       cp          --  Color Profile handle
    05650 *       Intent      --  Intent.
    05651 *       lpMem       --  Pointer to the memory block.If this point is NULL,
    05652 *                       require buffer size.
    05653 *       lpcbSize    --  size of memory block.
    05654 *
    05655 *  returns:
    05656 *       SINT        --  !=0 if the function was successful,
    05657 *                         0 otherwise.
    05658 *                       Returns number of bytes required/transferred
    05659 ***************************************************************************/
    05660
    05661 BOOL
    05662 GetHostColorRenderingDictionary(
    05663     PBYTE  pProfile,
    05664     DWORD  dwIntent,
    05665     PBYTE  pBuffer,
    05666     PDWORD pdwSize
    05667     )
    05668 {
    05669     DWORD dwBToATag, dwIndex;
    05670
    05671     switch (dwIntent)
    05672     {
    05673     case INTENT_PERCEPTUAL:
    05674         dwBToATag = TAG_BToA0;
    05675         break;
    05676
    05677     case INTENT_RELATIVE_COLORIMETRIC:
    05678     case INTENT_ABSOLUTE_COLORIMETRIC:
    05679         dwBToATag = TAG_BToA1;
    05680         break;
    05681
    05682     case INTENT_SATURATION:
    05683         dwBToATag = TAG_BToA2;
    05684         break;
    05685
    05686     default:
    05687         *pdwSize = 0;
    05688         return FALSE;
    05689     }
    05690
    05691     if (DoesCPTagExist(pProfile, dwBToATag, &dwIndex))
    05692     {
    05693         *pdwSize = CreateHostLutCRD(pProfile, dwIndex, pBuffer, dwIntent);
    05694
    05695         return *pdwSize > 0;
    05696     }
    05697     else if (DoesTRCAndColorantTagExist(pProfile))
    05698     {
    05699         return CreateHostMatrixCSAorCRD(pProfile, pBuffer, pdwSize, dwIntent, FALSE);
    05700     }
    05701     else
    05702     {
    05703         return FALSE;
    05704     }
    05705 }
    05706
    05707
    05708 /***************************************************************************
    05709 *                           CreateHostInputOutputArray
    05710 *  function:
    05711 *    this is the function which creates the output array from the data
    05712 *    supplied in the ColorProfile's LUT8 or LUT16 tag.
    05713 *  parameters:
    05714 *    MEMPTR     lpMem        : The buffer to save output array.
    05715 *    LPHOSTCLUT lpHostClut   :
    05716 *    SINT       nOutputCh    : Number of input channel.
    05717 *    SINT       nOutputTable : The size of each input table.
    05718 *    SINT       Offset       : The position of source output data(in icc profile).
    05719 *    CSIG       Tag          : To determin the Output table is 8 or 16 bits.
    05720 *    MEMPTR     Buff         : The buffer that contains source data(copyed from icc profile)
    05721 *
    05722 *  returns:
    05723 *       SINT    Returns number of bytes of Output Array
    05724 *
    05725 ***************************************************************************/
    05726
    05727 DWORD
    05728 CreateHostInputOutputArray(
    05729     PBYTE  pBuffer,
    05730     PBYTE  *ppArray,
    05731     DWORD  nNumChan,
    05732     DWORD  nTableSize,
    05733     DWORD  dwOffset,
    05734     DWORD  dwLutSig,
    05735     PBYTE  pLut
    05736     )
    05737 {
    05738     PBYTE   pStart = pBuffer;
    05739     PBYTE   pTable;
    05740     DWORD   i, j;
    05741
    05742     for (i=0; i<nNumChan; i++)
    05743     {
    05744         ppArray[i] = pBuffer;
    05745
    05746         if (dwLutSig == LUT8_TYPE)
    05747         {
    05748             pTable = (PBYTE) (((PLUT8TYPE)pLut)->data) +
    05749                 dwOffset + nTableSize * i;
    05750
    05751             CopyMemory(pBuffer, pTable, nTableSize);
    05752
    05753             pBuffer += nTableSize;
    05754         }
    05755         else
    05756         {
    05757             pTable = (PBYTE) (((PLUT16TYPE)pLut)->data) +
    05758                 2 * dwOffset +
    05759                 2 * nTableSize * i;
    05760
    05761             for (j=0; j<nTableSize; j++)
    05762             {
    05763                 *((PWORD)pBuffer) = FIX_ENDIAN16(*((PWORD)pTable));
    05764                 pBuffer += sizeof(WORD);
    05765                 pTable += sizeof(WORD);
    05766             }
    05767         }
    05768     }
    05769
    05770     return (DWORD) (pBuffer - pStart);
    05771 }
    05772
    05773
    05774 /***************************************************************************
    05775 *                           GetHostCSA
    05776 *  function:
    05777 *    this is the function which creates a Host CSA
    05778 *  parameters:
    05779 *       CHANDLE cp       --  Color Profile handle
    05780 *       MEMPTR lpMem     --  Pointer to the memory block. If this point is NULL,
    05781 *                            require buffer size.
    05782 *       LPDWORD lpcbSize --  Size of the memory block
    05783 *       CSIG InputIntent --
    05784 *       SINT Index       --  to the icc profile tag that contains the data of Intent
    05785 *       int  Type        --  DEF or DEFG
    05786 *  returns:
    05787 *       BOOL        --  TRUE if the function was successful,
    05788 *                       FALSE otherwise.
    05789 ***************************************************************************/
    05790
    05791 BOOL
    05792 GetHostCSA(
    05793     PBYTE  pProfile,
    05794     PBYTE  pBuffer,
    05795     PDWORD pdwSize,
    05796     DWORD  dwIntent,
    05797     DWORD  dwType
    05798     )
    05799 {
    05800     PHOSTCLUT  pHostClut;
    05801     PTAGDATA   pTagData;
    05802     PLUT16TYPE pLut;
    05803     DWORD      dwAToBTag;
    05804     DWORD      dwPCS, dwLutSig;
    05805     DWORD      nInputCh, nOutputCh, nGrids, SecondGrids;
    05806     DWORD      nInputTable, nOutputTable, nNumbers;
    05807     DWORD      dwIndex, i, j, k;
    05808     PBYTE      pTable;
    05809     PBYTE      pStart = pBuffer;
    05810
    05811     switch (dwIntent)
    05812     {
    05813     case INTENT_PERCEPTUAL:
    05814         dwAToBTag = TAG_AToB0;
    05815         break;
    05816
    05817     case INTENT_RELATIVE_COLORIMETRIC:
    05818     case INTENT_ABSOLUTE_COLORIMETRIC:
    05819         dwAToBTag = TAG_AToB1;
    05820         break;
    05821
    05822     case INTENT_SATURATION:
    05823         dwAToBTag = TAG_AToB2;
    05824         break;
    05825
    05826     default:
    05827         WARNING((__TEXT("Invalid intent passed to GetHostCSA: %d\n"), dwIntent));
    05828         SetLastError(ERROR_INVALID_PARAMETER);
    05829         return FALSE;
    05830         break;
    05831     }
    05832
    05833     if (!DoesCPTagExist(pProfile, dwAToBTag, &dwIndex))
    05834     {
    05835         if (DoesTRCAndColorantTagExist(pProfile) && (dwType == TYPE_CIEBASEDDEF))
    05836         {
    05837             //
    05838             // Create Host CSA from Matrix.
    05839             //
    05840
    05841             return CreateHostMatrixCSAorCRD(pProfile,pBuffer,pdwSize,dwIntent,TRUE);
    05842         }
    05843         else
    05844         {
    05845             WARNING((__TEXT("AToB tag not present for intent %d\n"), dwIntent));
    05846             SetLastError(ERROR_TAG_NOT_PRESENT);
    05847             return FALSE;
    05848         }
    05849     }
    05850
    05851     //
    05852     // Check if we can generate the CSA
    05853     //
    05854
    05855     dwPCS = GetCPConnSpace(pProfile);
    05856
    05857     pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
    05858                dwIndex * sizeof(TAGDATA));
    05859
    05860     pLut = (PLUT16TYPE)(pProfile + FIX_ENDIAN(pTagData->dwOffset));
    05861
    05862     dwLutSig = FIX_ENDIAN(pLut->dwSignature);
    05863
    05864     if (((dwPCS != SPACE_Lab) && (dwPCS != SPACE_XYZ)) ||
    05865         ((dwLutSig != LUT8_TYPE) && (dwLutSig != LUT16_TYPE)))
    05866     {
    05867         WARNING((__TEXT("Invalid color space - unable to create DEF(G) host CSA\n")));
    05868         SetLastError(ERROR_INVALID_PROFILE);
    05869         return FALSE;
    05870     }
    05871
    05872     //
    05873     // Estimate the memory size required to hold CSA
    05874     //
    05875
    05876     (void)GetCLUTInfo(dwLutSig, (PBYTE)pLut, &nInputCh, &nOutputCh, &nGrids,
    05877                 &nInputTable, &nOutputTable, &i);
    05878
    05879     if (!(nOutputCh == 3) ||
    05880         !((nInputCh == 3) && (dwType == TYPE_CIEBASEDDEF)) &&
    05881         !((nInputCh == 4) && (dwType == TYPE_CIEBASEDDEFG)))
    05882     {
    05883         return FALSE;
    05884     }
    05885
    05886     if (pBuffer == NULL)
    05887     {
    05888         //
    05889         // Return size
    05890         //
    05891
    05892         if (dwType == TYPE_CIEBASEDDEFG)
    05893             *pdwSize = nOutputCh * nGrids * nGrids * nGrids * nGrids;
    05894         else
    05895             *pdwSize = nOutputCh * nGrids * nGrids * nGrids;
    05896
    05897         *pdwSize +=                           // size of RenderTable 8-bits only
    05898             nInputCh * nInputTable * i    +   // size of input table 8/16-bits
    05899             nOutputCh * nOutputTable * i  +   // size of output table 8/16-bits
    05900             sizeof(HOSTCLUT) + 2048;          // data structure + other PS stuff
    05901
    05902         //
    05903         // Add space for new line.
    05904         //
    05905
    05906         *pdwSize += (((*pdwSize) / MAX_LINELEN) + 1) * STRLEN(NewLine);
    05907
    05908         return TRUE;
    05909     }
    05910
    05911     pHostClut = (PHOSTCLUT)pBuffer;
    05912     pBuffer += sizeof(HOSTCLUT);
    05913     pHostClut->wSize = sizeof(HOSTCLUT);
    05914     pHostClut->wDataType = DATATYPE_LUT;
    05915     pHostClut->dwPCS = dwPCS;
    05916     pHostClut->dwIntent = dwIntent;
    05917     pHostClut->nLutBits = (dwLutSig == LUT8_TYPE) ? 8 : 16;
    05918
    05919     //
    05920     // Get info about Illuminant White Point from the header
    05921     //
    05922
    05923     (void)GetCPWhitePoint(pProfile, pHostClut->afxIlluminantWP);
    05924
    05925     pHostClut->nInputCh = (BYTE)nInputCh;
    05926     pHostClut->nOutputCh = (BYTE)nOutputCh;
    05927     pHostClut->nClutPoints = (BYTE)nGrids;
    05928     pHostClut->nInputEntries = (WORD)nInputTable;
    05929     pHostClut->nOutputEntries = (WORD)nOutputTable;
    05930
    05931     //
    05932     // Input Array
    05933     //
    05934
    05935     pBuffer += CreateHostInputOutputArray(pBuffer, pHostClut->inputArray,
    05936              nInputCh, nInputTable, 0, dwLutSig, (PBYTE)pLut);
    05937
    05938     if (dwType == TYPE_CIEBASEDDEFG)
    05939     {
    05940         i = nInputTable * nInputCh +
    05941             nGrids * nGrids * nGrids * nGrids * nOutputCh;
    05942     }
    05943     else
    05944     {
    05945         i = nInputTable * nInputCh +
    05946             nGrids * nGrids * nGrids * nOutputCh;
    05947     }
    05948
    05949     //
    05950     // Output Array
    05951     //
    05952
    05953     pBuffer += CreateHostInputOutputArray(pBuffer, pHostClut->outputArray,
    05954              nOutputCh, nOutputTable, i, dwLutSig, (PBYTE)pLut);
    05955
    05956     //
    05957     // /Table
    05958     //
    05959
    05960     pHostClut->clut = pBuffer;
    05961     nNumbers = nGrids * nGrids * nOutputCh;
    05962     SecondGrids = 1;
    05963     if (dwType == TYPE_CIEBASEDDEFG)
    05964     {
    05965         SecondGrids = nGrids;
    05966     }
    05967
    05968     for (i=0; i<nGrids; i++)        // Nh strings should be sent
    05969     {
    05970         for (k=0; k<SecondGrids; k++)
    05971         {
    05972             if (dwLutSig == LUT8_TYPE)
    05973             {
    05974                 pTable = (PBYTE) (((PLUT8TYPE)pLut)->data) +
    05975                     nInputTable * nInputCh +
    05976                     nNumbers * (i * SecondGrids + k);
    05977             }
    05978             else
    05979             {
    05980                 pTable = (PBYTE) (((PLUT16TYPE)pLut)->data) +
    05981                     2 * nInputTable * nInputCh +
    05982                     2 * nNumbers * (i * SecondGrids + k);
    05983             }
    05984
    05985             if (dwLutSig == LUT8_TYPE)
    05986             {
    05987                 CopyMemory(pBuffer, pTable, nNumbers);
    05988                 pBuffer += nNumbers;
    05989             }
    05990             else
    05991             {
    05992                 for (j=0; j<nNumbers; j++)
    05993                 {
    05994                     *pBuffer++ = (BYTE)(FIX_ENDIAN16(*((PWORD)pTable)) / 256);
    05995                     pTable += sizeof(WORD);
    05996                 }
    05997             }
    05998         }
    05999     }
    06000
    06001     *pdwSize = (DWORD) (pBuffer - pStart);
    06002
    06003     return TRUE;
    06004 }
    06005
    06006
    06007 /***************************************************************************
    06008 *                            GetHostColorSpaceArray
    06009 *  function:
    06010 *    This is the main function which creates the Host CSA
    06011 *    from the data supplied in the Profile.
    06012 *  parameters:
    06013 *       cp          --  Color Profile handle
    06014 *       InputIntent --  Intent.
    06015 *       lpBuffer    --  Pointer to the memory block. If this point is NULL,
    06016 *                       require buffer size.
    06017 *       lpcbSize    --  Size of the memory block
    06018 *  returns:
    06019 *       BOOL        --  TRUE if the function was successful,
    06020 *                       FALSE otherwise.
    06021 ***************************************************************************/
    06022
    06023 BOOL
    06024 GetHostColorSpaceArray(
    06025     PBYTE  pProfile,
    06026     DWORD  dwIntent,
    06027     PBYTE  pBuffer,
    06028     PDWORD pdwSize
    06029     )
    06030 {
    06031     DWORD dwDev;
    06032     BOOL bRc = FALSE;
    06033
    06034     dwDev = GetCPDevSpace(pProfile);
    06035
    06036     switch (dwDev)
    06037     {
    06038     case SPACE_RGB:
    06039         bRc = GetHostCSA(pProfile, pBuffer, pdwSize,
    06040                   dwIntent, TYPE_CIEBASEDDEF);
    06041         break;
    06042     case SPACE_CMYK:
    06043         bRc = GetHostCSA(pProfile, pBuffer, pdwSize,
    06044                   dwIntent, TYPE_CIEBASEDDEFG);
    06045         break;
    06046     default:
    06047         break;
    06048     }
    06049
    06050     return bRc;
    06051 }
    06052
    06053
    06054 /***************************************************************************
    06055 *                         DoHostConversionCRD
    06056 *  function:
    06057 *    This function converts XYZ/Lab to RGB/CMYK by using HostCRD
    06058 *  parameters:
    06059 *       LPHOSTCLUT lpHostCRD  -- pointer to a HostCRD
    06060 *       LPHOSTCLUT lpHostCSA  -- pointer to a HostCSA
    06061 *       float far *Input      -- Input XYZ/Lab
    06062 *       float far *Output     -- Output RGB/CMYK
    06063 *  returns:
    06064 *       BOOL                  -- TRUE
    06065 ***************************************************************************/
    06066
    06067 BOOL
    06068 DoHostConversionCRD(
    06069     PHOSTCLUT   pHostCRD,
    06070     PHOSTCLUT   pHostCSA,
    06071     float       *pfInput,
    06072     float       *pfOutput,
    06073     BOOL        bCheckOutputTable
    06074     )
    06075 {
    06076     float      fTemp[MAXCHANNELS];
    06077     float      fTemp1[MAXCHANNELS];
    06078     DWORD      i, j;
    06079
    06080     //
    06081     // Input XYZ or Lab in range [0 2]
    06082     //
    06083     // When sampling the deviceCRD, skip the input table.
    06084     // If pHostCSA is not NULL, the current CRD is targetCRD, we
    06085     // need to do input table conversion
    06086     //
    06087
    06088     if (pHostCSA)
    06089     {
    06090         //
    06091         // Convert Lab to XYZ  in range [ 0 whitePoint ]
    06092         //
    06093
    06094         if ((pHostCRD->dwPCS == SPACE_XYZ) &&
    06095             (pHostCSA->dwPCS == SPACE_Lab))
    06096         {
    06097             LabToXYZ(pfInput, fTemp1, pHostCRD->afxIlluminantWP);
    06098         }
    06099         else if ((pHostCRD->dwPCS == SPACE_Lab) &&
    06100                  (pHostCSA->dwPCS == SPACE_XYZ))
    06101         {
    06102             //
    06103             // Convert XYZ to Lab in range [ 0 1]
    06104             //
    06105
    06106             XYZToLab(pfInput, fTemp, pHostCSA->afxIlluminantWP);
    06107         }
    06108         else if ((pHostCRD->dwPCS == SPACE_Lab) &&
    06109                  (pHostCSA->dwPCS == SPACE_Lab))
    06110         {
    06111             //
    06112             // Convert Lab to range [ 0 1]
    06113             //
    06114
    06115             for (i=0; i<3; i++)
    06116                 fTemp[i] = pfInput[i] / 2;
    06117         }
    06118         else
    06119         {
    06120             //
    06121             // Convert XYZ to XYZ (based on white point) to range [0 1]
    06122             //
    06123             // TODO:
    06124             //   different intents using different conversion.
    06125             //   icRelativeColorimetric: using Bradford transform.
    06126             //   icAbsoluteColorimetric: using scaling.
    06127             //
    06128
    06129             for (i=0; i<3; i++)
    06130                 fTemp1[i] = (pfInput[i] * pHostCRD->afxIlluminantWP[i]) / pHostCSA->afxIlluminantWP[i];
    06131         }
    06132
    06133         //
    06134         // Matrix, used for XYZ data only.
    06135         //
    06136
    06137         if (pHostCRD->dwPCS == SPACE_XYZ)
    06138         {
    06139             ApplyMatrix(pHostCRD->e, fTemp1, fTemp);
    06140         }
    06141
    06142         if (pHostCRD->wDataType != DATATYPE_MATRIX)
    06143         {
    06144             //
    06145             // Search input Table
    06146             //
    06147
    06148             (void)CheckInputOutputTable(pHostCRD, fTemp, FALSE, TRUE);
    06149         }
    06150     }
    06151
    06152     //
    06153     // If the current CRD is device CRD, we do not need to do input
    06154     // table conversion
    06155     //
    06156
    06157     else
    06158     {
    06159         WORD nGrids;
    06160
    06161         nGrids = pHostCRD->nClutPoints;
    06162
    06163         //
    06164         // Sample data may be XYZ or Lab. It depends on Target icc profile.
    06165         // If the PCS of the target icc profile is XYZ, input data will be XYZ.
    06166         // If the PCS of the target icc profile is Lab, input data will be Lab.
    06167         //
    06168
    06169         if (pHostCRD->wDataType == DATATYPE_MATRIX)
    06170         {
    06171             for (i = 0; i < 3; i++)
    06172             {
    06173                 fTemp[i] = pfInput[i];
    06174             }
    06175         }
    06176         else
    06177         {
    06178             for (i=0; i<3; i++)
    06179             {
    06180                 fTemp[i] = pfInput[i] * (nGrids - 1);
    06181                 if (fTemp[i] > (nGrids - 1))
    06182                     fTemp[i] = (float)(nGrids - 1);
    06183             }
    06184         }
    06185     }
    06186
    06187     if (pHostCRD->wDataType != DATATYPE_MATRIX)
    06188     {
    06189         //
    06190         // Rendering table
    06191         //
    06192
    06193         (void)CheckColorLookupTable(pHostCRD, fTemp);
    06194     }
    06195
    06196     //
    06197     // Output RGB or CMYK in range [0 1]
    06198     //
    06199
    06200     if (bCheckOutputTable)
    06201     {
    06202         (void)CheckInputOutputTable(pHostCRD, fTemp, FALSE, FALSE);
    06203     }
    06204
    06205     for (i=0; (i<=MAXCHANNELS) && (i<pHostCRD->nOutputCh); i++)
    06206     {
    06207         pfOutput[i] = fTemp[i];
    06208     }
    06209
    06210     return TRUE;
    06211 }
    06212
    06213 /***************************************************************************
    06214 *                         DoHostConversionCSA
    06215 *  function:
    06216 *    This function converts RGB/CMYK to XYZ/Lab by using HostCSA
    06217 *  parameters:
    06218 *       LPHOSTCLUT lpHostCLUT -- pointer to a HostCSA
    06219 *       float far *Input      -- Input XYZ/Lab
    06220 *       float far *Output     -- Output RGB/CMYK
    06221 *  returns:
    06222 *       BOOL                  -- TRUE
    06223 ***************************************************************************/
    06224
    06225 BOOL
    06226 DoHostConversionCSA(
    06227     PHOSTCLUT     pHostClut,
    06228     float         *pfInput,
    06229     float         *pfOutput
    06230     )
    06231 {
    06232     float      fTemp[MAXCHANNELS];
    06233     DWORD      i;
    06234
    06235     //
    06236     // Input RGB or CMYK in range [0 1]
    06237     //
    06238
    06239     for (i=0; (i<=MAXCHANNELS) && (i<pHostClut->nInputCh); i++)
    06240     {
    06241         fTemp[i] = pfInput[i];
    06242     }
    06243
    06244     //
    06245     // Search input Table
    06246     //
    06247
    06248     (void)CheckInputOutputTable(pHostClut, fTemp, TRUE, TRUE);
    06249
    06250     if (pHostClut->wDataType == DATATYPE_MATRIX)
    06251     {
    06252         ApplyMatrix(pHostClut->e, fTemp, pfOutput);
    06253     }
    06254     else
    06255     {
    06256         //
    06257         // Rendering table
    06258         //
    06259
    06260         (void)CheckColorLookupTable(pHostClut, fTemp);
    06261
    06262         //
    06263         // Output Table
    06264         //
    06265
    06266         (void)CheckInputOutputTable(pHostClut, fTemp, TRUE, FALSE);
    06267
    06268         //
    06269         // Output XYZ or Lab in range [0 2]
    06270         //
    06271
    06272         for (i=0; (i<=MAXCHANNELS) && (i<pHostClut->nOutputCh); i++)
    06273         {
    06274             pfOutput[i] = fTemp[i];
    06275         }
    06276     }
    06277
    06278     return TRUE;
    06279 }
    06280
    06281
    06282
    06283 /***************************************************************************
    06284 *                         CheckInputOutputTable
    06285 *  function:
    06286 *    This function check inputTable.
    06287 *  parameters:
    06288 *       LPHOSTCLUT lpHostClut --
    06289 *       float far  *fTemp     --  Input / output data
    06290 *  returns:
    06291 *       BOOL                  -- TRUE
    06292 ***************************************************************************/
    06293
    06294 BOOL
    06295 CheckInputOutputTable(
    06296     PHOSTCLUT    pHostClut,
    06297     float        *pfTemp,
    06298     BOOL         bCSA,
    06299     BOOL         bInputTable
    06300     )
    06301 {
    06302     PBYTE      *ppArray;
    06303     float      fIndex;
    06304     DWORD      nNumCh;
    06305     DWORD      nNumEntries, i;
    06306     WORD       nGrids;
    06307     WORD       floor1, ceiling1;
    06308
    06309     if (bInputTable)
    06310     {
    06311         nNumCh = pHostClut->nInputCh;
    06312         nNumEntries = pHostClut->nInputEntries - 1;
    06313         ppArray = pHostClut->inputArray;
    06314     }
    06315     else
    06316     {
    06317         nNumCh = pHostClut->nOutputCh;
    06318         nNumEntries = pHostClut->nOutputEntries - 1;
    06319         ppArray = pHostClut->outputArray;
    06320     }
    06321
    06322     nGrids = pHostClut->nClutPoints;
    06323     for (i=0; (i<=MAXCHANNELS) && (i<nNumCh); i++)
    06324     {
    06325         pfTemp[i] = (pfTemp[i] < 0) ? 0 : ((pfTemp[i] > 1) ? 1 : pfTemp[i]);
    06326
    06327         fIndex = pfTemp[i] * nNumEntries;
    06328
    06329         if (pHostClut->nLutBits == 8)
    06330         {
    06331             floor1 = ppArray[i][(DWORD)fIndex];
    06332             ceiling1 = ppArray[i][((DWORD)fIndex) + 1];
    06333
    06334             pfTemp[i] = (float)(floor1 + (ceiling1 - floor1) * (fIndex - floor(fIndex)));
    06335
    06336             if (bCSA && !bInputTable)
    06337                 pfTemp[i] = pfTemp[i] / 127.0f;
    06338             else
    06339                 pfTemp[i] = pfTemp[i] / 255.0f;
    06340         }
    06341         else
    06342         {
    06343             floor1 = ((PWORD)(ppArray[i]))[(DWORD)fIndex];
    06344             ceiling1 = ((PWORD)(ppArray[i]))[((DWORD)fIndex) + 1];
    06345
    06346             pfTemp[i] = (float)(floor1 + (ceiling1 - floor1) * (fIndex - floor(fIndex)));
    06347
    06348             if (bCSA && !bInputTable)
    06349                 pfTemp[i] = pfTemp[i] / 32767.0f;
    06350             else
    06351                 pfTemp[i] = pfTemp[i] / 65535.0f;
    06352
    06353         }
    06354
    06355         if (bInputTable)
    06356         {
    06357             pfTemp[i] *= (nGrids - 1);
    06358             if (pfTemp[i] > (nGrids - 1))
    06359                 pfTemp[i] =  (float)(nGrids - 1);
    06360         }
    06361     }
    06362
    06363     return TRUE;
    06364 }
    06365
    06366
    06367 /***************************************************************************
    06368 *                               g
    06369 *  function:
    06370 *    Calculate function y = g(x). used in Lab->XYZ conversion
    06371 *    y = g(x):      g(x) = x*x*x             if x >= 6/29
    06372 *                   g(x) = 108/841*(x-4/29)  otherwise
    06373 *  parameters:
    06374 *       f           --  x
    06375 *  returns:
    06376 *       SINT        --  y
    06377 ***************************************************************************/
    06378
    06379 float g(
    06380     float f
    06381     )
    06382 {
    06383     float fRc;
    06384
    06385     if (f >= (6.0f/29.0f))
    06386     {
    06387         fRc = f * f * f;
    06388     }
    06389     else
    06390     {
    06391         fRc = f - (4.0f / 29.0f) * (108.0f / 841.0f);
    06392     }
    06393
    06394     return fRc;
    06395 }
    06396
    06397 /***************************************************************************
    06398 *                          inverse_g
    06399 *  function:
    06400 *    Calculate inverse function y = g(x). used in XYZ->Lab conversion
    06401 *  parameters:
    06402 *       f           --  y
    06403 *  returns:
    06404 *       SINT        --  x
    06405 ***************************************************************************/
    06406
    06407 float
    06408 inverse_g(
    06409     float f
    06410     )
    06411 {
    06412     double fRc;
    06413
    06414     if (f >= (6.0f*6.0f*6.0f)/(29.0f*29.0f*29.0f))
    06415     {
    06416         fRc = pow(f, 1.0 / 3.0);
    06417     }
    06418     else
    06419     {
    06420         fRc = f * (841.0f / 108.0f) + (4.0f / 29.0f);
    06421     }
    06422
    06423     return (float)fRc;
    06424 }
    06425
    06426
    06427 void
    06428 LabToXYZ(
    06429     float      *pfInput,
    06430     float      *pfOutput,
    06431     PFIX_16_16 pafxWP
    06432     )
    06433 {
    06434     float   fL, fa, fb;
    06435
    06436     fL = (pfInput[0] * 50 + 16) / 116;
    06437     fa = (pfInput[1] * 128 - 128) / 500;
    06438     fb = (pfInput[2] * 128 - 128) / 200;
    06439
    06440     pfOutput[0] = pafxWP[0] * g(fL + fa) / FIX_16_16_SCALE;
    06441     pfOutput[1] = pafxWP[1] * g(fL) / FIX_16_16_SCALE;
    06442     pfOutput[2] = pafxWP[2] * g(fL - fb) / FIX_16_16_SCALE;
    06443
    06444     return;
    06445 }
    06446
    06447
    06448 void
    06449 XYZToLab(
    06450     float      *pfInput,
    06451     float      *pfOutput,
    06452     PFIX_16_16 pafxWP
    06453     )
    06454 {
    06455     float  fL, fa, fb;
    06456
    06457     fL = inverse_g(pfInput[0] * FIX_16_16_SCALE / pafxWP[0]);
    06458     fa = inverse_g(pfInput[1] * FIX_16_16_SCALE / pafxWP[1]);
    06459     fb = inverse_g(pfInput[2] * FIX_16_16_SCALE / pafxWP[2]);
    06460
    06461     pfOutput[0] = (fa * 116 - 16) / 100;
    06462     pfOutput[1] = (fL * 500 - fa * 500 + 128) / 255;
    06463     pfOutput[2] = (fa * 200 - fb * 200 + 128) / 255;
    06464
    06465     return;
    06466 }
    06467
    06468
    06469 BOOL
    06470 TableInterp3(
    06471     PHOSTCLUT  pHostClut,
    06472     float      *pfTemp
    06473     )
    06474 {
    06475
    06476     PBYTE        v000, v001, v010, v011;
    06477     PBYTE        v100, v101, v110, v111;
    06478     float        fA, fB, fC;
    06479     float        fVx0x, fVx1x;
    06480     float        fV0xx, fV1xx;
    06481     DWORD        tmpA, tmpBC;
    06482     DWORD        cellA, cellB, cellC;
    06483     DWORD        idx;
    06484     WORD         nGrids;
    06485     WORD         nOutputCh;
    06486
    06487     cellA = (DWORD)pfTemp[0];
    06488     fA = pfTemp[0] - cellA;
    06489
    06490     cellB = (DWORD)pfTemp[1];
    06491     fB = pfTemp[1] - cellB;
    06492
    06493     cellC = (DWORD)pfTemp[2];
    06494     fC = pfTemp[2] - cellC;
    06495
    06496     nGrids = pHostClut->nClutPoints;
    06497     nOutputCh = pHostClut->nOutputCh;
    06498     tmpA  = nOutputCh * nGrids * nGrids;
    06499     tmpBC = nOutputCh * (nGrids * cellB + cellC);
    06500
    06501     //
    06502     // Calculate 8 surrounding cells.
    06503     //
    06504
    06505     v000 = pHostClut->clut + tmpA * cellA + tmpBC;
    06506     v001 = (cellC < (DWORD)(nGrids - 1)) ? v000 + nOutputCh : v000;
    06507     v010 = (cellB < (DWORD)(nGrids - 1)) ? v000 + nOutputCh * nGrids : v000;
    06508     v011 = (cellC < (DWORD)(nGrids - 1)) ? v010 + nOutputCh : v010 ;
    06509
    06510     v100 = (cellA < (DWORD)(nGrids - 1)) ? v000 + tmpA : v000;
    06511     v101 = (cellC < (DWORD)(nGrids - 1)) ? v100 + nOutputCh : v100;
    06512     v110 = (cellB < (DWORD)(nGrids - 1)) ? v100 + nOutputCh * nGrids : v100;
    06513     v111 = (cellC < (DWORD)(nGrids - 1)) ? v110 + nOutputCh : v110;
    06514
    06515     for (idx=0; idx<nOutputCh; idx++)
    06516     {
    06517         //
    06518         // Calculate the average of 4 bottom cells.
    06519         //
    06520
    06521         fVx0x = *v000 + fC * (int)((int)*v001 - (int)*v000);
    06522         fVx1x = *v010 + fC * (int)((int)*v011 - (int)*v010);
    06523         fV0xx = fVx0x + fB * (fVx1x - fVx0x);
    06524
    06525         //
    06526         // Calculate the average of 4 upper cells.
    06527         //
    06528
    06529         fVx0x = *v100 + fC * (int)((int)*v101 - (int)*v100);
    06530         fVx1x = *v110 + fC * (int)((int)*v111 - (int)*v110);
    06531         fV1xx = fVx0x + fB * (fVx1x - fVx0x);
    06532
    06533         //
    06534         // Calculate the bottom and upper average.
    06535         //
    06536
    06537         pfTemp[idx] = (fV0xx + fA * (fV1xx - fV0xx)) / MAXCOLOR8;
    06538
    06539         if ( idx < (DWORD)(nOutputCh - 1))
    06540         {
    06541             v000++;
    06542             v001++;
    06543             v010++;
    06544             v011++;
    06545             v100++;
    06546             v101++;
    06547             v110++;
    06548             v111++;
    06549         }
    06550     }
    06551
    06552     return TRUE;
    06553 }
    06554
    06555
    06556 BOOL
    06557 TableInterp4(
    06558     PHOSTCLUT  pHostClut,
    06559     float      *pfTemp
    06560     )
    06561 {
    06562     PBYTE     v0000, v0001, v0010, v0011;
    06563     PBYTE     v0100, v0101, v0110, v0111;
    06564     PBYTE     v1000, v1001, v1010, v1011;
    06565     PBYTE     v1100, v1101, v1110, v1111;
    06566     float     fH, fI, fJ, fK;
    06567     float     fVxx0x, fVxx1x;
    06568     float     fVx0xx, fVx1xx;
    06569     float     fV0xxx, fV1xxx;
    06570     DWORD     tmpH, tmpI, tmpJK;
    06571     DWORD     cellH, cellI, cellJ, cellK;
    06572     DWORD     idx;
    06573     WORD      nGrids;
    06574     WORD      nOutputCh;
    06575
    06576     cellH = (DWORD)pfTemp[0];
    06577     fH = pfTemp[0] - cellH;
    06578
    06579     cellI = (DWORD)pfTemp[1];
    06580     fI = pfTemp[1] - cellI;
    06581
    06582     cellJ = (DWORD)pfTemp[2];
    06583     fJ = pfTemp[2] - cellJ;
    06584
    06585     cellK = (DWORD)pfTemp[3];
    06586     fK = pfTemp[3] - cellK;
    06587
    06588     nGrids = pHostClut->nClutPoints;
    06589     nOutputCh = pHostClut->nOutputCh;
    06590     tmpI  = nOutputCh * nGrids * nGrids;
    06591     tmpH  = tmpI * nGrids;
    06592     tmpJK = nOutputCh * (nGrids * cellJ + cellK);
    06593
    06594     //
    06595     // Calculate 16 surrounding cells.
    06596     //
    06597
    06598     v0000 = pHostClut->clut + tmpH * cellH + tmpI * cellI + tmpJK;
    06599     v0001 = (cellK < (DWORD)(nGrids - 1))? v0000 + nOutputCh : v0000;
    06600     v0010 = (cellJ < (DWORD)(nGrids - 1))? v0000 + nOutputCh * nGrids : v0000;
    06601     v0011 = (cellK < (DWORD)(nGrids - 1))? v0010 + nOutputCh : v0010;
    06602
    06603     v0100 = (cellI < (DWORD)(nGrids - 1))? v0000 + tmpI : v0000;
    06604     v0101 = (cellK < (DWORD)(nGrids - 1))? v0100 + nOutputCh : v0100;
    06605     v0110 = (cellJ < (DWORD)(nGrids - 1))? v0100 + nOutputCh * nGrids : v0100;
    06606     v0111 = (cellK < (DWORD)(nGrids - 1))? v0110 + nOutputCh : v0110;
    06607
    06608     v1000 = (cellH < (DWORD)(nGrids - 1))? v0000 + tmpH : v0000;
    06609     v1001 = (cellK < (DWORD)(nGrids - 1))? v1000 + nOutputCh : v1000;
    06610     v1010 = (cellJ < (DWORD)(nGrids - 1))? v1000 + nOutputCh * nGrids : v1000;
    06611     v1011 = (cellK < (DWORD)(nGrids - 1))? v1010 + nOutputCh : v1010;
    06612
    06613     v1100 = (cellI < (DWORD)(nGrids - 1))? v1000 + tmpI : v1000;
    06614     v1101 = (cellK < (DWORD)(nGrids - 1))? v1100 + nOutputCh : v1100;
    06615     v1110 = (cellJ < (DWORD)(nGrids - 1))? v1100 + nOutputCh * nGrids : v1100;
    06616     v1111 = (cellK < (DWORD)(nGrids - 1))? v1110 + nOutputCh : v1110;
    06617
    06618
    06619     for (idx=0; idx<nOutputCh; idx++)
    06620     {
    06621         //
    06622         // Calculate the average of 8 bottom cells.
    06623         //
    06624
    06625         fVxx0x = *v0000 + fK * (int)((int)*v0001 - (int)*v0000);
    06626         fVxx1x = *v0010 + fK * (int)((int)*v0011 - (int)*v0010);
    06627         fVx0xx = fVxx0x + fJ * (fVxx1x - fVxx0x);
    06628         fVxx0x = *v0100 + fK * (int)((int)*v0101 - (int)*v0100);
    06629         fVxx1x = *v0110 + fK * (int)((int)*v0111 - (int)*v0110);
    06630         fVx1xx = fVxx0x + fJ * (fVxx1x - fVxx0x);
    06631         fV0xxx = fVx0xx + fI * (fVx1xx - fVx0xx);
    06632
    06633         //
    06634         // Calculate the average of 8 upper cells.
    06635         //
    06636
    06637         fVxx0x = *v1000 + fK * (int)((int)*v1001 - (int)*v1000);
    06638         fVxx1x = *v1010 + fK * (int)((int)*v1011 - (int)*v1010);
    06639         fVx0xx = fVxx0x + fJ * (fVxx1x - fVxx0x);
    06640         fVxx0x = *v1100 + fK * (int)((int)*v1101 - (int)*v1100);
    06641         fVxx1x = *v1110 + fK * (int)((int)*v1111 - (int)*v1110);
    06642         fVx1xx = fVxx0x + fJ * (fVxx1x - fVxx0x);
    06643         fV1xxx = fVx0xx + fI * (fVx1xx - fVx0xx);
    06644
    06645         //
    06646         // Calculate the bottom and upper average.
    06647         //
    06648
    06649         pfTemp[idx] = (fV0xxx + fH * (fV1xxx - fV0xxx)) / MAXCOLOR8;
    06650
    06651         if (idx < (DWORD)(nOutputCh - 1))
    06652         {
    06653             v0000++;
    06654             v0001++;
    06655             v0010++;
    06656             v0011++;
    06657             v0100++;
    06658             v0101++;
    06659             v0110++;
    06660             v0111++;
    06661             v1000++;
    06662             v1001++;
    06663             v1010++;
    06664             v1011++;
    06665             v1100++;
    06666             v1101++;
    06667             v1110++;
    06668             v1111++;
    06669         }
    06670     }
    06671
    06672     return TRUE;
    06673 }
    06674
    06675 BOOL
    06676 InvertColorantArray(
    06677     double *lpInMatrix,
    06678     double *lpOutMatrix)
    06679 {
    06680     double det;
    06681
    06682     double *a;
    06683     double *b;
    06684     double *c;
    06685
    06686     a = &(lpInMatrix[0]);
    06687     b = &(lpInMatrix[3]);
    06688     c = &(lpInMatrix[6]);
    06689
    06690     det = a[0] * b[1] * c[2] + a[1] * b[2] * c[0] + a[2] * b[0] * c[1] -
    06691          (a[2] * b[1] * c[0] + a[1] * b[0] * c[2] + a[0] * b[2] * c[1]);
    06692
    06693     if (det == 0.0)    // What to do?
    06694     {
    06695         lpOutMatrix[0] = 1.0;
    06696         lpOutMatrix[1] = 0.0;
    06697         lpOutMatrix[2] = 0.0;
    06698
    06699         lpOutMatrix[3] = 0.0;
    06700         lpOutMatrix[4] = 1.0;
    06701         lpOutMatrix[5] = 0.0;
    06702
    06703         lpOutMatrix[6] = 0.0;
    06704         lpOutMatrix[7] = 0.0;
    06705         lpOutMatrix[8] = 1.0;
    06706     }
    06707     else
    06708     {
    06709         lpOutMatrix[0] = (b[1] * c[2] - b[2] * c[1]) / det;
    06710         lpOutMatrix[3] = -(b[0] * c[2] - b[2] * c[0]) / det;
    06711         lpOutMatrix[6] = (b[0] * c[1] - b[1] * c[0]) / det;
    06712
    06713         lpOutMatrix[1] = -(a[1] * c[2] - a[2] * c[1]) / det;
    06714         lpOutMatrix[4] = (a[0] * c[2] - a[2] * c[0]) / det;
    06715         lpOutMatrix[7] = -(a[0] * c[1] - a[1] * c[0]) / det;
    06716
    06717         lpOutMatrix[2] = (a[1] * b[2] - a[2] * b[1]) / det;
    06718         lpOutMatrix[5] = -(a[0] * b[2] - a[2] * b[0]) / det;
    06719         lpOutMatrix[8] = (a[0] * b[1] - a[1] * b[0]) / det;
    06720     }
    06721
    06722     return (TRUE);
    06723 }
    06724
    06725 VOID
    06726 ApplyMatrix(
    06727     FIX_16_16 *e,
    06728     float *Input,
    06729     float *Output)
    06730 {
    06731     DWORD i, j;
    06732
    06733     for (i=0; i<3; i++)
    06734     {
    06735         j = i * 3;
    06736
    06737         Output[i] = ((e[j]     * Input[0]) / FIX_16_16_SCALE) +
    06738                     ((e[j + 1] * Input[1]) / FIX_16_16_SCALE) +
    06739                     ((e[j + 2] * Input[2]) / FIX_16_16_SCALE);
    06740     }
    06741 }
    06742
    06743
    06744 /***************************************************************************
    06745 *                         CheckColorLookupTable
    06746 *  function:
    06747 *    This function check RenderTable.
    06748 *  parameters:
    06749 *       LPHOSTCLUT lpHostClut --
    06750 *       float far  *fTemp     --  Input (in range [0 gred-1]) /
    06751 *                                 output(in range [0 1)
    06752 *  returns:
    06753 *       BOOL                  -- TRUE
    06754 ***************************************************************************/
    06755
    06756 BOOL
    06757 CheckColorLookupTable(
    06758     PHOSTCLUT   pHostClut,
    06759     float       *pfTemp
    06760     )
    06761 {
    06762     if (pHostClut->nInputCh == 3)
    06763     {
    06764         return TableInterp3(pHostClut, pfTemp);
    06765     }
    06766     else if (pHostClut->nInputCh == 4)
    06767     {
    06768         return TableInterp4(pHostClut, pfTemp);
    06769     }
    06770     else
    06771         return FALSE;
    06772 }
    06773
    06774 //
    06775 // For testing purposes
    06776 //
    06777
    06778 BOOL WINAPI
    06779 GetPS2PreviewCRD (
    06780     HPROFILE  hDestProfile,
    06781     HPROFILE  hTargetProfile,
    06782     DWORD     dwIntent,
    06783     PBYTE     pBuffer,
    06784     PDWORD    pcbSize,
    06785     LPBOOL    pbBinary
    06786     )
    06787 {
    06788     PPROFOBJ pDestProfObj;
    06789     PPROFOBJ pTargetProfObj;
    06790
    06791     pDestProfObj = (PPROFOBJ)HDLTOPTR(hDestProfile);
    06792     pTargetProfObj = (PPROFOBJ)HDLTOPTR(hTargetProfile);
    06793
    06794
    06795     return InternalGetPS2PreviewCRD(pDestProfObj->pView, pTargetProfObj->pView, dwIntent, pBuffer, pcbSize, pbBinary);
    06796 }
    06797
    06798 #endif // !defined(KERNEL_MODE) || defined(USERMODE_DRIVER)
    06799
    06800 /*
    06801  *  Crc - 32 BIT ANSI X3.66 CRC checksum files
    06802  *
    06803  *
    06804  * Copyright (C) 1986 Gary S. Brown.  You may use this program, or
    06805  * code or tables extracted from it, as desired without restriction.
    06806  */
    06807
    06808 static DWORD  crc_32_tab[] = { /* CRC polynomial 0xedb88320 */
    06809 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
    06810 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
    06811 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
    06812 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
    06813 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
    06814 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
    06815 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
    06816 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
    06817 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
    06818 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
    06819 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
    06820 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
    06821 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
    06822 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
    06823 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
    06824 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
    06825 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
    06826 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
    06827 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
    06828 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
    06829 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
    06830 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
    06831 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
    06832 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
    06833 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
    06834 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
    06835 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
    06836 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
    06837 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
    06838 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
    06839 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
    06840 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
    06841 };
    06842
    06843 DWORD crc32(PBYTE buff, DWORD length)
    06844 {
    06845     DWORD crc, charcnt;
    06846     BYTE  c;
    06847
    06848     crc = 0xFFFFFFFF;
    06849     charcnt = 0;
    06850
    06851     for (charcnt = 0 ; charcnt < length ; charcnt++)
    06852     {
    06853         c = buff[charcnt];
    06854         crc = crc_32_tab[(crc ^ c) & 0xff] ^ (crc >> 8);
    06855     }
    06856
    06857     return crc;
    06858 }
    06859
    06860 /***************************************************************************
    06861 *                           IsSRGBColorProfile
    06862 *
    06863 *  function: check if the profile is sRGB
    06864 *
    06865 *  parameters:
    06866 *       cp          --  Color Profile handle
    06867 *
    06868 *  returns:
    06869 *       BOOL        --  TRUE if the profile is sRGB
    06870 *                       FALSE otherwise.
    06871 ***************************************************************************/
    06872
    06873 BOOL IsSRGBColorProfile(
    06874     PBYTE pProfile
    06875     )
    06876 {
    06877     BOOL  bMatch = FALSE;
    06878     DWORD dwRedTRCIndex, dwGreenTRCIndex, dwBlueTRCIndex;
    06879     DWORD dwRedCIndex, dwGreenCIndex, dwBlueCIndex;
    06880     DWORD dwSize;
    06881     DWORD dwRedTRCSize=0, dwGreenTRCSize=0, dwBlueTRCSize=0;
    06882     DWORD dwRedCSize=0, dwGreenCSize=0, dwBlueCSize=0;
    06883     PBYTE pRed, pGreen, pBlue, pRedC, pGreenC, pBlueC;
    06884     BYTE  DataBuffer[ALIGN_DWORD(sRGB_TAGSIZE)];
    06885
    06886     if (DoesCPTagExist(pProfile, TAG_REDTRC, &dwRedTRCIndex)             &&
    06887         GetCPElementDataSize(pProfile, dwRedTRCIndex, &dwRedTRCSize)     &&
    06888
    06889         DoesCPTagExist(pProfile, TAG_GREENTRC, &dwGreenTRCIndex)         &&
    06890         GetCPElementDataSize(pProfile, dwGreenTRCIndex, &dwGreenTRCSize) &&
    06891
    06892         DoesCPTagExist(pProfile, TAG_BLUETRC, &dwBlueTRCIndex)           &&
    06893         GetCPElementDataSize(pProfile, dwBlueTRCIndex, &dwBlueTRCSize)   &&
    06894
    06895         DoesCPTagExist(pProfile, TAG_REDCOLORANT, &dwRedCIndex)          &&
    06896         GetCPElementDataSize(pProfile, dwRedCIndex, &dwRedCSize)         &&
    06897
    06898         DoesCPTagExist(pProfile, TAG_GREENCOLORANT, &dwGreenCIndex)      &&
    06899         GetCPElementDataSize(pProfile, dwGreenCIndex, &dwGreenCSize)     &&
    06900
    06901         DoesCPTagExist(pProfile, TAG_BLUECOLORANT, &dwBlueCIndex)        &&
    06902         GetCPElementDataSize(pProfile, dwBlueCIndex, &dwBlueCSize))
    06903     {
    06904         dwSize = dwRedTRCSize + dwGreenTRCSize + dwBlueTRCSize +
    06905                  dwRedCSize   + dwGreenCSize   + dwBlueCSize;
    06906
    06907         if (dwSize == sRGB_TAGSIZE)
    06908         {
    06909             ZeroMemory(DataBuffer,sizeof(DataBuffer));
    06910
    06911             pRed    = DataBuffer;
    06912             pGreen  = pRed    + dwRedTRCSize;
    06913             pBlue   = pGreen  + dwGreenTRCSize;
    06914             pRedC   = pBlue   + dwBlueTRCSize;
    06915             pGreenC = pRedC   + dwRedCSize;
    06916             pBlueC  = pGreenC + dwGreenCSize;
    06917
    06918             if (GetCPElementData(pProfile, dwRedTRCIndex, pRed, &dwRedTRCSize)       &&
    06919                 GetCPElementData(pProfile, dwGreenTRCIndex, pGreen, &dwGreenTRCSize) &&
    06920                 GetCPElementData(pProfile, dwBlueTRCIndex, pBlue, &dwBlueTRCSize)    &&
    06921                 GetCPElementData(pProfile, dwRedCIndex, pRedC, &dwRedCSize)          &&
    06922                 GetCPElementData(pProfile, dwGreenCIndex, pGreenC, &dwGreenCSize)    &&
    06923                 GetCPElementData(pProfile, dwBlueCIndex, pBlueC, &dwBlueCSize))
    06924             {
    06925                 bMatch = (crc32(DataBuffer, sRGB_TAGSIZE) == sRGB_CRC);
    06926             }
    06927         }
    06928     }
    06929
    06930     return (bMatch);
    06931 }
    06932
    06933
    06934
    06935