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

Generated on Sat May 15 19:41:31 2004 for test by doxygen 1.3.7