Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

6944 lines
196 KiB

  1. /****************************Module*Header******************************\
  2. * Module Name: PS2.C
  3. *
  4. * Module Descripton: Functions for retrieving or creating PostScript
  5. * Level 2 operators from a profile. It is shared by mscms & pscript5
  6. *
  7. * Warnings:
  8. *
  9. * Issues:
  10. *
  11. * Public Routines:
  12. *
  13. * Created: 13 May 1996
  14. * Author: Srinivasan Chandrasekar [srinivac]
  15. *
  16. * Copyright (c) 1996, 1997 Microsoft Corporation
  17. \***********************************************************************/
  18. #include <math.h>
  19. #define MAX_LINELEN 240
  20. #define REVCURVE_RATIO 1
  21. #define CIEXYZRange 0x1FFEC // 1.9997 in 16.16 notation
  22. #define ALIGN_DWORD(nBytes) (((nBytes) + 3) & ~3)
  23. #define FIX_16_16_SHIFT 16
  24. #define FIX_16_16_SCALE (1 << (FIX_16_16_SHIFT))
  25. #define TO_FIX(x) ((x) << FIX_16_16_SHIFT)
  26. #define TO_INT(x) ((x) >> FIX_16_16_SHIFT)
  27. #define FIX_MUL(x, y) MulDiv((x), (y), FIX_16_16_SCALE)
  28. #define FIX_DIV(x, y) MulDiv((x), FIX_16_16_SCALE, (y))
  29. #define FLOOR(x) ((x) >> FIX_16_16_SHIFT << FIX_16_16_SHIFT)
  30. #define TYPE_CIEBASEDDEF 1
  31. #define TYPE_CIEBASEDDEFG 2
  32. #define TAG_PS2CSA 'ps2s'
  33. #define TAG_REDCOLORANT 'rXYZ'
  34. #define TAG_GREENCOLORANT 'gXYZ'
  35. #define TAG_BLUECOLORANT 'bXYZ'
  36. #define TAG_REDTRC 'rTRC'
  37. #define TAG_GREENTRC 'gTRC'
  38. #define TAG_BLUETRC 'bTRC'
  39. #define TAG_GRAYTRC 'kTRC'
  40. #define TAG_MEDIAWHITEPOINT 'wtpt'
  41. #define TAG_AToB0 'A2B0'
  42. #define TAG_AToB1 'A2B1'
  43. #define TAG_AToB2 'A2B2'
  44. #define TAG_PS2INTENT0 'psi0'
  45. #define TAG_PS2INTENT1 'psi1'
  46. #define TAG_PS2INTENT2 'psi2'
  47. #define TAG_PS2INTENT3 'psi3'
  48. #define TAG_CRDINTENT0 'psd0'
  49. #define TAG_CRDINTENT1 'psd1'
  50. #define TAG_CRDINTENT2 'psd2'
  51. #define TAG_CRDINTENT3 'psd3'
  52. #define TAG_BToA0 'B2A0'
  53. #define TAG_BToA1 'B2A1'
  54. #define TAG_BToA2 'B2A2'
  55. #define TAG_BToA3 'B2A3'
  56. #define LUT8_TYPE 'mft1'
  57. #define LUT16_TYPE 'mft2'
  58. #define SIG_CURVE_TYPE 'curv'
  59. #define GetCPConnSpace(pProfile) (FIX_ENDIAN(((PPROFILEHEADER)pProfile)->phConnectionSpace))
  60. #define GetCPDevSpace(pProfile) (FIX_ENDIAN(((PPROFILEHEADER)pProfile)->phDataColorSpace))
  61. #define GetCPRenderIntent(pProfile) (FIX_ENDIAN(((PPROFILEHEADER)pProfile)->phRenderingIntent))
  62. #define WriteObject(pBuf, pStr) (STRCPY(pBuf, pStr), STRLEN(pStr))
  63. #ifdef KERNEL_MODE
  64. #define WriteInt(pBuf, i) OPSprintf(pBuf, "%l ", (i))
  65. #define WriteHex(pBuf, x) OPSprintf(pBuf, "%x", ((x) & 0x00FF))
  66. #define STRLEN strlen
  67. #define STRCPY strcpy
  68. #else
  69. #define WriteInt(pBuf, i) wsprintfA(pBuf, "%lu ", (i))
  70. #define WriteHex(pBuf, x) wsprintfA(pBuf, "%2.2x", ((x) & 0x00FF))
  71. #define STRLEN lstrlenA
  72. #define STRCPY lstrcpyA
  73. #endif
  74. #define MAXCHANNELS 4
  75. #define PREVIEWCRDGRID 16
  76. #define MAXCOLOR8 255
  77. #define DATATYPE_LUT 0
  78. #define DATATYPE_MATRIX 1
  79. #define sRGB_CRC 0xa3d777b4L
  80. #define sRGB_TAGSIZE 6168
  81. #define BRADFORD_TRANSFORM
  82. //
  83. // Local typedefs
  84. //
  85. typedef DWORD FIX_16_16, *PFIX_16_16;
  86. typedef struct tagCURVETYPE {
  87. DWORD dwSignature;
  88. DWORD dwReserved;
  89. DWORD nCount;
  90. WORD data[0];
  91. } CURVETYPE, *PCURVETYPE;
  92. typedef struct tagXYZTYPE {
  93. DWORD dwSignature;
  94. DWORD dwReserved;
  95. FIX_16_16 afxData[0];
  96. } XYZTYPE, *PXYZTYPE;
  97. typedef struct tagLUT8TYPE {
  98. DWORD dwSignature;
  99. DWORD dwReserved;
  100. BYTE nInputChannels;
  101. BYTE nOutputChannels;
  102. BYTE nClutPoints;
  103. BYTE padding;
  104. FIX_16_16 e00;
  105. FIX_16_16 e01;
  106. FIX_16_16 e02;
  107. FIX_16_16 e10;
  108. FIX_16_16 e11;
  109. FIX_16_16 e12;
  110. FIX_16_16 e20;
  111. FIX_16_16 e21;
  112. FIX_16_16 e22;
  113. BYTE data[0];
  114. } LUT8TYPE, *PLUT8TYPE;
  115. typedef struct tagLUT16TYPE {
  116. DWORD dwSignature;
  117. DWORD dwReserved;
  118. BYTE nInputChannels;
  119. BYTE nOutputChannels;
  120. BYTE nClutPoints;
  121. BYTE padding;
  122. FIX_16_16 e00;
  123. FIX_16_16 e01;
  124. FIX_16_16 e02;
  125. FIX_16_16 e10;
  126. FIX_16_16 e11;
  127. FIX_16_16 e12;
  128. FIX_16_16 e20;
  129. FIX_16_16 e21;
  130. FIX_16_16 e22;
  131. WORD wInputEntries;
  132. WORD wOutputEntries;
  133. WORD data[0];
  134. } LUT16TYPE, *PLUT16TYPE;
  135. typedef struct tagHOSTCLUT {
  136. WORD wSize;
  137. WORD wDataType;
  138. DWORD dwDev;
  139. DWORD dwPCS;
  140. DWORD dwIntent;
  141. FIX_16_16 afxIlluminantWP[3];
  142. FIX_16_16 afxMediaWP[3];
  143. BYTE nInputCh;
  144. BYTE nOutputCh;
  145. BYTE nClutPoints;
  146. BYTE nLutBits;
  147. FIX_16_16 e[9];
  148. WORD nInputEntries;
  149. WORD nOutputEntries;
  150. PBYTE inputArray[MAXCHANNELS];
  151. PBYTE outputArray[MAXCHANNELS];
  152. PBYTE clut;
  153. } HOSTCLUT, *PHOSTCLUT;
  154. //
  155. // Internal functions
  156. //
  157. BOOL IsSRGBColorProfile(PBYTE);
  158. BOOL GetCSAFromProfile (PBYTE, DWORD, DWORD, PBYTE, PDWORD, PBOOL);
  159. BOOL GetPS2CSA_MONO_A(PBYTE, PBYTE, PDWORD, DWORD, PBOOL);
  160. BOOL GetPS2CSA_ABC(PBYTE, PBYTE, PDWORD, DWORD, PBOOL, BOOL);
  161. BOOL GetPS2CSA_ABC_Lab(PBYTE, PBYTE, PDWORD, DWORD, PBOOL);
  162. BOOL GetPS2CSA_DEFG(PBYTE, PBYTE, PDWORD, DWORD, DWORD, PBOOL);
  163. BOOL CreateMonoCRD(PBYTE, DWORD, PBYTE, PDWORD, DWORD);
  164. BOOL CreateLutCRD(PBYTE, DWORD, PBYTE, PDWORD, DWORD, BOOL);
  165. BOOL DoesCPTagExist(PBYTE, DWORD, PDWORD);
  166. BOOL DoesTRCAndColorantTagExist(PBYTE);
  167. BOOL GetCPWhitePoint(PBYTE, PFIX_16_16);
  168. BOOL GetCPMediaWhitePoint(PBYTE, PFIX_16_16);
  169. BOOL GetCPElementDataSize(PBYTE, DWORD, PDWORD);
  170. BOOL GetCPElementSize(PBYTE, DWORD, PDWORD);
  171. BOOL GetCPElementDataType(PBYTE, DWORD, PDWORD);
  172. BOOL GetCPElementData(PBYTE, DWORD, PBYTE, PDWORD);
  173. BOOL GetTRCElementSize(PBYTE, DWORD, PDWORD, PDWORD);
  174. DWORD Ascii85Encode(PBYTE, DWORD, DWORD);
  175. BOOL GetCRDInputOutputArraySize(PBYTE, DWORD, PDWORD, PDWORD, PDWORD, PDWORD);
  176. BOOL GetHostCSA(PBYTE, PBYTE, PDWORD, DWORD, DWORD);
  177. BOOL GetHostColorRenderingDictionary(PBYTE, DWORD, PBYTE, PDWORD);
  178. BOOL GetHostColorSpaceArray(PBYTE, DWORD, PBYTE, PDWORD);
  179. DWORD SendCRDBWPoint(PBYTE, PFIX_16_16);
  180. DWORD SendCRDPQR(PBYTE, DWORD, PFIX_16_16);
  181. DWORD SendCRDLMN(PBYTE, DWORD, PFIX_16_16, PFIX_16_16, DWORD);
  182. DWORD SendCRDABC(PBYTE, PBYTE, DWORD, DWORD, PBYTE, PFIX_16_16, DWORD, BOOL);
  183. DWORD SendCRDOutputTable(PBYTE, PBYTE, DWORD, DWORD, BOOL, BOOL);
  184. DWORD SendCSABWPoint(PBYTE, DWORD, PFIX_16_16, PFIX_16_16);
  185. VOID GetMediaWP(PBYTE, DWORD, PFIX_16_16, PFIX_16_16);
  186. DWORD CreateCRDRevArray(PBYTE, PBYTE, PCURVETYPE, PWORD, DWORD, BOOL);
  187. DWORD SendCRDRevArray(PBYTE, PBYTE, PCURVETYPE, DWORD, BOOL);
  188. DWORD CreateColSpArray(PBYTE, PBYTE, DWORD, BOOL);
  189. DWORD CreateColSpProc(PBYTE, PBYTE, DWORD, BOOL);
  190. DWORD CreateFloatString(PBYTE, PBYTE, DWORD);
  191. DWORD CreateInputArray(PBYTE, DWORD, DWORD, PBYTE, DWORD, PBYTE, BOOL, PBYTE);
  192. DWORD CreateOutputArray(PBYTE, DWORD, DWORD, DWORD, PBYTE, DWORD, PBYTE, BOOL, PBYTE);
  193. DWORD GetPublicArrayName(DWORD, PBYTE);
  194. BOOL GetRevCurve(PCURVETYPE, PWORD, PWORD);
  195. VOID GetCLUTInfo(DWORD, PBYTE, PDWORD, PDWORD, PDWORD, PDWORD, PDWORD, PDWORD);
  196. DWORD EnableGlobalDict(PBYTE);
  197. DWORD BeginGlobalDict(PBYTE);
  198. DWORD EndGlobalDict(PBYTE);
  199. DWORD WriteNewLineObject(PBYTE, const char *);
  200. DWORD WriteHNAToken(PBYTE, BYTE, DWORD);
  201. DWORD WriteIntStringU2S(PBYTE, PBYTE, DWORD);
  202. DWORD WriteIntStringU2S_L(PBYTE, PBYTE, DWORD);
  203. DWORD WriteHexBuffer(PBYTE, PBYTE, PBYTE, DWORD);
  204. DWORD WriteStringToken(PBYTE, BYTE, DWORD);
  205. DWORD WriteByteString(PBYTE, PBYTE, DWORD);
  206. DWORD WriteInt2ByteString(PBYTE, PBYTE, DWORD);
  207. DWORD WriteFixed(PBYTE, FIX_16_16);
  208. DWORD WriteFixed2dot30(PBYTE, DWORD);
  209. #if !defined(KERNEL_MODE) || defined(USERMODE_DRIVER)
  210. DWORD WriteDouble(PBYTE, double);
  211. BOOL CreateMatrixCRD(PBYTE, PBYTE, PDWORD, DWORD, BOOL);
  212. DWORD CreateHostLutCRD(PBYTE, DWORD, PBYTE, DWORD);
  213. DWORD CreateHostMatrixCSAorCRD(PBYTE, PBYTE, PDWORD, DWORD, BOOL);
  214. DWORD CreateHostInputOutputArray(PBYTE, PBYTE*, DWORD, DWORD, DWORD, DWORD, PBYTE);
  215. DWORD CreateHostTRCInputTable(PBYTE, PHOSTCLUT, PCURVETYPE, PCURVETYPE, PCURVETYPE);
  216. DWORD CreateHostRevTRCInputTable(PBYTE, PHOSTCLUT, PCURVETYPE, PCURVETYPE, PCURVETYPE);
  217. BOOL CheckInputOutputTable(PHOSTCLUT, float*, BOOL, BOOL);
  218. BOOL CheckColorLookupTable(PHOSTCLUT, float*);
  219. BOOL DoHostConversionCSA(PHOSTCLUT, float*, float*);
  220. BOOL DoHostConversionCRD(PHOSTCLUT, PHOSTCLUT, float*, float*, BOOL);
  221. float g(float);
  222. float inverse_g(float);
  223. BOOL TableInterp3(PHOSTCLUT, float*);
  224. BOOL TableInterp4(PHOSTCLUT, float*);
  225. void LabToXYZ(float*, float*, PFIX_16_16);
  226. void XYZToLab(float*, float*, PFIX_16_16);
  227. VOID ApplyMatrix(FIX_16_16 *e, float *Input, float *Output);
  228. BOOL CreateColorantArray(PBYTE, double *, DWORD);
  229. BOOL InvertColorantArray(double *, double *);
  230. #endif
  231. DWORD crc32(PBYTE buff, DWORD length);
  232. //
  233. // Global variables
  234. //
  235. const char ASCII85DecodeBegin[] = "<~";
  236. const char ASCII85DecodeEnd[] = "~> cvx exec ";
  237. const char TestingDEFG[] = "/SupportDEFG? {/CIEBasedDEFG \
  238. /ColorSpaceFamily resourcestatus { pop pop languagelevel 3 ge}{false} ifelse} def";
  239. const char SupportDEFG_S[] = "SupportDEFG? { ";
  240. const char NotSupportDEFG_S[] = "SupportDEFG? not { ";
  241. const char SupportDEFG_E[] = "}if ";
  242. const char IndexArray16b[] = " dup length 1 sub 3 -1 roll mul dup dup floor cvi\
  243. exch ceiling cvi 3 index exch get 32768 add 4 -1 roll 3 -1 roll get 32768 add\
  244. dup 3 1 roll sub 3 -1 roll dup floor cvi sub mul add ";
  245. const char IndexArray[] = " dup length 1 sub 3 -1 roll mul dup dup floor cvi\
  246. exch ceiling cvi 3 index exch get 4 -1 roll 3 -1 roll get\
  247. dup 3 1 roll sub 3 -1 roll dup floor cvi sub mul add ";
  248. const char StartClip[] = "dup 1.0 le{dup 0.0 ge{" ;
  249. const char EndClip[] = "}if}if " ;
  250. const char BeginString[] = "<";
  251. const char EndString[] = ">";
  252. const char BeginArray[] = "[";
  253. const char EndArray[] = "]";
  254. const char BeginFunction[] = "{";
  255. const char EndFunction[] = "}bind ";
  256. const char BeginDict[] = "<<" ;
  257. const char EndDict[] = ">>" ;
  258. const char BlackPoint[] = "[0 0 0]" ;
  259. const char DictType[] = "/ColorRenderingType 1 ";
  260. const char IntentType[] = "/RenderingIntent ";
  261. const char IntentPer[] = "/Perceptual";
  262. const char IntentSat[] = "/Saturation";
  263. const char IntentACol[] = "/AbsoluteColorimetric";
  264. const char IntentRCol[] = "/RelativeColorimetric";
  265. const char WhitePointTag[] = "/WhitePoint " ;
  266. const char BlackPointTag[] = "/BlackPoint " ;
  267. const char RangePQRTag[] = "/RangePQR " ;
  268. const char TransformPQRTag[] = "/TransformPQR " ;
  269. const char MatrixPQRTag[] = "/MatrixPQR " ;
  270. const char RangePQR[] = "[ -0.07 2.2 -0.02 1.4 -0.2 4.8 ]";
  271. const char MatrixPQR[] = "[0.8951 -0.7502 0.0389 0.2664 1.7135 -0.0685 -0.1614 0.0367 1.0296]";
  272. #ifdef BRADFORD_TRANSFORM
  273. const char *TransformPQR[3] = {"exch pop exch 3 get mul exch pop exch 3 get div ",
  274. "exch pop exch 4 get mul exch pop exch 4 get div ",
  275. "exch pop exch 5 get mul exch pop exch 5 get div " };
  276. #else
  277. const char *TransformPQR[3] = {"4 index 0 get div 2 index 0 get mul 4 {exch pop} repeat ",
  278. "4 index 1 get div 2 index 1 get mul 4 {exch pop} repeat ",
  279. "4 index 2 get div 2 index 2 get mul 4 {exch pop} repeat " };
  280. #endif
  281. const char RangeABCTag[] = "/RangeABC " ;
  282. const char MatrixATag[] = "/MatrixA ";
  283. const char MatrixABCTag[] = "/MatrixABC ";
  284. const char EncodeABCTag[] = "/EncodeABC " ;
  285. const char RangeLMNTag[] = "/RangeLMN " ;
  286. const char MatrixLMNTag[] = "/MatrixLMN " ;
  287. const char EncodeLMNTag[] = "/EncodeLMN " ;
  288. const char RenderTableTag[] = "/RenderTable " ;
  289. const char CIEBasedATag[] = "/CIEBasedA " ;
  290. const char CIEBasedABCTag[] = "/CIEBasedABC " ;
  291. const char CIEBasedDEFGTag[] = "/CIEBasedDEFG " ;
  292. const char CIEBasedDEFTag[] = "/CIEBasedDEF " ;
  293. const char DecodeATag[] = "/DecodeA " ;
  294. const char DecodeABCTag[] = "/DecodeABC " ;
  295. const char DecodeLMNTag[] = "/DecodeLMN " ;
  296. const char DeviceRGBTag[] = "/DeviceRGB " ;
  297. const char DeviceCMYKTag[] = "/DeviceCMYK " ;
  298. const char DeviceGrayTag[] = "/DeviceGray " ;
  299. const char TableTag[] = "/Table " ;
  300. const char DecodeDEFGTag[] = "/DecodeDEFG " ;
  301. const char DecodeDEFTag[] = "/DecodeDEF " ;
  302. const char NullOp[] = "";
  303. const char DupOp[] = "dup ";
  304. const char UserDictOp[] = "userdict ";
  305. const char GlobalDictOp[] = "globaldict ";
  306. const char CurrentGlobalOp[] = "currentglobal ";
  307. const char SetGlobalOp[] = "setglobal ";
  308. const char DefOp[] = "def ";
  309. const char BeginOp[] = "begin ";
  310. const char EndOp[] = "end ";
  311. const char TrueOp[] = "true ";
  312. const char FalseOp[] = "false ";
  313. const char MulOp[] = "mul ";
  314. const char DivOp[] = "div ";
  315. const char NewLine[] = "\r\n" ;
  316. const char Slash[] = "/" ;
  317. const char Space[] = " " ;
  318. const char CRDBegin[] = "%** CRD Begin ";
  319. const char CRDEnd[] = "%** CRD End ";
  320. const char CieBasedDEFGBegin[] = "%** CieBasedDEFG CSA Begin ";
  321. const char CieBasedDEFBegin[] = "%** CieBasedDEF CSA Begin ";
  322. const char CieBasedABCBegin[] = "%** CieBasedABC CSA Begin ";
  323. const char CieBasedABegin[] = "%** CieBasedA CSA Begin ";
  324. const char CieBasedDEFGEnd[] = "%** CieBasedDEFG CSA End ";
  325. const char CieBasedDEFEnd[] = "%** CieBasedDEF CSA End ";
  326. const char CieBasedABCEnd[] = "%** CieBasedABC CSA End ";
  327. const char CieBasedAEnd[] = "%** CieBasedA CSA End ";
  328. const char RangeABC[] = "[ 0 1 0 1 0 1 ] ";
  329. const char RangeLMN[] = "[ 0 2 0 2 0 2 ] ";
  330. const char Identity[] = "[1 0 0 0 1 0 0 0 1]";
  331. const char RangeABC_Lab[] = "[0 100 -128 127 -128 127]";
  332. const char Clip01[] = "dup 1.0 ge{pop 1.0}{dup 0.0 lt{pop 0.0}if}ifelse " ;
  333. const char DecodeA3[] = "256 div exp ";
  334. const char DecodeA3Rev[] = "256 div 1.0 exch div exp ";
  335. const char DecodeABCArray[] = "DecodeABC_";
  336. const char InputArray[] = "Inp_";
  337. const char OutputArray[] = "Out_";
  338. const char Scale8[] = "255 div " ;
  339. const char Scale16[] = "65535 div " ;
  340. const char Scale16XYZ[] = "32768 div " ;
  341. const char TFunction8[] = "exch 255 mul round cvi get 255 div " ;
  342. const char TFunction8XYZ[] = "exch 255 mul round cvi get 128 div " ;
  343. const char MatrixABCLab[] = "[1 1 1 1 0 0 0 0 -1]" ;
  344. const char DecodeABCLab1[] = "[{16 add 116 div} bind {500 div} bind {200 div} bind]";
  345. const char DecodeALab[] = " 50 mul 16 add 116 div ";
  346. const char DecodeLMNLab[] = "dup 0.206897 ge{dup dup mul mul}{0.137931 sub 0.128419 mul} ifelse ";
  347. const char RangeLMNLab[] = "[0 1 0 1 0 1]" ;
  348. const char EncodeLMNLab[] = "dup 0.008856 le{7.787 mul 0.13793 add}{0.3333 exp}ifelse " ;
  349. const char MatrixABCLabCRD[] = "[0 500 0 116 -500 200 0 0 -200]" ;
  350. const char MatrixABCXYZCRD[] = "[0 1 0 1 0 0 0 0 1]" ;
  351. const char EncodeABCLab1[] = "16 sub 100 div " ;
  352. const char EncodeABCLab2[] = "128 add 255 div " ;
  353. const char *DecodeABCLab[] = {"50 mul 16 add 116 div ",
  354. "128 mul 128 sub 500 div",
  355. "128 mul 128 sub 200 div"};
  356. const char ColorSpace1[] = "/CIEBasedABC << /DecodeLMN ";
  357. const char ColorSpace3[] = " exp} bind ";
  358. const char ColorSpace5[] = "/WhitePoint [0.9642 1 0.8249] ";
  359. const char PreViewInArray[] = "IPV_";
  360. const char PreViewOutArray[] = "OPV_";
  361. const char sRGBColorSpaceArray[] = "[/CIEBasedABC << \r\n\
  362. /DecodeLMN [{dup 0.03928 le {12.92321 div}{0.055 add 1.055 div 2.4 exp}ifelse} bind dup dup ] \r\n\
  363. /MatrixLMN [0.412457 0.212673 0.019334 0.357576 0.715152 0.119192 0.180437 0.072175 0.950301] \r\n\
  364. /WhitePoint [ 0.9505 1 1.0890 ] >> ]";
  365. #ifdef BRADFORD_TRANSFORM
  366. const char sRGBColorRenderingDictionary[] = "\
  367. /RangePQR [ -0.5 2 -0.5 2 -0.5 2 ] \r\n\
  368. /MatrixPQR [0.8951 -0.7502 0.0389 0.2664 1.7135 -0.0685 -0.1614 0.0367 1.0296] \r\n\
  369. /TransformPQR [\
  370. {exch pop exch 3 get mul exch pop exch 3 get div} bind \
  371. {exch pop exch 4 get mul exch pop exch 4 get div} bind \
  372. {exch pop exch 5 get mul exch pop exch 5 get div} bind] \r\n\
  373. /MatrixLMN [3.240449 -0.969265 0.055643 -1.537136 1.876011 -0.204026 -0.498531 0.041556 1.057229] \r\n\
  374. /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\
  375. /WhitePoint[0.9505 1 1.0890] >>";
  376. #else
  377. const char sRGBColorRenderingDictionary[] = "\
  378. /RangePQR [ -0.5 2 -0.5 2 -0.5 2 ] \r\n\
  379. /MatrixPQR [0.8951 -0.7502 0.0389 0.2664 1.7135 -0.0685 -0.1614 0.0367 1.0296] \r\n\
  380. /TransformPQR [\
  381. {4 index 0 get div 2 index 0 get mul 4 {exch pop} repeat} \
  382. {4 index 1 get div 2 index 1 get mul 4 {exch pop} repeat} \
  383. {4 index 2 get div 2 index 2 get mul 4 {exch pop} repeat}] \r\n\
  384. /MatrixLMN [3.240449 -0.969265 0.055643 -1.537136 1.876011 -0.204026 -0.498531 0.041556 1.057229] \r\n\
  385. /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\
  386. /WhitePoint[0.9505 1 1.0890] >>";
  387. #endif
  388. /******************************************************************************
  389. *
  390. * InternalGetPS2ColorSpaceArray
  391. *
  392. * Function:
  393. * This functions retrieves the PostScript Level 2 CSA from the profile,
  394. * or creates it if the profile tag is not present
  395. *
  396. * Arguments:
  397. * hProfile - handle identifing the profile object
  398. * dwIntent - rendering intent of CSA
  399. * dwCSAType - type of CSA
  400. * pbuffer - pointer to receive the CSA
  401. * pcbSize - pointer to size of buffer. If function fails because
  402. * buffer is not big enough, it is filled with required size.
  403. * pcbBinary - TRUE if binary data is requested. On return it is set to
  404. * reflect the data returned
  405. *
  406. * Returns:
  407. * TRUE if successful, FALSE otherwise
  408. *
  409. ******************************************************************************/
  410. BOOL
  411. InternalGetPS2ColorSpaceArray (
  412. PBYTE pProfile,
  413. DWORD dwIntent,
  414. DWORD dwCSAType,
  415. PBYTE pBuffer,
  416. PDWORD pcbSize,
  417. LPBOOL pbBinary
  418. )
  419. {
  420. DWORD dwInpBufSize;
  421. BOOL bRc;
  422. //
  423. // If profile has a CSA tag, get it directly
  424. //
  425. bRc = GetCSAFromProfile(pProfile, dwIntent, dwCSAType, pBuffer,
  426. pcbSize, pbBinary);
  427. if (! bRc && (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
  428. {
  429. //
  430. // Create a CSA from the profile data
  431. //
  432. switch (dwCSAType)
  433. {
  434. case CSA_ABC:
  435. bRc = GetPS2CSA_ABC(pProfile, pBuffer, pcbSize,
  436. dwIntent, pbBinary, FALSE);
  437. break;
  438. case CSA_DEF:
  439. bRc = GetPS2CSA_DEFG(pProfile, pBuffer, pcbSize, dwIntent,
  440. TYPE_CIEBASEDDEF, pbBinary);
  441. break;
  442. case CSA_RGB:
  443. case CSA_Lab:
  444. dwInpBufSize = *pcbSize;
  445. //
  446. // We get a DEF CSA followed by an ABC CSA and set it up so that
  447. // on PS interpreters that do not support the DEF CSA, the ABC one
  448. // is active
  449. //
  450. bRc = GetPS2CSA_DEFG(pProfile, pBuffer, pcbSize, dwIntent,
  451. TYPE_CIEBASEDDEF, pbBinary);
  452. if (bRc)
  453. {
  454. //
  455. // Create CieBasedABC for printers that do not support CieBasedDEF
  456. //
  457. DWORD cbNewSize = 0;
  458. PBYTE pNewBuffer;
  459. PBYTE pOldBuffer;
  460. if (pBuffer)
  461. {
  462. pNewBuffer = pBuffer + *pcbSize;
  463. pOldBuffer = pNewBuffer;
  464. pNewBuffer += WriteObject(pNewBuffer, NewLine);
  465. if (dwCSAType == CSA_Lab)
  466. {
  467. pNewBuffer += WriteNewLineObject(pNewBuffer, NotSupportDEFG_S);
  468. }
  469. cbNewSize = dwInpBufSize - (DWORD)(pNewBuffer - pBuffer);
  470. }
  471. else
  472. {
  473. pNewBuffer = NULL;
  474. }
  475. bRc = GetPS2CSA_ABC(pProfile, pNewBuffer, &cbNewSize,
  476. dwIntent, pbBinary, TRUE);
  477. if (pBuffer)
  478. {
  479. pNewBuffer += cbNewSize;
  480. if (dwCSAType == CSA_Lab)
  481. {
  482. pNewBuffer += WriteNewLineObject(pNewBuffer, SupportDEFG_E);
  483. }
  484. *pcbSize += (DWORD) (pNewBuffer - pOldBuffer);
  485. }
  486. else
  487. {
  488. *pcbSize += cbNewSize;
  489. }
  490. }
  491. else
  492. {
  493. *pcbSize = dwInpBufSize;
  494. bRc = GetPS2CSA_ABC(pProfile, pBuffer, pcbSize, dwIntent, pbBinary, FALSE);
  495. }
  496. break;
  497. case CSA_CMYK:
  498. case CSA_DEFG:
  499. bRc = GetPS2CSA_DEFG(pProfile, pBuffer, pcbSize, dwIntent,
  500. TYPE_CIEBASEDDEFG, pbBinary);
  501. break;
  502. case CSA_GRAY:
  503. case CSA_A:
  504. bRc = GetPS2CSA_MONO_A(pProfile, pBuffer, pcbSize, dwIntent, pbBinary);
  505. break;
  506. default:
  507. WARNING((__TEXT("Invalid CSA type passed to GetPS2ColorSpaceArray: %d\n"), dwCSAType));
  508. SetLastError(ERROR_INVALID_PARAMETER);
  509. return FALSE;
  510. }
  511. }
  512. return bRc;
  513. }
  514. /******************************************************************************
  515. *
  516. * InternalGetPS2ColorRenderingIntent
  517. *
  518. * Function:
  519. * This functions retrieves the PostScript Level 2 color rendering intent
  520. * from the profile, or creates it if the profile tag is not present
  521. *
  522. * Arguments:
  523. * hProfile - handle identifing the profile object
  524. * pbuffer - pointer to receive the color rendering intent
  525. * pcbSize - pointer to size of buffer. If function fails because
  526. * buffer is not big enough, it is filled with required size.
  527. * pcbBinary - TRUE if binary data is requested. On return it is set to
  528. * reflect the data returned
  529. *
  530. * Returns:
  531. * TRUE if successful, FALSE otherwise
  532. *
  533. ******************************************************************************/
  534. BOOL
  535. InternalGetPS2ColorRenderingIntent(
  536. PBYTE pProfile,
  537. DWORD dwIntent,
  538. PBYTE pBuffer,
  539. PDWORD pcbSize
  540. )
  541. {
  542. DWORD dwIndex, dwTag, dwSize;
  543. BOOL bRc = FALSE;
  544. switch (dwIntent)
  545. {
  546. case INTENT_PERCEPTUAL:
  547. dwTag = TAG_PS2INTENT0;
  548. break;
  549. case INTENT_RELATIVE_COLORIMETRIC:
  550. dwTag = TAG_PS2INTENT1;
  551. break;
  552. case INTENT_SATURATION:
  553. dwTag = TAG_PS2INTENT2;
  554. break;
  555. case INTENT_ABSOLUTE_COLORIMETRIC:
  556. dwTag = TAG_PS2INTENT3;
  557. break;
  558. default:
  559. WARNING((__TEXT("Invalid intent passed to GetPS2ColorRenderingIntent: %d\n"), dwIntent));
  560. SetLastError(ERROR_INVALID_PARAMETER);
  561. return FALSE;
  562. }
  563. if (DoesCPTagExist(pProfile, dwTag, &dwIndex))
  564. {
  565. (void)GetCPElementDataSize(pProfile, dwIndex, &dwSize);
  566. if (pBuffer)
  567. {
  568. if (*pcbSize >= dwSize + 1) // for NULL terminating
  569. {
  570. bRc = GetCPElementData(pProfile, dwIndex, pBuffer, &dwSize);
  571. }
  572. else
  573. {
  574. WARNING((__TEXT("Buffer too small to get CRI\n")));
  575. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  576. }
  577. }
  578. else
  579. bRc = TRUE;
  580. *pcbSize = dwSize;
  581. }
  582. else
  583. {
  584. WARNING((__TEXT("psi tag not present for intent %d in profile\n"), dwIntent));
  585. SetLastError(ERROR_TAG_NOT_PRESENT);
  586. }
  587. //
  588. // NULL terminate
  589. //
  590. if (bRc)
  591. {
  592. if (pBuffer)
  593. {
  594. pBuffer[*pcbSize] = '\0';
  595. }
  596. (*pcbSize)++;
  597. }
  598. return bRc;
  599. }
  600. /******************************************************************************
  601. *
  602. * InternalGetPS2ColorRenderingDictionary
  603. *
  604. * Function:
  605. * This functions retrieves the PostScript Level 2 CRD from the profile,
  606. * or creates it if the profile tag is not preesnt
  607. *
  608. * Arguments:
  609. * hProfile - handle identifing the profile object
  610. * dwIntent - intent whose CRD is required
  611. * pbuffer - pointer to receive the CSA
  612. * pcbSize - pointer to size of buffer. If function fails because
  613. * buffer is not big enough, it is filled with required size.
  614. * pcbBinary - TRUE if binary data is requested. On return it is set to
  615. * reflect the data returned
  616. *
  617. * Returns:
  618. * TRUE if successful, FALSE otherwise
  619. *
  620. ******************************************************************************/
  621. BOOL
  622. InternalGetPS2ColorRenderingDictionary(
  623. PBYTE pProfile,
  624. DWORD dwIntent,
  625. PBYTE pBuffer,
  626. PDWORD pcbSize,
  627. PBOOL pbBinary
  628. )
  629. {
  630. DWORD dwIndex, dwSize, dwDataType;
  631. DWORD dwCRDTag, dwBToATag;
  632. BOOL bRc = FALSE;
  633. switch (dwIntent)
  634. {
  635. case INTENT_PERCEPTUAL:
  636. dwCRDTag = TAG_CRDINTENT0;
  637. dwBToATag = TAG_BToA0;
  638. break;
  639. case INTENT_RELATIVE_COLORIMETRIC:
  640. dwCRDTag = TAG_CRDINTENT1;
  641. dwBToATag = TAG_BToA1;
  642. break;
  643. case INTENT_SATURATION:
  644. dwCRDTag = TAG_CRDINTENT2;
  645. dwBToATag = TAG_BToA2;
  646. break;
  647. case INTENT_ABSOLUTE_COLORIMETRIC:
  648. dwCRDTag = TAG_CRDINTENT3;
  649. dwBToATag = TAG_BToA1;
  650. break;
  651. default:
  652. WARNING((__TEXT("Invalid intent passed to GetPS2ColorRenderingDictionary: %d\n"), dwIntent));
  653. SetLastError(ERROR_INVALID_PARAMETER);
  654. return bRc;
  655. }
  656. if (DoesCPTagExist(pProfile, dwCRDTag, &dwIndex))
  657. {
  658. (void)GetCPElementDataSize(pProfile, dwIndex, &dwSize);
  659. (void)GetCPElementDataType(pProfile, dwIndex, &dwDataType);
  660. if (! *pbBinary && dwDataType == 1)
  661. {
  662. //
  663. // Profile has binary data, user asked for ASCII, so we have to
  664. // ASCII 85 encode it
  665. //
  666. dwSize = dwSize * 5 / 4 + sizeof(ASCII85DecodeBegin) + sizeof(ASCII85DecodeEnd) + 2048;
  667. }
  668. if (pBuffer)
  669. {
  670. if (*pcbSize >= dwSize)
  671. {
  672. (void)GetCPElementData(pProfile, dwIndex, pBuffer, &dwSize);
  673. if (! *pbBinary && dwDataType == 1)
  674. {
  675. dwSize = Ascii85Encode(pBuffer, dwSize, *pcbSize);
  676. }
  677. bRc = TRUE;
  678. }
  679. else
  680. {
  681. WARNING((__TEXT("Buffer too small to get CRD\n")));
  682. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  683. }
  684. }
  685. else
  686. bRc = TRUE;
  687. *pcbSize = dwSize;
  688. }
  689. else if (DoesCPTagExist(pProfile, dwBToATag, &dwIndex))
  690. {
  691. bRc = CreateLutCRD(pProfile, dwIndex, pBuffer, pcbSize, dwIntent, *pbBinary);
  692. }
  693. else if (DoesCPTagExist(pProfile, TAG_GRAYTRC, &dwIndex))
  694. {
  695. bRc = CreateMonoCRD(pProfile, dwIndex, pBuffer, pcbSize, dwIntent);
  696. }
  697. #if !defined(KERNEL_MODE) || defined(USERMODE_DRIVER)
  698. else if (DoesTRCAndColorantTagExist(pProfile))
  699. {
  700. bRc = CreateMatrixCRD(pProfile, pBuffer, pcbSize, dwIntent, *pbBinary);
  701. }
  702. #endif // !defined(KERNEL_MODE) || defined(USERMODE_DRIVER)
  703. else
  704. {
  705. WARNING((__TEXT("Profile doesn't have tags to create CRD\n")));
  706. SetLastError(ERROR_INVALID_PROFILE);
  707. }
  708. return bRc;
  709. }
  710. #if !defined(KERNEL_MODE) || defined(USERMODE_DRIVER)
  711. /******************************************************************************
  712. *
  713. * InternalGetPS2PreviewCRD
  714. *
  715. * Function:
  716. * This functions creates a preview PostScript Level 2 CRD from the
  717. * specified destination and target profiles
  718. * To do this, it does the following:
  719. * 1) Creates host deviceCRD deviceCSA targetCRD.
  720. * 2) Creates proofing CRD by sampling deviceCRD deviceCSA and targetCRD.
  721. * 3) Uses deviceCRD's input table as proofingCRD's input table.
  722. * 4) Uses targetCRD's output table as proofingCRD's output table.
  723. * 5) Sample data is XYZ or Lab, depends on PCS of targetCRD.
  724. *
  725. * Arguments:
  726. * pDestProf - memory mapped pointer to destination profile
  727. * pTargetProf - memory mapped pointer to target profile
  728. * dwIntent - intent whose CRD is required
  729. * pbuffer - pointer to receive the CSA
  730. * pcbSize - pointer to size of buffer. If function fails because
  731. * buffer is not big enough, it is filled with required size.
  732. * pcbBinary - TRUE if binary data is requested. On return it is set to
  733. * reflect the data returned
  734. *
  735. * Returns:
  736. * TRUE if successful, FALSE otherwise
  737. *
  738. ******************************************************************************/
  739. BOOL
  740. InternalGetPS2PreviewCRD(
  741. PBYTE pDestProf,
  742. PBYTE pTargetProf,
  743. DWORD dwIntent,
  744. PBYTE pBuffer,
  745. PDWORD pcbSize,
  746. PBOOL pbBinary
  747. )
  748. {
  749. DWORD i, j, k, l, dwDev, dwTag, dwPCS;
  750. DWORD dwInArraySize = 0, dwOutArraySize = 0;
  751. DWORD nDevGrids, nTargetGrids, nPreviewCRDGrids;
  752. DWORD cbDevCRD, cbTargetCSA, cbTargetCRD;
  753. float fInput[MAXCHANNELS];
  754. float fOutput[MAXCHANNELS];
  755. float fTemp[MAXCHANNELS];
  756. PBYTE pLineStart, pStart = pBuffer;
  757. PBYTE lpDevCRD = NULL, lpTargetCSA = NULL, lpTargetCRD = NULL;
  758. char pPublicArrayName[5];
  759. BOOL bRc = FALSE;
  760. dwDev = GetCPDevSpace(pTargetProf);
  761. i = (dwDev == SPACE_CMYK) ? 4 : 3;
  762. //
  763. // Get the input array size IntentTag and Grid of the destination profile
  764. //
  765. if (!GetCRDInputOutputArraySize(
  766. pTargetProf,
  767. dwIntent,
  768. &dwInArraySize,
  769. NULL,
  770. &dwTag,
  771. &nTargetGrids))
  772. return FALSE;
  773. //
  774. // Get the output array size IntentTag and Grid of the target profile
  775. //
  776. if (!GetCRDInputOutputArraySize(
  777. pDestProf,
  778. dwIntent,
  779. NULL,
  780. &dwOutArraySize,
  781. &dwTag,
  782. &nDevGrids))
  783. return FALSE;
  784. nPreviewCRDGrids = (nTargetGrids > nDevGrids) ? nTargetGrids : nDevGrids;
  785. //
  786. // Min proofing CRD grid will be PREVIEWCRDGRID
  787. //
  788. if (nPreviewCRDGrids < PREVIEWCRDGRID)
  789. nPreviewCRDGrids = PREVIEWCRDGRID;
  790. if (pBuffer == NULL)
  791. {
  792. //
  793. // Return size of buffer needed
  794. //
  795. *pcbSize = nPreviewCRDGrids * nPreviewCRDGrids * nPreviewCRDGrids *
  796. i * 2 + // CLUT size (Hex output)
  797. dwOutArraySize + // Output Array size
  798. dwInArraySize + // Input Array size
  799. 4096; // Extra PostScript stuff
  800. //
  801. // Add space for new line.
  802. //
  803. *pcbSize += (((*pcbSize) / MAX_LINELEN) + 1) * STRLEN(NewLine);
  804. return TRUE;
  805. }
  806. //
  807. // Query the sizes of host target CRD, target CSA and device CRD
  808. //
  809. if (!GetHostColorRenderingDictionary(pTargetProf, dwIntent, NULL, &cbTargetCRD) ||
  810. !GetHostColorSpaceArray(pTargetProf, dwIntent, NULL, &cbTargetCSA) ||
  811. !GetHostColorRenderingDictionary(pDestProf, dwIntent, NULL, &cbDevCRD))
  812. {
  813. return FALSE;
  814. }
  815. //
  816. // Allocate buffers for host target CRD, target CSA and device CRD
  817. //
  818. if (((lpTargetCRD = MemAlloc(cbTargetCRD)) == NULL) ||
  819. ((lpTargetCSA = MemAlloc(cbTargetCSA)) == NULL) ||
  820. ((lpDevCRD = MemAlloc(cbDevCRD)) == NULL))
  821. {
  822. goto Done;
  823. }
  824. //
  825. // Build host target CRD, target CSA and device CRD
  826. //
  827. if (!GetHostColorRenderingDictionary(pTargetProf, dwIntent, lpTargetCRD, &cbTargetCRD) ||
  828. !GetHostColorSpaceArray(pTargetProf, dwIntent, lpTargetCSA, &cbTargetCSA) ||
  829. !GetHostColorRenderingDictionary(pDestProf, dwIntent, lpDevCRD, &cbDevCRD))
  830. {
  831. goto Done;
  832. }
  833. //
  834. // Create global data
  835. //
  836. GetPublicArrayName(dwTag, pPublicArrayName);
  837. //
  838. // Build Proofing CRD based on Host target CRD, target CSA and dest CRD.
  839. // We use target CRD input tables and matrix as the input tables and
  840. // matrix of the ProofCRD. We use dest CRD output tables as the
  841. // output tables of the ProofCRD.
  842. //
  843. pBuffer += WriteNewLineObject(pBuffer, CRDBegin);
  844. pBuffer += EnableGlobalDict(pBuffer);
  845. pBuffer += BeginGlobalDict(pBuffer);
  846. pBuffer += CreateInputArray(pBuffer, 0, 0, pPublicArrayName,
  847. 0, NULL, *pbBinary, lpTargetCRD);
  848. pBuffer += CreateOutputArray(pBuffer, 0, 0, 0,
  849. pPublicArrayName, 0, NULL, *pbBinary, lpDevCRD);
  850. pBuffer += EndGlobalDict(pBuffer);
  851. //
  852. // Start writing the CRD
  853. //
  854. pBuffer += WriteNewLineObject(pBuffer, BeginDict); // Begin dictionary
  855. pBuffer += WriteObject(pBuffer, DictType); // Dictionary type
  856. //
  857. // Send /RenderingIntent
  858. //
  859. switch (dwIntent)
  860. {
  861. case INTENT_PERCEPTUAL:
  862. pBuffer += WriteNewLineObject(pBuffer, IntentType);
  863. pBuffer += WriteObject(pBuffer, IntentPer);
  864. break;
  865. case INTENT_SATURATION:
  866. pBuffer += WriteNewLineObject(pBuffer, IntentType);
  867. pBuffer += WriteObject(pBuffer, IntentSat);
  868. break;
  869. case INTENT_RELATIVE_COLORIMETRIC:
  870. pBuffer += WriteNewLineObject(pBuffer, IntentType);
  871. pBuffer += WriteObject(pBuffer, IntentRCol);
  872. break;
  873. case INTENT_ABSOLUTE_COLORIMETRIC:
  874. pBuffer += WriteNewLineObject(pBuffer, IntentType);
  875. pBuffer += WriteObject(pBuffer, IntentACol);
  876. break;
  877. }
  878. //
  879. // /BlackPoint & /WhitePoint
  880. //
  881. pBuffer += SendCRDBWPoint(pBuffer, ((PHOSTCLUT)lpTargetCRD)->afxIlluminantWP);
  882. //
  883. // Send PQR - used for Absolute Colorimetric
  884. //
  885. pBuffer += SendCRDPQR(pBuffer, dwIntent, ((PHOSTCLUT)lpTargetCRD)->afxIlluminantWP);
  886. //
  887. // Send LMN - For Absolute Colorimetric use WhitePoint's XYZs
  888. //
  889. pBuffer += SendCRDLMN(pBuffer, dwIntent,
  890. ((PHOSTCLUT)lpTargetCRD)->afxIlluminantWP,
  891. ((PHOSTCLUT)lpTargetCRD)->afxMediaWP,
  892. ((PHOSTCLUT)lpTargetCRD)->dwPCS);
  893. //
  894. // Send ABC
  895. //
  896. pBuffer += SendCRDABC(pBuffer, pPublicArrayName,
  897. ((PHOSTCLUT)lpTargetCRD)->dwPCS,
  898. ((PHOSTCLUT)lpTargetCRD)->nInputCh,
  899. NULL,
  900. ((PHOSTCLUT)lpTargetCRD)->e,
  901. (((PHOSTCLUT)lpTargetCRD)->nLutBits == 8)? LUT8_TYPE : LUT16_TYPE,
  902. *pbBinary);
  903. //
  904. // /RenderTable
  905. //
  906. pBuffer += WriteNewLineObject(pBuffer, RenderTableTag);
  907. pBuffer += WriteObject(pBuffer, BeginArray);
  908. pBuffer += WriteInt(pBuffer, nPreviewCRDGrids); // Send down Na
  909. pBuffer += WriteInt(pBuffer, nPreviewCRDGrids); // Send down Nb
  910. pBuffer += WriteInt(pBuffer, nPreviewCRDGrids); // Send down Nc
  911. pLineStart = pBuffer;
  912. pBuffer += WriteNewLineObject(pBuffer, BeginArray);
  913. dwPCS = ((PHOSTCLUT)lpDevCRD)->dwPCS;
  914. for (i=0; i<nPreviewCRDGrids; i++) // Na strings should be sent
  915. {
  916. pBuffer += WriteObject(pBuffer, NewLine);
  917. pLineStart = pBuffer;
  918. if (*pbBinary)
  919. {
  920. pBuffer += WriteStringToken(pBuffer, 143,
  921. nPreviewCRDGrids * nPreviewCRDGrids * ((PHOSTCLUT)lpDevCRD)->nOutputCh);
  922. }
  923. else
  924. {
  925. pBuffer += WriteObject(pBuffer, BeginString);
  926. }
  927. fInput[0] = ((float)i) / (nPreviewCRDGrids - 1);
  928. for (j=0; j<nPreviewCRDGrids; j++)
  929. {
  930. fInput[1] = ((float)j) / (nPreviewCRDGrids - 1);
  931. for (k=0; k<nPreviewCRDGrids; k++)
  932. {
  933. fInput[2] = ((float)k) / (nPreviewCRDGrids - 1);
  934. DoHostConversionCRD((PHOSTCLUT)lpTargetCRD, NULL, fInput, fOutput, 1);
  935. DoHostConversionCSA((PHOSTCLUT)lpTargetCSA, fOutput, fTemp);
  936. DoHostConversionCRD((PHOSTCLUT)lpDevCRD, (PHOSTCLUT)lpTargetCSA,
  937. fTemp, fOutput, 0);
  938. for (l=0; l<((PHOSTCLUT)lpDevCRD)->nOutputCh; l++)
  939. {
  940. if (*pbBinary)
  941. {
  942. *pBuffer++ = (BYTE)(fOutput[l] * 255);
  943. }
  944. else
  945. {
  946. pBuffer += WriteHex(pBuffer, (USHORT)(fOutput[l] * 255));
  947. if ((pBuffer - pLineStart) > MAX_LINELEN)
  948. {
  949. pLineStart = pBuffer;
  950. pBuffer += WriteObject(pBuffer, NewLine);
  951. }
  952. }
  953. }
  954. }
  955. }
  956. if (!*pbBinary)
  957. pBuffer += WriteObject(pBuffer, EndString);
  958. }
  959. pBuffer += WriteNewLineObject(pBuffer, EndArray);
  960. pBuffer += WriteInt(pBuffer, ((PHOSTCLUT)lpDevCRD)->nOutputCh);
  961. //
  962. // Send output table
  963. //
  964. pBuffer += SendCRDOutputTable(pBuffer, pPublicArrayName,
  965. ((PHOSTCLUT)lpDevCRD)->nOutputCh,
  966. (((PHOSTCLUT)lpDevCRD)->nLutBits == 8)? LUT8_TYPE : LUT16_TYPE,
  967. TRUE,
  968. *pbBinary);
  969. pBuffer += WriteNewLineObject(pBuffer, EndArray);
  970. pBuffer += WriteObject(pBuffer, EndDict); // End dictionary definition
  971. pBuffer += WriteNewLineObject(pBuffer, CRDEnd);
  972. bRc = TRUE;
  973. Done:
  974. *pcbSize = (DWORD)(pBuffer - pStart);
  975. if (lpTargetCRD)
  976. MemFree(lpTargetCRD);
  977. if (lpTargetCSA)
  978. MemFree(lpTargetCSA);
  979. if (lpDevCRD)
  980. MemFree(lpDevCRD);
  981. return bRc;
  982. }
  983. #endif // !defined(KERNEL_MODE) || defined(USERMODE_DRIVER)
  984. /******************************************************************************
  985. *
  986. * GetCSAFromProfile
  987. *
  988. * Function:
  989. * This function gets the Color Space Array from the profile if the
  990. * tag is present
  991. *
  992. * Arguments:
  993. * pProfile - pointer to the memory mapped profile
  994. * dwIntent - rendering intent of CSA requested
  995. * dwCSAType - type of CSA requested
  996. * pBuffer - pointer to receive the CSA
  997. * pcbSize - pointer to size of buffer. If function fails because
  998. * buffer is not big enough, it is filled with required size.
  999. * pcbBinary - TRUE if binary data is requested. On return it is set to
  1000. * reflect the data returned
  1001. *
  1002. * Returns:
  1003. * TRUE if successful, FALSE otherwise
  1004. *
  1005. ******************************************************************************/
  1006. BOOL
  1007. GetCSAFromProfile (
  1008. PBYTE pProfile,
  1009. DWORD dwIntent,
  1010. DWORD dwCSAType,
  1011. PBYTE pBuffer,
  1012. PDWORD pcbSize,
  1013. PBOOL pbBinary
  1014. )
  1015. {
  1016. DWORD dwDev, dwProfileIntent;
  1017. DWORD dwIndex, dwSize, dwDataType;
  1018. BOOL bRc = FALSE;
  1019. //
  1020. // This function can fail without setting an error, so reset error
  1021. // here to prevent confusion later
  1022. //
  1023. SetLastError(0);
  1024. //
  1025. // Get the profile's color space and rendering intent
  1026. //
  1027. dwDev = GetCPDevSpace(pProfile);
  1028. dwProfileIntent = GetCPRenderIntent(pProfile);
  1029. //
  1030. // If the rendering intents don't match, or the profile's color space
  1031. // is incompatible with requested CSA type, fail
  1032. //
  1033. if ((dwIntent != dwProfileIntent) ||
  1034. ((dwDev == SPACE_GRAY) &&
  1035. ((dwCSAType != CSA_GRAY) && (dwCSAType != CSA_A))))
  1036. {
  1037. WARNING((__TEXT("Can't use profile's CSA tag due to different rendering intents\n")));
  1038. return FALSE;
  1039. }
  1040. if (DoesCPTagExist(pProfile, TAG_PS2CSA, &dwIndex))
  1041. {
  1042. (void)GetCPElementDataSize(pProfile, dwIndex, &dwSize);
  1043. (void)GetCPElementDataType(pProfile, dwIndex, &dwDataType);
  1044. if (! *pbBinary && dwDataType == 1)
  1045. {
  1046. //
  1047. // Profile has binary data, user asked for ASCII, so we have to
  1048. // ASCII 85 encode it
  1049. //
  1050. dwSize = dwSize * 5 / 4 + sizeof(ASCII85DecodeBegin) + sizeof(ASCII85DecodeEnd) + 2048;
  1051. }
  1052. if (pBuffer)
  1053. {
  1054. if (*pcbSize >= dwSize)
  1055. {
  1056. (void)GetCPElementData(pProfile, dwIndex, pBuffer, &dwSize);
  1057. if (! *pbBinary && dwDataType == 1)
  1058. {
  1059. dwSize = Ascii85Encode(pBuffer, dwSize, *pcbSize);
  1060. }
  1061. bRc = TRUE;
  1062. }
  1063. else
  1064. {
  1065. WARNING((__TEXT("Buffer too small to get CSA\n")));
  1066. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  1067. }
  1068. }
  1069. else
  1070. bRc = TRUE;
  1071. *pcbSize = dwSize;
  1072. }
  1073. return bRc;
  1074. }
  1075. /******************************************************************************
  1076. *
  1077. * GetPS2CSA_MONO_A
  1078. *
  1079. * Function:
  1080. * This function creates a CIEBasedA colorspace array from an input
  1081. * GRAY profile
  1082. *
  1083. * Arguments:
  1084. * pProfile - pointer to the memory mapped profile
  1085. * pBuffer - pointer to receive the CSA
  1086. * pcbSize - pointer to size of buffer. If function fails because
  1087. * buffer is not big enough, it is filled with required size.
  1088. * dwIntent - rendering intent of CSA requested
  1089. * pcbBinary - TRUE if binary data is requested. On return it is set to
  1090. * reflect the data returned
  1091. *
  1092. * Returns:
  1093. * TRUE if successful, FALSE otherwise
  1094. *
  1095. ******************************************************************************/
  1096. BOOL
  1097. GetPS2CSA_MONO_A(
  1098. PBYTE pProfile,
  1099. PBYTE pBuffer,
  1100. PDWORD pcbSize,
  1101. DWORD dwIntent,
  1102. PBOOL pbBinary
  1103. )
  1104. {
  1105. PCURVETYPE pData;
  1106. PTAGDATA pTagData;
  1107. PBYTE pLineStart, pStart = pBuffer;
  1108. PBYTE pTable;
  1109. DWORD i, dwPCS, nCount;
  1110. DWORD dwIndex, dwSize;
  1111. DWORD afxIlluminantWP[3];
  1112. DWORD afxMediaWP[3];
  1113. //
  1114. // Check if we can generate the CSA
  1115. // Required tag is gray TRC
  1116. //
  1117. if (! DoesCPTagExist(pProfile, TAG_GRAYTRC, &dwIndex))
  1118. {
  1119. WARNING((__TEXT("Gray TRC tag not present to create MONO_A CSA\n")));
  1120. SetLastError(ERROR_TAG_NOT_PRESENT);
  1121. return FALSE;
  1122. }
  1123. dwPCS = GetCPConnSpace(pProfile);
  1124. (void)GetCPElementSize(pProfile, dwIndex, &dwSize);
  1125. pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
  1126. dwIndex * sizeof(TAGDATA));
  1127. pData = (PCURVETYPE)(pProfile + FIX_ENDIAN(pTagData->dwOffset));
  1128. nCount = FIX_ENDIAN(pData->nCount);
  1129. //
  1130. // Estimate size required to hold the CSA
  1131. //
  1132. dwSize = nCount * 6 + // Number of INT elements
  1133. 3 * (STRLEN(IndexArray) +
  1134. STRLEN(StartClip) +
  1135. STRLEN(EndClip)) +
  1136. 2048; // + other PS stuff
  1137. //
  1138. // Add space for new line.
  1139. //
  1140. dwSize += (((dwSize) / MAX_LINELEN) + 1) * STRLEN(NewLine);
  1141. if (! pBuffer)
  1142. {
  1143. *pcbSize = dwSize;
  1144. return TRUE;
  1145. }
  1146. else if (*pcbSize < dwSize)
  1147. {
  1148. WARNING((__TEXT("Buffer too small to get MONO_A CSA\n")));
  1149. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  1150. return FALSE;
  1151. }
  1152. //
  1153. // Get info about Illuminant White Point from the header
  1154. //
  1155. (void)GetCPWhitePoint(pProfile, afxIlluminantWP);
  1156. //
  1157. // Support absolute whitePoint
  1158. //
  1159. (void)GetMediaWP(pProfile, dwIntent, afxIlluminantWP, afxMediaWP);
  1160. //
  1161. // Start creating the ColorSpace
  1162. //
  1163. pBuffer += WriteNewLineObject(pBuffer, CieBasedABegin);
  1164. pBuffer += WriteNewLineObject(pBuffer, BeginArray); // Begin array
  1165. //
  1166. // /CIEBasedA
  1167. //
  1168. pBuffer += WriteObject(pBuffer, CIEBasedATag); // Create entry
  1169. pBuffer += WriteObject(pBuffer, BeginDict); // Begin dictionary
  1170. //
  1171. // Send /BlackPoint & /WhitePoint
  1172. //
  1173. pBuffer += SendCSABWPoint(pBuffer, dwIntent, afxIlluminantWP, afxMediaWP);
  1174. //
  1175. // /DecodeA
  1176. //
  1177. pBuffer += WriteObject(pBuffer, NewLine);
  1178. pLineStart = pBuffer;
  1179. if (nCount != 0)
  1180. {
  1181. pBuffer += WriteObject(pBuffer, DecodeATag);
  1182. pBuffer += WriteObject(pBuffer, BeginArray);
  1183. pBuffer += WriteObject(pBuffer, BeginFunction);
  1184. pTable = (PBYTE)(pData->data);
  1185. if (nCount == 1) // Gamma supplied in ui16 format
  1186. {
  1187. pBuffer += WriteInt(pBuffer, FIX_ENDIAN16(*((PWORD)pTable)));
  1188. pBuffer += WriteObject(pBuffer, DecodeA3);
  1189. //
  1190. // If the PCS is Lab, we need to convert Lab to XYZ
  1191. // Now, the range is from 0 --> 0.99997.
  1192. // Actually, the conversion from Lab to XYZ is not needed
  1193. //
  1194. if (dwPCS == SPACE_Lab)
  1195. {
  1196. pBuffer += WriteObject(pBuffer, DecodeALab);
  1197. pBuffer += WriteObject(pBuffer, DecodeLMNLab);
  1198. }
  1199. }
  1200. else
  1201. {
  1202. pBuffer += WriteObject(pBuffer, StartClip);
  1203. pBuffer += WriteObject(pBuffer, BeginArray);
  1204. for (i=0; i<nCount; i++)
  1205. {
  1206. pBuffer += WriteInt(pBuffer, FIX_ENDIAN16(*((PWORD)pTable)));
  1207. pTable += sizeof(WORD);
  1208. if (((DWORD) (pBuffer - pLineStart)) > MAX_LINELEN)
  1209. {
  1210. pLineStart = pBuffer;
  1211. pBuffer += WriteObject (pBuffer, NewLine);
  1212. }
  1213. }
  1214. pBuffer += WriteObject(pBuffer, EndArray);
  1215. pLineStart = pBuffer;
  1216. pBuffer += WriteObject(pBuffer, NewLine);
  1217. pBuffer += WriteObject(pBuffer, IndexArray);
  1218. pBuffer += WriteObject(pBuffer, Scale16);
  1219. //
  1220. // If the PCS is Lab, we need to convert Lab to XYZ
  1221. // Now, the range is from 0 --> .99997.
  1222. // Actually, the conversion from Lab to XYZ is not needed.
  1223. //
  1224. if (dwPCS == SPACE_Lab)
  1225. {
  1226. pBuffer += WriteObject(pBuffer, DecodeALab);
  1227. pBuffer += WriteObject(pBuffer, DecodeLMNLab);
  1228. }
  1229. pBuffer += WriteObject(pBuffer, EndClip);
  1230. }
  1231. pBuffer += WriteObject(pBuffer, EndFunction);
  1232. pBuffer += WriteObject(pBuffer, EndArray);
  1233. }
  1234. //
  1235. // /MatrixA
  1236. //
  1237. pBuffer += WriteNewLineObject(pBuffer, MatrixATag);
  1238. pBuffer += WriteObject(pBuffer, BeginArray);
  1239. for (i=0; i<3; i++)
  1240. {
  1241. if (dwIntent == INTENT_ABSOLUTE_COLORIMETRIC)
  1242. {
  1243. pBuffer += WriteFixed(pBuffer, afxMediaWP[i]);
  1244. }
  1245. else
  1246. {
  1247. pBuffer += WriteFixed(pBuffer, afxIlluminantWP[i]);
  1248. }
  1249. }
  1250. pBuffer += WriteObject(pBuffer, EndArray);
  1251. //
  1252. // /RangeLMN
  1253. //
  1254. pBuffer += WriteNewLineObject(pBuffer, RangeLMNTag);
  1255. pBuffer += WriteObject(pBuffer, RangeLMN);
  1256. //
  1257. // /End dictionary
  1258. //
  1259. pBuffer += WriteObject(pBuffer, EndDict); // End dictionary definition
  1260. pBuffer += WriteObject(pBuffer, EndArray);
  1261. pBuffer += WriteNewLineObject(pBuffer, CieBasedAEnd);
  1262. *pcbSize = (DWORD) (pBuffer - pStart);
  1263. return TRUE;
  1264. }
  1265. /******************************************************************************
  1266. *
  1267. * GetPS2CSA_ABC
  1268. *
  1269. * Function:
  1270. * This function creates a CIEBasedABC colorspace array from an input
  1271. * RGB profile
  1272. *
  1273. * Arguments:
  1274. * pProfile - pointer to the memory mapped profile
  1275. * pBuffer - pointer to receive the CSA
  1276. * pcbSize - pointer to size of buffer. If function fails because
  1277. * buffer is not big enough, it is filled with required size.
  1278. * dwIntent - rendering intent of CSA requested
  1279. * pcbBinary - TRUE if binary data is requested. On return it is set to
  1280. * reflect the data returned
  1281. * bBackup - TRUE: A CIEBasedDEF has been created, this CSA is a backup
  1282. * in case some old printer can not support CIEBasedDEF.
  1283. * FALSE: No CIEBasedDEF. This is the only CSA.
  1284. *
  1285. * Returns:
  1286. * TRUE if successful, FALSE otherwise
  1287. *
  1288. ******************************************************************************/
  1289. BOOL
  1290. GetPS2CSA_ABC(
  1291. PBYTE pProfile,
  1292. PBYTE pBuffer,
  1293. PDWORD pcbSize,
  1294. DWORD dwIntent,
  1295. PBOOL pbBinary,
  1296. BOOL bBackup
  1297. )
  1298. {
  1299. PBYTE pStart = pBuffer;
  1300. DWORD i, dwPCS, dwDev, dwSize;
  1301. FIX_16_16 afxIlluminantWP[3];
  1302. FIX_16_16 afxMediaWP[3];
  1303. //
  1304. // Check if we can generate the CSA:
  1305. // Required tags are red, green and blue Colorants & TRCs
  1306. //
  1307. dwPCS = GetCPConnSpace(pProfile);
  1308. dwDev = GetCPDevSpace(pProfile);
  1309. //
  1310. // Call another function to handle Lab profiles
  1311. //
  1312. if (dwDev == SPACE_Lab)
  1313. {
  1314. return GetPS2CSA_ABC_Lab(pProfile, pBuffer, pcbSize, dwIntent, pbBinary);
  1315. }
  1316. //
  1317. // We only handle RGB profiles in this function
  1318. //
  1319. if ((dwDev != SPACE_RGB) ||
  1320. !DoesTRCAndColorantTagExist(pProfile))
  1321. {
  1322. WARNING((__TEXT("Colorant or TRC tag not present to create ABC CSA\n")));
  1323. SetLastError(ERROR_TAG_NOT_PRESENT);
  1324. return FALSE;
  1325. }
  1326. //
  1327. // Estimate size required to hold the CSA
  1328. //
  1329. dwSize = 65530;
  1330. if (! pBuffer)
  1331. {
  1332. *pcbSize = dwSize;
  1333. return TRUE;
  1334. }
  1335. else if (*pcbSize < dwSize)
  1336. {
  1337. WARNING((__TEXT("Buffer too small to get ABC CSA\n")));
  1338. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  1339. return FALSE;
  1340. }
  1341. //
  1342. // Get info about Illuminant White Point from the header
  1343. //
  1344. (void)GetCPWhitePoint(pProfile, afxIlluminantWP);
  1345. //
  1346. // Support absolute whitePoint
  1347. //
  1348. (void)GetMediaWP(pProfile, dwIntent, afxIlluminantWP, afxMediaWP);
  1349. //
  1350. // Create global data
  1351. //
  1352. pBuffer += WriteNewLineObject(pBuffer, CieBasedABCBegin);
  1353. if (IsSRGBColorProfile(pProfile))
  1354. {
  1355. pBuffer += WriteNewLineObject(pBuffer, sRGBColorSpaceArray);
  1356. }
  1357. else
  1358. {
  1359. pBuffer += EnableGlobalDict(pBuffer);
  1360. if (bBackup)
  1361. {
  1362. pBuffer += WriteNewLineObject(pBuffer, NotSupportDEFG_S);
  1363. }
  1364. pBuffer += BeginGlobalDict(pBuffer);
  1365. pBuffer += CreateColSpArray(pProfile, pBuffer, TAG_REDTRC, *pbBinary);
  1366. pBuffer += CreateColSpArray(pProfile, pBuffer, TAG_GREENTRC, *pbBinary);
  1367. pBuffer += CreateColSpArray(pProfile, pBuffer, TAG_BLUETRC, *pbBinary);
  1368. pBuffer += WriteNewLineObject(pBuffer, EndOp);
  1369. if (bBackup)
  1370. {
  1371. pBuffer += WriteNewLineObject(pBuffer, SupportDEFG_E);
  1372. }
  1373. pBuffer += WriteNewLineObject(pBuffer, SetGlobalOp);
  1374. if (bBackup)
  1375. {
  1376. pBuffer += WriteNewLineObject(pBuffer, NotSupportDEFG_S);
  1377. }
  1378. //
  1379. // Start creating the ColorSpace
  1380. //
  1381. pBuffer += WriteNewLineObject(pBuffer, BeginArray); // Begin array
  1382. //
  1383. // /CIEBasedABC
  1384. //
  1385. pBuffer += WriteObject(pBuffer, CIEBasedABCTag); // Create entry
  1386. pBuffer += WriteObject(pBuffer, BeginDict); // Begin dictionary
  1387. //
  1388. // /BlackPoint & /WhitePoint
  1389. //
  1390. pBuffer += SendCSABWPoint(pBuffer, dwIntent, afxIlluminantWP, afxMediaWP);
  1391. //
  1392. // /DecodeABC
  1393. //
  1394. pBuffer += WriteNewLineObject(pBuffer, DecodeABCTag);
  1395. pBuffer += WriteObject(pBuffer, BeginArray);
  1396. pBuffer += WriteObject(pBuffer, NewLine);
  1397. pBuffer += CreateColSpProc(pProfile, pBuffer, TAG_REDTRC, *pbBinary);
  1398. pBuffer += WriteObject(pBuffer, NewLine);
  1399. pBuffer += CreateColSpProc(pProfile, pBuffer, TAG_GREENTRC, *pbBinary);
  1400. pBuffer += WriteObject(pBuffer, NewLine);
  1401. pBuffer += CreateColSpProc(pProfile, pBuffer, TAG_BLUETRC, *pbBinary);
  1402. pBuffer += WriteObject(pBuffer, EndArray);
  1403. //
  1404. // /MatrixABC
  1405. //
  1406. pBuffer += WriteNewLineObject(pBuffer, MatrixABCTag);
  1407. pBuffer += WriteObject(pBuffer, BeginArray);
  1408. pBuffer += CreateFloatString(pProfile, pBuffer, TAG_REDCOLORANT);
  1409. pBuffer += CreateFloatString(pProfile, pBuffer, TAG_GREENCOLORANT);
  1410. pBuffer += CreateFloatString(pProfile, pBuffer, TAG_BLUECOLORANT);
  1411. pBuffer += WriteObject(pBuffer, EndArray);
  1412. //
  1413. // /RangeLMN
  1414. //
  1415. pBuffer += WriteObject(pBuffer, NewLine);
  1416. pBuffer += WriteObject(pBuffer, RangeLMNTag);
  1417. pBuffer += WriteObject(pBuffer, RangeLMN);
  1418. //
  1419. // /DecodeLMN
  1420. //
  1421. if (dwIntent == INTENT_ABSOLUTE_COLORIMETRIC)
  1422. {
  1423. //
  1424. // Support absolute whitePoint
  1425. //
  1426. pBuffer += WriteNewLineObject(pBuffer, DecodeLMNTag);
  1427. pBuffer += WriteObject(pBuffer, BeginArray);
  1428. for (i=0; i<3; i++)
  1429. {
  1430. pBuffer += WriteObject(pBuffer, BeginFunction);
  1431. pBuffer += WriteFixed(pBuffer, FIX_DIV(afxMediaWP[i], afxIlluminantWP[i]));
  1432. pBuffer += WriteObject(pBuffer, MulOp);
  1433. pBuffer += WriteObject(pBuffer, EndFunction);
  1434. }
  1435. pBuffer += WriteObject (pBuffer, EndArray);
  1436. }
  1437. //
  1438. // End dictionary definition
  1439. //
  1440. pBuffer += WriteNewLineObject(pBuffer, EndDict);
  1441. pBuffer += WriteObject(pBuffer, EndArray);
  1442. pBuffer += WriteNewLineObject(pBuffer, CieBasedABCEnd);
  1443. }
  1444. *pcbSize = (DWORD) (pBuffer - pStart);
  1445. return TRUE;
  1446. }
  1447. /******************************************************************************
  1448. *
  1449. * GetPS2CSA_ABC_Lab
  1450. *
  1451. * Function:
  1452. * This function creates a CIEBasedABC colorspace array from an input
  1453. * Lab profile
  1454. *
  1455. * Arguments:
  1456. * pProfile - pointer to the memory mapped profile
  1457. * pBuffer - pointer to receive the CSA
  1458. * pcbSize - pointer to size of buffer. If function fails because
  1459. * buffer is not big enough, it is filled with required size.
  1460. * dwIntent - rendering intent of CSA requested
  1461. * pcbBinary - TRUE if binary data is requested. On return it is set to
  1462. * reflect the data returned
  1463. *
  1464. * Returns:
  1465. * TRUE if successful, FALSE otherwise
  1466. *
  1467. ******************************************************************************/
  1468. BOOL
  1469. GetPS2CSA_ABC_Lab(
  1470. PBYTE pProfile,
  1471. PBYTE pBuffer,
  1472. PDWORD pcbSize,
  1473. DWORD dwIntent,
  1474. PBOOL pbBinary
  1475. )
  1476. {
  1477. PBYTE pStart = pBuffer;
  1478. DWORD i, dwSize;
  1479. FIX_16_16 afxIlluminantWP[3];
  1480. FIX_16_16 afxMediaWP[3];
  1481. //
  1482. // Estimate size required to hold the CSA
  1483. //
  1484. dwSize = 65530;
  1485. if (! pBuffer)
  1486. {
  1487. *pcbSize = dwSize;
  1488. return TRUE;
  1489. }
  1490. else if (*pcbSize < dwSize)
  1491. {
  1492. WARNING((__TEXT("Buffer too small to get ABC_Lab CSA\n")));
  1493. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  1494. return FALSE;
  1495. }
  1496. //
  1497. // Get info about Illuminant White Point from the header
  1498. //
  1499. (void)GetCPWhitePoint(pProfile, afxIlluminantWP);
  1500. //
  1501. // Support absolute whitePoint
  1502. //
  1503. GetMediaWP(pProfile, dwIntent, afxIlluminantWP, afxMediaWP);
  1504. //
  1505. // Start creating the ColorSpace
  1506. //
  1507. pBuffer += WriteNewLineObject(pBuffer, BeginArray); // Begin array
  1508. //
  1509. // /CIEBasedABC
  1510. //
  1511. pBuffer += WriteObject(pBuffer, CIEBasedABCTag); // Create entry
  1512. pBuffer += WriteObject(pBuffer, BeginDict); // Begin dictionary
  1513. //
  1514. // /BlackPoint & /WhitePoint
  1515. //
  1516. pBuffer += SendCSABWPoint(pBuffer, dwIntent, afxIlluminantWP, afxMediaWP);
  1517. //
  1518. // /RangeABC
  1519. //
  1520. pBuffer += WriteNewLineObject(pBuffer, RangeABCTag);
  1521. pBuffer += WriteObject(pBuffer, RangeABC_Lab);
  1522. //
  1523. // /DecodeABC
  1524. //
  1525. pBuffer += WriteNewLineObject(pBuffer, DecodeABCTag);
  1526. pBuffer += WriteObject(pBuffer, DecodeABCLab1);
  1527. //
  1528. // /MatrixABC
  1529. //
  1530. pBuffer += WriteNewLineObject(pBuffer, MatrixABCTag);
  1531. pBuffer += WriteObject(pBuffer, MatrixABCLab);
  1532. //
  1533. // /DecodeLMN
  1534. //
  1535. pBuffer += WriteNewLineObject(pBuffer, DecodeLMNTag);
  1536. pBuffer += WriteObject(pBuffer, BeginArray);
  1537. for (i=0; i<3; i++)
  1538. {
  1539. pBuffer += WriteObject(pBuffer, BeginFunction);
  1540. pBuffer += WriteObject(pBuffer, DecodeLMNLab);
  1541. if (dwIntent == INTENT_ABSOLUTE_COLORIMETRIC)
  1542. {
  1543. pBuffer += WriteFixed(pBuffer, afxMediaWP[i]);
  1544. }
  1545. else
  1546. {
  1547. pBuffer += WriteFixed(pBuffer, afxIlluminantWP[i]);
  1548. }
  1549. pBuffer += WriteObject(pBuffer, MulOp);
  1550. pBuffer += WriteObject(pBuffer, EndFunction);
  1551. pBuffer += WriteObject(pBuffer, NewLine);
  1552. }
  1553. pBuffer += WriteObject(pBuffer, EndArray);
  1554. //
  1555. // End dictionary definition
  1556. //
  1557. pBuffer += WriteNewLineObject(pBuffer, EndDict);
  1558. pBuffer += WriteObject(pBuffer, EndArray);
  1559. pBuffer += WriteNewLineObject(pBuffer, CieBasedABCEnd);
  1560. *pcbSize = (DWORD) (pBuffer - pStart);
  1561. return TRUE;
  1562. }
  1563. /******************************************************************************
  1564. *
  1565. * GetPS2CSA_DEFG
  1566. *
  1567. * Function:
  1568. * This function creates DEF and DEFG based CSAs from the data supplied
  1569. * in the RGB or CMYK profiles respectively
  1570. *
  1571. * Arguments:
  1572. * pProfile - pointer to the memory mapped profile
  1573. * pBuffer - pointer to receive the CSA
  1574. * pcbSize - pointer to size of buffer. If function fails because
  1575. * buffer is not big enough, it is filled with required size.
  1576. * dwIntent - rendering intent of CSA requested
  1577. * dwType - whether DEF CSA or DEFG CSA is required
  1578. * pcbBinary - TRUE if binary data is requested. On return it is set to
  1579. * reflect the data returned
  1580. *
  1581. * Returns:
  1582. * TRUE if successful, FALSE otherwise
  1583. *
  1584. ******************************************************************************/
  1585. BOOL
  1586. GetPS2CSA_DEFG(
  1587. PBYTE pProfile,
  1588. PBYTE pBuffer,
  1589. PDWORD pcbSize,
  1590. DWORD dwIntent,
  1591. DWORD dwType,
  1592. PBOOL pbBinary
  1593. )
  1594. {
  1595. PLUT16TYPE pLut;
  1596. PTAGDATA pTagData;
  1597. PBYTE pLineStart, pStart = pBuffer;
  1598. PBYTE pTable;
  1599. DWORD i, j, k, dwPCS, dwDev, dwIndex, dwTag, dwLutSig, SecondGrids, dwSize;
  1600. DWORD nInputCh, nOutputCh, nGrids, nInputTable, nOutputTable, nNumbers;
  1601. FIX_16_16 afxIlluminantWP[3];
  1602. FIX_16_16 afxMediaWP[3];
  1603. char pPublicArrayName[5];
  1604. //
  1605. // Make sure required tags exist
  1606. //
  1607. switch (dwIntent)
  1608. {
  1609. case INTENT_PERCEPTUAL:
  1610. dwTag = TAG_AToB0;
  1611. break;
  1612. case INTENT_RELATIVE_COLORIMETRIC:
  1613. dwTag = TAG_AToB1;
  1614. break;
  1615. case INTENT_SATURATION:
  1616. dwTag = TAG_AToB2;
  1617. break;
  1618. case INTENT_ABSOLUTE_COLORIMETRIC:
  1619. dwTag = TAG_AToB1;
  1620. break;
  1621. default:
  1622. WARNING((__TEXT("Invalid intent passed to GetPS2CSA_DEFG: %d\n"), dwIntent));
  1623. SetLastError(ERROR_INVALID_PARAMETER);
  1624. return FALSE;
  1625. }
  1626. if (! DoesCPTagExist(pProfile, dwTag, &dwIndex))
  1627. {
  1628. WARNING((__TEXT("AToB%d tag not present to create DEF(G) CSA\n"), dwIntent));
  1629. SetLastError(ERROR_TAG_NOT_PRESENT);
  1630. return FALSE;
  1631. }
  1632. //
  1633. // Check if we can generate the CSA
  1634. // Required tags is AToBi, where i is the rendering intent
  1635. //
  1636. dwPCS = GetCPConnSpace(pProfile);
  1637. dwDev = GetCPDevSpace(pProfile);
  1638. if ((dwType == TYPE_CIEBASEDDEF && dwDev != SPACE_RGB) ||
  1639. (dwType == TYPE_CIEBASEDDEFG && dwDev != SPACE_CMYK))
  1640. {
  1641. WARNING((__TEXT("RGB profile & requesting CMYK CSA or vice versa\n")));
  1642. SetLastError(ERROR_TAG_NOT_PRESENT);
  1643. return FALSE;
  1644. }
  1645. pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
  1646. dwIndex * sizeof(TAGDATA));
  1647. pLut = (PLUT16TYPE)(pProfile + FIX_ENDIAN(pTagData->dwOffset));
  1648. dwLutSig = FIX_ENDIAN(pLut->dwSignature);
  1649. if (((dwPCS != SPACE_Lab) && (dwPCS != SPACE_XYZ)) ||
  1650. ((dwLutSig != LUT8_TYPE) && (dwLutSig != LUT16_TYPE)))
  1651. {
  1652. WARNING((__TEXT("Invalid color space - unable to create DEF(G) CSA\n")));
  1653. SetLastError(ERROR_INVALID_PROFILE);
  1654. return FALSE;
  1655. }
  1656. //
  1657. // Estimate size required to hold the CSA
  1658. //
  1659. (void)GetCLUTInfo(dwLutSig, (PBYTE)pLut, &nInputCh, &nOutputCh, &nGrids,
  1660. &nInputTable, &nOutputTable, NULL);
  1661. //
  1662. // Calculate size of buffer needed
  1663. //
  1664. if (dwType == TYPE_CIEBASEDDEFG)
  1665. {
  1666. dwSize = nOutputCh * nGrids * nGrids * nGrids * nGrids * 2;
  1667. }
  1668. else
  1669. {
  1670. dwSize = nOutputCh * nGrids * nGrids * nGrids * 2;
  1671. }
  1672. dwSize = dwSize +
  1673. nInputCh * nInputTable * 6 +
  1674. nOutputCh * nOutputTable * 6 + // Number of INT bytes
  1675. nInputCh * (STRLEN(IndexArray) +
  1676. STRLEN(StartClip) +
  1677. STRLEN(EndClip)) +
  1678. nOutputCh * (STRLEN(IndexArray) +
  1679. STRLEN(StartClip) +
  1680. STRLEN(EndClip)) +
  1681. 4096; // + other PS stuff
  1682. //
  1683. // Add space for new line.
  1684. //
  1685. dwSize += (((dwSize) / MAX_LINELEN) + 1) * STRLEN(NewLine);
  1686. if (! pBuffer)
  1687. {
  1688. *pcbSize = dwSize;
  1689. return TRUE;
  1690. }
  1691. else if (*pcbSize < dwSize)
  1692. {
  1693. WARNING((__TEXT("Buffer too small to get DEFG CSA\n")));
  1694. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  1695. return FALSE;
  1696. }
  1697. //
  1698. // Get info about Illuminant White Point from the header
  1699. //
  1700. (void)GetCPWhitePoint(pProfile, afxIlluminantWP);
  1701. //
  1702. // Support absolute whitePoint
  1703. //
  1704. (void)GetMediaWP(pProfile, dwIntent, afxIlluminantWP, afxMediaWP);
  1705. //
  1706. // Testing CieBasedDEFG support
  1707. //
  1708. pBuffer += WriteNewLineObject(pBuffer, TestingDEFG);
  1709. //
  1710. // Create global data
  1711. //
  1712. GetPublicArrayName(dwTag, pPublicArrayName);
  1713. if (dwType == TYPE_CIEBASEDDEFG)
  1714. {
  1715. pBuffer += WriteNewLineObject(pBuffer, CieBasedDEFGBegin);
  1716. }
  1717. else
  1718. {
  1719. pBuffer += WriteNewLineObject(pBuffer, CieBasedDEFBegin);
  1720. }
  1721. pBuffer += EnableGlobalDict(pBuffer);
  1722. pBuffer += WriteNewLineObject(pBuffer, SupportDEFG_S);
  1723. pBuffer += BeginGlobalDict(pBuffer);
  1724. pBuffer += CreateInputArray(pBuffer, nInputCh, nInputTable,
  1725. pPublicArrayName, dwLutSig, (PBYTE)pLut, *pbBinary, NULL);
  1726. if (dwType == TYPE_CIEBASEDDEFG)
  1727. {
  1728. i = nInputTable * nInputCh +
  1729. nGrids * nGrids * nGrids * nGrids * nOutputCh;
  1730. }
  1731. else
  1732. {
  1733. i = nInputTable * nInputCh +
  1734. nGrids * nGrids * nGrids * nOutputCh;
  1735. }
  1736. pBuffer += CreateOutputArray(pBuffer, nOutputCh, nOutputTable, i,
  1737. pPublicArrayName, dwLutSig, (PBYTE)pLut, *pbBinary, NULL);
  1738. pBuffer += WriteNewLineObject(pBuffer, EndOp);
  1739. pBuffer += WriteNewLineObject(pBuffer, SupportDEFG_E);
  1740. pBuffer += WriteNewLineObject(pBuffer, SetGlobalOp);
  1741. pBuffer += WriteNewLineObject(pBuffer, SupportDEFG_S);
  1742. //
  1743. // Start creating the ColorSpace
  1744. //
  1745. pBuffer += WriteNewLineObject(pBuffer, BeginArray); // Begin array
  1746. //
  1747. // /CIEBasedDEF(G)
  1748. //
  1749. if (dwType == TYPE_CIEBASEDDEFG)
  1750. {
  1751. pBuffer += WriteObject(pBuffer, CIEBasedDEFGTag);
  1752. }
  1753. else
  1754. {
  1755. pBuffer += WriteObject(pBuffer, CIEBasedDEFTag);
  1756. }
  1757. pBuffer += WriteObject(pBuffer, BeginDict); // Begin dictionary
  1758. //
  1759. // /BlackPoint & /WhitePoint
  1760. //
  1761. pBuffer += SendCSABWPoint(pBuffer, dwIntent, afxIlluminantWP, afxMediaWP);
  1762. //
  1763. // /DecodeDEF(G)
  1764. //
  1765. pLineStart = pBuffer;
  1766. if (dwType == TYPE_CIEBASEDDEFG)
  1767. {
  1768. pBuffer += WriteNewLineObject(pBuffer, DecodeDEFGTag);
  1769. }
  1770. else
  1771. {
  1772. pBuffer += WriteNewLineObject(pBuffer, DecodeDEFTag);
  1773. }
  1774. pBuffer += WriteObject(pBuffer, BeginArray);
  1775. for (i=0; i<nInputCh; i++)
  1776. {
  1777. pLineStart = pBuffer;
  1778. pBuffer += WriteNewLineObject(pBuffer, BeginFunction);
  1779. pBuffer += WriteObject(pBuffer, StartClip);
  1780. pBuffer += WriteObject(pBuffer, InputArray);
  1781. pBuffer += WriteObject(pBuffer, pPublicArrayName);
  1782. pBuffer += WriteInt(pBuffer, i);
  1783. if (! *pbBinary) // Output ASCII
  1784. {
  1785. pBuffer += WriteObject(pBuffer, IndexArray);
  1786. }
  1787. else
  1788. { // Output BINARY
  1789. if (dwLutSig == LUT8_TYPE)
  1790. {
  1791. pBuffer += WriteObject(pBuffer, IndexArray);
  1792. }
  1793. else
  1794. {
  1795. pBuffer += WriteObject(pBuffer, IndexArray16b);
  1796. }
  1797. }
  1798. pBuffer += WriteObject(pBuffer, (dwLutSig == LUT8_TYPE) ? Scale8 : Scale16);
  1799. pBuffer += WriteObject(pBuffer, EndClip);
  1800. pBuffer += WriteObject(pBuffer, EndFunction);
  1801. }
  1802. pBuffer += WriteObject(pBuffer, EndArray);
  1803. //
  1804. // /Table
  1805. //
  1806. pBuffer += WriteNewLineObject(pBuffer, TableTag);
  1807. pBuffer += WriteObject(pBuffer, BeginArray);
  1808. pBuffer += WriteInt(pBuffer, nGrids); // Send down Nh
  1809. pBuffer += WriteInt(pBuffer, nGrids); // Send down Ni
  1810. pBuffer += WriteInt(pBuffer, nGrids); // Send down Nj
  1811. nNumbers = nGrids * nGrids * nOutputCh;
  1812. SecondGrids = 1;
  1813. if (dwType == TYPE_CIEBASEDDEFG)
  1814. {
  1815. pBuffer += WriteInt (pBuffer, nGrids); // Send down Nk
  1816. SecondGrids = nGrids;
  1817. }
  1818. pBuffer += WriteNewLineObject(pBuffer, BeginArray);
  1819. for (i=0; i<nGrids; i++) // Nh strings should be sent
  1820. {
  1821. if (dwType == TYPE_CIEBASEDDEFG)
  1822. {
  1823. pBuffer += WriteNewLineObject(pBuffer, BeginArray);
  1824. }
  1825. for (k=0; k<SecondGrids; k++)
  1826. {
  1827. pLineStart = pBuffer;
  1828. pBuffer += WriteObject(pBuffer, NewLine);
  1829. if (dwLutSig == LUT8_TYPE)
  1830. {
  1831. pTable = (PBYTE)(((PLUT8TYPE)pLut)->data) +
  1832. nInputTable * nInputCh +
  1833. nNumbers * (i * SecondGrids + k);
  1834. }
  1835. else
  1836. {
  1837. pTable = (PBYTE)(((PLUT16TYPE)pLut)->data) +
  1838. 2 * nInputTable * nInputCh +
  1839. 2 * nNumbers * (i * SecondGrids + k);
  1840. }
  1841. if (! *pbBinary) // Output ASCII
  1842. {
  1843. pBuffer += WriteObject(pBuffer, BeginString);
  1844. if (dwLutSig == LUT8_TYPE)
  1845. {
  1846. pBuffer += WriteHexBuffer(pBuffer, pTable, pLineStart, nNumbers);
  1847. }
  1848. else
  1849. {
  1850. for (j=0; j<nNumbers; j++)
  1851. {
  1852. pBuffer += WriteHex(pBuffer, FIX_ENDIAN16(*((PWORD)pTable)) / 256);
  1853. pTable += sizeof(WORD);
  1854. if (((DWORD) (pBuffer - pLineStart)) > MAX_LINELEN)
  1855. {
  1856. pLineStart = pBuffer;
  1857. pBuffer += WriteObject(pBuffer, NewLine);
  1858. }
  1859. }
  1860. }
  1861. pBuffer += WriteObject(pBuffer, EndString);
  1862. }
  1863. else
  1864. { // Output BINARY
  1865. pBuffer += WriteStringToken(pBuffer, 143, nNumbers);
  1866. if (dwLutSig == LUT8_TYPE)
  1867. pBuffer += WriteByteString(pBuffer, pTable, nNumbers);
  1868. else
  1869. pBuffer += WriteInt2ByteString(pBuffer, pTable, nNumbers);
  1870. }
  1871. pBuffer += WriteObject (pBuffer, NewLine);
  1872. }
  1873. if (dwType == TYPE_CIEBASEDDEFG)
  1874. {
  1875. pBuffer += WriteObject(pBuffer, EndArray);
  1876. }
  1877. }
  1878. pBuffer += WriteObject(pBuffer, EndArray);
  1879. pBuffer += WriteObject(pBuffer, EndArray); // End array
  1880. //
  1881. // /DecodeABC
  1882. //
  1883. pLineStart = pBuffer;
  1884. pBuffer += WriteNewLineObject(pBuffer, DecodeABCTag);
  1885. pBuffer += WriteObject(pBuffer, BeginArray);
  1886. for (i=0; i<nOutputCh; i++)
  1887. {
  1888. pLineStart = pBuffer;
  1889. pBuffer += WriteNewLineObject(pBuffer, BeginFunction);
  1890. pBuffer += WriteObject(pBuffer, Clip01);
  1891. pBuffer += WriteObject(pBuffer, OutputArray);
  1892. pBuffer += WriteObject(pBuffer, pPublicArrayName);
  1893. pBuffer += WriteInt(pBuffer, i);
  1894. if (! *pbBinary)
  1895. {
  1896. pBuffer += WriteObject(pBuffer, NewLine);
  1897. if (dwLutSig == LUT8_TYPE)
  1898. {
  1899. pBuffer += WriteObject(pBuffer, TFunction8XYZ);
  1900. }
  1901. else
  1902. {
  1903. pBuffer += WriteObject(pBuffer, IndexArray);
  1904. pBuffer += WriteObject(pBuffer, Scale16XYZ);
  1905. }
  1906. }
  1907. else
  1908. {
  1909. if (dwLutSig == LUT8_TYPE)
  1910. {
  1911. pBuffer += WriteObject(pBuffer, TFunction8XYZ);
  1912. }
  1913. else
  1914. {
  1915. pBuffer += WriteObject(pBuffer, IndexArray16b);
  1916. pBuffer += WriteObject(pBuffer, Scale16XYZ);
  1917. }
  1918. }
  1919. //
  1920. // Now, We get CieBasedXYZ output. Output range 0 --> 1.99997
  1921. // If the connection space is absolute XYZ, We need to convert
  1922. // from relative XYZ to absolute XYZ.
  1923. //
  1924. if ((dwPCS == SPACE_XYZ) && (dwIntent == INTENT_ABSOLUTE_COLORIMETRIC))
  1925. {
  1926. pBuffer += WriteFixed(pBuffer, FIX_DIV(afxMediaWP[i], afxIlluminantWP[i]));
  1927. pBuffer += WriteObject(pBuffer, MulOp);
  1928. }
  1929. else if (dwPCS == SPACE_Lab)
  1930. {
  1931. //
  1932. // If the connection space is Lab, We need to convert XYZ to Lab
  1933. //
  1934. pBuffer += WriteObject(pBuffer, DecodeABCLab[i]);
  1935. }
  1936. pBuffer += WriteObject(pBuffer, EndFunction);
  1937. }
  1938. pBuffer += WriteObject(pBuffer, EndArray);
  1939. if (dwPCS == SPACE_Lab)
  1940. {
  1941. //
  1942. // /MatrixABC
  1943. //
  1944. pBuffer += WriteNewLineObject(pBuffer, MatrixABCTag);
  1945. pBuffer += WriteObject(pBuffer, MatrixABCLab);
  1946. //
  1947. // /DecodeLMN
  1948. //
  1949. pLineStart = pBuffer;
  1950. pBuffer += WriteNewLineObject(pBuffer, DecodeLMNTag);
  1951. pBuffer += WriteObject(pBuffer, BeginArray);
  1952. for (i=0; i<3; i++)
  1953. {
  1954. pLineStart = pBuffer;
  1955. pBuffer += WriteNewLineObject(pBuffer, BeginFunction);
  1956. pBuffer += WriteObject(pBuffer, DecodeLMNLab);
  1957. if (dwIntent == INTENT_ABSOLUTE_COLORIMETRIC)
  1958. {
  1959. pBuffer += WriteFixed(pBuffer, afxMediaWP[i]);
  1960. }
  1961. else
  1962. {
  1963. pBuffer += WriteFixed(pBuffer, afxIlluminantWP[i]);
  1964. }
  1965. pBuffer += WriteObject(pBuffer, MulOp);
  1966. pBuffer += WriteObject(pBuffer, EndFunction);
  1967. }
  1968. pBuffer += WriteObject(pBuffer, EndArray);
  1969. }
  1970. else
  1971. {
  1972. //
  1973. // /RangeLMN
  1974. //
  1975. pBuffer += WriteNewLineObject(pBuffer, RangeLMNTag);
  1976. pBuffer += WriteObject(pBuffer, RangeLMN);
  1977. }
  1978. //
  1979. // End dictionary definition
  1980. //
  1981. pBuffer += WriteNewLineObject(pBuffer, EndDict);
  1982. pBuffer += WriteObject(pBuffer, EndArray);
  1983. if (dwType == TYPE_CIEBASEDDEFG)
  1984. {
  1985. pBuffer += WriteNewLineObject(pBuffer, CieBasedDEFGEnd);
  1986. }
  1987. else
  1988. {
  1989. pBuffer += WriteNewLineObject(pBuffer, CieBasedDEFEnd);
  1990. }
  1991. pBuffer += WriteNewLineObject(pBuffer, SupportDEFG_E);
  1992. *pcbSize = (DWORD) (pBuffer - pStart);
  1993. return TRUE;
  1994. }
  1995. BOOL
  1996. InternalGetPS2CSAFromLCS(
  1997. LPLOGCOLORSPACE pLogColorSpace,
  1998. PBYTE pBuffer,
  1999. PDWORD pcbSize,
  2000. PBOOL pbBinary
  2001. )
  2002. {
  2003. PBYTE pStart = pBuffer;
  2004. DWORD dwSize = 1024*2; // same value as in pscript/icm.c
  2005. if (! pBuffer)
  2006. {
  2007. *pcbSize = dwSize;
  2008. return TRUE;
  2009. }
  2010. if (*pcbSize < dwSize)
  2011. {
  2012. WARNING((__TEXT("Buffer too small to get CSA from LCS\n")));
  2013. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  2014. return FALSE;
  2015. }
  2016. pBuffer += WriteObject(pBuffer, NewLine);
  2017. pBuffer += WriteObject(pBuffer, BeginArray); // Begin array
  2018. pBuffer += WriteObject(pBuffer, ColorSpace1);
  2019. pBuffer += WriteObject(pBuffer, BeginArray); // [
  2020. //
  2021. // Red gamma
  2022. //
  2023. pBuffer += WriteObject(pBuffer, BeginFunction);
  2024. pBuffer += WriteFixed(pBuffer, pLogColorSpace->lcsGammaRed);
  2025. pBuffer += WriteObject(pBuffer, ColorSpace3);
  2026. //
  2027. // Green gamma
  2028. //
  2029. pBuffer += WriteObject(pBuffer, BeginFunction);
  2030. pBuffer += WriteFixed(pBuffer, pLogColorSpace->lcsGammaGreen);
  2031. pBuffer += WriteObject(pBuffer, ColorSpace3);
  2032. //
  2033. // Blue Gamma
  2034. //
  2035. pBuffer += WriteObject(pBuffer, BeginFunction);
  2036. pBuffer += WriteFixed(pBuffer, pLogColorSpace->lcsGammaBlue);
  2037. pBuffer += WriteObject(pBuffer, ColorSpace3);
  2038. pBuffer += WriteObject(pBuffer, EndArray); // ]
  2039. pBuffer += WriteObject(pBuffer, ColorSpace5); // /WhitePoint
  2040. //
  2041. // Matrix LMN
  2042. //
  2043. pBuffer += WriteObject(pBuffer, MatrixLMNTag);
  2044. pBuffer += WriteObject(pBuffer, BeginArray);
  2045. //
  2046. // Red Value
  2047. //
  2048. pBuffer += WriteFixed2dot30(pBuffer, pLogColorSpace->lcsEndpoints.ciexyzRed.ciexyzX);
  2049. pBuffer += WriteFixed2dot30(pBuffer, pLogColorSpace->lcsEndpoints.ciexyzRed.ciexyzY);
  2050. pBuffer += WriteFixed2dot30(pBuffer, pLogColorSpace->lcsEndpoints.ciexyzRed.ciexyzZ);
  2051. //
  2052. // Green Value
  2053. //
  2054. pBuffer += WriteFixed2dot30(pBuffer, pLogColorSpace->lcsEndpoints.ciexyzGreen.ciexyzX);
  2055. pBuffer += WriteFixed2dot30(pBuffer, pLogColorSpace->lcsEndpoints.ciexyzGreen.ciexyzY);
  2056. pBuffer += WriteFixed2dot30(pBuffer, pLogColorSpace->lcsEndpoints.ciexyzGreen.ciexyzZ);
  2057. //
  2058. // Blue Value
  2059. //
  2060. pBuffer += WriteFixed2dot30(pBuffer, pLogColorSpace->lcsEndpoints.ciexyzBlue.ciexyzX);
  2061. pBuffer += WriteFixed2dot30(pBuffer, pLogColorSpace->lcsEndpoints.ciexyzBlue.ciexyzY);
  2062. pBuffer += WriteFixed2dot30(pBuffer, pLogColorSpace->lcsEndpoints.ciexyzBlue.ciexyzZ);
  2063. pBuffer += WriteObject(pBuffer, EndArray); // ]
  2064. pBuffer += WriteObject(pBuffer, EndDict); // End dictionary
  2065. pBuffer += WriteObject(pBuffer, EndArray); // ]
  2066. *pcbSize = (DWORD) (pBuffer - pStart);
  2067. return TRUE;
  2068. }
  2069. /******************************************************************************
  2070. *
  2071. * CreateColorSpArray
  2072. *
  2073. * Function:
  2074. * This function creates an array that is used in /DecodeABC
  2075. *
  2076. * Arguments:
  2077. * pProfile - pointer to the memory mapped profile
  2078. * pBuffer - pointer to receive the array
  2079. * dwCPTag - Channel TRC tag
  2080. * bBinary - TRUE if binary data is requested
  2081. *
  2082. * Returns:
  2083. * Length of the data created in bytes
  2084. *
  2085. ******************************************************************************/
  2086. DWORD
  2087. CreateColSpArray(
  2088. PBYTE pProfile,
  2089. PBYTE pBuffer,
  2090. DWORD dwCPTag,
  2091. BOOL bBinary
  2092. )
  2093. {
  2094. PCURVETYPE pData;
  2095. PTAGDATA pTagData;
  2096. PBYTE pLineStart, pStart = pBuffer;
  2097. PBYTE pTable;
  2098. DWORD i, nCount, dwIndex;
  2099. pLineStart = pBuffer;
  2100. if (DoesCPTagExist(pProfile, dwCPTag, &dwIndex))
  2101. {
  2102. pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
  2103. dwIndex * sizeof(TAGDATA));
  2104. pData = (PCURVETYPE)(pProfile + FIX_ENDIAN(pTagData->dwOffset));
  2105. nCount = FIX_ENDIAN(pData->nCount);
  2106. if (nCount > 1)
  2107. {
  2108. pBuffer += WriteNewLineObject(pBuffer, Slash);
  2109. pBuffer += WriteObject(pBuffer, DecodeABCArray);
  2110. pBuffer += WriteInt(pBuffer, dwCPTag);
  2111. pTable = (PBYTE)(pData->data);
  2112. if (! bBinary) // Output ASCII CS
  2113. {
  2114. pBuffer += WriteObject(pBuffer, BeginArray);
  2115. for (i=0; i<nCount; i++)
  2116. {
  2117. pBuffer += WriteInt(pBuffer, FIX_ENDIAN16(*((PWORD)pTable)));
  2118. pTable += sizeof(WORD);
  2119. if (((DWORD) (pBuffer - pLineStart)) > MAX_LINELEN)
  2120. {
  2121. pLineStart = pBuffer;
  2122. pBuffer += WriteObject(pBuffer, NewLine);
  2123. }
  2124. }
  2125. pBuffer += WriteObject(pBuffer, EndArray);
  2126. }
  2127. else
  2128. { // Output BINARY CS
  2129. pBuffer += WriteHNAToken(pBuffer, 149, nCount);
  2130. pBuffer += WriteIntStringU2S(pBuffer, pTable, nCount);
  2131. }
  2132. pBuffer += WriteObject(pBuffer, DefOp);
  2133. }
  2134. }
  2135. return (DWORD) (pBuffer - pStart);
  2136. }
  2137. /******************************************************************************
  2138. *
  2139. * CreateColorSpProc
  2140. *
  2141. * Function:
  2142. * This function creates a PostScript procedure for the color space
  2143. *
  2144. * Arguments:
  2145. * pProfile - pointer to the memory mapped profile
  2146. * pBuffer - pointer to receive the procedure
  2147. * dwCPTag - Channel TRC tag
  2148. * bBinary - TRUE if binary data is requested
  2149. *
  2150. * Returns:
  2151. * Length of the data created in bytes
  2152. *
  2153. ******************************************************************************/
  2154. DWORD
  2155. CreateColSpProc(
  2156. PBYTE pProfile,
  2157. PBYTE pBuffer,
  2158. DWORD dwCPTag,
  2159. BOOL bBinary
  2160. )
  2161. {
  2162. PCURVETYPE pData;
  2163. PTAGDATA pTagData;
  2164. PBYTE pStart = pBuffer;
  2165. PBYTE pTable;
  2166. DWORD nCount, dwIndex;
  2167. pBuffer += WriteObject(pBuffer, BeginFunction);
  2168. if (DoesCPTagExist(pProfile, dwCPTag, &dwIndex))
  2169. {
  2170. pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
  2171. dwIndex * sizeof(TAGDATA));
  2172. pData = (PCURVETYPE)(pProfile + FIX_ENDIAN(pTagData->dwOffset));
  2173. nCount = FIX_ENDIAN(pData->nCount);
  2174. if (nCount != 0)
  2175. {
  2176. if (nCount == 1) // Gamma supplied in ui16 format
  2177. {
  2178. pTable = (PBYTE)(pData->data);
  2179. pBuffer += WriteInt(pBuffer, FIX_ENDIAN16(*((PWORD)pTable)));
  2180. pBuffer += WriteObject(pBuffer, DecodeA3);
  2181. }
  2182. else
  2183. {
  2184. pBuffer += WriteObject(pBuffer, StartClip);
  2185. pBuffer += WriteObject(pBuffer, DecodeABCArray);
  2186. pBuffer += WriteInt(pBuffer, dwCPTag);
  2187. if (! bBinary) // Output ASCII CS
  2188. {
  2189. pBuffer += WriteObject(pBuffer, IndexArray);
  2190. }
  2191. else
  2192. { // Output BINARY CS
  2193. pBuffer += WriteObject(pBuffer, IndexArray16b);
  2194. }
  2195. pBuffer += WriteObject(pBuffer, Scale16);
  2196. pBuffer += WriteObject(pBuffer, EndClip);
  2197. }
  2198. }
  2199. }
  2200. pBuffer += WriteObject(pBuffer, EndFunction);
  2201. return (DWORD) (pBuffer - pStart);
  2202. }
  2203. /******************************************************************************
  2204. *
  2205. * CreateFloatString
  2206. *
  2207. * Function:
  2208. * This function creates a string of floating point numbers for
  2209. * the X, Y and Z values of the specified colorant.
  2210. *
  2211. * Arguments:
  2212. * pProfile - pointer to the memory mapped profile
  2213. * pBuffer - pointer to receive the string
  2214. * dwCPTag - Colorant tag
  2215. *
  2216. * Returns:
  2217. * Length of the data created in bytes
  2218. *
  2219. ******************************************************************************/
  2220. DWORD
  2221. CreateFloatString(
  2222. PBYTE pProfile,
  2223. PBYTE pBuffer,
  2224. DWORD dwCPTag
  2225. )
  2226. {
  2227. PTAGDATA pTagData;
  2228. PBYTE pStart = pBuffer;
  2229. PDWORD pTable;
  2230. DWORD i, dwIndex;
  2231. if (DoesCPTagExist(pProfile, dwCPTag, &dwIndex))
  2232. {
  2233. pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
  2234. dwIndex * sizeof(TAGDATA));
  2235. pTable = (PDWORD)(pProfile + FIX_ENDIAN(pTagData->dwOffset)) + 2;
  2236. for (i=0; i<3; i++)
  2237. {
  2238. pBuffer += WriteFixed(pBuffer, FIX_ENDIAN(*pTable));
  2239. pTable ++;
  2240. }
  2241. }
  2242. return (DWORD) (pBuffer - pStart);
  2243. }
  2244. /******************************************************************************
  2245. *
  2246. * CreateInputArray
  2247. *
  2248. * Function:
  2249. * This function creates the Color Rendering Dictionary (CRD)
  2250. * from the data supplied in the ColorProfile's LUT8 or LUT16 tag.
  2251. *
  2252. * Arguments:
  2253. * pBuffer - pointer to receive the data
  2254. * nInputChannels - number of input channels
  2255. * nInputTable - size of input table
  2256. * pIntent - rendering intent signature (eg. A2B0)
  2257. * dwTag - signature of the look up table (8 or 16 bits)
  2258. * pLut - pointer to the look up table
  2259. * bBinary - TRUE if binary data is requested
  2260. *
  2261. * Returns:
  2262. * Length of the data created in bytes
  2263. *
  2264. ******************************************************************************/
  2265. DWORD
  2266. CreateInputArray(
  2267. PBYTE pBuffer,
  2268. DWORD nInputChannels,
  2269. DWORD nInputTable,
  2270. PBYTE pIntent,
  2271. DWORD dwTag,
  2272. PBYTE pLut,
  2273. BOOL bBinary,
  2274. PBYTE pHostClut
  2275. )
  2276. {
  2277. DWORD i, j;
  2278. PBYTE pLineStart, pStart = pBuffer;
  2279. PBYTE pTable;
  2280. if (pHostClut)
  2281. {
  2282. nInputChannels = ((PHOSTCLUT)pHostClut)->nInputCh;
  2283. nInputTable = ((PHOSTCLUT)pHostClut)->nInputEntries;
  2284. dwTag = ((PHOSTCLUT)pHostClut)->nLutBits == 8 ? LUT8_TYPE : LUT16_TYPE;
  2285. }
  2286. for (i=0; i<nInputChannels; i++)
  2287. {
  2288. pLineStart = pBuffer;
  2289. pBuffer += WriteNewLineObject(pBuffer, Slash);
  2290. if (pHostClut)
  2291. pBuffer += WriteObject(pBuffer, PreViewInArray);
  2292. else
  2293. pBuffer += WriteObject(pBuffer, InputArray);
  2294. pBuffer += WriteObject(pBuffer, pIntent);
  2295. pBuffer += WriteInt(pBuffer, i);
  2296. if (pHostClut)
  2297. {
  2298. pTable = ((PHOSTCLUT)pHostClut)->inputArray[i];
  2299. }
  2300. else
  2301. {
  2302. if (dwTag == LUT8_TYPE)
  2303. {
  2304. pTable = (PBYTE)(((PLUT8TYPE)pLut)->data) + nInputTable * i;
  2305. }
  2306. else
  2307. {
  2308. pTable = (PBYTE)(((PLUT16TYPE)pLut)->data) + 2 * nInputTable * i;
  2309. }
  2310. }
  2311. if (! bBinary)
  2312. {
  2313. if (dwTag == LUT8_TYPE)
  2314. {
  2315. pBuffer += WriteObject(pBuffer, BeginString);
  2316. pBuffer += WriteHexBuffer(pBuffer, pTable, pLineStart, nInputTable);
  2317. pBuffer += WriteObject(pBuffer, EndString);
  2318. }
  2319. else
  2320. {
  2321. pBuffer += WriteObject(pBuffer, BeginArray);
  2322. for (j=0; j<nInputTable; j++)
  2323. {
  2324. if (pHostClut)
  2325. pBuffer += WriteInt(pBuffer, *((PWORD)pTable));
  2326. else
  2327. pBuffer += WriteInt(pBuffer, FIX_ENDIAN16(*((PWORD)pTable)));
  2328. pTable += sizeof(WORD);
  2329. if (((DWORD) (pBuffer - pLineStart)) > MAX_LINELEN)
  2330. {
  2331. pLineStart = pBuffer;
  2332. pBuffer += WriteObject(pBuffer, NewLine);
  2333. }
  2334. }
  2335. pBuffer += WriteObject(pBuffer, EndArray);
  2336. }
  2337. }
  2338. else
  2339. {
  2340. if (dwTag == LUT8_TYPE)
  2341. {
  2342. pBuffer += WriteStringToken(pBuffer, 143, nInputTable);
  2343. pBuffer += WriteByteString(pBuffer, pTable, nInputTable);
  2344. }
  2345. else
  2346. {
  2347. pBuffer += WriteHNAToken(pBuffer, 149, nInputTable);
  2348. if (pHostClut)
  2349. pBuffer += WriteIntStringU2S_L(pBuffer, pTable, nInputTable);
  2350. else
  2351. pBuffer += WriteIntStringU2S(pBuffer, pTable, nInputTable);
  2352. }
  2353. }
  2354. pBuffer += WriteObject(pBuffer, DefOp);
  2355. }
  2356. return (DWORD) (pBuffer - pStart);
  2357. }
  2358. /******************************************************************************
  2359. *
  2360. * CreateOutputArray
  2361. *
  2362. * Function:
  2363. * This function creates the Color Rendering Dictionary (CRD)
  2364. * from the data supplied in the ColorProfile's LUT8 or LUT16 tag.
  2365. *
  2366. * Arguments:
  2367. * pBuffer - pointer to receive the data
  2368. * nOutputChannels- number of output channels
  2369. * nOutputTable - size of output table
  2370. * dwOffset - offset into the output table
  2371. * pIntent - rendering intent signature (eg. A2B0)
  2372. * dwTag - signature of the look up table (8 or 16 bits)
  2373. * pLut - pointer to the look up table
  2374. * bBinary - TRUE if binary data is requested
  2375. *
  2376. * Returns:
  2377. * Length of the data created in bytes
  2378. *
  2379. ******************************************************************************/
  2380. DWORD
  2381. CreateOutputArray(
  2382. PBYTE pBuffer,
  2383. DWORD nOutputChannels,
  2384. DWORD nOutputTable,
  2385. DWORD dwOffset,
  2386. PBYTE pIntent,
  2387. DWORD dwTag,
  2388. PBYTE pLut,
  2389. BOOL bBinary,
  2390. PBYTE pHostClut
  2391. )
  2392. {
  2393. DWORD i, j;
  2394. PBYTE pLineStart, pStart = pBuffer;
  2395. PBYTE pTable;
  2396. if (pHostClut)
  2397. {
  2398. nOutputChannels = ((PHOSTCLUT)pHostClut)->nOutputCh;
  2399. nOutputTable = ((PHOSTCLUT)pHostClut)->nOutputEntries;
  2400. dwTag = ((PHOSTCLUT)pHostClut)->nLutBits == 8 ? LUT8_TYPE : LUT16_TYPE;
  2401. }
  2402. for (i=0; i<nOutputChannels; i++)
  2403. {
  2404. pLineStart = pBuffer;
  2405. pBuffer += WriteNewLineObject(pBuffer, Slash);
  2406. if (pHostClut)
  2407. pBuffer += WriteObject(pBuffer, PreViewOutArray);
  2408. else
  2409. pBuffer += WriteObject(pBuffer, OutputArray);
  2410. pBuffer += WriteObject(pBuffer, pIntent);
  2411. pBuffer += WriteInt(pBuffer, i);
  2412. if (pHostClut)
  2413. {
  2414. pTable = ((PHOSTCLUT)pHostClut)->outputArray[i];
  2415. }
  2416. else
  2417. {
  2418. if (dwTag == LUT8_TYPE)
  2419. {
  2420. pTable = (PBYTE)(((PLUT8TYPE)pLut)->data) +
  2421. dwOffset + nOutputTable * i;
  2422. }
  2423. else
  2424. {
  2425. pTable = (PBYTE)(((PLUT16TYPE)pLut)->data) +
  2426. 2 * dwOffset + 2 * nOutputTable * i;
  2427. }
  2428. }
  2429. if (! bBinary)
  2430. {
  2431. if (dwTag == LUT8_TYPE)
  2432. {
  2433. pBuffer += WriteObject(pBuffer, BeginString);
  2434. pBuffer += WriteHexBuffer(pBuffer, pTable, pLineStart, nOutputTable);
  2435. pBuffer += WriteObject(pBuffer, EndString);
  2436. }
  2437. else
  2438. {
  2439. pBuffer += WriteObject(pBuffer, BeginArray);
  2440. for (j=0; j<nOutputTable; j++)
  2441. {
  2442. if (pHostClut)
  2443. pBuffer += WriteInt(pBuffer, *((PWORD)pTable));
  2444. else
  2445. pBuffer += WriteInt(pBuffer, FIX_ENDIAN16(*((PWORD)pTable)));
  2446. pTable += sizeof(WORD);
  2447. if (((DWORD) (pBuffer - pLineStart)) > MAX_LINELEN)
  2448. {
  2449. pLineStart = pBuffer;
  2450. pBuffer += WriteObject(pBuffer, NewLine);
  2451. }
  2452. }
  2453. pBuffer += WriteObject(pBuffer, EndArray);
  2454. }
  2455. }
  2456. else
  2457. {
  2458. if (dwTag == LUT8_TYPE)
  2459. {
  2460. pBuffer += WriteStringToken(pBuffer, 143, 256);
  2461. pBuffer += WriteByteString(pBuffer, pTable, 256L);
  2462. }
  2463. else
  2464. {
  2465. pBuffer += WriteHNAToken(pBuffer, 149, nOutputTable);
  2466. if (pHostClut)
  2467. pBuffer += WriteIntStringU2S_L(pBuffer, pTable, nOutputTable);
  2468. else
  2469. pBuffer += WriteIntStringU2S(pBuffer, pTable, nOutputTable);
  2470. }
  2471. }
  2472. pBuffer += WriteObject(pBuffer, DefOp);
  2473. }
  2474. return (DWORD)(pBuffer - pStart);
  2475. }
  2476. /******************************************************************************
  2477. *
  2478. * GetPublicArrayName
  2479. *
  2480. * Function:
  2481. * This function creates a string with the lookup table's signature
  2482. *
  2483. * Arguments:
  2484. * dwIntentSig - the look up table signature
  2485. * pPublicArrayName - pointer to buffer
  2486. *
  2487. * Returns:
  2488. * Length of the data created in bytes
  2489. *
  2490. ******************************************************************************/
  2491. DWORD
  2492. GetPublicArrayName(
  2493. DWORD dwIntentSig,
  2494. PBYTE pPublicArrayName
  2495. )
  2496. {
  2497. *((DWORD *)pPublicArrayName) = dwIntentSig;
  2498. pPublicArrayName[sizeof(DWORD)] = '\0';
  2499. return sizeof(DWORD) + 1;
  2500. }
  2501. /***************************************************************************
  2502. * CreateMonoCRD
  2503. * function:
  2504. * this is the function which creates the Color Rendering Dictionary (CRD)
  2505. * from the data supplied in the GrayTRC tag.
  2506. *
  2507. * returns:
  2508. * BOOL -- !=0 if the function was successful,
  2509. * 0 otherwise.
  2510. * Returns number of bytes required/transferred
  2511. ***************************************************************************/
  2512. BOOL
  2513. CreateMonoCRD(
  2514. PBYTE pProfile,
  2515. DWORD dwIndex,
  2516. PBYTE pBuffer,
  2517. PDWORD pcbSize,
  2518. DWORD dwIntent
  2519. )
  2520. {
  2521. PTAGDATA pTagData;
  2522. PCURVETYPE pData;
  2523. PBYTE pLineStart, pStart = pBuffer;
  2524. PWORD pCurve, pRevCurve, pRevCurveStart;
  2525. DWORD dwPCS, dwSize, nCount, i;
  2526. FIX_16_16 afxIlluminantWP[3];
  2527. FIX_16_16 afxMediaWP[3];
  2528. dwPCS = GetCPConnSpace(pProfile);
  2529. pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
  2530. dwIndex * sizeof(TAGDATA));
  2531. pData = (PCURVETYPE)(pProfile + FIX_ENDIAN(pTagData->dwOffset));
  2532. nCount = FIX_ENDIAN(pData->nCount);
  2533. //
  2534. // Estimate size required to hold the CRD
  2535. //
  2536. dwSize = nCount * 6 * REVCURVE_RATIO + // Number of INT elements
  2537. 2048; // + other PS stuff
  2538. //
  2539. // Add space for new line.
  2540. //
  2541. dwSize += (((dwSize) / MAX_LINELEN) + 1) * STRLEN(NewLine);
  2542. if (! pBuffer)
  2543. {
  2544. *pcbSize = dwSize;
  2545. return TRUE;
  2546. }
  2547. else if (*pcbSize < dwSize)
  2548. {
  2549. WARNING((__TEXT("Buffer too small to get Mono CRD\n")));
  2550. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  2551. return FALSE;
  2552. }
  2553. //
  2554. // Allocate memory, each entry occupy 2 bytes (1 word),
  2555. //
  2556. // input buffer = (nCount * sizeof(WORD)
  2557. // output buffer = (nCount * sizeof(WORD) * REVCURVE_RATIO)
  2558. //
  2559. if ((pRevCurveStart = MemAlloc(nCount * sizeof(WORD) * (REVCURVE_RATIO + 1))) == NULL)
  2560. {
  2561. WARNING((__TEXT("Unable to allocate memory for reverse curve\n")));
  2562. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2563. return FALSE;
  2564. }
  2565. //
  2566. // pCurve will points input buffer (which used in GetRevCurve)
  2567. //
  2568. pCurve = pRevCurveStart + nCount * REVCURVE_RATIO;
  2569. pRevCurve = pRevCurveStart;
  2570. (void)GetRevCurve(pData, pCurve, pRevCurve);
  2571. //
  2572. // Get info about Illuminant White Point from the header
  2573. //
  2574. (void)GetCPWhitePoint(pProfile, afxIlluminantWP);
  2575. //
  2576. // Support absolute whitePoint
  2577. //
  2578. if (dwIntent == INTENT_ABSOLUTE_COLORIMETRIC)
  2579. {
  2580. if (! GetCPMediaWhitePoint(pProfile, afxMediaWP))
  2581. {
  2582. afxMediaWP[0] = afxIlluminantWP[0];
  2583. afxMediaWP[1] = afxIlluminantWP[1];
  2584. afxMediaWP[2] = afxIlluminantWP[2];
  2585. }
  2586. }
  2587. //
  2588. // Start writing the CRD
  2589. //
  2590. pBuffer += WriteNewLineObject(pBuffer, BeginDict); // Begin dictionary
  2591. pBuffer += WriteObject(pBuffer, DictType); // Dictionary type
  2592. //
  2593. // Send /RenderingIntent
  2594. //
  2595. switch (dwIntent)
  2596. {
  2597. case INTENT_PERCEPTUAL:
  2598. pBuffer += WriteNewLineObject(pBuffer, IntentType);
  2599. pBuffer += WriteObject(pBuffer, IntentPer);
  2600. break;
  2601. case INTENT_SATURATION:
  2602. pBuffer += WriteNewLineObject(pBuffer, IntentType);
  2603. pBuffer += WriteObject(pBuffer, IntentSat);
  2604. break;
  2605. case INTENT_RELATIVE_COLORIMETRIC:
  2606. pBuffer += WriteNewLineObject(pBuffer, IntentType);
  2607. pBuffer += WriteObject(pBuffer, IntentRCol);
  2608. break;
  2609. case INTENT_ABSOLUTE_COLORIMETRIC:
  2610. pBuffer += WriteNewLineObject(pBuffer, IntentType);
  2611. pBuffer += WriteObject(pBuffer, IntentACol);
  2612. break;
  2613. }
  2614. //
  2615. // Send /BlackPoint & /WhitePoint
  2616. //
  2617. pBuffer += SendCRDBWPoint(pBuffer, afxIlluminantWP);
  2618. //
  2619. // Send PQR
  2620. //
  2621. pBuffer += SendCRDPQR(pBuffer, dwIntent, afxIlluminantWP);
  2622. //
  2623. // Send LMN
  2624. //
  2625. pBuffer += SendCRDLMN(pBuffer, dwIntent, afxIlluminantWP, afxMediaWP, dwPCS);
  2626. //
  2627. // /MatrixABC
  2628. //
  2629. if (dwPCS == SPACE_XYZ)
  2630. {
  2631. //
  2632. // Switch ABC to BAC, since we want to output B
  2633. // which is converted from Y
  2634. //
  2635. pBuffer += WriteNewLineObject(pBuffer, MatrixABCTag);
  2636. pBuffer += WriteObject(pBuffer, MatrixABCXYZCRD);
  2637. }
  2638. else if (dwPCS == SPACE_Lab)
  2639. {
  2640. pBuffer += WriteNewLineObject(pBuffer, MatrixABCTag);
  2641. pBuffer += WriteObject(pBuffer, MatrixABCLabCRD);
  2642. }
  2643. //
  2644. // /EncodeABC
  2645. //
  2646. if (nCount != 0)
  2647. {
  2648. pBuffer += WriteObject(pBuffer, NewLine);
  2649. pLineStart = pBuffer;
  2650. pBuffer += WriteObject(pBuffer, EncodeABCTag);
  2651. pBuffer += WriteObject(pBuffer, BeginArray);
  2652. pBuffer += WriteObject(pBuffer, BeginFunction);
  2653. if (nCount == 1) // Gamma supplied in ui16 format
  2654. {
  2655. PBYTE pTable;
  2656. pTable = (PBYTE) (pData->data);
  2657. pBuffer += WriteInt(pBuffer, FIX_ENDIAN16(*((PWORD)pTable)));
  2658. pBuffer += WriteObject(pBuffer, DecodeA3Rev);
  2659. }
  2660. else
  2661. {
  2662. if (dwPCS == SPACE_Lab)
  2663. {
  2664. pBuffer += WriteObject(pBuffer, EncodeABCLab1);
  2665. }
  2666. pBuffer += WriteObject(pBuffer, StartClip);
  2667. pBuffer += WriteObject(pBuffer, BeginArray);
  2668. for (i=0; i<nCount * REVCURVE_RATIO; i++)
  2669. {
  2670. pBuffer += WriteInt(pBuffer, *((WORD *)pRevCurve));
  2671. pRevCurve++;
  2672. if (((DWORD) (pBuffer - pLineStart)) > MAX_LINELEN)
  2673. {
  2674. pLineStart = pBuffer;
  2675. pBuffer += WriteObject(pBuffer, NewLine);
  2676. }
  2677. }
  2678. pBuffer += WriteObject(pBuffer, EndArray);
  2679. pLineStart = pBuffer;
  2680. pBuffer += WriteNewLineObject(pBuffer, IndexArray);
  2681. pBuffer += WriteObject(pBuffer, Scale16);
  2682. pBuffer += WriteObject(pBuffer, EndClip);
  2683. }
  2684. pBuffer += WriteObject (pBuffer, EndFunction);
  2685. pBuffer += WriteObject (pBuffer, DupOp);
  2686. pBuffer += WriteObject (pBuffer, DupOp);
  2687. pBuffer += WriteObject (pBuffer, EndArray);
  2688. }
  2689. pBuffer += WriteObject(pBuffer, EndDict); // End dictionary definition
  2690. MemFree(pRevCurveStart);
  2691. *pcbSize = (DWORD) (pBuffer - pStart);
  2692. return TRUE;
  2693. }
  2694. /***************************************************************************
  2695. * CreateLutCRD
  2696. * function:
  2697. * this is the function which creates the Color Rendering Dictionary (CRD)
  2698. * from the data supplied in the ColorProfile's LUT8 or LUT16 tag.
  2699. *
  2700. * returns:
  2701. * BOOL -- !=0 if the function was successful,
  2702. * 0 otherwise.
  2703. * Returns number of bytes required/transferred
  2704. ***************************************************************************/
  2705. BOOL
  2706. CreateLutCRD(
  2707. PBYTE pProfile,
  2708. DWORD dwIndex,
  2709. PBYTE pBuffer,
  2710. PDWORD pcbSize,
  2711. DWORD dwIntent,
  2712. BOOL bBinary
  2713. )
  2714. {
  2715. PTAGDATA pTagData;
  2716. PLUT16TYPE pLut;
  2717. PBYTE pTable;
  2718. PBYTE pLineStart, pStart = pBuffer;
  2719. DWORD dwPCS, dwSize, dwLutSig, dwTag, i, j;
  2720. DWORD nInputCh, nOutputCh, nGrids, nInputTable, nOutputTable, nNumbers;
  2721. FIX_16_16 afxIlluminantWP[3];
  2722. FIX_16_16 afxMediaWP[3];
  2723. char pPublicArrayName[5];
  2724. //
  2725. // Check if we can generate the CSA
  2726. // Required tags is AToBi, where i is the rendering intent
  2727. //
  2728. dwPCS = GetCPConnSpace(pProfile);
  2729. pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
  2730. dwIndex * sizeof(TAGDATA));
  2731. dwTag = FIX_ENDIAN(pTagData->tagType);
  2732. pLut = (PLUT16TYPE)(pProfile + FIX_ENDIAN(pTagData->dwOffset));
  2733. dwLutSig = FIX_ENDIAN(pLut->dwSignature);
  2734. if ((dwLutSig != LUT8_TYPE) && (dwLutSig != LUT16_TYPE))
  2735. {
  2736. WARNING((__TEXT("Invalid profile - unable to create Lut CRD\n")));
  2737. SetLastError(ERROR_INVALID_PROFILE);
  2738. return FALSE;
  2739. }
  2740. //
  2741. // Estimate size required to hold the CSA
  2742. //
  2743. (void)GetCLUTInfo(dwLutSig, (PBYTE)pLut, &nInputCh, &nOutputCh, &nGrids,
  2744. &nInputTable, &nOutputTable, NULL);
  2745. //
  2746. // Calculate size of buffer needed
  2747. //
  2748. dwSize = nInputCh * nInputTable * 6 +
  2749. nOutputCh * nOutputTable * 6 + // Number of INT bytes
  2750. nOutputCh * nGrids * nGrids * nGrids * 2 + // LUT HEX bytes
  2751. nInputCh * (STRLEN(IndexArray) +
  2752. STRLEN(StartClip) +
  2753. STRLEN(EndClip)) +
  2754. nOutputCh * (STRLEN(IndexArray) +
  2755. STRLEN(StartClip) +
  2756. STRLEN(EndClip)) +
  2757. 2048; // + other PS stuff
  2758. //
  2759. // Add space for new line.
  2760. //
  2761. dwSize += (((dwSize) / MAX_LINELEN) + 1) * STRLEN(NewLine);
  2762. if (! pBuffer)
  2763. {
  2764. *pcbSize = dwSize;
  2765. return TRUE;
  2766. }
  2767. else if (*pcbSize < dwSize)
  2768. {
  2769. WARNING((__TEXT("Buffer too small to get DEFG CSA\n")));
  2770. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  2771. return FALSE;
  2772. }
  2773. //
  2774. // Get info about Illuminant White Point from the header
  2775. //
  2776. (void)GetCPWhitePoint(pProfile, afxIlluminantWP);
  2777. //
  2778. // Support absolute whitePoint
  2779. //
  2780. if (dwIntent == INTENT_ABSOLUTE_COLORIMETRIC)
  2781. {
  2782. if (! GetCPMediaWhitePoint(pProfile, afxMediaWP))
  2783. {
  2784. afxMediaWP[0] = afxIlluminantWP[0];
  2785. afxMediaWP[1] = afxIlluminantWP[1];
  2786. afxMediaWP[2] = afxIlluminantWP[2];
  2787. }
  2788. }
  2789. //
  2790. // Define global array used in EncodeABC and RenderTable
  2791. //
  2792. GetPublicArrayName(dwTag, pPublicArrayName);
  2793. pBuffer += WriteNewLineObject(pBuffer, CRDBegin);
  2794. pBuffer += EnableGlobalDict(pBuffer);
  2795. pBuffer += BeginGlobalDict(pBuffer);
  2796. pBuffer += CreateInputArray(pBuffer, nInputCh, nInputTable,
  2797. pPublicArrayName, dwLutSig, (PBYTE)pLut, bBinary, NULL);
  2798. i = nInputTable * nInputCh +
  2799. nGrids * nGrids * nGrids * nOutputCh;
  2800. pBuffer += CreateOutputArray(pBuffer, nOutputCh, nOutputTable, i,
  2801. pPublicArrayName, dwLutSig, (PBYTE)pLut, bBinary, NULL);
  2802. pBuffer += EndGlobalDict(pBuffer);
  2803. //
  2804. // Start writing the CRD
  2805. //
  2806. pBuffer += WriteNewLineObject(pBuffer, BeginDict); // Begin dictionary
  2807. pBuffer += WriteObject(pBuffer, DictType); // Dictionary type
  2808. //
  2809. // Send /RenderingIntent
  2810. //
  2811. switch (dwIntent)
  2812. {
  2813. case INTENT_PERCEPTUAL:
  2814. pBuffer += WriteNewLineObject(pBuffer, IntentType);
  2815. pBuffer += WriteObject(pBuffer, IntentPer);
  2816. break;
  2817. case INTENT_SATURATION:
  2818. pBuffer += WriteNewLineObject(pBuffer, IntentType);
  2819. pBuffer += WriteObject(pBuffer, IntentSat);
  2820. break;
  2821. case INTENT_RELATIVE_COLORIMETRIC:
  2822. pBuffer += WriteNewLineObject(pBuffer, IntentType);
  2823. pBuffer += WriteObject(pBuffer, IntentRCol);
  2824. break;
  2825. case INTENT_ABSOLUTE_COLORIMETRIC:
  2826. pBuffer += WriteNewLineObject(pBuffer, IntentType);
  2827. pBuffer += WriteObject(pBuffer, IntentACol);
  2828. break;
  2829. }
  2830. //
  2831. // Send /BlackPoint & /WhitePoint
  2832. //
  2833. pBuffer += SendCRDBWPoint(pBuffer, afxIlluminantWP);
  2834. //
  2835. // Send PQR
  2836. //
  2837. pBuffer += SendCRDPQR(pBuffer, dwIntent, afxIlluminantWP);
  2838. //
  2839. // Send LMN
  2840. //
  2841. pBuffer += SendCRDLMN(pBuffer, dwIntent, afxIlluminantWP, afxMediaWP, dwPCS);
  2842. //
  2843. // Send ABC
  2844. //
  2845. pBuffer += SendCRDABC(pBuffer, pPublicArrayName, dwPCS, nInputCh,
  2846. (PBYTE)pLut, NULL, dwLutSig, bBinary);
  2847. //
  2848. // /RenderTable
  2849. //
  2850. pBuffer += WriteNewLineObject(pBuffer, RenderTableTag);
  2851. pBuffer += WriteObject(pBuffer, BeginArray);
  2852. pBuffer += WriteInt(pBuffer, nGrids); // Send down Na
  2853. pBuffer += WriteInt(pBuffer, nGrids); // Send down Nb
  2854. pBuffer += WriteInt(pBuffer, nGrids); // Send down Nc
  2855. pLineStart = pBuffer;
  2856. pBuffer += WriteNewLineObject(pBuffer, BeginArray);
  2857. nNumbers = nGrids * nGrids * nOutputCh;
  2858. for (i=0; i<nGrids; i++) // Na strings should be sent
  2859. {
  2860. pBuffer += WriteObject(pBuffer, NewLine);
  2861. pLineStart = pBuffer;
  2862. if (dwLutSig == LUT8_TYPE)
  2863. {
  2864. pTable = (PBYTE)(((PLUT8TYPE)pLut)->data) + nInputTable * nInputCh + nNumbers * i;
  2865. }
  2866. else
  2867. {
  2868. pTable = (PBYTE)(((PLUT16TYPE)pLut)->data) + 2 * nInputTable * nInputCh + 2 * nNumbers * i;
  2869. }
  2870. if (! bBinary)
  2871. {
  2872. pBuffer += WriteObject(pBuffer, BeginString);
  2873. if (dwLutSig == LUT8_TYPE)
  2874. {
  2875. pBuffer += WriteHexBuffer(pBuffer, pTable, pLineStart, nNumbers);
  2876. }
  2877. else
  2878. {
  2879. for (j=0; j<nNumbers; j++)
  2880. {
  2881. pBuffer += WriteHex(pBuffer, FIX_ENDIAN16(*((PWORD)pTable)) / 256);
  2882. pTable += sizeof(WORD);
  2883. if (((DWORD) (pBuffer - pLineStart)) > MAX_LINELEN)
  2884. {
  2885. pLineStart = pBuffer;
  2886. pBuffer += WriteObject(pBuffer, NewLine);
  2887. }
  2888. }
  2889. }
  2890. pBuffer += WriteObject(pBuffer, EndString);
  2891. }
  2892. else
  2893. {
  2894. pBuffer += WriteStringToken(pBuffer, 143, nNumbers);
  2895. if (dwLutSig == LUT8_TYPE)
  2896. {
  2897. pBuffer += WriteByteString(pBuffer, pTable, nNumbers);
  2898. }
  2899. else
  2900. {
  2901. pBuffer += WriteInt2ByteString(pBuffer, pTable, nNumbers);
  2902. }
  2903. }
  2904. }
  2905. pBuffer += WriteObject(pBuffer, EndArray); // End array
  2906. pBuffer += WriteInt(pBuffer, nOutputCh); // Send down m
  2907. pBuffer += SendCRDOutputTable(pBuffer, pPublicArrayName,
  2908. nOutputCh, dwLutSig, FALSE, bBinary);
  2909. pBuffer += WriteObject(pBuffer, EndArray); // End array
  2910. pBuffer += WriteObject(pBuffer, EndDict); // End dictionary definition
  2911. pBuffer += WriteNewLineObject(pBuffer, CRDEnd);
  2912. *pcbSize = (DWORD) (pBuffer - pStart);
  2913. return TRUE;
  2914. }
  2915. #if !defined(KERNEL_MODE) || defined(USERMODE_DRIVER)
  2916. /***************************************************************************
  2917. * CreateMatrixCRD
  2918. * function:
  2919. * this is the function which creates the Color Rendering Dictionary (CRD)
  2920. * from the data supplied in the redTRC, greenTRC, blueTRA, redColorant,
  2921. * greenColorant and BlueColorant tags
  2922. *
  2923. * returns:
  2924. * BOOL -- !=0 if the function was successful,
  2925. * 0 otherwise.
  2926. * Returns number of bytes required/transferred
  2927. ***************************************************************************/
  2928. // With matrix/TRC model, only the CIEXYZ encoding of the PCS can be used.
  2929. // So, we don't need to worry about CIELAB.
  2930. BOOL
  2931. CreateMatrixCRD(
  2932. PBYTE pProfile,
  2933. PBYTE pBuffer,
  2934. PDWORD pcbSize,
  2935. DWORD dwIntent,
  2936. BOOL bBinary
  2937. )
  2938. {
  2939. PTAGDATA pTagData;
  2940. DWORD dwRedTRCIndex, dwGreenTRCIndex, dwBlueTRCIndex;
  2941. DWORD dwRedCount, dwGreenCount, dwBlueCount;
  2942. PBYTE pMem = NULL;
  2943. PCURVETYPE pRed, pGreen, pBlue;
  2944. DWORD i, dwSize;
  2945. PBYTE pStart = pBuffer;
  2946. PWORD pRevCurve;
  2947. FIX_16_16 afxIlluminantWP[3];
  2948. double adColorant[9];
  2949. double adRevColorant[9];
  2950. //
  2951. // Check this is sRGB color profile or not.
  2952. //
  2953. if (IsSRGBColorProfile(pProfile))
  2954. {
  2955. dwSize = 4096; // hack - approx.
  2956. //
  2957. // Return buffer size, if this is a size request
  2958. //
  2959. if (! pBuffer)
  2960. {
  2961. *pcbSize = dwSize;
  2962. return TRUE;
  2963. }
  2964. //
  2965. // Check buffer size.
  2966. //
  2967. if (*pcbSize < dwSize)
  2968. {
  2969. WARNING((__TEXT("Buffer too small to get sRGB CRD\n")));
  2970. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  2971. return FALSE;
  2972. }
  2973. //
  2974. // Start writing the CRD
  2975. //
  2976. pBuffer += WriteNewLineObject(pBuffer, CRDBegin);
  2977. pBuffer += WriteNewLineObject(pBuffer, BeginDict); // Begin dictionary
  2978. pBuffer += WriteObject(pBuffer, DictType); // Dictionary type
  2979. //
  2980. // Send /RenderingIntent
  2981. //
  2982. switch (dwIntent)
  2983. {
  2984. case INTENT_PERCEPTUAL:
  2985. pBuffer += WriteNewLineObject(pBuffer, IntentType);
  2986. pBuffer += WriteObject(pBuffer, IntentPer);
  2987. break;
  2988. case INTENT_SATURATION:
  2989. pBuffer += WriteNewLineObject(pBuffer, IntentType);
  2990. pBuffer += WriteObject(pBuffer, IntentSat);
  2991. break;
  2992. case INTENT_RELATIVE_COLORIMETRIC:
  2993. pBuffer += WriteNewLineObject(pBuffer, IntentType);
  2994. pBuffer += WriteObject(pBuffer, IntentRCol);
  2995. break;
  2996. case INTENT_ABSOLUTE_COLORIMETRIC:
  2997. pBuffer += WriteNewLineObject(pBuffer, IntentType);
  2998. pBuffer += WriteObject(pBuffer, IntentACol);
  2999. break;
  3000. }
  3001. //
  3002. // Write prepaired sRGB CRD.
  3003. //
  3004. pBuffer += WriteNewLineObject(pBuffer, sRGBColorRenderingDictionary);
  3005. //
  3006. // End CRD.
  3007. //
  3008. pBuffer += WriteNewLineObject(pBuffer, CRDEnd);
  3009. }
  3010. else
  3011. {
  3012. //
  3013. // Get each TRC index for Red, Green and Blue.
  3014. //
  3015. if (!DoesCPTagExist(pProfile, TAG_REDTRC, &dwRedTRCIndex) ||
  3016. !DoesCPTagExist(pProfile, TAG_GREENTRC, &dwGreenTRCIndex) ||
  3017. !DoesCPTagExist(pProfile, TAG_BLUETRC, &dwBlueTRCIndex))
  3018. {
  3019. return FALSE;
  3020. }
  3021. //
  3022. // Get CURVETYPE data for each Red, Green and Blue
  3023. //
  3024. pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
  3025. dwRedTRCIndex * sizeof(TAGDATA));
  3026. pRed = (PCURVETYPE)(pProfile + FIX_ENDIAN(pTagData->dwOffset));
  3027. pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
  3028. dwGreenTRCIndex * sizeof(TAGDATA));
  3029. pGreen = (PCURVETYPE)(pProfile + FIX_ENDIAN(pTagData->dwOffset));
  3030. pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
  3031. dwBlueTRCIndex * sizeof(TAGDATA));
  3032. pBlue = (PCURVETYPE)(pProfile + FIX_ENDIAN(pTagData->dwOffset));
  3033. //
  3034. // Get curve count for each Red, Green and Blue.
  3035. //
  3036. dwRedCount = FIX_ENDIAN(pRed->nCount);
  3037. dwGreenCount = FIX_ENDIAN(pGreen->nCount);
  3038. dwBlueCount = FIX_ENDIAN(pBlue->nCount);
  3039. //
  3040. // Estimate the memory size required to hold CRD
  3041. //
  3042. dwSize = (dwRedCount + dwGreenCount + dwBlueCount) * 6 * REVCURVE_RATIO +
  3043. 4096; // Number of INT elements + other PS stuff
  3044. //
  3045. // Add space for new line.
  3046. //
  3047. dwSize += (((dwSize) / MAX_LINELEN) + 1) * STRLEN(NewLine);
  3048. if (pBuffer == NULL) // This is a size request
  3049. {
  3050. *pcbSize = dwSize;
  3051. return TRUE;
  3052. }
  3053. //
  3054. // Check buffer size.
  3055. //
  3056. if (*pcbSize < dwSize)
  3057. {
  3058. WARNING((__TEXT("Buffer too small to get sRGB CRD\n")));
  3059. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  3060. return FALSE;
  3061. }
  3062. //
  3063. // Allocate buffer for curves
  3064. //
  3065. if ((pRevCurve = MemAlloc(dwRedCount * sizeof(WORD) * (REVCURVE_RATIO + 1))) == NULL)
  3066. {
  3067. WARNING((__TEXT("Unable to allocate memory for reserved curve\n")));
  3068. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  3069. MemFree(pMem);
  3070. return FALSE;
  3071. }
  3072. //
  3073. // Get info about Illuminant White Point from the header
  3074. //
  3075. (void)GetCPWhitePoint(pProfile, afxIlluminantWP);
  3076. //
  3077. // Start writing the CRD
  3078. //
  3079. pBuffer += EnableGlobalDict(pBuffer);
  3080. pBuffer += BeginGlobalDict(pBuffer);
  3081. pBuffer += CreateCRDRevArray(pProfile, pBuffer, pRed, pRevCurve, TAG_REDTRC, bBinary);
  3082. pBuffer += CreateCRDRevArray(pProfile, pBuffer, pGreen, pRevCurve, TAG_GREENTRC, bBinary);
  3083. pBuffer += CreateCRDRevArray(pProfile, pBuffer, pBlue, pRevCurve, TAG_BLUETRC, bBinary);
  3084. pBuffer += EndGlobalDict(pBuffer);
  3085. //
  3086. // Start writing the CRD
  3087. //
  3088. pBuffer += WriteNewLineObject(pBuffer, CRDBegin);
  3089. pBuffer += WriteNewLineObject(pBuffer, BeginDict); // Begin dictionary
  3090. pBuffer += WriteObject(pBuffer, DictType); // Dictionary type
  3091. //
  3092. // Send /RenderingIntent
  3093. //
  3094. switch (dwIntent)
  3095. {
  3096. case INTENT_PERCEPTUAL:
  3097. pBuffer += WriteNewLineObject(pBuffer, IntentType);
  3098. pBuffer += WriteObject(pBuffer, IntentPer);
  3099. break;
  3100. case INTENT_SATURATION:
  3101. pBuffer += WriteNewLineObject(pBuffer, IntentType);
  3102. pBuffer += WriteObject(pBuffer, IntentSat);
  3103. break;
  3104. case INTENT_RELATIVE_COLORIMETRIC:
  3105. pBuffer += WriteNewLineObject(pBuffer, IntentType);
  3106. pBuffer += WriteObject(pBuffer, IntentRCol);
  3107. break;
  3108. case INTENT_ABSOLUTE_COLORIMETRIC:
  3109. pBuffer += WriteNewLineObject(pBuffer, IntentType);
  3110. pBuffer += WriteObject(pBuffer, IntentACol);
  3111. break;
  3112. }
  3113. //
  3114. // Send /BlackPoint & /WhitePoint
  3115. //
  3116. pBuffer += SendCRDBWPoint(pBuffer, afxIlluminantWP);
  3117. //
  3118. // Send PQR
  3119. //
  3120. pBuffer += SendCRDPQR(pBuffer, dwIntent, afxIlluminantWP);
  3121. //
  3122. // Send LMN
  3123. //
  3124. CreateColorantArray(pProfile, &adColorant[0], TAG_REDCOLORANT);
  3125. CreateColorantArray(pProfile, &adColorant[3], TAG_GREENCOLORANT);
  3126. CreateColorantArray(pProfile, &adColorant[6], TAG_BLUECOLORANT);
  3127. InvertColorantArray(adColorant, adRevColorant);
  3128. pBuffer += WriteNewLineObject(pBuffer, MatrixLMNTag);
  3129. pBuffer += WriteObject(pBuffer, BeginArray);
  3130. for (i = 0; i < 9; i++)
  3131. {
  3132. pBuffer += WriteDouble(pBuffer, adRevColorant[i]);
  3133. }
  3134. pBuffer += WriteObject(pBuffer, EndArray);
  3135. //
  3136. // /EncodeABC
  3137. //
  3138. pBuffer += WriteNewLineObject(pBuffer, EncodeABCTag);
  3139. pBuffer += WriteObject(pBuffer, BeginArray);
  3140. pBuffer += WriteObject(pBuffer, NewLine);
  3141. pBuffer += SendCRDRevArray(pProfile, pBuffer, pRed, TAG_REDTRC, bBinary);
  3142. pBuffer += WriteObject(pBuffer, NewLine);
  3143. pBuffer += SendCRDRevArray(pProfile, pBuffer, pGreen, TAG_GREENTRC, bBinary);
  3144. pBuffer += WriteObject(pBuffer, NewLine);
  3145. pBuffer += SendCRDRevArray(pProfile, pBuffer, pBlue, TAG_BLUETRC, bBinary);
  3146. pBuffer += WriteNewLineObject(pBuffer, EndArray);
  3147. pBuffer += WriteObject(pBuffer, EndDict); // End dictionary definition
  3148. pBuffer += WriteNewLineObject(pBuffer, CRDEnd);
  3149. MemFree (pRevCurve);
  3150. }
  3151. *pcbSize = (DWORD)(pBuffer - pStart);
  3152. return TRUE;
  3153. }
  3154. DWORD
  3155. CreateCRDRevArray(
  3156. PBYTE pProfile,
  3157. PBYTE pBuffer,
  3158. PCURVETYPE pData,
  3159. PWORD pRevCurve,
  3160. DWORD dwTag,
  3161. BOOL bBinary
  3162. )
  3163. {
  3164. DWORD i, nCount;
  3165. PBYTE pStart, pLineStart;
  3166. PWORD pCurve;
  3167. pStart = pBuffer;
  3168. pLineStart = pBuffer;
  3169. nCount = FIX_ENDIAN(pData->nCount);
  3170. if (nCount > 1)
  3171. {
  3172. pBuffer += WriteNewLineObject(pBuffer, Slash);
  3173. pBuffer += WriteObject(pBuffer, InputArray);
  3174. pBuffer += WriteInt(pBuffer, (INT) dwTag);
  3175. pCurve = pRevCurve + (REVCURVE_RATIO * nCount);
  3176. GetRevCurve (pData, pCurve, pRevCurve);
  3177. if (!bBinary) // Output ASCII DATA
  3178. {
  3179. pBuffer += WriteObject(pBuffer, BeginArray);
  3180. for (i = 0; i < nCount * REVCURVE_RATIO; i++)
  3181. {
  3182. pBuffer += WriteInt(pBuffer, *pRevCurve);
  3183. pRevCurve++;
  3184. if (((DWORD) (pBuffer - pLineStart)) > MAX_LINELEN)
  3185. {
  3186. pLineStart = pBuffer;
  3187. pBuffer += WriteObject(pBuffer, NewLine);
  3188. }
  3189. }
  3190. pBuffer += WriteObject(pBuffer, EndArray);
  3191. }
  3192. else // Output BINARY DATA
  3193. {
  3194. pBuffer += WriteHNAToken(pBuffer, 149, nCount);
  3195. pBuffer += WriteIntStringU2S_L(pBuffer, (PBYTE) pRevCurve, nCount);
  3196. }
  3197. pBuffer += WriteObject(pBuffer, DefOp);
  3198. }
  3199. return (DWORD)(pBuffer - pStart);
  3200. }
  3201. DWORD
  3202. SendCRDRevArray(
  3203. PBYTE pProfile,
  3204. PBYTE pBuffer,
  3205. PCURVETYPE pData,
  3206. DWORD dwTag,
  3207. BOOL bBinary
  3208. )
  3209. {
  3210. DWORD nCount;
  3211. PBYTE pStart;
  3212. PWORD pTable;
  3213. pStart = pBuffer;
  3214. pBuffer += WriteObject(pBuffer, BeginFunction);
  3215. nCount = FIX_ENDIAN(pData->nCount);
  3216. if (nCount != 0)
  3217. {
  3218. if (nCount == 1) // Gamma supplied in ui16 format
  3219. {
  3220. pTable = pData->data;
  3221. pBuffer += WriteInt(pBuffer, FIX_ENDIAN16(*pTable));
  3222. pBuffer += WriteObject(pBuffer, DecodeA3Rev);
  3223. }
  3224. else
  3225. {
  3226. pBuffer += WriteObject(pBuffer, StartClip);
  3227. pBuffer += WriteObject(pBuffer, InputArray);
  3228. pBuffer += WriteInt(pBuffer, dwTag);
  3229. if (!bBinary) // Output ASCII CS
  3230. {
  3231. pBuffer += WriteObject(pBuffer, IndexArray);
  3232. }
  3233. else // Output BINARY CS
  3234. {
  3235. pBuffer += WriteObject(pBuffer, IndexArray16b);
  3236. }
  3237. pBuffer += WriteObject(pBuffer, Scale16);
  3238. pBuffer += WriteObject(pBuffer, EndClip);
  3239. }
  3240. }
  3241. pBuffer += WriteObject(pBuffer, EndFunction);
  3242. return (DWORD)(pBuffer - pStart);
  3243. }
  3244. BOOL
  3245. CreateColorantArray(
  3246. PBYTE pProfile,
  3247. double *lpArray,
  3248. DWORD dwTag
  3249. )
  3250. {
  3251. PTAGDATA pTagData;
  3252. PXYZTYPE pData;
  3253. PFIX_16_16 pTable;
  3254. DWORD i, dwIndex;
  3255. BYTE buffer[1000];
  3256. if (DoesCPTagExist(pProfile, dwTag, &dwIndex))
  3257. {
  3258. pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
  3259. dwIndex * sizeof(TAGDATA));
  3260. pData = (PXYZTYPE)(pProfile + FIX_ENDIAN(pTagData->dwOffset));
  3261. pTable = pData->afxData;
  3262. for (i = 0; i < 3; i++)
  3263. {
  3264. FIX_16_16 afxData = FIX_ENDIAN(*pTable);
  3265. //
  3266. // Convert Fix 16.16 to double.
  3267. //
  3268. *lpArray = ((double) afxData) / ((double) FIX_16_16_SCALE);
  3269. pTable++; lpArray++;
  3270. }
  3271. return (TRUE);
  3272. }
  3273. return (FALSE);
  3274. }
  3275. #endif // !defined(KERNEL_MODE) || defined(USERMODE_DRIVER)
  3276. /***************************************************************************
  3277. * GetRevCurve
  3278. * function:
  3279. * returns:
  3280. * BOOL -- TRUE: successful,
  3281. * FALSE: otherwise.
  3282. ***************************************************************************/
  3283. BOOL
  3284. GetRevCurve(
  3285. PCURVETYPE pData,
  3286. PWORD pInput,
  3287. PWORD pOutput
  3288. )
  3289. {
  3290. PBYTE pTable;
  3291. DWORD nCount, dwStore, i, j;
  3292. DWORD dwBegin, dwEnd, dwTemp;
  3293. nCount = FIX_ENDIAN(pData->nCount);
  3294. pTable = (PBYTE)pData->data;
  3295. if(nCount < 2)
  3296. {
  3297. WARNING((__TEXT("nCount < 2 in GetRevCurve\n")));
  3298. return FALSE;
  3299. }
  3300. for (i=0; i<nCount; i++)
  3301. {
  3302. pInput[i] = FIX_ENDIAN16(*((PWORD)pTable));
  3303. pTable += sizeof(WORD);
  3304. }
  3305. j = nCount * REVCURVE_RATIO;
  3306. for (i=0; i<j; i++)
  3307. {
  3308. dwStore = i * 65535 / (j - 1);
  3309. pOutput[i] = (dwStore < 65535) ? (WORD) dwStore : 65535;
  3310. }
  3311. for (i=0; i<j; i++)
  3312. {
  3313. dwBegin = 0;
  3314. dwEnd = nCount - 1;
  3315. for (;;)
  3316. {
  3317. if ((dwEnd - dwBegin) <= 1)
  3318. break;
  3319. dwTemp = (dwEnd + dwBegin) / 2;
  3320. if (pOutput[i] < pInput[dwTemp])
  3321. dwEnd = dwTemp;
  3322. else
  3323. dwBegin = dwTemp;
  3324. }
  3325. if (pOutput[i] <= pInput[dwBegin])
  3326. {
  3327. dwStore = dwBegin;
  3328. }
  3329. else if (pOutput[i] >= pInput[dwEnd])
  3330. {
  3331. dwStore = dwEnd;
  3332. }
  3333. else
  3334. {
  3335. dwStore = (pInput[dwEnd] - pOutput[i]) / (pOutput[i] - pInput[dwBegin]);
  3336. dwStore = (dwBegin * dwStore + dwEnd) / (dwStore + 1);
  3337. }
  3338. dwStore = dwStore * 65535 / (nCount - 1);
  3339. pOutput[i] = (dwStore < 65535) ? (WORD) dwStore : 65535;
  3340. }
  3341. return TRUE;
  3342. }
  3343. BOOL
  3344. DoesCPTagExist(
  3345. PBYTE pProfile,
  3346. DWORD dwTag,
  3347. PDWORD pdwIndex
  3348. )
  3349. {
  3350. DWORD i, dwCount;
  3351. PTAGDATA pTagData;
  3352. BOOL bRc;
  3353. //
  3354. // Get count of tag items - it is right after the profile header
  3355. //
  3356. dwCount = FIX_ENDIAN(*((DWORD *)(pProfile + sizeof(PROFILEHEADER))));
  3357. //
  3358. // Tag data records follow the count.
  3359. //
  3360. pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD));
  3361. //
  3362. // Check if any of these records match the tag passed in.
  3363. //
  3364. bRc = FALSE;
  3365. dwTag = FIX_ENDIAN(dwTag); // to match tags in profile
  3366. for (i=0; i<dwCount; i++)
  3367. {
  3368. if (pTagData->tagType == dwTag)
  3369. {
  3370. if (pdwIndex)
  3371. {
  3372. *pdwIndex = i;
  3373. }
  3374. bRc = TRUE;
  3375. break;
  3376. }
  3377. pTagData++; // Next record
  3378. }
  3379. return bRc;
  3380. }
  3381. BOOL
  3382. DoesTRCAndColorantTagExist(
  3383. PBYTE pProfile
  3384. )
  3385. {
  3386. if (DoesCPTagExist(pProfile,TAG_REDCOLORANT,NULL) &&
  3387. DoesCPTagExist(pProfile,TAG_REDTRC,NULL) &&
  3388. DoesCPTagExist(pProfile,TAG_GREENCOLORANT,NULL) &&
  3389. DoesCPTagExist(pProfile,TAG_GREENTRC,NULL) &&
  3390. DoesCPTagExist(pProfile,TAG_BLUECOLORANT,NULL) &&
  3391. DoesCPTagExist(pProfile,TAG_BLUETRC,NULL))
  3392. {
  3393. return TRUE;
  3394. }
  3395. return FALSE;
  3396. }
  3397. BOOL
  3398. GetCPWhitePoint(
  3399. PBYTE pProfile,
  3400. PFIX_16_16 pafxWP
  3401. )
  3402. {
  3403. pafxWP[0] = FIX_ENDIAN(((PPROFILEHEADER)pProfile)->phIlluminant.ciexyzX);
  3404. pafxWP[1] = FIX_ENDIAN(((PPROFILEHEADER)pProfile)->phIlluminant.ciexyzY);
  3405. pafxWP[2] = FIX_ENDIAN(((PPROFILEHEADER)pProfile)->phIlluminant.ciexyzZ);
  3406. return TRUE;
  3407. }
  3408. BOOL
  3409. GetCPMediaWhitePoint(
  3410. PBYTE pProfile,
  3411. PFIX_16_16 pafxMediaWP
  3412. )
  3413. {
  3414. PTAGDATA pTagData;
  3415. PDWORD pTable;
  3416. DWORD dwIndex, i;
  3417. if (DoesCPTagExist (pProfile, TAG_MEDIAWHITEPOINT, &dwIndex))
  3418. {
  3419. pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
  3420. dwIndex * sizeof(TAGDATA));
  3421. //
  3422. // Skip the first 2 DWORDs to get to the real data
  3423. //
  3424. pTable = (PDWORD)(pProfile + FIX_ENDIAN(pTagData->dwOffset)) + 2;
  3425. for (i=0; i<3; i++)
  3426. {
  3427. pafxMediaWP[i] = FIX_ENDIAN(*pTable);
  3428. pTable++;
  3429. }
  3430. return TRUE;
  3431. }
  3432. return FALSE;
  3433. }
  3434. BOOL
  3435. GetCPElementDataSize(
  3436. PBYTE pProfile,
  3437. DWORD dwIndex,
  3438. PDWORD pcbSize)
  3439. {
  3440. PTAGDATA pTagData;
  3441. pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
  3442. dwIndex * sizeof(TAGDATA));
  3443. //
  3444. // Actual data Size of elements of type 'dataType' is 3 DWORDs less than the
  3445. // total tag data size
  3446. //
  3447. *pcbSize = FIX_ENDIAN(pTagData->cbSize) - 3 * sizeof(DWORD);
  3448. return TRUE;
  3449. }
  3450. BOOL
  3451. GetCPElementSize(
  3452. PBYTE pProfile,
  3453. DWORD dwIndex,
  3454. PDWORD pcbSize)
  3455. {
  3456. PTAGDATA pTagData;
  3457. pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
  3458. dwIndex * sizeof(TAGDATA));
  3459. *pcbSize = FIX_ENDIAN(pTagData->cbSize);
  3460. return TRUE;
  3461. }
  3462. BOOL
  3463. GetCPElementDataType(
  3464. PBYTE pProfile,
  3465. DWORD dwIndex,
  3466. PDWORD pdwDataType)
  3467. {
  3468. PTAGDATA pTagData;
  3469. PBYTE pData;
  3470. pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
  3471. dwIndex * sizeof(TAGDATA));
  3472. pData = pProfile + FIX_ENDIAN(pTagData->dwOffset);
  3473. *pdwDataType = FIX_ENDIAN(*((DWORD *)(pData + 2 * sizeof(DWORD))));
  3474. return TRUE;
  3475. }
  3476. BOOL
  3477. GetCPElementData(
  3478. PBYTE pProfile,
  3479. DWORD dwIndex,
  3480. PBYTE pBuffer,
  3481. PDWORD pdwSize
  3482. )
  3483. {
  3484. PTAGDATA pTagData;
  3485. PBYTE pData;
  3486. pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
  3487. dwIndex * sizeof(TAGDATA));
  3488. pData = pProfile + FIX_ENDIAN(pTagData->dwOffset);
  3489. //
  3490. // Actual data Size of elements of type 'dataType' is 3 DWORDs less than the
  3491. // total tag data size
  3492. //
  3493. *pdwSize = FIX_ENDIAN(pTagData->cbSize) - 3 * sizeof(DWORD);
  3494. if (pBuffer)
  3495. {
  3496. CopyMemory(pBuffer, (pData + 3*sizeof(DWORD)), *pdwSize);
  3497. }
  3498. return TRUE;
  3499. }
  3500. BOOL
  3501. GetTRCElementSize(
  3502. PBYTE pProfile,
  3503. DWORD dwTag,
  3504. PDWORD pdwIndex,
  3505. PDWORD pdwSize
  3506. )
  3507. {
  3508. DWORD dwDataType;
  3509. if (!DoesCPTagExist(pProfile, dwTag, pdwIndex) ||
  3510. !GetCPElementDataType(pProfile, *pdwIndex, &dwDataType) ||
  3511. !(dwDataType != SIG_CURVE_TYPE) ||
  3512. !GetCPElementSize(pProfile, *pdwIndex, pdwSize))
  3513. {
  3514. return FALSE;
  3515. }
  3516. return TRUE;
  3517. }
  3518. DWORD
  3519. Ascii85Encode(
  3520. PBYTE pBuffer,
  3521. DWORD dwDataSize,
  3522. DWORD dwBufSize
  3523. )
  3524. {
  3525. // WINBUG #83136 2-7-2000 bhouse Investigate empty function Ascii85Encode
  3526. // Old Comment:
  3527. // - To be done
  3528. #if 0
  3529. PBYTE pTempBuf, pPtr;
  3530. DWORD dwASCII85Size = 0;
  3531. DWORD dwBufSize = DataSize * 5 / 4 + sizeof(ASCII85DecodeBegin)+sizeof(ASCII85DecodeEnd) + 2048;
  3532. if ((pTempBuf = (PBYTE)MemAlloc(dwBufSize)))
  3533. {
  3534. pPtr = pTempBuf;
  3535. pPtr += WriteObject(pPtr, NewLine);
  3536. pPtr += WriteObject(pPtr, ASCII85DecodeBegin);
  3537. pPtr += WriteObject(pPtr, NewLine);
  3538. pPtr += WriteASCII85Cont(pPtr, dwBufSize, pBuffer, dwDataSize);
  3539. pPtr += WriteObject(pPtr, ASCII85DecodeEnd);
  3540. dwAscii85Size = (DWORD)(pPtr - pTempBuf);
  3541. lstrcpyn(pBuffer, pTempBuf, dwAscii85Size);
  3542. MemFree(pTempBuf);
  3543. }
  3544. return dwAscii85Size;
  3545. #else
  3546. return 0;
  3547. #endif
  3548. }
  3549. /***************************************************************************
  3550. *
  3551. * Function to write the Homogeneous Number Array token into the buffer
  3552. *
  3553. ***************************************************************************/
  3554. DWORD
  3555. WriteHNAToken(
  3556. PBYTE pBuffer,
  3557. BYTE token,
  3558. DWORD dwNum
  3559. )
  3560. {
  3561. *pBuffer++ = token;
  3562. *pBuffer++ = 32; // 16-bit fixed integer, high-order byte first
  3563. *pBuffer++ = (BYTE)((dwNum & 0xFF00) >> 8);
  3564. *pBuffer++ = (BYTE)(dwNum & 0x00FF);
  3565. return 4;
  3566. }
  3567. /***************************************************************************
  3568. *
  3569. * Function to convert 2-bytes unsigned integer to 2-bytes signed
  3570. * integer(-32768) and write them to the buffer. High byte first.
  3571. *
  3572. ***************************************************************************/
  3573. DWORD
  3574. WriteIntStringU2S(
  3575. PBYTE pBuffer,
  3576. PBYTE pData,
  3577. DWORD dwNum
  3578. )
  3579. {
  3580. DWORD i, dwTemp;
  3581. for (i=0; i<dwNum; i++)
  3582. {
  3583. dwTemp = FIX_ENDIAN16(*((PWORD)pData)) - 32768;
  3584. *pBuffer++ = (BYTE)((dwTemp & 0xFF00) >> 8);
  3585. *pBuffer++ = (BYTE)(dwTemp & 0x00FF);
  3586. pData += sizeof(WORD);
  3587. }
  3588. return dwNum * 2;
  3589. }
  3590. /***************************************************************************
  3591. *
  3592. * Function to convert 2-bytes unsigned integer to 2-bytes signed
  3593. * integer(-32768) and write them to the buffer. Low-order byte first.
  3594. *
  3595. ***************************************************************************/
  3596. DWORD
  3597. WriteIntStringU2S_L(
  3598. PBYTE pBuffer,
  3599. PBYTE pData,
  3600. DWORD dwNum
  3601. )
  3602. {
  3603. DWORD i, dwTemp;
  3604. for (i=0; i<dwNum; i++)
  3605. {
  3606. dwTemp = *((PWORD)pData) - 32768;
  3607. *pBuffer++ = (BYTE)((dwTemp & 0xFF00) >> 8);
  3608. *pBuffer++ = (BYTE)(dwTemp & 0x00FF);
  3609. pData += sizeof(WORD);
  3610. }
  3611. return dwNum * 2;
  3612. }
  3613. /***************************************************************************
  3614. *
  3615. * Function to put the chunk of memory as string of Hex
  3616. *
  3617. ***************************************************************************/
  3618. DWORD
  3619. WriteHexBuffer(
  3620. PBYTE pBuffer,
  3621. PBYTE pData,
  3622. PBYTE pLineStart,
  3623. DWORD dwBytes
  3624. )
  3625. {
  3626. PBYTE pStart = pBuffer;
  3627. for ( ; dwBytes ; dwBytes-- )
  3628. {
  3629. WriteHex(pBuffer, *pData);
  3630. pBuffer += 2;
  3631. pData++;
  3632. if (((DWORD)(pBuffer - pLineStart)) > MAX_LINELEN)
  3633. {
  3634. pLineStart = pBuffer;
  3635. pBuffer += WriteObject(pBuffer, NewLine);
  3636. }
  3637. }
  3638. return( (DWORD)(pBuffer - pStart));
  3639. }
  3640. /***************************************************************************
  3641. *
  3642. * Function to write the string token into the buffer
  3643. *
  3644. ***************************************************************************/
  3645. DWORD
  3646. WriteStringToken(
  3647. PBYTE pBuffer,
  3648. BYTE token,
  3649. DWORD dwNum
  3650. )
  3651. {
  3652. *pBuffer++ = token;
  3653. *pBuffer++ = (BYTE)((dwNum & 0xFF00) >> 8);
  3654. *pBuffer++ = (BYTE)(dwNum & 0x00FF);
  3655. return 3;
  3656. }
  3657. /***************************************************************************
  3658. *
  3659. * Function to put the chunk of memory into buffer
  3660. *
  3661. ***************************************************************************/
  3662. DWORD
  3663. WriteByteString(
  3664. PBYTE pBuffer,
  3665. PBYTE pData,
  3666. DWORD dwBytes
  3667. )
  3668. {
  3669. DWORD i;
  3670. for (i=0; i<dwBytes; i++)
  3671. *pBuffer++ = *pData++;
  3672. return dwBytes;
  3673. }
  3674. /***************************************************************************
  3675. *
  3676. * Function to put the chunk of memory into buffer
  3677. *
  3678. ***************************************************************************/
  3679. DWORD
  3680. WriteInt2ByteString(
  3681. PBYTE pBuffer,
  3682. PBYTE pData,
  3683. DWORD dwBytes
  3684. )
  3685. {
  3686. DWORD i;
  3687. for (i=0; i<dwBytes ; i++)
  3688. {
  3689. *pBuffer++ = (BYTE)(FIX_ENDIAN16(*((PWORD)pData))/256);
  3690. pData += sizeof(WORD);
  3691. }
  3692. return dwBytes;
  3693. }
  3694. #ifndef KERNEL_MODE
  3695. DWORD
  3696. WriteFixed(
  3697. PBYTE pBuffer,
  3698. FIX_16_16 fxNum
  3699. )
  3700. {
  3701. double dFloat = (double) ((long) fxNum) / (double) FIX_16_16_SCALE;
  3702. return (WriteDouble(pBuffer,dFloat));
  3703. }
  3704. #else
  3705. DWORD
  3706. WriteFixed(
  3707. PBYTE pBuffer,
  3708. FIX_16_16 fxNum
  3709. )
  3710. {
  3711. PBYTE pStart = pBuffer;
  3712. DWORD i;
  3713. //
  3714. // Integer portion
  3715. //
  3716. #ifndef KERNEL_MODE
  3717. pBuffer += wsprintfA(pBuffer, "%lu", fxNum >> FIX_16_16_SHIFT);
  3718. #else
  3719. pBuffer += OPSprintf(pBuffer, "%l", fxNum >> FIX_16_16_SHIFT);
  3720. #endif
  3721. //
  3722. // Fractional part
  3723. //
  3724. fxNum &= 0xffff;
  3725. if (fxNum != 0)
  3726. {
  3727. //
  3728. // We output a maximum of 6 digits after the
  3729. // decimal point
  3730. //
  3731. *pBuffer++ = '.';
  3732. i = 0;
  3733. while (fxNum && i++ < 6)
  3734. {
  3735. fxNum *= 10;
  3736. *pBuffer++ = (BYTE)(fxNum >> FIX_16_16_SHIFT) + '0'; // quotient + '0'
  3737. fxNum -= FLOOR(fxNum); // remainder
  3738. }
  3739. }
  3740. *pBuffer++ = ' ';
  3741. return (DWORD) (pBuffer - pStart);
  3742. }
  3743. #endif
  3744. DWORD
  3745. WriteFixed2dot30(
  3746. PBYTE pBuffer,
  3747. DWORD fxNum
  3748. )
  3749. {
  3750. PBYTE pStart = pBuffer;
  3751. DWORD i;
  3752. //
  3753. // Integer portion
  3754. //
  3755. #ifndef KERNEL_MODE
  3756. pBuffer += wsprintfA(pBuffer, "%lu", fxNum >> 30);
  3757. #else
  3758. pBuffer += OPSprintf(pBuffer, "%l", fxNum >> 30);
  3759. #endif
  3760. //
  3761. // Fractional part
  3762. //
  3763. fxNum &= 0x3fffffffL;
  3764. if (fxNum != 0)
  3765. {
  3766. //
  3767. // We output a maximum of 10 digits after the
  3768. // decimal point
  3769. //
  3770. *pBuffer++ = '.';
  3771. i = 0;
  3772. while (fxNum && i++ < 10)
  3773. {
  3774. fxNum *= 10;
  3775. *pBuffer++ = (BYTE)(fxNum >> 30) + '0'; // quotient + '0'
  3776. fxNum -= ((fxNum >> 30) << 30); // remainder
  3777. }
  3778. }
  3779. *pBuffer++ = ' ';
  3780. return (DWORD) (pBuffer - pStart);
  3781. }
  3782. #if !defined(KERNEL_MODE) || defined(USERMODE_DRIVER)
  3783. /***************************************************************************
  3784. *
  3785. * Function to write the float into the buffer
  3786. *
  3787. ***************************************************************************/
  3788. DWORD WriteDouble(PBYTE pBuffer, double dFloat)
  3789. {
  3790. LONG lFloat = (LONG) floor(dFloat * 10000.0 + 0.5);
  3791. double dFloat1 = lFloat / 10000.0 ;
  3792. double dInt = floor(fabs(dFloat1));
  3793. double dFract = fabs(dFloat1) - dInt ;
  3794. char cSign = ' ' ;
  3795. if (dFloat1 < 0)
  3796. {
  3797. cSign = '-' ;
  3798. }
  3799. return (wsprintfA(pBuffer, (LPSTR) "%c%d.%0.4lu ",
  3800. cSign, (WORD) dInt , (DWORD) (dFract * 10000.0)));
  3801. }
  3802. #endif // !defined(KERNEL_MODE) || defined(USERMODE_DRIVER)
  3803. DWORD WriteNewLineObject(
  3804. PBYTE pBuffer,
  3805. const char *pData)
  3806. {
  3807. PBYTE pStart = pBuffer;
  3808. pBuffer += WriteObject(pBuffer, NewLine);
  3809. pBuffer += WriteObject(pBuffer, pData);
  3810. return (DWORD)(pBuffer - pStart);
  3811. }
  3812. DWORD
  3813. SendCRDBWPoint(
  3814. PBYTE pBuffer,
  3815. PFIX_16_16 pafxWP
  3816. )
  3817. {
  3818. PBYTE pStart = pBuffer;
  3819. int i;
  3820. //
  3821. // /BlackPoint
  3822. //
  3823. pBuffer += WriteObject(pBuffer, NewLine);
  3824. pBuffer += WriteObject(pBuffer, BlackPointTag);
  3825. pBuffer += WriteObject(pBuffer, BlackPoint);
  3826. //
  3827. // /WhitePoint
  3828. //
  3829. pBuffer += WriteObject(pBuffer, NewLine);
  3830. pBuffer += WriteObject(pBuffer, WhitePointTag);
  3831. pBuffer += WriteObject(pBuffer, BeginArray);
  3832. for (i=0; i<3; i++)
  3833. {
  3834. pBuffer += WriteFixed(pBuffer, pafxWP[i]);
  3835. }
  3836. pBuffer += WriteObject(pBuffer, EndArray);
  3837. return (DWORD)(pBuffer - pStart);
  3838. }
  3839. DWORD
  3840. SendCRDPQR(
  3841. PBYTE pBuffer,
  3842. DWORD dwIntent,
  3843. PFIX_16_16 pafxWP
  3844. )
  3845. {
  3846. PBYTE pStart = pBuffer;
  3847. int i;
  3848. if (dwIntent != INTENT_ABSOLUTE_COLORIMETRIC)
  3849. {
  3850. //
  3851. // /RangePQR
  3852. //
  3853. pBuffer += WriteNewLineObject(pBuffer, RangePQRTag);
  3854. pBuffer += WriteObject(pBuffer, RangePQR);
  3855. //
  3856. // /MatrixPQR
  3857. //
  3858. pBuffer += WriteNewLineObject(pBuffer, MatrixPQRTag);
  3859. pBuffer += WriteObject(pBuffer, MatrixPQR);
  3860. }
  3861. else
  3862. {
  3863. //
  3864. // /RangePQR
  3865. //
  3866. pBuffer += WriteNewLineObject(pBuffer, RangePQRTag);
  3867. pBuffer += WriteObject(pBuffer, BeginArray);
  3868. for (i=0; i<3; i++)
  3869. {
  3870. pBuffer += WriteFixed(pBuffer, 0);
  3871. pBuffer += WriteFixed(pBuffer, pafxWP[i]);
  3872. }
  3873. pBuffer += WriteObject(pBuffer, EndArray);
  3874. //
  3875. // /MatrixPQR
  3876. //
  3877. pBuffer += WriteNewLineObject(pBuffer, MatrixPQRTag);
  3878. pBuffer += WriteObject(pBuffer, Identity);
  3879. }
  3880. //
  3881. // /TransformPQR
  3882. //
  3883. pBuffer += WriteNewLineObject(pBuffer, TransformPQRTag);
  3884. pBuffer += WriteObject(pBuffer, BeginArray);
  3885. for (i=0; i<3; i++)
  3886. {
  3887. pBuffer += WriteObject(pBuffer, BeginFunction);
  3888. pBuffer += WriteObject(pBuffer,
  3889. (dwIntent != INTENT_ABSOLUTE_COLORIMETRIC) ? TransformPQR[i] : NullOp);
  3890. pBuffer += WriteObject(pBuffer, EndFunction);
  3891. }
  3892. pBuffer += WriteObject(pBuffer, EndArray);
  3893. return (DWORD)(pBuffer - pStart);
  3894. }
  3895. DWORD
  3896. SendCRDLMN(
  3897. PBYTE pBuffer,
  3898. DWORD dwIntent,
  3899. PFIX_16_16 pafxIlluminantWP,
  3900. PFIX_16_16 pafxMediaWP,
  3901. DWORD dwPCS
  3902. )
  3903. {
  3904. PBYTE pStart = pBuffer;
  3905. DWORD i, j;
  3906. //
  3907. // /MatrixLMN
  3908. //
  3909. if (dwIntent == INTENT_ABSOLUTE_COLORIMETRIC)
  3910. {
  3911. pBuffer += WriteNewLineObject(pBuffer, MatrixLMNTag);
  3912. pBuffer += WriteObject(pBuffer, BeginArray);
  3913. for (i=0; i<3; i++)
  3914. {
  3915. for (j=0; j<3; j++)
  3916. pBuffer += WriteFixed(pBuffer,
  3917. (i == j) ? FIX_DIV(pafxIlluminantWP[i], pafxMediaWP[i]) : 0);
  3918. }
  3919. pBuffer += WriteObject(pBuffer, EndArray);
  3920. }
  3921. //
  3922. // /RangeLMN
  3923. //
  3924. pBuffer += WriteNewLineObject(pBuffer, RangeLMNTag);
  3925. if (dwPCS == SPACE_XYZ)
  3926. {
  3927. pBuffer += WriteObject(pBuffer, BeginArray);
  3928. for (i=0; i<3; i++)
  3929. {
  3930. pBuffer += WriteFixed(pBuffer, 0);
  3931. pBuffer += WriteFixed(pBuffer, pafxIlluminantWP[i]);
  3932. }
  3933. pBuffer += WriteObject(pBuffer, EndArray);
  3934. }
  3935. else
  3936. {
  3937. pBuffer += WriteObject(pBuffer, RangeLMNLab);
  3938. }
  3939. //
  3940. // /EncodeLMN
  3941. //
  3942. pBuffer += WriteNewLineObject(pBuffer, EncodeLMNTag);
  3943. pBuffer += WriteObject(pBuffer, BeginArray);
  3944. for (i=0; i<3; i++)
  3945. {
  3946. pBuffer += WriteObject(pBuffer, BeginFunction);
  3947. if (dwPCS != SPACE_XYZ)
  3948. {
  3949. pBuffer += WriteFixed(pBuffer, pafxIlluminantWP[i]);
  3950. pBuffer += WriteObject(pBuffer, DivOp);
  3951. pBuffer += WriteObject(pBuffer, EncodeLMNLab);
  3952. }
  3953. pBuffer += WriteObject(pBuffer, EndFunction);
  3954. }
  3955. pBuffer += WriteObject(pBuffer, EndArray);
  3956. return (DWORD)(pBuffer - pStart);
  3957. }
  3958. DWORD
  3959. SendCRDABC(
  3960. PBYTE pBuffer,
  3961. PBYTE pPublicArrayName,
  3962. DWORD dwPCS,
  3963. DWORD nInputCh,
  3964. PBYTE pLut,
  3965. PFIX_16_16 e,
  3966. DWORD dwLutSig,
  3967. BOOL bBinary
  3968. )
  3969. {
  3970. PBYTE pLineStart, pStart = pBuffer;
  3971. PBYTE pTable;
  3972. DWORD i, j;
  3973. FIX_16_16 fxTempMatrixABC[9];
  3974. //
  3975. // /RangeABC
  3976. //
  3977. pBuffer += WriteNewLineObject(pBuffer, RangeABCTag);
  3978. pBuffer += WriteObject(pBuffer, RangeABC);
  3979. //
  3980. // /MatrixABC
  3981. //
  3982. pBuffer += WriteNewLineObject(pBuffer, MatrixABCTag);
  3983. if (dwPCS == SPACE_XYZ)
  3984. {
  3985. pBuffer += WriteObject(pBuffer, BeginArray);
  3986. if (e)
  3987. {
  3988. for (i=0; i<3; i++)
  3989. {
  3990. for (j=0; j<3; j++)
  3991. {
  3992. pBuffer += WriteFixed(pBuffer, e[i + j * 3]);
  3993. }
  3994. }
  3995. }
  3996. else
  3997. {
  3998. if (dwLutSig == LUT8_TYPE)
  3999. {
  4000. pTable = (PBYTE) &((PLUT8TYPE)pLut)->e00;
  4001. }
  4002. else
  4003. {
  4004. pTable = (PBYTE) &((PLUT16TYPE)pLut)->e00;
  4005. }
  4006. for (i=0; i<9; i++)
  4007. {
  4008. fxTempMatrixABC[i] = FIX_DIV(FIX_ENDIAN(*((PDWORD)pTable)), CIEXYZRange);
  4009. pTable += sizeof(DWORD);
  4010. }
  4011. for (i=0; i<3; i++)
  4012. {
  4013. for (j=0; j<3; j++)
  4014. {
  4015. pBuffer += WriteFixed(pBuffer, fxTempMatrixABC[i + j * 3]);
  4016. }
  4017. }
  4018. }
  4019. pBuffer += WriteObject(pBuffer, EndArray);
  4020. }
  4021. else
  4022. {
  4023. pBuffer += WriteObject(pBuffer, MatrixABCLabCRD);
  4024. }
  4025. //
  4026. // /EncodeABC
  4027. //
  4028. if (nInputCh == 0)
  4029. {
  4030. return (DWORD)(pBuffer - pStart);
  4031. }
  4032. pLineStart = pBuffer;
  4033. pBuffer += WriteNewLineObject(pBuffer, EncodeABCTag);
  4034. pBuffer += WriteObject(pBuffer, BeginArray);
  4035. for (i=0; i<nInputCh; i++)
  4036. {
  4037. pLineStart = pBuffer;
  4038. pBuffer += WriteNewLineObject(pBuffer, BeginFunction);
  4039. if (dwPCS == SPACE_Lab)
  4040. {
  4041. pBuffer += WriteObject(pBuffer, (i == 0) ? EncodeABCLab1 : EncodeABCLab2);
  4042. }
  4043. pBuffer += WriteObject(pBuffer, StartClip);
  4044. if (e)
  4045. pBuffer += WriteObject(pBuffer, PreViewInArray);
  4046. else
  4047. pBuffer += WriteObject(pBuffer, InputArray);
  4048. pBuffer += WriteObject(pBuffer, pPublicArrayName);
  4049. pBuffer += WriteInt(pBuffer, i);
  4050. if (!bBinary) // Output ASCII CRD
  4051. {
  4052. pBuffer += WriteNewLineObject(pBuffer, IndexArray);
  4053. }
  4054. else
  4055. { // Output BINARY CRD
  4056. if (dwLutSig == LUT8_TYPE)
  4057. {
  4058. pBuffer += WriteObject(pBuffer, IndexArray);
  4059. }
  4060. else
  4061. {
  4062. pBuffer += WriteObject(pBuffer, IndexArray16b);
  4063. }
  4064. }
  4065. pBuffer += WriteObject(pBuffer, (dwLutSig == LUT8_TYPE) ?
  4066. Scale8 : Scale16);
  4067. pBuffer += WriteObject(pBuffer, EndClip);
  4068. pBuffer += WriteObject(pBuffer, EndFunction);
  4069. }
  4070. pBuffer += WriteObject(pBuffer, EndArray);
  4071. return (DWORD)(pBuffer - pStart);
  4072. }
  4073. DWORD
  4074. SendCRDOutputTable(
  4075. PBYTE pBuffer,
  4076. PBYTE pPublicArrayName,
  4077. DWORD nOutputCh,
  4078. DWORD dwLutSig,
  4079. BOOL bHost,
  4080. BOOL bBinary
  4081. )
  4082. {
  4083. PBYTE pStart = pBuffer;
  4084. DWORD i;
  4085. for (i=0; i<nOutputCh; i++)
  4086. {
  4087. pBuffer += WriteNewLineObject(pBuffer, BeginFunction);
  4088. pBuffer += WriteObject(pBuffer, Clip01);
  4089. if (bHost)
  4090. pBuffer += WriteObject(pBuffer, PreViewOutArray);
  4091. else
  4092. pBuffer += WriteObject(pBuffer, OutputArray);
  4093. pBuffer += WriteObject(pBuffer, pPublicArrayName);
  4094. pBuffer += WriteInt(pBuffer, i);
  4095. if (! bBinary)
  4096. {
  4097. pBuffer += WriteObject(pBuffer, NewLine);
  4098. if (dwLutSig == LUT8_TYPE)
  4099. {
  4100. pBuffer += WriteObject(pBuffer, TFunction8);
  4101. }
  4102. else
  4103. {
  4104. pBuffer += WriteObject(pBuffer, IndexArray);
  4105. pBuffer += WriteObject(pBuffer, Scale16);
  4106. }
  4107. }
  4108. else
  4109. {
  4110. if (dwLutSig == LUT8_TYPE)
  4111. {
  4112. pBuffer += WriteObject(pBuffer, TFunction8);
  4113. }
  4114. else
  4115. {
  4116. pBuffer += WriteObject(pBuffer, IndexArray16b);
  4117. pBuffer += WriteObject(pBuffer, Scale16);
  4118. }
  4119. }
  4120. pBuffer += WriteObject(pBuffer, EndFunction);
  4121. }
  4122. return (DWORD)(pBuffer - pStart);
  4123. }
  4124. VOID
  4125. GetCLUTInfo(
  4126. DWORD dwLutSig,
  4127. PBYTE pLut,
  4128. PDWORD pnInputCh,
  4129. PDWORD pnOutputCh,
  4130. PDWORD pnGrids,
  4131. PDWORD pnInputTable,
  4132. PDWORD pnOutputTable,
  4133. PDWORD pdwSize
  4134. )
  4135. {
  4136. if (dwLutSig == LUT8_TYPE)
  4137. {
  4138. *pnInputCh = ((PLUT8TYPE)pLut)->nInputChannels;
  4139. *pnOutputCh = ((PLUT8TYPE)pLut)->nOutputChannels;
  4140. *pnGrids = ((PLUT8TYPE)pLut)->nClutPoints;
  4141. *pnInputTable = 256L;
  4142. *pnOutputTable = 256L;
  4143. if (pdwSize)
  4144. *pdwSize = 1;
  4145. }
  4146. else
  4147. {
  4148. *pnInputCh = ((PLUT16TYPE)pLut)->nInputChannels;
  4149. *pnOutputCh = ((PLUT16TYPE)pLut)->nOutputChannels;
  4150. *pnGrids = ((PLUT16TYPE)pLut)->nClutPoints;
  4151. *pnInputTable = FIX_ENDIAN16(((PLUT16TYPE)pLut)->wInputEntries);
  4152. *pnOutputTable = FIX_ENDIAN16(((PLUT16TYPE)pLut)->wOutputEntries);
  4153. if (pdwSize)
  4154. *pdwSize = 2;
  4155. }
  4156. return;
  4157. }
  4158. DWORD
  4159. EnableGlobalDict(
  4160. PBYTE pBuffer
  4161. )
  4162. {
  4163. PBYTE pStart = pBuffer;
  4164. pBuffer += WriteNewLineObject(pBuffer, CurrentGlobalOp);
  4165. pBuffer += WriteObject(pBuffer, TrueOp);
  4166. pBuffer += WriteObject(pBuffer, SetGlobalOp);
  4167. return (DWORD)(pBuffer - pStart);
  4168. }
  4169. DWORD
  4170. BeginGlobalDict(
  4171. PBYTE pBuffer
  4172. )
  4173. {
  4174. PBYTE pStart = pBuffer;
  4175. pBuffer += WriteNewLineObject(pBuffer, GlobalDictOp);
  4176. pBuffer += WriteObject(pBuffer, BeginOp);
  4177. return (DWORD)(pBuffer - pStart);
  4178. }
  4179. DWORD
  4180. EndGlobalDict(
  4181. PBYTE pBuffer
  4182. )
  4183. {
  4184. PBYTE pStart = pBuffer;
  4185. pBuffer += WriteNewLineObject(pBuffer, EndOp);
  4186. pBuffer += WriteObject(pBuffer, SetGlobalOp);
  4187. return (DWORD)(pBuffer - pStart);
  4188. }
  4189. DWORD
  4190. SendCSABWPoint(
  4191. PBYTE pBuffer,
  4192. DWORD dwIntent,
  4193. PFIX_16_16 pafxIlluminantWP,
  4194. PFIX_16_16 pafxMediaWP
  4195. )
  4196. {
  4197. PBYTE pStart = pBuffer;
  4198. int i;
  4199. //
  4200. // /BlackPoint
  4201. //
  4202. pBuffer += WriteNewLineObject(pBuffer, BlackPointTag);
  4203. pBuffer += WriteObject(pBuffer, BlackPoint);
  4204. //
  4205. // /WhitePoint
  4206. //
  4207. pBuffer += WriteNewLineObject(pBuffer, WhitePointTag);
  4208. pBuffer += WriteObject(pBuffer, BeginArray);
  4209. for (i=0; i<3; i++)
  4210. {
  4211. if (dwIntent == INTENT_ABSOLUTE_COLORIMETRIC)
  4212. {
  4213. pBuffer += WriteFixed(pBuffer, pafxMediaWP[i]);
  4214. }
  4215. else
  4216. {
  4217. pBuffer += WriteFixed(pBuffer, pafxIlluminantWP[i]);
  4218. }
  4219. }
  4220. pBuffer += WriteObject(pBuffer, EndArray);
  4221. return (DWORD)(pBuffer - pStart);
  4222. }
  4223. VOID
  4224. GetMediaWP(
  4225. PBYTE pProfile,
  4226. DWORD dwIntent,
  4227. PFIX_16_16 pafxIlluminantWP,
  4228. PFIX_16_16 pafxMediaWP
  4229. )
  4230. {
  4231. if (dwIntent == INTENT_ABSOLUTE_COLORIMETRIC)
  4232. {
  4233. if (! GetCPMediaWhitePoint(pProfile, pafxMediaWP))
  4234. {
  4235. pafxMediaWP[0] = pafxIlluminantWP[0];
  4236. pafxMediaWP[1] = pafxIlluminantWP[1];
  4237. pafxMediaWP[2] = pafxIlluminantWP[2];
  4238. }
  4239. }
  4240. return;
  4241. }
  4242. BOOL
  4243. GetCRDInputOutputArraySize(
  4244. PBYTE pProfile,
  4245. DWORD dwIntent,
  4246. PDWORD pdwInTblSize,
  4247. PDWORD pdwOutTblSize,
  4248. PDWORD pdwTag,
  4249. PDWORD pnGrids
  4250. )
  4251. {
  4252. PTAGDATA pTagData;
  4253. PLUT16TYPE pLut;
  4254. DWORD dwIndex, dwLutSig;
  4255. DWORD nInputEntries, nOutputEntries;
  4256. DWORD nInputCh, nOutputCh, nGrids;
  4257. BOOL bRet = TRUE;
  4258. //
  4259. // Make sure required tags exist
  4260. //
  4261. switch (dwIntent)
  4262. {
  4263. case INTENT_PERCEPTUAL:
  4264. *pdwTag = TAG_BToA0;
  4265. break;
  4266. case INTENT_RELATIVE_COLORIMETRIC:
  4267. case INTENT_ABSOLUTE_COLORIMETRIC:
  4268. *pdwTag = TAG_BToA1;
  4269. break;
  4270. case INTENT_SATURATION:
  4271. *pdwTag = TAG_BToA2;
  4272. break;
  4273. default:
  4274. WARNING((__TEXT("Invalid intent passed to GetCRDInputOutputArraySize: %d\n"), dwIntent));
  4275. SetLastError(ERROR_INVALID_PARAMETER);
  4276. return FALSE;
  4277. }
  4278. if (DoesCPTagExist(pProfile, *pdwTag, &dwIndex))
  4279. {
  4280. pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
  4281. dwIndex * sizeof(TAGDATA));
  4282. pLut = (PLUT16TYPE)(pProfile + FIX_ENDIAN(pTagData->dwOffset));
  4283. dwLutSig = FIX_ENDIAN(pLut->dwSignature);
  4284. if ((dwLutSig != LUT8_TYPE) && (dwLutSig != LUT16_TYPE))
  4285. {
  4286. WARNING((__TEXT("Invalid Lut type - unable to create proofing CRD\n")));
  4287. SetLastError(ERROR_INVALID_PROFILE);
  4288. return FALSE;
  4289. }
  4290. (void)GetCLUTInfo(dwLutSig, (PBYTE)pLut, &nInputCh, &nOutputCh,
  4291. &nGrids, &nInputEntries, &nOutputEntries, NULL);
  4292. if (pdwInTblSize)
  4293. {
  4294. if (nInputCh != 3)
  4295. {
  4296. return FALSE;
  4297. }
  4298. *pdwInTblSize = nInputCh * nInputEntries * 6; // Number of INT bytes
  4299. *pnGrids = nGrids;
  4300. }
  4301. if (pdwOutTblSize)
  4302. {
  4303. if ((nOutputCh != 3) && (nOutputCh != 4))
  4304. {
  4305. return FALSE;
  4306. }
  4307. *pdwOutTblSize = nOutputCh * nOutputEntries * 6; // Number of INT bytes
  4308. *pnGrids = nGrids;
  4309. }
  4310. return TRUE;
  4311. }
  4312. else
  4313. {
  4314. //
  4315. // Matrix icc profile.
  4316. //
  4317. *pnGrids = 2;
  4318. if (pdwInTblSize)
  4319. {
  4320. bRet = GetHostCSA(pProfile, NULL, pdwInTblSize,
  4321. dwIntent, TYPE_CIEBASEDDEF);
  4322. *pdwInTblSize = *pdwInTblSize * 3;
  4323. }
  4324. if (bRet && pdwOutTblSize)
  4325. {
  4326. bRet = GetHostCSA(pProfile, NULL, pdwInTblSize,
  4327. dwIntent, TYPE_CIEBASEDDEF);
  4328. *pdwOutTblSize = *pdwOutTblSize * 3;
  4329. }
  4330. return bRet;
  4331. }
  4332. }
  4333. #if !defined(KERNEL_MODE) || defined(USERMODE_DRIVER)
  4334. DWORD
  4335. CreateHostLutCRD(
  4336. PBYTE pProfile,
  4337. DWORD dwIndex,
  4338. PBYTE pBuffer,
  4339. DWORD dwIntent
  4340. )
  4341. {
  4342. PLUT16TYPE pLut;
  4343. PHOSTCLUT pHostClut;
  4344. PTAGDATA pTagData;
  4345. PBYTE pTable;
  4346. DWORD nInputCh, nOutputCh, nGrids;
  4347. DWORD nInputEntries, nOutputEntries, nNumbers;
  4348. DWORD dwPCS, dwLutSig;
  4349. DWORD dwSize, i, j;
  4350. PBYTE pStart = pBuffer;
  4351. //
  4352. // Check if we can generate the CSA
  4353. // Required tags is AToBi, where i is the rendering intent
  4354. //
  4355. dwPCS = GetCPConnSpace(pProfile);
  4356. pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
  4357. dwIndex * sizeof(TAGDATA));
  4358. pLut = (PLUT16TYPE)(pProfile + FIX_ENDIAN(pTagData->dwOffset));
  4359. dwLutSig = FIX_ENDIAN(pLut->dwSignature);
  4360. if ((dwLutSig != LUT8_TYPE) && (dwLutSig != LUT16_TYPE))
  4361. {
  4362. WARNING((__TEXT("Invalid profile - unable to create Lut CRD\n")));
  4363. SetLastError(ERROR_INVALID_PROFILE);
  4364. return 0;
  4365. }
  4366. (void)GetCLUTInfo(dwLutSig, (PBYTE)pLut, &nInputCh, &nOutputCh,
  4367. &nGrids, &nInputEntries, &nOutputEntries, &i);
  4368. if (((nOutputCh != 3) && (nOutputCh != 4)) || (nInputCh != 3))
  4369. {
  4370. return 0;
  4371. }
  4372. if (pBuffer == NULL)
  4373. {
  4374. //
  4375. // Return size
  4376. //
  4377. dwSize = nInputCh * nInputEntries * i + // Input table 8/16-bits
  4378. nOutputCh * nOutputEntries * i + // Output table 8/16-bits
  4379. nOutputCh * nGrids * nGrids * nGrids + // CLUT 8-bits only
  4380. sizeof(HOSTCLUT) + // Data structure
  4381. 2048; // Other PS stuff
  4382. //
  4383. // Add space for new line.
  4384. //
  4385. dwSize += (((dwSize) / MAX_LINELEN) + 1) * STRLEN(NewLine);
  4386. return dwSize;
  4387. }
  4388. pHostClut = (PHOSTCLUT)pBuffer;
  4389. pBuffer += sizeof(HOSTCLUT);
  4390. pHostClut->wSize = sizeof(HOSTCLUT);
  4391. pHostClut->wDataType = DATATYPE_LUT;
  4392. pHostClut->dwPCS = dwPCS;
  4393. pHostClut->dwIntent = dwIntent;
  4394. pHostClut->nLutBits = (dwLutSig == LUT8_TYPE) ? 8 : 16;
  4395. (void)GetCPWhitePoint(pProfile, pHostClut->afxIlluminantWP);
  4396. //
  4397. // Support absolute whitePoint
  4398. //
  4399. if (!GetCPMediaWhitePoint(pProfile, pHostClut->afxMediaWP))
  4400. {
  4401. pHostClut->afxMediaWP[0] = pHostClut->afxIlluminantWP[0];
  4402. pHostClut->afxMediaWP[1] = pHostClut->afxIlluminantWP[1];
  4403. pHostClut->afxMediaWP[2] = pHostClut->afxIlluminantWP[2];
  4404. }
  4405. pHostClut->nInputCh = (BYTE)nInputCh;
  4406. pHostClut->nOutputCh = (BYTE)nOutputCh;
  4407. pHostClut->nClutPoints = (BYTE)nGrids;
  4408. pHostClut->nInputEntries = (WORD)nInputEntries;
  4409. pHostClut->nOutputEntries = (WORD)nOutputEntries;
  4410. //
  4411. // Input array
  4412. //
  4413. pBuffer += CreateHostInputOutputArray(
  4414. pBuffer,
  4415. pHostClut->inputArray,
  4416. nInputCh,
  4417. nInputEntries,
  4418. 0,
  4419. dwLutSig,
  4420. (PBYTE)pLut);
  4421. //
  4422. // The offset to the position of output array.
  4423. //
  4424. i = nInputEntries * nInputCh +
  4425. nGrids * nGrids * nGrids * nOutputCh;
  4426. //
  4427. // Output array
  4428. //
  4429. pBuffer += CreateHostInputOutputArray(
  4430. pBuffer,
  4431. pHostClut->outputArray,
  4432. nOutputCh,
  4433. nOutputEntries,
  4434. i,
  4435. dwLutSig,
  4436. (PBYTE)pLut);
  4437. //
  4438. // Matrix
  4439. //
  4440. if (dwPCS == SPACE_XYZ)
  4441. {
  4442. if (dwLutSig == LUT8_TYPE)
  4443. {
  4444. pTable = (PBYTE) &((PLUT8TYPE)pLut)->e00;
  4445. } else
  4446. {
  4447. pTable = (PBYTE) &((PLUT16TYPE)pLut)->e00;
  4448. }
  4449. for (i=0; i<9; i++)
  4450. {
  4451. pHostClut->e[i] = FIX_DIV(FIX_ENDIAN(*((PDWORD)pTable)), CIEXYZRange);
  4452. pTable += sizeof(DWORD);
  4453. }
  4454. }
  4455. //
  4456. // RenderTable
  4457. //
  4458. nNumbers = nGrids * nGrids * nOutputCh;
  4459. pHostClut->clut = pBuffer;
  4460. for (i=0; i<nGrids; i++) // Na strings should be sent
  4461. {
  4462. if (dwLutSig == LUT8_TYPE)
  4463. {
  4464. pTable = (PBYTE)(((PLUT8TYPE)pLut)->data) +
  4465. nInputEntries * nInputCh +
  4466. nNumbers * i;
  4467. }
  4468. else
  4469. {
  4470. pTable = (PBYTE)(((PLUT16TYPE)pLut)->data) +
  4471. 2 * nInputEntries * nInputCh +
  4472. 2 * nNumbers * i;
  4473. }
  4474. if (dwLutSig == LUT8_TYPE)
  4475. {
  4476. CopyMemory(pBuffer, pTable, nNumbers);
  4477. pBuffer += nNumbers;
  4478. }
  4479. else
  4480. {
  4481. for (j=0; j<nNumbers; j++)
  4482. {
  4483. *pBuffer++ = (BYTE)(FIX_ENDIAN16(*((PWORD)pTable)) / 256);
  4484. pTable += sizeof(WORD);
  4485. }
  4486. }
  4487. }
  4488. return (DWORD)(pBuffer - pStart);
  4489. }
  4490. DWORD
  4491. CreateHostMatrixCSAorCRD(
  4492. PBYTE pProfile,
  4493. PBYTE pBuffer,
  4494. PDWORD pcbSize,
  4495. DWORD dwIntent,
  4496. BOOL bCSA
  4497. )
  4498. {
  4499. PTAGDATA pTagData;
  4500. DWORD dwRedTRCIndex, dwGreenTRCIndex, dwBlueTRCIndex;
  4501. DWORD dwRedCount, dwGreenCount, dwBlueCount;
  4502. PCURVETYPE pRed, pGreen, pBlue;
  4503. PHOSTCLUT pHostClut;
  4504. PBYTE pStart = pBuffer;
  4505. DWORD i, dwSize;
  4506. double adArray[9], adRevArray[9], adTemp[9];
  4507. //
  4508. // Get each TRC index for Red, Green and Blue.
  4509. //
  4510. if (!DoesCPTagExist(pProfile, TAG_REDTRC, &dwRedTRCIndex) ||
  4511. !DoesCPTagExist(pProfile, TAG_GREENTRC, &dwGreenTRCIndex) ||
  4512. !DoesCPTagExist(pProfile, TAG_BLUETRC, &dwBlueTRCIndex))
  4513. {
  4514. return FALSE;
  4515. }
  4516. //
  4517. // Get CURVETYPE data for each Red, Green and Blue
  4518. //
  4519. pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
  4520. dwRedTRCIndex * sizeof(TAGDATA));
  4521. pRed = (PCURVETYPE)(pProfile + FIX_ENDIAN(pTagData->dwOffset));
  4522. pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
  4523. dwGreenTRCIndex * sizeof(TAGDATA));
  4524. pGreen = (PCURVETYPE)(pProfile + FIX_ENDIAN(pTagData->dwOffset));
  4525. pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
  4526. dwBlueTRCIndex * sizeof(TAGDATA));
  4527. pBlue = (PCURVETYPE)(pProfile + FIX_ENDIAN(pTagData->dwOffset));
  4528. //
  4529. // Get curve count for each Red, Green and Blue.
  4530. //
  4531. dwRedCount = FIX_ENDIAN(pRed->nCount);
  4532. dwGreenCount = FIX_ENDIAN(pGreen->nCount);
  4533. dwBlueCount = FIX_ENDIAN(pBlue->nCount);
  4534. //
  4535. // Estimate the memory size required to hold CRD
  4536. //
  4537. dwSize = (dwRedCount + dwGreenCount + dwBlueCount) * 2 +
  4538. sizeof(HOSTCLUT) + 2048; // data structure + extra safe space
  4539. //
  4540. // Add space for new line.
  4541. //
  4542. dwSize += (((dwSize) / MAX_LINELEN) + 1) * STRLEN(NewLine);
  4543. if (pBuffer == NULL) // This is a size request
  4544. {
  4545. *pcbSize = dwSize;
  4546. return TRUE;
  4547. }
  4548. //
  4549. // Check buffer size.
  4550. //
  4551. if (*pcbSize < dwSize)
  4552. {
  4553. WARNING((__TEXT("Buffer too small to get Host Matrix CSA/CRD\n")));
  4554. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  4555. return FALSE;
  4556. }
  4557. pHostClut = (PHOSTCLUT)pBuffer;
  4558. pBuffer += sizeof(HOSTCLUT);
  4559. pHostClut->wSize = sizeof(HOSTCLUT);
  4560. pHostClut->wDataType = DATATYPE_MATRIX;
  4561. pHostClut->dwPCS = SPACE_XYZ;
  4562. pHostClut->dwIntent = dwIntent;
  4563. pHostClut->nClutPoints = 2;
  4564. (void)GetCPWhitePoint(pProfile, pHostClut->afxIlluminantWP);
  4565. if (bCSA)
  4566. {
  4567. pHostClut->nInputEntries = (USHORT) dwRedCount;
  4568. pHostClut->nInputCh = 3;
  4569. pBuffer += CreateHostTRCInputTable(pBuffer, pHostClut,
  4570. pRed, pGreen, pBlue);
  4571. }
  4572. else
  4573. {
  4574. pHostClut->nOutputEntries = (USHORT) dwRedCount;
  4575. pHostClut->nOutputCh = 3;
  4576. pBuffer += CreateHostRevTRCInputTable(pBuffer, pHostClut,
  4577. pRed, pGreen, pBlue);
  4578. }
  4579. if (!CreateColorantArray(pProfile, &adTemp[0], TAG_REDCOLORANT) ||
  4580. !CreateColorantArray(pProfile, &adTemp[3], TAG_GREENCOLORANT) ||
  4581. !CreateColorantArray(pProfile, &adTemp[6], TAG_BLUECOLORANT))
  4582. {
  4583. WARNING((__TEXT("Fail to create colorant array for Host Matrix CSA/CRD\n")));
  4584. return FALSE;
  4585. }
  4586. for (i = 0; i < 9; i++)
  4587. {
  4588. adArray[i] = adTemp[i/8*8 + i*3%8];
  4589. }
  4590. if (bCSA)
  4591. {
  4592. for (i = 0; i < 9; i++)
  4593. {
  4594. //
  4595. // Convert double to Fix 16.16
  4596. //
  4597. pHostClut->e[i] = (FIX_16_16)(adArray[i] * (double)FIX_16_16_SCALE);
  4598. }
  4599. }
  4600. else
  4601. {
  4602. InvertColorantArray(adArray, adRevArray);
  4603. for (i = 0; i < 9; i++)
  4604. {
  4605. //
  4606. // Convert double to Fix 16.16
  4607. //
  4608. pHostClut->e[i] = (FIX_16_16)(adRevArray[i] * (double)FIX_16_16_SCALE);
  4609. }
  4610. }
  4611. *pcbSize = (DWORD)(pBuffer - pStart);
  4612. return TRUE;
  4613. }
  4614. DWORD
  4615. CreateHostTRCInputTable(
  4616. PBYTE pBuffer,
  4617. PHOSTCLUT pHostClut,
  4618. PCURVETYPE pRed,
  4619. PCURVETYPE pGreen,
  4620. PCURVETYPE pBlue
  4621. )
  4622. {
  4623. DWORD i;
  4624. PWORD pBuffer16 = (PWORD) pBuffer;
  4625. PWORD pTable;
  4626. //
  4627. // Red
  4628. //
  4629. pHostClut->inputArray[0] = (PBYTE) pBuffer16;
  4630. pTable = pRed->data;
  4631. for (i = 0; i < pHostClut->nInputEntries; i++)
  4632. {
  4633. *pBuffer16++ = FIX_ENDIAN16(*pTable);
  4634. pTable++;
  4635. }
  4636. //
  4637. // Green
  4638. //
  4639. pHostClut->inputArray[1] = (PBYTE) pBuffer16;
  4640. pTable = pGreen->data;
  4641. for (i = 0; i < pHostClut->nInputEntries; i++)
  4642. {
  4643. *pBuffer16++ = FIX_ENDIAN16(*pTable);
  4644. pTable++;
  4645. }
  4646. //
  4647. // Blue
  4648. //
  4649. pHostClut->inputArray[2] = (PBYTE) pBuffer16;
  4650. pTable = pBlue->data;
  4651. for (i = 0; i < pHostClut->nInputEntries; i++)
  4652. {
  4653. *pBuffer16++ = FIX_ENDIAN16(*pTable);
  4654. pTable++;
  4655. }
  4656. return (DWORD)((PBYTE)pBuffer16 - pBuffer);
  4657. }
  4658. DWORD
  4659. CreateHostRevTRCInputTable(
  4660. PBYTE pBuffer,
  4661. PHOSTCLUT pHostClut,
  4662. PCURVETYPE pRed,
  4663. PCURVETYPE pGreen,
  4664. PCURVETYPE pBlue
  4665. )
  4666. {
  4667. PWORD pTemp = MemAlloc(pHostClut->nOutputEntries * (REVCURVE_RATIO + 1) * 2);
  4668. if (! pTemp)
  4669. {
  4670. return 0;
  4671. }
  4672. //
  4673. // Red
  4674. //
  4675. pHostClut->outputArray[0] = pBuffer;
  4676. GetRevCurve(pRed, pTemp, (PWORD) pHostClut->outputArray[0]);
  4677. //
  4678. // Green
  4679. //
  4680. pHostClut->outputArray[1] = pHostClut->outputArray[0] +
  4681. 2 * REVCURVE_RATIO * pHostClut->nOutputEntries;
  4682. GetRevCurve(pGreen, pTemp, (PWORD) pHostClut->outputArray[1]);
  4683. //
  4684. // Blue
  4685. //
  4686. pHostClut->outputArray[2] = pHostClut->outputArray[1] +
  4687. 2 * REVCURVE_RATIO * pHostClut->nOutputEntries;
  4688. GetRevCurve(pBlue, pTemp, (PWORD) pHostClut->outputArray[2]);
  4689. MemFree(pTemp);
  4690. return (DWORD)(2 * REVCURVE_RATIO * pHostClut->nOutputEntries * 3);
  4691. }
  4692. /***************************************************************************
  4693. * GetHostColorRenderingDictionary
  4694. * function:
  4695. * this is the main function which creates the Host CRD
  4696. * parameters:
  4697. * cp -- Color Profile handle
  4698. * Intent -- Intent.
  4699. * lpMem -- Pointer to the memory block.If this point is NULL,
  4700. * require buffer size.
  4701. * lpcbSize -- size of memory block.
  4702. *
  4703. * returns:
  4704. * SINT -- !=0 if the function was successful,
  4705. * 0 otherwise.
  4706. * Returns number of bytes required/transferred
  4707. ***************************************************************************/
  4708. BOOL
  4709. GetHostColorRenderingDictionary(
  4710. PBYTE pProfile,
  4711. DWORD dwIntent,
  4712. PBYTE pBuffer,
  4713. PDWORD pdwSize
  4714. )
  4715. {
  4716. DWORD dwBToATag, dwIndex;
  4717. switch (dwIntent)
  4718. {
  4719. case INTENT_PERCEPTUAL:
  4720. dwBToATag = TAG_BToA0;
  4721. break;
  4722. case INTENT_RELATIVE_COLORIMETRIC:
  4723. case INTENT_ABSOLUTE_COLORIMETRIC:
  4724. dwBToATag = TAG_BToA1;
  4725. break;
  4726. case INTENT_SATURATION:
  4727. dwBToATag = TAG_BToA2;
  4728. break;
  4729. default:
  4730. *pdwSize = 0;
  4731. return FALSE;
  4732. }
  4733. if (DoesCPTagExist(pProfile, dwBToATag, &dwIndex))
  4734. {
  4735. *pdwSize = CreateHostLutCRD(pProfile, dwIndex, pBuffer, dwIntent);
  4736. return *pdwSize > 0;
  4737. }
  4738. else if (DoesTRCAndColorantTagExist(pProfile))
  4739. {
  4740. return CreateHostMatrixCSAorCRD(pProfile, pBuffer, pdwSize, dwIntent, FALSE);
  4741. }
  4742. else
  4743. {
  4744. return FALSE;
  4745. }
  4746. }
  4747. /***************************************************************************
  4748. * CreateHostInputOutputArray
  4749. * function:
  4750. * this is the function which creates the output array from the data
  4751. * supplied in the ColorProfile's LUT8 or LUT16 tag.
  4752. * parameters:
  4753. * MEMPTR lpMem : The buffer to save output array.
  4754. * LPHOSTCLUT lpHostClut :
  4755. * SINT nOutputCh : Number of input channel.
  4756. * SINT nOutputTable : The size of each input table.
  4757. * SINT Offset : The position of source output data(in icc profile).
  4758. * CSIG Tag : To determin the Output table is 8 or 16 bits.
  4759. * MEMPTR Buff : The buffer that contains source data(copyed from icc profile)
  4760. *
  4761. * returns:
  4762. * SINT Returns number of bytes of Output Array
  4763. *
  4764. ***************************************************************************/
  4765. DWORD
  4766. CreateHostInputOutputArray(
  4767. PBYTE pBuffer,
  4768. PBYTE *ppArray,
  4769. DWORD nNumChan,
  4770. DWORD nTableSize,
  4771. DWORD dwOffset,
  4772. DWORD dwLutSig,
  4773. PBYTE pLut
  4774. )
  4775. {
  4776. PBYTE pStart = pBuffer;
  4777. PBYTE pTable;
  4778. DWORD i, j;
  4779. for (i=0; i<nNumChan; i++)
  4780. {
  4781. ppArray[i] = pBuffer;
  4782. if (dwLutSig == LUT8_TYPE)
  4783. {
  4784. pTable = (PBYTE) (((PLUT8TYPE)pLut)->data) +
  4785. dwOffset + nTableSize * i;
  4786. CopyMemory(pBuffer, pTable, nTableSize);
  4787. pBuffer += nTableSize;
  4788. }
  4789. else
  4790. {
  4791. pTable = (PBYTE) (((PLUT16TYPE)pLut)->data) +
  4792. 2 * dwOffset +
  4793. 2 * nTableSize * i;
  4794. for (j=0; j<nTableSize; j++)
  4795. {
  4796. *((PWORD)pBuffer) = FIX_ENDIAN16(*((PWORD)pTable));
  4797. pBuffer += sizeof(WORD);
  4798. pTable += sizeof(WORD);
  4799. }
  4800. }
  4801. }
  4802. return (DWORD) (pBuffer - pStart);
  4803. }
  4804. /***************************************************************************
  4805. * GetHostCSA
  4806. * function:
  4807. * this is the function which creates a Host CSA
  4808. * parameters:
  4809. * CHANDLE cp -- Color Profile handle
  4810. * MEMPTR lpMem -- Pointer to the memory block. If this point is NULL,
  4811. * require buffer size.
  4812. * LPDWORD lpcbSize -- Size of the memory block
  4813. * CSIG InputIntent --
  4814. * SINT Index -- to the icc profile tag that contains the data of Intent
  4815. * int Type -- DEF or DEFG
  4816. * returns:
  4817. * BOOL -- TRUE if the function was successful,
  4818. * FALSE otherwise.
  4819. ***************************************************************************/
  4820. BOOL
  4821. GetHostCSA(
  4822. PBYTE pProfile,
  4823. PBYTE pBuffer,
  4824. PDWORD pdwSize,
  4825. DWORD dwIntent,
  4826. DWORD dwType
  4827. )
  4828. {
  4829. PHOSTCLUT pHostClut;
  4830. PTAGDATA pTagData;
  4831. PLUT16TYPE pLut;
  4832. DWORD dwAToBTag;
  4833. DWORD dwPCS, dwLutSig;
  4834. DWORD nInputCh, nOutputCh, nGrids, SecondGrids;
  4835. DWORD nInputTable, nOutputTable, nNumbers;
  4836. DWORD dwIndex, i, j, k;
  4837. PBYTE pTable;
  4838. PBYTE pStart = pBuffer;
  4839. switch (dwIntent)
  4840. {
  4841. case INTENT_PERCEPTUAL:
  4842. dwAToBTag = TAG_AToB0;
  4843. break;
  4844. case INTENT_RELATIVE_COLORIMETRIC:
  4845. case INTENT_ABSOLUTE_COLORIMETRIC:
  4846. dwAToBTag = TAG_AToB1;
  4847. break;
  4848. case INTENT_SATURATION:
  4849. dwAToBTag = TAG_AToB2;
  4850. break;
  4851. default:
  4852. WARNING((__TEXT("Invalid intent passed to GetHostCSA: %d\n"), dwIntent));
  4853. SetLastError(ERROR_INVALID_PARAMETER);
  4854. return FALSE;
  4855. break;
  4856. }
  4857. if (!DoesCPTagExist(pProfile, dwAToBTag, &dwIndex))
  4858. {
  4859. if (DoesTRCAndColorantTagExist(pProfile) && (dwType == TYPE_CIEBASEDDEF))
  4860. {
  4861. //
  4862. // Create Host CSA from Matrix.
  4863. //
  4864. return CreateHostMatrixCSAorCRD(pProfile,pBuffer,pdwSize,dwIntent,TRUE);
  4865. }
  4866. else
  4867. {
  4868. WARNING((__TEXT("AToB tag not present for intent %d\n"), dwIntent));
  4869. SetLastError(ERROR_TAG_NOT_PRESENT);
  4870. return FALSE;
  4871. }
  4872. }
  4873. //
  4874. // Check if we can generate the CSA
  4875. //
  4876. dwPCS = GetCPConnSpace(pProfile);
  4877. pTagData = (PTAGDATA)(pProfile + sizeof(PROFILEHEADER) + sizeof(DWORD) +
  4878. dwIndex * sizeof(TAGDATA));
  4879. pLut = (PLUT16TYPE)(pProfile + FIX_ENDIAN(pTagData->dwOffset));
  4880. dwLutSig = FIX_ENDIAN(pLut->dwSignature);
  4881. if (((dwPCS != SPACE_Lab) && (dwPCS != SPACE_XYZ)) ||
  4882. ((dwLutSig != LUT8_TYPE) && (dwLutSig != LUT16_TYPE)))
  4883. {
  4884. WARNING((__TEXT("Invalid color space - unable to create DEF(G) host CSA\n")));
  4885. SetLastError(ERROR_INVALID_PROFILE);
  4886. return FALSE;
  4887. }
  4888. //
  4889. // Estimate the memory size required to hold CSA
  4890. //
  4891. (void)GetCLUTInfo(dwLutSig, (PBYTE)pLut, &nInputCh, &nOutputCh, &nGrids,
  4892. &nInputTable, &nOutputTable, &i);
  4893. if (!(nOutputCh == 3) ||
  4894. !((nInputCh == 3) && (dwType == TYPE_CIEBASEDDEF)) &&
  4895. !((nInputCh == 4) && (dwType == TYPE_CIEBASEDDEFG)))
  4896. {
  4897. return FALSE;
  4898. }
  4899. if (pBuffer == NULL)
  4900. {
  4901. //
  4902. // Return size
  4903. //
  4904. if (dwType == TYPE_CIEBASEDDEFG)
  4905. *pdwSize = nOutputCh * nGrids * nGrids * nGrids * nGrids;
  4906. else
  4907. *pdwSize = nOutputCh * nGrids * nGrids * nGrids;
  4908. *pdwSize += // size of RenderTable 8-bits only
  4909. nInputCh * nInputTable * i + // size of input table 8/16-bits
  4910. nOutputCh * nOutputTable * i + // size of output table 8/16-bits
  4911. sizeof(HOSTCLUT) + 2048; // data structure + other PS stuff
  4912. //
  4913. // Add space for new line.
  4914. //
  4915. *pdwSize += (((*pdwSize) / MAX_LINELEN) + 1) * STRLEN(NewLine);
  4916. return TRUE;
  4917. }
  4918. pHostClut = (PHOSTCLUT)pBuffer;
  4919. pBuffer += sizeof(HOSTCLUT);
  4920. pHostClut->wSize = sizeof(HOSTCLUT);
  4921. pHostClut->wDataType = DATATYPE_LUT;
  4922. pHostClut->dwPCS = dwPCS;
  4923. pHostClut->dwIntent = dwIntent;
  4924. pHostClut->nLutBits = (dwLutSig == LUT8_TYPE) ? 8 : 16;
  4925. //
  4926. // Get info about Illuminant White Point from the header
  4927. //
  4928. (void)GetCPWhitePoint(pProfile, pHostClut->afxIlluminantWP);
  4929. pHostClut->nInputCh = (BYTE)nInputCh;
  4930. pHostClut->nOutputCh = (BYTE)nOutputCh;
  4931. pHostClut->nClutPoints = (BYTE)nGrids;
  4932. pHostClut->nInputEntries = (WORD)nInputTable;
  4933. pHostClut->nOutputEntries = (WORD)nOutputTable;
  4934. //
  4935. // Input Array
  4936. //
  4937. pBuffer += CreateHostInputOutputArray(pBuffer, pHostClut->inputArray,
  4938. nInputCh, nInputTable, 0, dwLutSig, (PBYTE)pLut);
  4939. if (dwType == TYPE_CIEBASEDDEFG)
  4940. {
  4941. i = nInputTable * nInputCh +
  4942. nGrids * nGrids * nGrids * nGrids * nOutputCh;
  4943. }
  4944. else
  4945. {
  4946. i = nInputTable * nInputCh +
  4947. nGrids * nGrids * nGrids * nOutputCh;
  4948. }
  4949. //
  4950. // Output Array
  4951. //
  4952. pBuffer += CreateHostInputOutputArray(pBuffer, pHostClut->outputArray,
  4953. nOutputCh, nOutputTable, i, dwLutSig, (PBYTE)pLut);
  4954. //
  4955. // /Table
  4956. //
  4957. pHostClut->clut = pBuffer;
  4958. nNumbers = nGrids * nGrids * nOutputCh;
  4959. SecondGrids = 1;
  4960. if (dwType == TYPE_CIEBASEDDEFG)
  4961. {
  4962. SecondGrids = nGrids;
  4963. }
  4964. for (i=0; i<nGrids; i++) // Nh strings should be sent
  4965. {
  4966. for (k=0; k<SecondGrids; k++)
  4967. {
  4968. if (dwLutSig == LUT8_TYPE)
  4969. {
  4970. pTable = (PBYTE) (((PLUT8TYPE)pLut)->data) +
  4971. nInputTable * nInputCh +
  4972. nNumbers * (i * SecondGrids + k);
  4973. }
  4974. else
  4975. {
  4976. pTable = (PBYTE) (((PLUT16TYPE)pLut)->data) +
  4977. 2 * nInputTable * nInputCh +
  4978. 2 * nNumbers * (i * SecondGrids + k);
  4979. }
  4980. if (dwLutSig == LUT8_TYPE)
  4981. {
  4982. CopyMemory(pBuffer, pTable, nNumbers);
  4983. pBuffer += nNumbers;
  4984. }
  4985. else
  4986. {
  4987. for (j=0; j<nNumbers; j++)
  4988. {
  4989. *pBuffer++ = (BYTE)(FIX_ENDIAN16(*((PWORD)pTable)) / 256);
  4990. pTable += sizeof(WORD);
  4991. }
  4992. }
  4993. }
  4994. }
  4995. *pdwSize = (DWORD) (pBuffer - pStart);
  4996. return TRUE;
  4997. }
  4998. /***************************************************************************
  4999. * GetHostColorSpaceArray
  5000. * function:
  5001. * This is the main function which creates the Host CSA
  5002. * from the data supplied in the Profile.
  5003. * parameters:
  5004. * cp -- Color Profile handle
  5005. * InputIntent -- Intent.
  5006. * lpBuffer -- Pointer to the memory block. If this point is NULL,
  5007. * require buffer size.
  5008. * lpcbSize -- Size of the memory block
  5009. * returns:
  5010. * BOOL -- TRUE if the function was successful,
  5011. * FALSE otherwise.
  5012. ***************************************************************************/
  5013. BOOL
  5014. GetHostColorSpaceArray(
  5015. PBYTE pProfile,
  5016. DWORD dwIntent,
  5017. PBYTE pBuffer,
  5018. PDWORD pdwSize
  5019. )
  5020. {
  5021. DWORD dwDev;
  5022. BOOL bRc = FALSE;
  5023. dwDev = GetCPDevSpace(pProfile);
  5024. switch (dwDev)
  5025. {
  5026. case SPACE_RGB:
  5027. bRc = GetHostCSA(pProfile, pBuffer, pdwSize,
  5028. dwIntent, TYPE_CIEBASEDDEF);
  5029. break;
  5030. case SPACE_CMYK:
  5031. bRc = GetHostCSA(pProfile, pBuffer, pdwSize,
  5032. dwIntent, TYPE_CIEBASEDDEFG);
  5033. break;
  5034. default:
  5035. break;
  5036. }
  5037. return bRc;
  5038. }
  5039. /***************************************************************************
  5040. * DoHostConversionCRD
  5041. * function:
  5042. * This function converts XYZ/Lab to RGB/CMYK by using HostCRD
  5043. * parameters:
  5044. * LPHOSTCLUT lpHostCRD -- pointer to a HostCRD
  5045. * LPHOSTCLUT lpHostCSA -- pointer to a HostCSA
  5046. * float far *Input -- Input XYZ/Lab
  5047. * float far *Output -- Output RGB/CMYK
  5048. * returns:
  5049. * BOOL -- TRUE
  5050. ***************************************************************************/
  5051. BOOL
  5052. DoHostConversionCRD(
  5053. PHOSTCLUT pHostCRD,
  5054. PHOSTCLUT pHostCSA,
  5055. float *pfInput,
  5056. float *pfOutput,
  5057. BOOL bCheckOutputTable
  5058. )
  5059. {
  5060. float fTemp[MAXCHANNELS];
  5061. float fTemp1[MAXCHANNELS];
  5062. DWORD i, j;
  5063. //
  5064. // Input XYZ or Lab in range [0 2]
  5065. //
  5066. // When sampling the deviceCRD, skip the input table.
  5067. // If pHostCSA is not NULL, the current CRD is targetCRD, we
  5068. // need to do input table conversion
  5069. //
  5070. if (pHostCSA)
  5071. {
  5072. //
  5073. // Convert Lab to XYZ in range [ 0 whitePoint ]
  5074. //
  5075. if ((pHostCRD->dwPCS == SPACE_XYZ) &&
  5076. (pHostCSA->dwPCS == SPACE_Lab))
  5077. {
  5078. LabToXYZ(pfInput, fTemp1, pHostCRD->afxIlluminantWP);
  5079. }
  5080. else if ((pHostCRD->dwPCS == SPACE_Lab) &&
  5081. (pHostCSA->dwPCS == SPACE_XYZ))
  5082. {
  5083. //
  5084. // Convert XYZ to Lab in range [ 0 1]
  5085. //
  5086. XYZToLab(pfInput, fTemp, pHostCSA->afxIlluminantWP);
  5087. }
  5088. else if ((pHostCRD->dwPCS == SPACE_Lab) &&
  5089. (pHostCSA->dwPCS == SPACE_Lab))
  5090. {
  5091. //
  5092. // Convert Lab to range [ 0 1]
  5093. //
  5094. for (i=0; i<3; i++)
  5095. fTemp[i] = pfInput[i] / 2;
  5096. }
  5097. else
  5098. {
  5099. //
  5100. // Convert XYZ to XYZ (based on white point) to range [0 1]
  5101. //
  5102. // different intents using different conversion.
  5103. // icRelativeColorimetric: using Bradford transform.
  5104. // icAbsoluteColorimetric: using scaling.
  5105. //
  5106. for (i=0; i<3; i++)
  5107. fTemp1[i] = (pfInput[i] * pHostCRD->afxIlluminantWP[i]) / pHostCSA->afxIlluminantWP[i];
  5108. }
  5109. //
  5110. // Matrix, used for XYZ data only.
  5111. //
  5112. if (pHostCRD->dwPCS == SPACE_XYZ)
  5113. {
  5114. ApplyMatrix(pHostCRD->e, fTemp1, fTemp);
  5115. }
  5116. if (pHostCRD->wDataType != DATATYPE_MATRIX)
  5117. {
  5118. //
  5119. // Search input Table
  5120. //
  5121. (void)CheckInputOutputTable(pHostCRD, fTemp, FALSE, TRUE);
  5122. }
  5123. }
  5124. //
  5125. // If the current CRD is device CRD, we do not need to do input
  5126. // table conversion
  5127. //
  5128. else
  5129. {
  5130. WORD nGrids;
  5131. nGrids = pHostCRD->nClutPoints;
  5132. //
  5133. // Sample data may be XYZ or Lab. It depends on Target icc profile.
  5134. // If the PCS of the target icc profile is XYZ, input data will be XYZ.
  5135. // If the PCS of the target icc profile is Lab, input data will be Lab.
  5136. //
  5137. if (pHostCRD->wDataType == DATATYPE_MATRIX)
  5138. {
  5139. for (i = 0; i < 3; i++)
  5140. {
  5141. fTemp[i] = pfInput[i];
  5142. }
  5143. }
  5144. else
  5145. {
  5146. for (i=0; i<3; i++)
  5147. {
  5148. fTemp[i] = pfInput[i] * (nGrids - 1);
  5149. if (fTemp[i] > (nGrids - 1))
  5150. fTemp[i] = (float)(nGrids - 1);
  5151. }
  5152. }
  5153. }
  5154. if (pHostCRD->wDataType != DATATYPE_MATRIX)
  5155. {
  5156. //
  5157. // Rendering table
  5158. //
  5159. (void)CheckColorLookupTable(pHostCRD, fTemp);
  5160. }
  5161. //
  5162. // Output RGB or CMYK in range [0 1]
  5163. //
  5164. if (bCheckOutputTable)
  5165. {
  5166. (void)CheckInputOutputTable(pHostCRD, fTemp, FALSE, FALSE);
  5167. }
  5168. for (i=0; (i<=MAXCHANNELS) && (i<pHostCRD->nOutputCh); i++)
  5169. {
  5170. pfOutput[i] = fTemp[i];
  5171. }
  5172. return TRUE;
  5173. }
  5174. /***************************************************************************
  5175. * DoHostConversionCSA
  5176. * function:
  5177. * This function converts RGB/CMYK to XYZ/Lab by using HostCSA
  5178. * parameters:
  5179. * LPHOSTCLUT lpHostCLUT -- pointer to a HostCSA
  5180. * float far *Input -- Input XYZ/Lab
  5181. * float far *Output -- Output RGB/CMYK
  5182. * returns:
  5183. * BOOL -- TRUE
  5184. ***************************************************************************/
  5185. BOOL
  5186. DoHostConversionCSA(
  5187. PHOSTCLUT pHostClut,
  5188. float *pfInput,
  5189. float *pfOutput
  5190. )
  5191. {
  5192. float fTemp[MAXCHANNELS];
  5193. DWORD i;
  5194. //
  5195. // Input RGB or CMYK in range [0 1]
  5196. //
  5197. for (i=0; (i<=MAXCHANNELS) && (i<pHostClut->nInputCh); i++)
  5198. {
  5199. fTemp[i] = pfInput[i];
  5200. }
  5201. //
  5202. // Search input Table
  5203. //
  5204. (void)CheckInputOutputTable(pHostClut, fTemp, TRUE, TRUE);
  5205. if (pHostClut->wDataType == DATATYPE_MATRIX)
  5206. {
  5207. ApplyMatrix(pHostClut->e, fTemp, pfOutput);
  5208. }
  5209. else
  5210. {
  5211. //
  5212. // Rendering table
  5213. //
  5214. (void)CheckColorLookupTable(pHostClut, fTemp);
  5215. //
  5216. // Output Table
  5217. //
  5218. (void)CheckInputOutputTable(pHostClut, fTemp, TRUE, FALSE);
  5219. //
  5220. // Output XYZ or Lab in range [0 2]
  5221. //
  5222. for (i=0; (i<=MAXCHANNELS) && (i<pHostClut->nOutputCh); i++)
  5223. {
  5224. pfOutput[i] = fTemp[i];
  5225. }
  5226. }
  5227. return TRUE;
  5228. }
  5229. /***************************************************************************
  5230. * CheckInputOutputTable
  5231. * function:
  5232. * This function check inputTable.
  5233. * parameters:
  5234. * LPHOSTCLUT lpHostClut --
  5235. * float far *fTemp -- Input / output data
  5236. * returns:
  5237. * BOOL -- TRUE
  5238. ***************************************************************************/
  5239. BOOL
  5240. CheckInputOutputTable(
  5241. PHOSTCLUT pHostClut,
  5242. float *pfTemp,
  5243. BOOL bCSA,
  5244. BOOL bInputTable
  5245. )
  5246. {
  5247. PBYTE *ppArray;
  5248. float fIndex;
  5249. DWORD nNumCh;
  5250. DWORD nNumEntries, i;
  5251. WORD nGrids;
  5252. WORD floor1, ceiling1;
  5253. if (bInputTable)
  5254. {
  5255. nNumCh = pHostClut->nInputCh;
  5256. nNumEntries = pHostClut->nInputEntries - 1;
  5257. ppArray = pHostClut->inputArray;
  5258. }
  5259. else
  5260. {
  5261. nNumCh = pHostClut->nOutputCh;
  5262. nNumEntries = pHostClut->nOutputEntries - 1;
  5263. ppArray = pHostClut->outputArray;
  5264. }
  5265. nGrids = pHostClut->nClutPoints;
  5266. for (i=0; (i<=MAXCHANNELS) && (i<nNumCh); i++)
  5267. {
  5268. pfTemp[i] = (pfTemp[i] < 0) ? 0 : ((pfTemp[i] > 1) ? 1 : pfTemp[i]);
  5269. fIndex = pfTemp[i] * nNumEntries;
  5270. if (pHostClut->nLutBits == 8)
  5271. {
  5272. floor1 = ppArray[i][(DWORD)fIndex];
  5273. ceiling1 = ppArray[i][((DWORD)fIndex) + 1];
  5274. pfTemp[i] = (float)(floor1 + (ceiling1 - floor1) * (fIndex - floor(fIndex)));
  5275. if (bCSA && !bInputTable)
  5276. pfTemp[i] = pfTemp[i] / 127.0f;
  5277. else
  5278. pfTemp[i] = pfTemp[i] / 255.0f;
  5279. }
  5280. else
  5281. {
  5282. floor1 = ((PWORD)(ppArray[i]))[(DWORD)fIndex];
  5283. ceiling1 = ((PWORD)(ppArray[i]))[((DWORD)fIndex) + 1];
  5284. pfTemp[i] = (float)(floor1 + (ceiling1 - floor1) * (fIndex - floor(fIndex)));
  5285. if (bCSA && !bInputTable)
  5286. pfTemp[i] = pfTemp[i] / 32767.0f;
  5287. else
  5288. pfTemp[i] = pfTemp[i] / 65535.0f;
  5289. }
  5290. if (bInputTable)
  5291. {
  5292. pfTemp[i] *= (nGrids - 1);
  5293. if (pfTemp[i] > (nGrids - 1))
  5294. pfTemp[i] = (float)(nGrids - 1);
  5295. }
  5296. }
  5297. return TRUE;
  5298. }
  5299. /***************************************************************************
  5300. * g
  5301. * function:
  5302. * Calculate function y = g(x). used in Lab->XYZ conversion
  5303. * y = g(x): g(x) = x*x*x if x >= 6/29
  5304. * g(x) = 108/841*(x-4/29) otherwise
  5305. * parameters:
  5306. * f -- x
  5307. * returns:
  5308. * SINT -- y
  5309. ***************************************************************************/
  5310. float g(
  5311. float f
  5312. )
  5313. {
  5314. float fRc;
  5315. if (f >= (6.0f/29.0f))
  5316. {
  5317. fRc = f * f * f;
  5318. }
  5319. else
  5320. {
  5321. fRc = f - (4.0f / 29.0f) * (108.0f / 841.0f);
  5322. }
  5323. return fRc;
  5324. }
  5325. /***************************************************************************
  5326. * inverse_g
  5327. * function:
  5328. * Calculate inverse function y = g(x). used in XYZ->Lab conversion
  5329. * parameters:
  5330. * f -- y
  5331. * returns:
  5332. * SINT -- x
  5333. ***************************************************************************/
  5334. float
  5335. inverse_g(
  5336. float f
  5337. )
  5338. {
  5339. double fRc;
  5340. if (f >= (6.0f*6.0f*6.0f)/(29.0f*29.0f*29.0f))
  5341. {
  5342. fRc = pow(f, 1.0 / 3.0);
  5343. }
  5344. else
  5345. {
  5346. fRc = f * (841.0f / 108.0f) + (4.0f / 29.0f);
  5347. }
  5348. return (float)fRc;
  5349. }
  5350. void
  5351. LabToXYZ(
  5352. float *pfInput,
  5353. float *pfOutput,
  5354. PFIX_16_16 pafxWP
  5355. )
  5356. {
  5357. float fL, fa, fb;
  5358. fL = (pfInput[0] * 50 + 16) / 116;
  5359. fa = (pfInput[1] * 128 - 128) / 500;
  5360. fb = (pfInput[2] * 128 - 128) / 200;
  5361. pfOutput[0] = pafxWP[0] * g(fL + fa) / FIX_16_16_SCALE;
  5362. pfOutput[1] = pafxWP[1] * g(fL) / FIX_16_16_SCALE;
  5363. pfOutput[2] = pafxWP[2] * g(fL - fb) / FIX_16_16_SCALE;
  5364. return;
  5365. }
  5366. void
  5367. XYZToLab(
  5368. float *pfInput,
  5369. float *pfOutput,
  5370. PFIX_16_16 pafxWP
  5371. )
  5372. {
  5373. float fL, fa, fb;
  5374. fL = inverse_g(pfInput[0] * FIX_16_16_SCALE / pafxWP[0]);
  5375. fa = inverse_g(pfInput[1] * FIX_16_16_SCALE / pafxWP[1]);
  5376. fb = inverse_g(pfInput[2] * FIX_16_16_SCALE / pafxWP[2]);
  5377. pfOutput[0] = (fa * 116 - 16) / 100;
  5378. pfOutput[1] = (fL * 500 - fa * 500 + 128) / 255;
  5379. pfOutput[2] = (fa * 200 - fb * 200 + 128) / 255;
  5380. return;
  5381. }
  5382. BOOL
  5383. TableInterp3(
  5384. PHOSTCLUT pHostClut,
  5385. float *pfTemp
  5386. )
  5387. {
  5388. PBYTE v000, v001, v010, v011;
  5389. PBYTE v100, v101, v110, v111;
  5390. float fA, fB, fC;
  5391. float fVx0x, fVx1x;
  5392. float fV0xx, fV1xx;
  5393. DWORD tmpA, tmpBC;
  5394. DWORD cellA, cellB, cellC;
  5395. DWORD idx;
  5396. WORD nGrids;
  5397. WORD nOutputCh;
  5398. cellA = (DWORD)pfTemp[0];
  5399. fA = pfTemp[0] - cellA;
  5400. cellB = (DWORD)pfTemp[1];
  5401. fB = pfTemp[1] - cellB;
  5402. cellC = (DWORD)pfTemp[2];
  5403. fC = pfTemp[2] - cellC;
  5404. nGrids = pHostClut->nClutPoints;
  5405. nOutputCh = pHostClut->nOutputCh;
  5406. tmpA = nOutputCh * nGrids * nGrids;
  5407. tmpBC = nOutputCh * (nGrids * cellB + cellC);
  5408. //
  5409. // Calculate 8 surrounding cells.
  5410. //
  5411. v000 = pHostClut->clut + tmpA * cellA + tmpBC;
  5412. v001 = (cellC < (DWORD)(nGrids - 1)) ? v000 + nOutputCh : v000;
  5413. v010 = (cellB < (DWORD)(nGrids - 1)) ? v000 + nOutputCh * nGrids : v000;
  5414. v011 = (cellC < (DWORD)(nGrids - 1)) ? v010 + nOutputCh : v010 ;
  5415. v100 = (cellA < (DWORD)(nGrids - 1)) ? v000 + tmpA : v000;
  5416. v101 = (cellC < (DWORD)(nGrids - 1)) ? v100 + nOutputCh : v100;
  5417. v110 = (cellB < (DWORD)(nGrids - 1)) ? v100 + nOutputCh * nGrids : v100;
  5418. v111 = (cellC < (DWORD)(nGrids - 1)) ? v110 + nOutputCh : v110;
  5419. for (idx=0; idx<nOutputCh; idx++)
  5420. {
  5421. //
  5422. // Calculate the average of 4 bottom cells.
  5423. //
  5424. fVx0x = *v000 + fC * (int)((int)*v001 - (int)*v000);
  5425. fVx1x = *v010 + fC * (int)((int)*v011 - (int)*v010);
  5426. fV0xx = fVx0x + fB * (fVx1x - fVx0x);
  5427. //
  5428. // Calculate the average of 4 upper cells.
  5429. //
  5430. fVx0x = *v100 + fC * (int)((int)*v101 - (int)*v100);
  5431. fVx1x = *v110 + fC * (int)((int)*v111 - (int)*v110);
  5432. fV1xx = fVx0x + fB * (fVx1x - fVx0x);
  5433. //
  5434. // Calculate the bottom and upper average.
  5435. //
  5436. pfTemp[idx] = (fV0xx + fA * (fV1xx - fV0xx)) / MAXCOLOR8;
  5437. if ( idx < (DWORD)(nOutputCh - 1))
  5438. {
  5439. v000++;
  5440. v001++;
  5441. v010++;
  5442. v011++;
  5443. v100++;
  5444. v101++;
  5445. v110++;
  5446. v111++;
  5447. }
  5448. }
  5449. return TRUE;
  5450. }
  5451. BOOL
  5452. TableInterp4(
  5453. PHOSTCLUT pHostClut,
  5454. float *pfTemp
  5455. )
  5456. {
  5457. PBYTE v0000, v0001, v0010, v0011;
  5458. PBYTE v0100, v0101, v0110, v0111;
  5459. PBYTE v1000, v1001, v1010, v1011;
  5460. PBYTE v1100, v1101, v1110, v1111;
  5461. float fH, fI, fJ, fK;
  5462. float fVxx0x, fVxx1x;
  5463. float fVx0xx, fVx1xx;
  5464. float fV0xxx, fV1xxx;
  5465. DWORD tmpH, tmpI, tmpJK;
  5466. DWORD cellH, cellI, cellJ, cellK;
  5467. DWORD idx;
  5468. WORD nGrids;
  5469. WORD nOutputCh;
  5470. cellH = (DWORD)pfTemp[0];
  5471. fH = pfTemp[0] - cellH;
  5472. cellI = (DWORD)pfTemp[1];
  5473. fI = pfTemp[1] - cellI;
  5474. cellJ = (DWORD)pfTemp[2];
  5475. fJ = pfTemp[2] - cellJ;
  5476. cellK = (DWORD)pfTemp[3];
  5477. fK = pfTemp[3] - cellK;
  5478. nGrids = pHostClut->nClutPoints;
  5479. nOutputCh = pHostClut->nOutputCh;
  5480. tmpI = nOutputCh * nGrids * nGrids;
  5481. tmpH = tmpI * nGrids;
  5482. tmpJK = nOutputCh * (nGrids * cellJ + cellK);
  5483. //
  5484. // Calculate 16 surrounding cells.
  5485. //
  5486. v0000 = pHostClut->clut + tmpH * cellH + tmpI * cellI + tmpJK;
  5487. v0001 = (cellK < (DWORD)(nGrids - 1))? v0000 + nOutputCh : v0000;
  5488. v0010 = (cellJ < (DWORD)(nGrids - 1))? v0000 + nOutputCh * nGrids : v0000;
  5489. v0011 = (cellK < (DWORD)(nGrids - 1))? v0010 + nOutputCh : v0010;
  5490. v0100 = (cellI < (DWORD)(nGrids - 1))? v0000 + tmpI : v0000;
  5491. v0101 = (cellK < (DWORD)(nGrids - 1))? v0100 + nOutputCh : v0100;
  5492. v0110 = (cellJ < (DWORD)(nGrids - 1))? v0100 + nOutputCh * nGrids : v0100;
  5493. v0111 = (cellK < (DWORD)(nGrids - 1))? v0110 + nOutputCh : v0110;
  5494. v1000 = (cellH < (DWORD)(nGrids - 1))? v0000 + tmpH : v0000;
  5495. v1001 = (cellK < (DWORD)(nGrids - 1))? v1000 + nOutputCh : v1000;
  5496. v1010 = (cellJ < (DWORD)(nGrids - 1))? v1000 + nOutputCh * nGrids : v1000;
  5497. v1011 = (cellK < (DWORD)(nGrids - 1))? v1010 + nOutputCh : v1010;
  5498. v1100 = (cellI < (DWORD)(nGrids - 1))? v1000 + tmpI : v1000;
  5499. v1101 = (cellK < (DWORD)(nGrids - 1))? v1100 + nOutputCh : v1100;
  5500. v1110 = (cellJ < (DWORD)(nGrids - 1))? v1100 + nOutputCh * nGrids : v1100;
  5501. v1111 = (cellK < (DWORD)(nGrids - 1))? v1110 + nOutputCh : v1110;
  5502. for (idx=0; idx<nOutputCh; idx++)
  5503. {
  5504. //
  5505. // Calculate the average of 8 bottom cells.
  5506. //
  5507. fVxx0x = *v0000 + fK * (int)((int)*v0001 - (int)*v0000);
  5508. fVxx1x = *v0010 + fK * (int)((int)*v0011 - (int)*v0010);
  5509. fVx0xx = fVxx0x + fJ * (fVxx1x - fVxx0x);
  5510. fVxx0x = *v0100 + fK * (int)((int)*v0101 - (int)*v0100);
  5511. fVxx1x = *v0110 + fK * (int)((int)*v0111 - (int)*v0110);
  5512. fVx1xx = fVxx0x + fJ * (fVxx1x - fVxx0x);
  5513. fV0xxx = fVx0xx + fI * (fVx1xx - fVx0xx);
  5514. //
  5515. // Calculate the average of 8 upper cells.
  5516. //
  5517. fVxx0x = *v1000 + fK * (int)((int)*v1001 - (int)*v1000);
  5518. fVxx1x = *v1010 + fK * (int)((int)*v1011 - (int)*v1010);
  5519. fVx0xx = fVxx0x + fJ * (fVxx1x - fVxx0x);
  5520. fVxx0x = *v1100 + fK * (int)((int)*v1101 - (int)*v1100);
  5521. fVxx1x = *v1110 + fK * (int)((int)*v1111 - (int)*v1110);
  5522. fVx1xx = fVxx0x + fJ * (fVxx1x - fVxx0x);
  5523. fV1xxx = fVx0xx + fI * (fVx1xx - fVx0xx);
  5524. //
  5525. // Calculate the bottom and upper average.
  5526. //
  5527. pfTemp[idx] = (fV0xxx + fH * (fV1xxx - fV0xxx)) / MAXCOLOR8;
  5528. if (idx < (DWORD)(nOutputCh - 1))
  5529. {
  5530. v0000++;
  5531. v0001++;
  5532. v0010++;
  5533. v0011++;
  5534. v0100++;
  5535. v0101++;
  5536. v0110++;
  5537. v0111++;
  5538. v1000++;
  5539. v1001++;
  5540. v1010++;
  5541. v1011++;
  5542. v1100++;
  5543. v1101++;
  5544. v1110++;
  5545. v1111++;
  5546. }
  5547. }
  5548. return TRUE;
  5549. }
  5550. BOOL
  5551. InvertColorantArray(
  5552. double *lpInMatrix,
  5553. double *lpOutMatrix)
  5554. {
  5555. double det;
  5556. double *a;
  5557. double *b;
  5558. double *c;
  5559. a = &(lpInMatrix[0]);
  5560. b = &(lpInMatrix[3]);
  5561. c = &(lpInMatrix[6]);
  5562. det = a[0] * b[1] * c[2] + a[1] * b[2] * c[0] + a[2] * b[0] * c[1] -
  5563. (a[2] * b[1] * c[0] + a[1] * b[0] * c[2] + a[0] * b[2] * c[1]);
  5564. if (det == 0.0) // What to do?
  5565. {
  5566. lpOutMatrix[0] = 1.0;
  5567. lpOutMatrix[1] = 0.0;
  5568. lpOutMatrix[2] = 0.0;
  5569. lpOutMatrix[3] = 0.0;
  5570. lpOutMatrix[4] = 1.0;
  5571. lpOutMatrix[5] = 0.0;
  5572. lpOutMatrix[6] = 0.0;
  5573. lpOutMatrix[7] = 0.0;
  5574. lpOutMatrix[8] = 1.0;
  5575. }
  5576. else
  5577. {
  5578. lpOutMatrix[0] = (b[1] * c[2] - b[2] * c[1]) / det;
  5579. lpOutMatrix[3] = -(b[0] * c[2] - b[2] * c[0]) / det;
  5580. lpOutMatrix[6] = (b[0] * c[1] - b[1] * c[0]) / det;
  5581. lpOutMatrix[1] = -(a[1] * c[2] - a[2] * c[1]) / det;
  5582. lpOutMatrix[4] = (a[0] * c[2] - a[2] * c[0]) / det;
  5583. lpOutMatrix[7] = -(a[0] * c[1] - a[1] * c[0]) / det;
  5584. lpOutMatrix[2] = (a[1] * b[2] - a[2] * b[1]) / det;
  5585. lpOutMatrix[5] = -(a[0] * b[2] - a[2] * b[0]) / det;
  5586. lpOutMatrix[8] = (a[0] * b[1] - a[1] * b[0]) / det;
  5587. }
  5588. return (TRUE);
  5589. }
  5590. VOID
  5591. ApplyMatrix(
  5592. FIX_16_16 *e,
  5593. float *Input,
  5594. float *Output)
  5595. {
  5596. DWORD i, j;
  5597. for (i=0; i<3; i++)
  5598. {
  5599. j = i * 3;
  5600. Output[i] = ((e[j] * Input[0]) / FIX_16_16_SCALE) +
  5601. ((e[j + 1] * Input[1]) / FIX_16_16_SCALE) +
  5602. ((e[j + 2] * Input[2]) / FIX_16_16_SCALE);
  5603. }
  5604. }
  5605. /***************************************************************************
  5606. * CheckColorLookupTable
  5607. * function:
  5608. * This function check RenderTable.
  5609. * parameters:
  5610. * LPHOSTCLUT lpHostClut --
  5611. * float far *fTemp -- Input (in range [0 gred-1]) /
  5612. * output(in range [0 1)
  5613. * returns:
  5614. * BOOL -- TRUE
  5615. ***************************************************************************/
  5616. BOOL
  5617. CheckColorLookupTable(
  5618. PHOSTCLUT pHostClut,
  5619. float *pfTemp
  5620. )
  5621. {
  5622. if (pHostClut->nInputCh == 3)
  5623. {
  5624. return TableInterp3(pHostClut, pfTemp);
  5625. }
  5626. else if (pHostClut->nInputCh == 4)
  5627. {
  5628. return TableInterp4(pHostClut, pfTemp);
  5629. }
  5630. else
  5631. return FALSE;
  5632. }
  5633. //
  5634. // For testing purposes
  5635. //
  5636. BOOL WINAPI
  5637. GetPS2PreviewCRD (
  5638. HPROFILE hDestProfile,
  5639. HPROFILE hTargetProfile,
  5640. DWORD dwIntent,
  5641. PBYTE pBuffer,
  5642. PDWORD pcbSize,
  5643. LPBOOL pbBinary
  5644. )
  5645. {
  5646. PPROFOBJ pDestProfObj;
  5647. PPROFOBJ pTargetProfObj;
  5648. pDestProfObj = (PPROFOBJ)HDLTOPTR(hDestProfile);
  5649. pTargetProfObj = (PPROFOBJ)HDLTOPTR(hTargetProfile);
  5650. return InternalGetPS2PreviewCRD(pDestProfObj->pView, pTargetProfObj->pView, dwIntent, pBuffer, pcbSize, pbBinary);
  5651. }
  5652. #endif // !defined(KERNEL_MODE) || defined(USERMODE_DRIVER)
  5653. /*
  5654. * Crc - 32 BIT ANSI X3.66 CRC checksum files
  5655. *
  5656. *
  5657. * Copyright (C) 1986 Gary S. Brown. You may use this program, or
  5658. * code or tables extracted from it, as desired without restriction.
  5659. */
  5660. static DWORD crc_32_tab[] = { /* CRC polynomial 0xedb88320 */
  5661. 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
  5662. 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
  5663. 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
  5664. 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
  5665. 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
  5666. 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
  5667. 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
  5668. 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
  5669. 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
  5670. 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
  5671. 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
  5672. 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
  5673. 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
  5674. 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
  5675. 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
  5676. 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
  5677. 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
  5678. 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
  5679. 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
  5680. 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
  5681. 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
  5682. 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
  5683. 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
  5684. 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
  5685. 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
  5686. 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
  5687. 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
  5688. 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
  5689. 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
  5690. 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
  5691. 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
  5692. 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
  5693. };
  5694. DWORD crc32(PBYTE buff, DWORD length)
  5695. {
  5696. DWORD crc, charcnt;
  5697. BYTE c;
  5698. crc = 0xFFFFFFFF;
  5699. charcnt = 0;
  5700. for (charcnt = 0 ; charcnt < length ; charcnt++)
  5701. {
  5702. c = buff[charcnt];
  5703. crc = crc_32_tab[(crc ^ c) & 0xff] ^ (crc >> 8);
  5704. }
  5705. return crc;
  5706. }
  5707. /***************************************************************************
  5708. * IsSRGBColorProfile
  5709. *
  5710. * function: check if the profile is sRGB
  5711. *
  5712. * parameters:
  5713. * cp -- Color Profile handle
  5714. *
  5715. * returns:
  5716. * BOOL -- TRUE if the profile is sRGB
  5717. * FALSE otherwise.
  5718. ***************************************************************************/
  5719. BOOL IsSRGBColorProfile(
  5720. PBYTE pProfile
  5721. )
  5722. {
  5723. BOOL bMatch = FALSE;
  5724. DWORD dwRedTRCIndex, dwGreenTRCIndex, dwBlueTRCIndex;
  5725. DWORD dwRedCIndex, dwGreenCIndex, dwBlueCIndex;
  5726. DWORD dwSize;
  5727. DWORD dwRedTRCSize=0, dwGreenTRCSize=0, dwBlueTRCSize=0;
  5728. DWORD dwRedCSize=0, dwGreenCSize=0, dwBlueCSize=0;
  5729. PBYTE pRed, pGreen, pBlue, pRedC, pGreenC, pBlueC;
  5730. BYTE DataBuffer[ALIGN_DWORD(sRGB_TAGSIZE)];
  5731. if (DoesCPTagExist(pProfile, TAG_REDTRC, &dwRedTRCIndex) &&
  5732. GetCPElementDataSize(pProfile, dwRedTRCIndex, &dwRedTRCSize) &&
  5733. DoesCPTagExist(pProfile, TAG_GREENTRC, &dwGreenTRCIndex) &&
  5734. GetCPElementDataSize(pProfile, dwGreenTRCIndex, &dwGreenTRCSize) &&
  5735. DoesCPTagExist(pProfile, TAG_BLUETRC, &dwBlueTRCIndex) &&
  5736. GetCPElementDataSize(pProfile, dwBlueTRCIndex, &dwBlueTRCSize) &&
  5737. DoesCPTagExist(pProfile, TAG_REDCOLORANT, &dwRedCIndex) &&
  5738. GetCPElementDataSize(pProfile, dwRedCIndex, &dwRedCSize) &&
  5739. DoesCPTagExist(pProfile, TAG_GREENCOLORANT, &dwGreenCIndex) &&
  5740. GetCPElementDataSize(pProfile, dwGreenCIndex, &dwGreenCSize) &&
  5741. DoesCPTagExist(pProfile, TAG_BLUECOLORANT, &dwBlueCIndex) &&
  5742. GetCPElementDataSize(pProfile, dwBlueCIndex, &dwBlueCSize))
  5743. {
  5744. dwSize = dwRedTRCSize + dwGreenTRCSize + dwBlueTRCSize +
  5745. dwRedCSize + dwGreenCSize + dwBlueCSize;
  5746. if (dwSize == sRGB_TAGSIZE)
  5747. {
  5748. ZeroMemory(DataBuffer,sizeof(DataBuffer));
  5749. pRed = DataBuffer;
  5750. pGreen = pRed + dwRedTRCSize;
  5751. pBlue = pGreen + dwGreenTRCSize;
  5752. pRedC = pBlue + dwBlueTRCSize;
  5753. pGreenC = pRedC + dwRedCSize;
  5754. pBlueC = pGreenC + dwGreenCSize;
  5755. if (GetCPElementData(pProfile, dwRedTRCIndex, pRed, &dwRedTRCSize) &&
  5756. GetCPElementData(pProfile, dwGreenTRCIndex, pGreen, &dwGreenTRCSize) &&
  5757. GetCPElementData(pProfile, dwBlueTRCIndex, pBlue, &dwBlueTRCSize) &&
  5758. GetCPElementData(pProfile, dwRedCIndex, pRedC, &dwRedCSize) &&
  5759. GetCPElementData(pProfile, dwGreenCIndex, pGreenC, &dwGreenCSize) &&
  5760. GetCPElementData(pProfile, dwBlueCIndex, pBlueC, &dwBlueCSize))
  5761. {
  5762. bMatch = (crc32(DataBuffer, sRGB_TAGSIZE) == sRGB_CRC);
  5763. }
  5764. }
  5765. }
  5766. return (bMatch);
  5767. }