1ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//--------------------------------------------------------------------------------- 2ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// 3ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Little Color Management System 4ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Copyright (c) 1998-2011 Marti Maria Saguer 5ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// 6ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Permission is hereby granted, free of charge, to any person obtaining 7ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// a copy of this software and associated documentation files (the "Software"), 8ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// to deal in the Software without restriction, including without limitation 9ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// the rights to use, copy, modify, merge, publish, distribute, sublicense, 10ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// and/or sell copies of the Software, and to permit persons to whom the Software 11ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// is furnished to do so, subject to the following conditions: 12ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// 13ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// The above copyright notice and this permission notice shall be included in 14ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// all copies or substantial portions of the Software. 15ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// 16ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 18ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// 24ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//--------------------------------------------------------------------------------- 25ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// 26ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 27ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "lcms2_internal.h" 28ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 29ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// PostScript ColorRenderingDictionary and ColorSpaceArray 30ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 31ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 32ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define MAXPSCOLS 60 // Columns on tables 33ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 34ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* 35ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Implementation 36ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov -------------- 37ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 38ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov PostScript does use XYZ as its internal PCS. But since PostScript 39ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov interpolation tables are limited to 8 bits, I use Lab as a way to 40ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov improve the accuracy, favoring perceptual results. So, for the creation 41ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov of each CRD, CSA the profiles are converted to Lab via a device 42ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov link between profile -> Lab or Lab -> profile. The PS code necessary to 43ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov convert Lab <-> XYZ is also included. 44ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 45ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 46ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 47ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Color Space Arrays (CSA) 48ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ================================================================================== 49ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 50ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov In order to obtain precision, code chooses between three ways to implement 51ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov the device -> XYZ transform. These cases identifies monochrome profiles (often 52ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov implemented as a set of curves), matrix-shaper and Pipeline-based. 53ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 54ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Monochrome 55ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ----------- 56ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 57ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov This is implemented as /CIEBasedA CSA. The prelinearization curve is 58ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov placed into /DecodeA section, and matrix equals to D50. Since here is 59ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov no interpolation tables, I do the conversion directly to XYZ 60ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 61ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NOTE: CLUT-based monochrome profiles are NOT supported. So, cmsFLAGS_MATRIXINPUT 62ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov flag is forced on such profiles. 63ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 64ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov [ /CIEBasedA 65ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov << 66ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /DecodeA { transfer function } bind 67ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /MatrixA [D50] 68ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /RangeLMN [ 0.0 cmsD50X 0.0 cmsD50Y 0.0 cmsD50Z ] 69ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /WhitePoint [D50] 70ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /BlackPoint [BP] 71ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /RenderingIntent (intent) 72ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov >> 73ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ] 74ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 75ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov On simpler profiles, the PCS is already XYZ, so no conversion is required. 76ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 77ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 78ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Matrix-shaper based 79ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ------------------- 80ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 81ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov This is implemented both with /CIEBasedABC or /CIEBasedDEF on dependig 82ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov of profile implementation. Since here there are no interpolation tables, I do 83ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov the conversion directly to XYZ 84ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 85ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 86ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 87ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov [ /CIEBasedABC 88ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov << 89ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /DecodeABC [ {transfer1} {transfer2} {transfer3} ] 90ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /MatrixABC [Matrix] 91ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /RangeLMN [ 0.0 cmsD50X 0.0 cmsD50Y 0.0 cmsD50Z ] 92ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /DecodeLMN [ { / 2} dup dup ] 93ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /WhitePoint [D50] 94ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /BlackPoint [BP] 95ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /RenderingIntent (intent) 96ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov >> 97ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ] 98ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 99ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CLUT based 101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ---------- 102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Lab is used in such cases. 104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov [ /CIEBasedDEF 106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov << 107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /DecodeDEF [ <prelinearization> ] 108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /Table [ p p p [<...>]] 109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /RangeABC [ 0 1 0 1 0 1] 110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /DecodeABC[ <postlinearization> ] 111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /RangeLMN [ -0.236 1.254 0 1 -0.635 1.640 ] 112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov % -128/500 1+127/500 0 1 -127/200 1+128/200 113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /MatrixABC [ 1 1 1 1 0 0 0 0 -1] 114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /WhitePoint [D50] 115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /BlackPoint [BP] 116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /RenderingIntent (intent) 117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ] 118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Color Rendering Dictionaries (CRD) 121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ================================== 122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov These are always implemented as CLUT, and always are using Lab. Since CRD are expected to 123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov be used as resources, the code adds the definition as well. 124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov << 126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /ColorRenderingType 1 127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /WhitePoint [ D50 ] 128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /BlackPoint [BP] 129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /MatrixPQR [ Bradford ] 130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /RangePQR [-0.125 1.375 -0.125 1.375 -0.125 1.375 ] 131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /TransformPQR [ 132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov {4 index 3 get div 2 index 3 get mul exch pop exch pop exch pop exch pop } bind 133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov {4 index 4 get div 2 index 4 get mul exch pop exch pop exch pop exch pop } bind 134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov {4 index 5 get div 2 index 5 get mul exch pop exch pop exch pop exch pop } bind 135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ] 136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /MatrixABC <...> 137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /EncodeABC <...> 138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /RangeABC <.. used for XYZ -> Lab> 139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /EncodeLMN 140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /RenderTable [ p p p [<...>]] 141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /RenderingIntent (Perceptual) 143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov >> 144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /Current exch /ColorRendering defineresource pop 145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov The following stages are used to convert from XYZ to Lab 148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov -------------------------------------------------------- 149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Input is given at LMN stage on X, Y, Z 151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Encode LMN gives us f(X/Xn), f(Y/Yn), f(Z/Zn) 153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /EncodeLMN [ 155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 0.964200 div dup 0.008856 le {7.787 mul 16 116 div add}{1 3 div exp} ifelse } bind 157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1.000000 div dup 0.008856 le {7.787 mul 16 116 div add}{1 3 div exp} ifelse } bind 158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 0.824900 div dup 0.008856 le {7.787 mul 16 116 div add}{1 3 div exp} ifelse } bind 159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ] 161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov MatrixABC is used to compute f(Y/Yn), f(X/Xn) - f(Y/Yn), f(Y/Yn) - f(Z/Zn) 164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov | 0 1 0| 166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov | 1 -1 0| 167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov | 0 1 -1| 168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /MatrixABC [ 0 1 0 1 -1 1 0 0 -1 ] 170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov EncodeABC finally gives Lab values. 172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /EncodeABC [ 174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 116 mul 16 sub 100 div } bind 175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 500 mul 128 add 255 div } bind 176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 200 mul 128 add 255 div } bind 177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ] 178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov The following stages are used to convert Lab to XYZ 180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ---------------------------------------------------- 181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /RangeABC [ 0 1 0 1 0 1] 183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /DecodeABC [ { 100 mul 16 add 116 div } bind 184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 255 mul 128 sub 500 div } bind 185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 255 mul 128 sub 200 div } bind 186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ] 187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /MatrixABC [ 1 1 1 1 0 0 0 0 -1] 189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /DecodeLMN [ 190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov {dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse 0.964200 mul} bind 191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov {dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse } bind 192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov {dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse 0.824900 mul} bind 193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ] 194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov*/ 197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* 199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov PostScript algorithms discussion. 201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ========================================================================================================= 202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1D interpolation algorithm 204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1D interpolation (float) 207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ------------------------ 208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov val2 = Domain * Value; 210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cell0 = (int) floor(val2); 212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cell1 = (int) ceil(val2); 213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov rest = val2 - cell0; 215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y0 = LutTable[cell0] ; 217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y1 = LutTable[cell1] ; 218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y = y0 + (y1 - y0) * rest; 220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov PostScript code Stack 224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ================================================ 225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { % v 227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov <check 0..1.0> 228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov [array] % v tab 229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dup % v tab tab 230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov length 1 sub % v tab dom 231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3 -1 roll % tab dom v 233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mul % tab val2 235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dup % tab val2 val2 236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dup % tab val2 val2 val2 237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov floor cvi % tab val2 val2 cell0 238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov exch % tab val2 cell0 val2 239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ceiling cvi % tab val2 cell0 cell1 240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3 index % tab val2 cell0 cell1 tab 242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov exch % tab val2 cell0 tab cell1 243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov get % tab val2 cell0 y1 244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 4 -1 roll % val2 cell0 y1 tab 246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3 -1 roll % val2 y1 tab cell0 247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov get % val2 y1 y0 248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dup % val2 y1 y0 y0 250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3 1 roll % val2 y0 y1 y0 251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sub % val2 y0 (y1-y0) 253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3 -1 roll % y0 (y1-y0) val2 254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dup % y0 (y1-y0) val2 val2 255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov floor cvi % y0 (y1-y0) val2 floor(val2) 256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sub % y0 (y1-y0) rest 257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mul % y0 t1 258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov add % y 259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 65535 div % result 260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } bind 262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov*/ 265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// This struct holds the memory block currently being write 268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovtypedef struct { 269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsStageCLutData* Pipeline; 270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsIOHANDLER* m; 271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int FirstComponent; 273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int SecondComponent; 274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const char* PreMaj; 276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const char* PostMaj; 277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const char* PreMin; 278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const char* PostMin; 279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int FixWhite; // Force mapping of pure white 281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsColorSpaceSignature ColorSpace; // ColorSpace of profile 283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} cmsPsSamplerCargo; 286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic int _cmsPSActualColumn = 0; 288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Convert to byte 291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 292ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsUInt8Number Word2Byte(cmsUInt16Number w) 293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return (cmsUInt8Number) floor((cmsFloat64Number) w / 257.0 + 0.5); 295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Convert to byte (using ICC2 notation) 299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* 300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 301ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsUInt8Number L2Byte(cmsUInt16Number w) 302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int ww = w + 0x0080; 304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (ww > 0xFFFF) return 0xFF; 306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return (cmsUInt8Number) ((cmsUInt16Number) (ww >> 8) & 0xFF); 308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov*/ 310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Write a cooked byte 312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid WriteByte(cmsIOHANDLER* m, cmsUInt8Number b) 315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "%02x", b); 317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsPSActualColumn += 2; 318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (_cmsPSActualColumn > MAXPSCOLS) { 320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "\n"); 322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsPSActualColumn = 0; 323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ----------------------------------------------------------------- PostScript generation 327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Removes offending Carriage returns 330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovchar* RemoveCR(const char* txt) 332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static char Buffer[2048]; 334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov char* pt; 335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov strncpy(Buffer, txt, 2047); 337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Buffer[2047] = 0; 338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (pt = Buffer; *pt; pt++) 339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (*pt == '\n' || *pt == '\r') *pt = ' '; 340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return Buffer; 342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid EmitHeader(cmsIOHANDLER* m, const char* Title, cmsHPROFILE hProfile) 347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov time_t timer; 349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsMLU *Description, *Copyright; 350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov char DescASCII[256], CopyrightASCII[256]; 351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov time(&timer); 353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Description = (cmsMLU*) cmsReadTag(hProfile, cmsSigProfileDescriptionTag); 355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Copyright = (cmsMLU*) cmsReadTag(hProfile, cmsSigCopyrightTag); 356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov DescASCII[0] = DescASCII[255] = 0; 358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CopyrightASCII[0] = CopyrightASCII[255] = 0; 359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (Description != NULL) cmsMLUgetASCII(Description, cmsNoLanguage, cmsNoCountry, DescASCII, 255); 361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (Copyright != NULL) cmsMLUgetASCII(Copyright, cmsNoLanguage, cmsNoCountry, CopyrightASCII, 255); 362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "%%!PS-Adobe-3.0\n"); 364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "%%\n"); 365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "%% %s\n", Title); 366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "%% Source: %s\n", RemoveCR(DescASCII)); 367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "%% %s\n", RemoveCR(CopyrightASCII)); 368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "%% Created: %s", ctime(&timer)); // ctime appends a \n!!! 369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "%%\n"); 370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "%%%%BeginResource\n"); 371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Emits White & Black point. White point is always D50, Black point is the device 376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Black point adapted to D50. 377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid EmitWhiteBlackD50(cmsIOHANDLER* m, cmsCIEXYZ* BlackPoint) 380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "/BlackPoint [%f %f %f]\n", BlackPoint -> X, 383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov BlackPoint -> Y, 384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov BlackPoint -> Z); 385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "/WhitePoint [%f %f %f]\n", cmsD50_XYZ()->X, 387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsD50_XYZ()->Y, 388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsD50_XYZ()->Z); 389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 390ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid EmitRangeCheck(cmsIOHANDLER* m) 394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "dup 0.0 lt { pop 0.0 } if " 396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov "dup 1.0 gt { pop 1.0 } if "); 397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Does write the intent 401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid EmitIntent(cmsIOHANDLER* m, int RenderingIntent) 404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const char *intent; 406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov switch (RenderingIntent) { 408ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case INTENT_PERCEPTUAL: intent = "Perceptual"; break; 410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case INTENT_RELATIVE_COLORIMETRIC: intent = "RelativeColorimetric"; break; 411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case INTENT_ABSOLUTE_COLORIMETRIC: intent = "AbsoluteColorimetric"; break; 412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case INTENT_SATURATION: intent = "Saturation"; break; 413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov default: intent = "Undefined"; break; 415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "/RenderingIntent (%s)\n", intent ); 418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// 421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Convert L* to Y 422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// 423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Y = Yn*[ (L* + 16) / 116] ^ 3 if (L*) >= 6 / 29 424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// = Yn*( L* / 116) / 7.787 if (L*) < 6 / 29 425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// 426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* 428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid EmitL2Y(cmsIOHANDLER* m) 430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, 432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov "{ " 433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov "100 mul 16 add 116 div " // (L * 100 + 16) / 116 434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov "dup 6 29 div ge " // >= 6 / 29 ? 435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov "{ dup dup mul mul } " // yes, ^3 and done 436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov "{ 4 29 div sub 108 841 div mul } " // no, slope limiting 437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov "ifelse } bind "); 438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov*/ 440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Lab -> XYZ, see the discussion above 443ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid EmitLab2XYZ(cmsIOHANDLER* m) 446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "/RangeABC [ 0 1 0 1 0 1]\n"); 448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "/DecodeABC [\n"); 449ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "{100 mul 16 add 116 div } bind\n"); 450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "{255 mul 128 sub 500 div } bind\n"); 451ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "{255 mul 128 sub 200 div } bind\n"); 452ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "]\n"); 453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "/MatrixABC [ 1 1 1 1 0 0 0 0 -1]\n"); 454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "/RangeLMN [ -0.236 1.254 0 1 -0.635 1.640 ]\n"); 455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "/DecodeLMN [\n"); 456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "{dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse 0.964200 mul} bind\n"); 457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "{dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse } bind\n"); 458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "{dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse 0.824900 mul} bind\n"); 459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "]\n"); 460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Outputs a table of words. It does use 16 bits 465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 467ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Emit1Gamma(cmsIOHANDLER* m, cmsToneCurve* Table) 468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number i; 470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsFloat64Number gamma; 471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (Table == NULL) return; // Error 473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (Table ->nEntries <= 0) return; // Empty table 475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 476ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Suppress whole if identity 477ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (cmsIsToneCurveLinear(Table)) return; 478ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Check if is really an exponential. If so, emit "exp" 480ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gamma = cmsEstimateGamma(Table, 0.001); 481ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (gamma > 0) { 482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "{ %g exp } bind ", gamma); 483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "{ "); 487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Bounds check 489ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov EmitRangeCheck(m); 490ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 491ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Emit intepolation code 492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 493ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // PostScript code Stack 494ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // =============== ======================== 495ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // v 496ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, " ["); 497ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 498ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (i=0; i < Table->nEntries; i++) { 499ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "%d ", Table->Table16[i]); 500ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 501ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 502ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "] "); // v tab 503ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 504ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "dup "); // v tab tab 505ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "length 1 sub "); // v tab dom 506ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "3 -1 roll "); // tab dom v 507ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "mul "); // tab val2 508ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "dup "); // tab val2 val2 509ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "dup "); // tab val2 val2 val2 510ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "floor cvi "); // tab val2 val2 cell0 511ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "exch "); // tab val2 cell0 val2 512ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "ceiling cvi "); // tab val2 cell0 cell1 513ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "3 index "); // tab val2 cell0 cell1 tab 514ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "exch "); // tab val2 cell0 tab cell1 515ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "get "); // tab val2 cell0 y1 516ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "4 -1 roll "); // val2 cell0 y1 tab 517ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "3 -1 roll "); // val2 y1 tab cell0 518ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "get "); // val2 y1 y0 519ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "dup "); // val2 y1 y0 y0 520ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "3 1 roll "); // val2 y0 y1 y0 521ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "sub "); // val2 y0 (y1-y0) 522ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "3 -1 roll "); // y0 (y1-y0) val2 523ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "dup "); // y0 (y1-y0) val2 val2 524ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "floor cvi "); // y0 (y1-y0) val2 floor(val2) 525ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "sub "); // y0 (y1-y0) rest 526ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "mul "); // y0 t1 527ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "add "); // y 528ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "65535 div "); // result 529ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 530ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, " } bind "); 531ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 532ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 533ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 534ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Compare gamma table 535ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 536ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 537ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool GammaTableEquals(cmsUInt16Number* g1, cmsUInt16Number* g2, int nEntries) 538ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 539ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return memcmp(g1, g2, nEntries* sizeof(cmsUInt16Number)) == 0; 540ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 541ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 542ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 543ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Does write a set of gamma curves 544ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 545ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 546ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid EmitNGamma(cmsIOHANDLER* m, int n, cmsToneCurve* g[]) 547ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 548ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int i; 549ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 550ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for( i=0; i < n; i++ ) 551ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 552ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (g[i] == NULL) return; // Error 553ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 554ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (i > 0 && GammaTableEquals(g[i-1]->Table16, g[i]->Table16, g[i]->nEntries)) { 555ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 556ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "dup "); 557ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 558ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else { 559ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Emit1Gamma(m, g[i]); 560ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 561ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 562ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 563ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 564ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 565ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 566ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 567ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 568ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 569ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Following code dumps a LUT onto memory stream 570ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 571ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 572ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// This is the sampler. Intended to work in SAMPLER_INSPECT mode, 573ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// that is, the callback will be called for each knot with 574ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// 575ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// In[] The grid location coordinates, normalized to 0..ffff 576ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Out[] The Pipeline values, normalized to 0..ffff 577ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// 578ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Returning a value other than 0 does terminate the sampling process 579ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// 580ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Each row contains Pipeline values for all but first component. So, I 581ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// detect row changing by keeping a copy of last value of first 582ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// component. -1 is used to mark begining of whole block. 583ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 584ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 585ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovint OutputValueSampler(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void* Cargo) 586ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 587ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsPsSamplerCargo* sc = (cmsPsSamplerCargo*) Cargo; 588ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number i; 589ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 590ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 591ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (sc -> FixWhite) { 592ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 593ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (In[0] == 0xFFFF) { // Only in L* = 100, ab = [-8..8] 594ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 595ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ((In[1] >= 0x7800 && In[1] <= 0x8800) && 596ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (In[2] >= 0x7800 && In[2] <= 0x8800)) { 597ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 598ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt16Number* Black; 599ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt16Number* White; 600ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number nOutputs; 601ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 602ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!_cmsEndPointsBySpace(sc ->ColorSpace, &White, &Black, &nOutputs)) 603ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 604ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 605ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (i=0; i < nOutputs; i++) 606ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Out[i] = White[i]; 607ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 608ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 609ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 610ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 611ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 612ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 613ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 614ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Hadle the parenthesis on rows 615ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 616ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (In[0] != sc ->FirstComponent) { 617ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 618ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (sc ->FirstComponent != -1) { 619ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 620ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(sc ->m, sc ->PostMin); 621ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sc ->SecondComponent = -1; 622ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(sc ->m, sc ->PostMaj); 623ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 624ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 625ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Begin block 626ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsPSActualColumn = 0; 627ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 628ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(sc ->m, sc ->PreMaj); 629ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sc ->FirstComponent = In[0]; 630ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 631ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 632ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 633ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (In[1] != sc ->SecondComponent) { 634ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 635ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (sc ->SecondComponent != -1) { 636ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 637ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(sc ->m, sc ->PostMin); 638ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 639ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 640ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(sc ->m, sc ->PreMin); 641ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sc ->SecondComponent = In[1]; 642ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 643ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 644ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Dump table. 645ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 646ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (i=0; i < sc -> Pipeline ->Params->nOutputs; i++) { 647ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 648ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt16Number wWordOut = Out[i]; 649ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt8Number wByteOut; // Value as byte 650ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 651ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 652ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // We always deal with Lab4 653ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 654ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov wByteOut = Word2Byte(wWordOut); 655ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov WriteByte(sc -> m, wByteOut); 656ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 657ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 658ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 1; 659ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 660ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 661ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Writes a Pipeline on memstream. Could be 8 or 16 bits based 662ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 663ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 664ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid WriteCLUT(cmsIOHANDLER* m, cmsStage* mpe, const char* PreMaj, 665ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const char* PostMaj, 666ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const char* PreMin, 667ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const char* PostMin, 668ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int FixWhite, 669ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsColorSpaceSignature ColorSpace) 670ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 671ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number i; 672ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsPsSamplerCargo sc; 673ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 674ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sc.FirstComponent = -1; 675ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sc.SecondComponent = -1; 676ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sc.Pipeline = (_cmsStageCLutData *) mpe ->Data; 677ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sc.m = m; 678ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sc.PreMaj = PreMaj; 679ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sc.PostMaj= PostMaj; 680ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 681ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sc.PreMin = PreMin; 682ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sc.PostMin = PostMin; 683ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sc.FixWhite = FixWhite; 684ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sc.ColorSpace = ColorSpace; 685ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 686ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "["); 687ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 688ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (i=0; i < sc.Pipeline->Params->nInputs; i++) 689ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, " %d ", sc.Pipeline->Params->nSamples[i]); 690ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 691ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, " [\n"); 692ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 693ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsStageSampleCLut16bit(mpe, OutputValueSampler, (void*) &sc, SAMPLER_INSPECT); 694ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 695ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, PostMin); 696ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, PostMaj); 697ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "] "); 698ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 699ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 700ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 701ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 702ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Dumps CIEBasedA Color Space Array 703ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 704ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 705ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovint EmitCIEBasedA(cmsIOHANDLER* m, cmsToneCurve* Curve, cmsCIEXYZ* BlackPoint) 706ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 707ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 708ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "[ /CIEBasedA\n"); 709ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, " <<\n"); 710ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 711ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "/DecodeA "); 712ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 713ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Emit1Gamma(m, Curve); 714ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 715ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, " \n"); 716ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 717ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "/MatrixA [ 0.9642 1.0000 0.8249 ]\n"); 718ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "/RangeLMN [ 0.0 0.9642 0.0 1.0000 0.0 0.8249 ]\n"); 719ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 720ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov EmitWhiteBlackD50(m, BlackPoint); 721ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov EmitIntent(m, INTENT_PERCEPTUAL); 722ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 723ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, ">>\n"); 724ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "]\n"); 725ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 726ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 1; 727ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 728ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 729ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 730ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Dumps CIEBasedABC Color Space Array 731ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 732ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 733ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovint EmitCIEBasedABC(cmsIOHANDLER* m, cmsFloat64Number* Matrix, cmsToneCurve** CurveSet, cmsCIEXYZ* BlackPoint) 734ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 735ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int i; 736ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 737ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "[ /CIEBasedABC\n"); 738ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "<<\n"); 739ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "/DecodeABC [ "); 740ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 741ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov EmitNGamma(m, 3, CurveSet); 742ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 743ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "]\n"); 744ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 745ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "/MatrixABC [ " ); 746ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 747ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for( i=0; i < 3; i++ ) { 748ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 749ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "%.6f %.6f %.6f ", Matrix[i + 3*0], 750ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Matrix[i + 3*1], 751ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Matrix[i + 3*2]); 752ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 753ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 754ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 755ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "]\n"); 756ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 757ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "/RangeLMN [ 0.0 0.9642 0.0 1.0000 0.0 0.8249 ]\n"); 758ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 759ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov EmitWhiteBlackD50(m, BlackPoint); 760ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov EmitIntent(m, INTENT_PERCEPTUAL); 761ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 762ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, ">>\n"); 763ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "]\n"); 764ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 765ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 766ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 1; 767ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 768ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 769ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 770ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 771ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovint EmitCIEBasedDEF(cmsIOHANDLER* m, cmsPipeline* Pipeline, int Intent, cmsCIEXYZ* BlackPoint) 772ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 773ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const char* PreMaj; 774ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const char* PostMaj; 775ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const char* PreMin, *PostMin; 776ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsStage* mpe; 777ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 778ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mpe = Pipeline ->Elements; 779ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 780ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov switch (cmsStageInputChannels(mpe)) { 781ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 3: 782ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 783ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "[ /CIEBasedDEF\n"); 784ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov PreMaj ="<"; 785ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov PostMaj= ">\n"; 786ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov PreMin = PostMin = ""; 787ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 788ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 4: 789ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "[ /CIEBasedDEFG\n"); 790ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov PreMaj = "["; 791ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov PostMaj = "]\n"; 792ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov PreMin = "<"; 793ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov PostMin = ">\n"; 794ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 795ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov default: 796ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 797ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 798ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 799ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 800ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "<<\n"); 801ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 802ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (cmsStageType(mpe) == cmsSigCurveSetElemType) { 803ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 804ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "/DecodeDEF [ "); 805ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov EmitNGamma(m, cmsStageOutputChannels(mpe), _cmsStageGetPtrToCurveSet(mpe)); 806ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "]\n"); 807ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 808ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mpe = mpe ->Next; 809ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 810ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 811ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (cmsStageType(mpe) == cmsSigCLutElemType) { 812ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 813ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "/Table "); 814ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov WriteCLUT(m, mpe, PreMaj, PostMaj, PreMin, PostMin, FALSE, (cmsColorSpaceSignature) 0); 815ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "]\n"); 816ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 817ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 818ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov EmitLab2XYZ(m); 819ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov EmitWhiteBlackD50(m, BlackPoint); 820ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov EmitIntent(m, Intent); 821ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 822ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, " >>\n"); 823ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "]\n"); 824ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 825ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 1; 826ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 827ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 828ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Generates a curve from a gray profile 829ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 830ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 831ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsToneCurve* ExtractGray2Y(cmsContext ContextID, cmsHPROFILE hProfile, int Intent) 832ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 833ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsToneCurve* Out = cmsBuildTabulatedToneCurve16(ContextID, 256, NULL); 834ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsHPROFILE hXYZ = cmsCreateXYZProfile(); 835ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsHTRANSFORM xform = cmsCreateTransformTHR(ContextID, hProfile, TYPE_GRAY_8, hXYZ, TYPE_XYZ_DBL, Intent, cmsFLAGS_NOOPTIMIZE); 836ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int i; 837ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 838ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (Out != NULL) { 839ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (i=0; i < 256; i++) { 840ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 841ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt8Number Gray = (cmsUInt8Number) i; 842ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsCIEXYZ XYZ; 843ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 844ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsDoTransform(xform, &Gray, &XYZ, 1); 845ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 846ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Out ->Table16[i] =_cmsQuickSaturateWord(XYZ.Y * 65535.0); 847ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 848ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 849ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 850ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsDeleteTransform(xform); 851ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsCloseProfile(hXYZ); 852ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return Out; 853ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 854ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 855ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 856ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 857ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Because PostScript has only 8 bits in /Table, we should use 858ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// a more perceptually uniform space... I do choose Lab. 859ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 860ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 861ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovint WriteInputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, int Intent, cmsUInt32Number dwFlags) 862ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 863ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsHPROFILE hLab; 864ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsHTRANSFORM xform; 865ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number nChannels; 866ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number InputFormat; 867ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int rc; 868ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsHPROFILE Profiles[2]; 869ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsCIEXYZ BlackPointAdaptedToD50; 870ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 871ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Does create a device-link based transform. 872ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // The DeviceLink is next dumped as working CSA. 873ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 874ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov InputFormat = cmsFormatterForColorspaceOfProfile(hProfile, 2, FALSE); 875ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov nChannels = T_CHANNELS(InputFormat); 876ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 877ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 878ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsDetectBlackPoint(&BlackPointAdaptedToD50, hProfile, Intent, 0); 879ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 880ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Adjust output to Lab4 881ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov hLab = cmsCreateLab4ProfileTHR(m ->ContextID, NULL); 882ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 883ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Profiles[0] = hProfile; 884ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Profiles[1] = hLab; 885ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 886ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov xform = cmsCreateMultiprofileTransform(Profiles, 2, InputFormat, TYPE_Lab_DBL, Intent, 0); 887ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsCloseProfile(hLab); 888ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 889ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (xform == NULL) { 890ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 891ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsSignalError(m ->ContextID, cmsERROR_COLORSPACE_CHECK, "Cannot create transform Profile -> Lab"); 892ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 893ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 894ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 895ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Only 1, 3 and 4 channels are allowed 896ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 897ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov switch (nChannels) { 898ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 899ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 1: { 900ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsToneCurve* Gray2Y = ExtractGray2Y(m ->ContextID, hProfile, Intent); 901ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov EmitCIEBasedA(m, Gray2Y, &BlackPointAdaptedToD50); 902ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsFreeToneCurve(Gray2Y); 903ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 904ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 905ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 906ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 3: 907ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 4: { 908ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number OutFrm = TYPE_Lab_16; 909ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsPipeline* DeviceLink; 910ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsTRANSFORM* v = (_cmsTRANSFORM*) xform; 911ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 912ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov DeviceLink = cmsPipelineDup(v ->Lut); 913ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (DeviceLink == NULL) return 0; 914ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 915ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dwFlags |= cmsFLAGS_FORCE_CLUT; 916ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsOptimizePipeline(m->ContextID, &DeviceLink, Intent, &InputFormat, &OutFrm, &dwFlags); 917ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 918ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov rc = EmitCIEBasedDEF(m, DeviceLink, Intent, &BlackPointAdaptedToD50); 919ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsPipelineFree(DeviceLink); 920ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (rc == 0) return 0; 921ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 922ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 923ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 924ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov default: 925ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 926ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsSignalError(m ->ContextID, cmsERROR_COLORSPACE_CHECK, "Only 3, 4 channels supported for CSA. This profile has %d channels.", nChannels); 927ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 928ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 929ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 930ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 931ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsDeleteTransform(xform); 932ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 933ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 1; 934ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 935ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 936ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 937ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsFloat64Number* GetPtrToMatrix(const cmsStage* mpe) 938ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 939ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsStageMatrixData* Data = (_cmsStageMatrixData*) mpe ->Data; 940ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 941ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return Data -> Double; 942ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 943ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 944ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 945ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Does create CSA based on matrix-shaper. Allowed types are gray and RGB based 946ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 947ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 948ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovint WriteInputMatrixShaper(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsStage* Matrix, cmsStage* Shaper) 949ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 950ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsColorSpaceSignature ColorSpace; 951ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int rc; 952ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsCIEXYZ BlackPointAdaptedToD50; 953ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 954ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ColorSpace = cmsGetColorSpace(hProfile); 955ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 956ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsDetectBlackPoint(&BlackPointAdaptedToD50, hProfile, INTENT_RELATIVE_COLORIMETRIC, 0); 957ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 958ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (ColorSpace == cmsSigGrayData) { 959ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 960ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsToneCurve** ShaperCurve = _cmsStageGetPtrToCurveSet(Shaper); 961ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov rc = EmitCIEBasedA(m, ShaperCurve[0], &BlackPointAdaptedToD50); 962ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 963ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 964ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 965ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (ColorSpace == cmsSigRgbData) { 966ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 967ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsMAT3 Mat; 968ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int i, j; 969ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 970ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memmove(&Mat, GetPtrToMatrix(Matrix), sizeof(Mat)); 971ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 972ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (i=0; i < 3; i++) 973ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (j=0; j < 3; j++) 974ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Mat.v[i].n[j] *= MAX_ENCODEABLE_XYZ; 975ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 976ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov rc = EmitCIEBasedABC(m, (cmsFloat64Number *) &Mat, 977ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsStageGetPtrToCurveSet(Shaper), 978ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov &BlackPointAdaptedToD50); 979ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 980ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else { 981ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 982ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsSignalError(m ->ContextID, cmsERROR_COLORSPACE_CHECK, "Profile is not suitable for CSA. Unsupported colorspace."); 983ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 984ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 985ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 986ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return rc; 987ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 988ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 989ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 990ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 991ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Creates a PostScript color list from a named profile data. 992ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// This is a HP extension, and it works in Lab instead of XYZ 993ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 994ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 995ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovint WriteNamedColorCSA(cmsIOHANDLER* m, cmsHPROFILE hNamedColor, int Intent) 996ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 997ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsHTRANSFORM xform; 998ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsHPROFILE hLab; 999ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int i, nColors; 1000ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov char ColorName[32]; 1001ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsNAMEDCOLORLIST* NamedColorList; 1002ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1003ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov hLab = cmsCreateLab4ProfileTHR(m ->ContextID, NULL); 1004ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov xform = cmsCreateTransform(hNamedColor, TYPE_NAMED_COLOR_INDEX, hLab, TYPE_Lab_DBL, Intent, 0); 1005ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (xform == NULL) return 0; 1006ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1007ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NamedColorList = cmsGetNamedColorList(xform); 1008ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (NamedColorList == NULL) return 0; 1009ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1010ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "<<\n"); 1011ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "(colorlistcomment) (%s)\n", "Named color CSA"); 1012ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "(Prefix) [ (Pantone ) (PANTONE ) ]\n"); 1013ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "(Suffix) [ ( CV) ( CVC) ( C) ]\n"); 1014ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1015ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov nColors = cmsNamedColorCount(NamedColorList); 1016ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1017ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1018ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (i=0; i < nColors; i++) { 1019ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1020ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt16Number In[1]; 1021ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsCIELab Lab; 1022ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1023ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov In[0] = (cmsUInt16Number) i; 1024ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1025ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!cmsNamedColorInfo(NamedColorList, i, ColorName, NULL, NULL, NULL, NULL)) 1026ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov continue; 1027ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1028ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsDoTransform(xform, In, &Lab, 1); 1029ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, " (%s) [ %.3f %.3f %.3f ]\n", ColorName, Lab.L, Lab.a, Lab.b); 1030ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1031ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1032ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1033ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1034ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, ">>\n"); 1035ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1036ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsDeleteTransform(xform); 1037ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsCloseProfile(hLab); 1038ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 1; 1039ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1040ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1041ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1042ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Does create a Color Space Array on XYZ colorspace for PostScript usage 1043ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 1044ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsUInt32Number GenerateCSA(cmsContext ContextID, 1045ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsHPROFILE hProfile, 1046ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number Intent, 1047ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number dwFlags, 1048ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsIOHANDLER* mem) 1049ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1050ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number dwBytesUsed; 1051ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsPipeline* lut = NULL; 1052ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsStage* Matrix, *Shaper; 1053ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1054ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1055ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Is a named color profile? 1056ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (cmsGetDeviceClass(hProfile) == cmsSigNamedColorClass) { 1057ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1058ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!WriteNamedColorCSA(mem, hProfile, Intent)) goto Error; 1059ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1060ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else { 1061ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1062ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1063ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Any profile class are allowed (including devicelink), but 1064ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // output (PCS) colorspace must be XYZ or Lab 1065ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsColorSpaceSignature ColorSpace = cmsGetPCS(hProfile); 1066ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1067ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (ColorSpace != cmsSigXYZData && 1068ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ColorSpace != cmsSigLabData) { 1069ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1070ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsSignalError(ContextID, cmsERROR_COLORSPACE_CHECK, "Invalid output color space"); 1071ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Error; 1072ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1073ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1074ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1075ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Read the lut with all necessary conversion stages 1076ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov lut = _cmsReadInputLUT(hProfile, Intent); 1077ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (lut == NULL) goto Error; 1078ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1079ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1080ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Tone curves + matrix can be implemented without any LUT 1081ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (cmsPipelineCheckAndRetreiveStages(lut, 2, cmsSigCurveSetElemType, cmsSigMatrixElemType, &Shaper, &Matrix)) { 1082ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1083ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!WriteInputMatrixShaper(mem, hProfile, Matrix, Shaper)) goto Error; 1084ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1085ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1086ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else { 1087ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // We need a LUT for the rest 1088ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!WriteInputLUT(mem, hProfile, Intent, dwFlags)) goto Error; 1089ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1090ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1091ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1092ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1093ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Done, keep memory usage 1094ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dwBytesUsed = mem ->UsedSpace; 1095ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1096ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Get rid of LUT 1097ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (lut != NULL) cmsPipelineFree(lut); 1098ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1099ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Finally, return used byte count 1100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return dwBytesUsed; 1101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1102ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError: 1103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (lut != NULL) cmsPipelineFree(lut); 1104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 1105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ------------------------------------------------------ Color Rendering Dictionary (CRD) 1108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* 1112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Black point compensation plus chromatic adaptation: 1114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Step 1 - Chromatic adaptation 1116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ============================= 1117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov WPout 1119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov X = ------- PQR 1120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Wpin 1121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Step 2 - Black point compensation 1123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ================================= 1124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (WPout - BPout)*X - WPout*(BPin - BPout) 1126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov out = --------------------------------------- 1127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov WPout - BPin 1128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Algorithm discussion 1131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ==================== 1132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TransformPQR(WPin, BPin, WPout, BPout, PQR) 1134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Wpin,etc= { Xws Yws Zws Pws Qws Rws } 1136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Algorithm Stack 0...n 1139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov =========================================================== 1140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov PQR BPout WPout BPin WPin 1141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 4 index 3 get WPin PQR BPout WPout BPin WPin 1142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov div (PQR/WPin) BPout WPout BPin WPin 1143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2 index 3 get WPout (PQR/WPin) BPout WPout BPin WPin 1144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mult WPout*(PQR/WPin) BPout WPout BPin WPin 1145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2 index 3 get WPout WPout*(PQR/WPin) BPout WPout BPin WPin 1147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2 index 3 get BPout WPout WPout*(PQR/WPin) BPout WPout BPin WPin 1148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sub (WPout-BPout) WPout*(PQR/WPin) BPout WPout BPin WPin 1149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mult (WPout-BPout)* WPout*(PQR/WPin) BPout WPout BPin WPin 1150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2 index 3 get WPout (BPout-WPout)* WPout*(PQR/WPin) BPout WPout BPin WPin 1152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 4 index 3 get BPin WPout (BPout-WPout)* WPout*(PQR/WPin) BPout WPout BPin WPin 1153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3 index 3 get BPout BPin WPout (BPout-WPout)* WPout*(PQR/WPin) BPout WPout BPin WPin 1154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sub (BPin-BPout) WPout (BPout-WPout)* WPout*(PQR/WPin) BPout WPout BPin WPin 1156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mult (BPin-BPout)*WPout (BPout-WPout)* WPout*(PQR/WPin) BPout WPout BPin WPin 1157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sub (BPout-WPout)* WPout*(PQR/WPin)-(BPin-BPout)*WPout BPout WPout BPin WPin 1158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3 index 3 get BPin (BPout-WPout)* WPout*(PQR/WPin)-(BPin-BPout)*WPout BPout WPout BPin WPin 1160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3 index 3 get WPout BPin (BPout-WPout)* WPout*(PQR/WPin)-(BPin-BPout)*WPout BPout WPout BPin WPin 1161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov exch 1162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sub (WPout-BPin) (BPout-WPout)* WPout*(PQR/WPin)-(BPin-BPout)*WPout BPout WPout BPin WPin 1163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov div 1164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov exch pop 1166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov exch pop 1167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov exch pop 1168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov exch pop 1169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov*/ 1171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 1174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid EmitPQRStage(cmsIOHANDLER* m, cmsHPROFILE hProfile, int DoBPC, int lIsAbsolute) 1175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (lIsAbsolute) { 1179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // For absolute colorimetric intent, encode back to relative 1181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // and generate a relative Pipeline 1182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Relative encoding is obtained across XYZpcs*(D50/WhitePoint) 1184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsCIEXYZ White; 1186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsReadMediaWhitePoint(&White, hProfile); 1188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m,"/MatrixPQR [1 0 0 0 1 0 0 0 1 ]\n"); 1190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m,"/RangePQR [ -0.5 2 -0.5 2 -0.5 2 ]\n"); 1191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "%% Absolute colorimetric -- encode to relative to maximize LUT usage\n" 1193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov "/TransformPQR [\n" 1194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov "{0.9642 mul %g div exch pop exch pop exch pop exch pop} bind\n" 1195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov "{1.0000 mul %g div exch pop exch pop exch pop exch pop} bind\n" 1196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov "{0.8249 mul %g div exch pop exch pop exch pop exch pop} bind\n]\n", 1197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov White.X, White.Y, White.Z); 1198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 1199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m,"%% Bradford Cone Space\n" 1203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov "/MatrixPQR [0.8951 -0.7502 0.0389 0.2664 1.7135 -0.0685 -0.1614 0.0367 1.0296 ] \n"); 1204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "/RangePQR [ -0.5 2 -0.5 2 -0.5 2 ]\n"); 1206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // No BPC 1209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!DoBPC) { 1211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "%% VonKries-like transform in Bradford Cone Space\n" 1213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov "/TransformPQR [\n" 1214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov "{exch pop exch 3 get mul exch pop exch 3 get div} bind\n" 1215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov "{exch pop exch 4 get mul exch pop exch 4 get div} bind\n" 1216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov "{exch pop exch 5 get mul exch pop exch 5 get div} bind\n]\n"); 1217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else { 1218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // BPC 1220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "%% VonKries-like transform in Bradford Cone Space plus BPC\n" 1222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov "/TransformPQR [\n"); 1223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "{4 index 3 get div 2 index 3 get mul " 1225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov "2 index 3 get 2 index 3 get sub mul " 1226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov "2 index 3 get 4 index 3 get 3 index 3 get sub mul sub " 1227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov "3 index 3 get 3 index 3 get exch sub div " 1228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov "exch pop exch pop exch pop exch pop } bind\n"); 1229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "{4 index 4 get div 2 index 4 get mul " 1231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov "2 index 4 get 2 index 4 get sub mul " 1232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov "2 index 4 get 4 index 4 get 3 index 4 get sub mul sub " 1233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov "3 index 4 get 3 index 4 get exch sub div " 1234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov "exch pop exch pop exch pop exch pop } bind\n"); 1235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "{4 index 5 get div 2 index 5 get mul " 1237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov "2 index 5 get 2 index 5 get sub mul " 1238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov "2 index 5 get 4 index 5 get 3 index 5 get sub mul sub " 1239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov "3 index 5 get 3 index 5 get exch sub div " 1240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov "exch pop exch pop exch pop exch pop } bind\n]\n"); 1241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 1249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid EmitXYZ2Lab(cmsIOHANDLER* m) 1250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "/RangeLMN [ -0.635 2.0 0 2 -0.635 2.0 ]\n"); 1252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "/EncodeLMN [\n"); 1253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "{ 0.964200 div dup 0.008856 le {7.787 mul 16 116 div add}{1 3 div exp} ifelse } bind\n"); 1254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "{ 1.000000 div dup 0.008856 le {7.787 mul 16 116 div add}{1 3 div exp} ifelse } bind\n"); 1255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "{ 0.824900 div dup 0.008856 le {7.787 mul 16 116 div add}{1 3 div exp} ifelse } bind\n"); 1256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "]\n"); 1257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "/MatrixABC [ 0 1 0 1 -1 1 0 0 -1 ]\n"); 1258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "/EncodeABC [\n"); 1259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "{ 116 mul 16 sub 100 div } bind\n"); 1262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "{ 500 mul 128 add 256 div } bind\n"); 1263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "{ 200 mul 128 add 256 div } bind\n"); 1264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "]\n"); 1267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Due to impedance mismatch between XYZ and almost all RGB and CMYK spaces 1272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// I choose to dump LUTS in Lab instead of XYZ. There is still a lot of wasted 1273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// space on 3D CLUT, but since space seems not to be a problem here, 33 points 1274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// would give a reasonable accurancy. Note also that CRD tables must operate in 1275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// 8 bits. 1276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 1278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovint WriteOutputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, int Intent, cmsUInt32Number dwFlags) 1279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsHPROFILE hLab; 1281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsHTRANSFORM xform; 1282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int i, nChannels; 1283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number OutputFormat; 1284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsTRANSFORM* v; 1285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsPipeline* DeviceLink; 1286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsHPROFILE Profiles[3]; 1287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsCIEXYZ BlackPointAdaptedToD50; 1288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsBool lDoBPC = (dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION); 1289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsBool lFixWhite = !(dwFlags & cmsFLAGS_NOWHITEONWHITEFIXUP); 1290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number InFrm = TYPE_Lab_16; 1291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int RelativeEncodingIntent; 1292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsColorSpaceSignature ColorSpace; 1293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov hLab = cmsCreateLab4ProfileTHR(m ->ContextID, NULL); 1296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (hLab == NULL) return 0; 1297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov OutputFormat = cmsFormatterForColorspaceOfProfile(hProfile, 2, FALSE); 1299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov nChannels = T_CHANNELS(OutputFormat); 1300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ColorSpace = cmsGetColorSpace(hProfile); 1302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // For absolute colorimetric, the LUT is encoded as relative in order to preserve precision. 1304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov RelativeEncodingIntent = Intent; 1306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (RelativeEncodingIntent == INTENT_ABSOLUTE_COLORIMETRIC) 1307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov RelativeEncodingIntent = INTENT_RELATIVE_COLORIMETRIC; 1308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Use V4 Lab always 1311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Profiles[0] = hLab; 1312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Profiles[1] = hProfile; 1313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov xform = cmsCreateMultiprofileTransformTHR(m ->ContextID, 1315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Profiles, 2, TYPE_Lab_DBL, 1316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov OutputFormat, RelativeEncodingIntent, 0); 1317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsCloseProfile(hLab); 1318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (xform == NULL) { 1320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsSignalError(m ->ContextID, cmsERROR_COLORSPACE_CHECK, "Cannot create transform Lab -> Profile in CRD creation"); 1322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 1323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Get a copy of the internal devicelink 1326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v = (_cmsTRANSFORM*) xform; 1327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov DeviceLink = cmsPipelineDup(v ->Lut); 1328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (DeviceLink == NULL) return 0; 1329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // We need a CLUT 1332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dwFlags |= cmsFLAGS_FORCE_CLUT; 1333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsOptimizePipeline(m->ContextID, &DeviceLink, RelativeEncodingIntent, &InFrm, &OutputFormat, &dwFlags); 1334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "<<\n"); 1336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "/ColorRenderingType 1\n"); 1337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsDetectBlackPoint(&BlackPointAdaptedToD50, hProfile, Intent, 0); 1340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Emit headers, etc. 1342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov EmitWhiteBlackD50(m, &BlackPointAdaptedToD50); 1343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov EmitPQRStage(m, hProfile, lDoBPC, Intent == INTENT_ABSOLUTE_COLORIMETRIC); 1344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov EmitXYZ2Lab(m); 1345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // FIXUP: map Lab (100, 0, 0) to perfect white, because the particular encoding for Lab 1348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // does map a=b=0 not falling into any specific node. Since range a,b goes -128..127, 1349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // zero is slightly moved towards right, so assure next node (in L=100 slice) is mapped to 1350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // zero. This would sacrifice a bit of highlights, but failure to do so would cause 1351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // scum dot. Ouch. 1352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (Intent == INTENT_ABSOLUTE_COLORIMETRIC) 1354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov lFixWhite = FALSE; 1355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "/RenderTable "); 1357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov WriteCLUT(m, cmsPipelineGetPtrToFirstStage(DeviceLink), "<", ">\n", "", "", lFixWhite, ColorSpace); 1360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, " %d {} bind ", nChannels); 1362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (i=1; i < nChannels; i++) 1364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "dup "); 1365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "]\n"); 1367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov EmitIntent(m, Intent); 1370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, ">>\n"); 1372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!(dwFlags & cmsFLAGS_NODEFAULTRESOURCEDEF)) { 1374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "/Current exch /ColorRendering defineresource pop\n"); 1376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsPipelineFree(DeviceLink); 1379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsDeleteTransform(xform); 1380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 1; 1382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Builds a ASCII string containing colorant list in 0..1.0 range 1386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 1387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid BuildColorantList(char *Colorant, int nColorant, cmsUInt16Number Out[]) 1388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov char Buff[32]; 1390ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int j; 1391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Colorant[0] = 0; 1393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (nColorant > cmsMAXCHANNELS) 1394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov nColorant = cmsMAXCHANNELS; 1395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (j=0; j < nColorant; j++) { 1397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sprintf(Buff, "%.3f", Out[j] / 65535.0); 1399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov strcat(Colorant, Buff); 1400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (j < nColorant -1) 1401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov strcat(Colorant, " "); 1402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Creates a PostScript color list from a named profile data. 1408ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// This is a HP extension. 1409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 1411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovint WriteNamedColorCRD(cmsIOHANDLER* m, cmsHPROFILE hNamedColor, int Intent, cmsUInt32Number dwFlags) 1412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsHTRANSFORM xform; 1414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int i, nColors, nColorant; 1415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number OutputFormat; 1416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov char ColorName[32]; 1417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov char Colorant[128]; 1418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsNAMEDCOLORLIST* NamedColorList; 1419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov OutputFormat = cmsFormatterForColorspaceOfProfile(hNamedColor, 2, FALSE); 1422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov nColorant = T_CHANNELS(OutputFormat); 1423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov xform = cmsCreateTransform(hNamedColor, TYPE_NAMED_COLOR_INDEX, NULL, OutputFormat, Intent, dwFlags); 1426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (xform == NULL) return 0; 1427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NamedColorList = cmsGetNamedColorList(xform); 1430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (NamedColorList == NULL) return 0; 1431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "<<\n"); 1433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "(colorlistcomment) (%s) \n", "Named profile"); 1434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "(Prefix) [ (Pantone ) (PANTONE ) ]\n"); 1435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, "(Suffix) [ ( CV) ( CVC) ( C) ]\n"); 1436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov nColors = cmsNamedColorCount(NamedColorList); 1438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (i=0; i < nColors; i++) { 1440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt16Number In[1]; 1442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt16Number Out[cmsMAXCHANNELS]; 1443ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov In[0] = (cmsUInt16Number) i; 1445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!cmsNamedColorInfo(NamedColorList, i, ColorName, NULL, NULL, NULL, NULL)) 1447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov continue; 1448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1449ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsDoTransform(xform, In, Out, 1); 1450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov BuildColorantList(Colorant, nColorant, Out); 1451ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, " (%s) [ %s ]\n", ColorName, Colorant); 1452ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, " >>"); 1455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!(dwFlags & cmsFLAGS_NODEFAULTRESOURCEDEF)) { 1457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(m, " /Current exch /HPSpotTable defineresource pop\n"); 1459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsDeleteTransform(xform); 1462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 1; 1463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1467ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// This one does create a Color Rendering Dictionary. 1468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// CRD are always LUT-Based, no matter if profile is 1469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// implemented as matrix-shaper. 1470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 1472ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsUInt32Number GenerateCRD(cmsContext ContextID, 1473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsHPROFILE hProfile, 1474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number Intent, cmsUInt32Number dwFlags, 1475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsIOHANDLER* mem) 1476ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1477ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number dwBytesUsed; 1478ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!(dwFlags & cmsFLAGS_NODEFAULTRESOURCEDEF)) { 1480ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1481ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov EmitHeader(mem, "Color Rendering Dictionary (CRD)", hProfile); 1482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Is a named color profile? 1486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (cmsGetDeviceClass(hProfile) == cmsSigNamedColorClass) { 1487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!WriteNamedColorCRD(mem, hProfile, Intent, dwFlags)) { 1489ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 1490ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1491ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else { 1493ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1494ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // CRD are always implemented as LUT 1495ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1496ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!WriteOutputLUT(mem, hProfile, Intent, dwFlags)) { 1497ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 1498ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1499ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1500ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1501ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!(dwFlags & cmsFLAGS_NODEFAULTRESOURCEDEF)) { 1502ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1503ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(mem, "%%%%EndResource\n"); 1504ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsIOPrintf(mem, "\n%% CRD End\n"); 1505ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1506ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1507ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Done, keep memory usage 1508ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dwBytesUsed = mem ->UsedSpace; 1509ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1510ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Finally, return used byte count 1511ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return dwBytesUsed; 1512ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1513ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUNUSED_PARAMETER(ContextID); 1514ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1515ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1516ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1517ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1518ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1519ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsUInt32Number CMSEXPORT cmsGetPostScriptColorResource(cmsContext ContextID, 1520ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsPSResourceType Type, 1521ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsHPROFILE hProfile, 1522ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number Intent, 1523ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number dwFlags, 1524ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsIOHANDLER* io) 1525ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1526ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number rc; 1527ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1528ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1529ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov switch (Type) { 1530ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1531ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cmsPS_RESOURCE_CSA: 1532ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov rc = GenerateCSA(ContextID, hProfile, Intent, dwFlags, io); 1533ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1534ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1535ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov default: 1536ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cmsPS_RESOURCE_CRD: 1537ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov rc = GenerateCRD(ContextID, hProfile, Intent, dwFlags, io); 1538ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1539ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1540ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1541ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return rc; 1542ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1543ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1544ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1545ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1546ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsUInt32Number CMSEXPORT cmsGetPostScriptCRD(cmsContext ContextID, 1547ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsHPROFILE hProfile, 1548ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number Intent, cmsUInt32Number dwFlags, 1549ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov void* Buffer, cmsUInt32Number dwBufferLen) 1550ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1551ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsIOHANDLER* mem; 1552ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number dwBytesUsed; 1553ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1554ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Set up the serialization engine 1555ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (Buffer == NULL) 1556ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mem = cmsOpenIOhandlerFromNULL(ContextID); 1557ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 1558ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mem = cmsOpenIOhandlerFromMem(ContextID, Buffer, dwBufferLen, "w"); 1559ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1560ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!mem) return 0; 1561ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1562ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dwBytesUsed = cmsGetPostScriptColorResource(ContextID, cmsPS_RESOURCE_CRD, hProfile, Intent, dwFlags, mem); 1563ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1564ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Get rid of memory stream 1565ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsCloseIOhandler(mem); 1566ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1567ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return dwBytesUsed; 1568ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1569ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1570ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1571ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1572ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Does create a Color Space Array on XYZ colorspace for PostScript usage 1573ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsUInt32Number CMSEXPORT cmsGetPostScriptCSA(cmsContext ContextID, 1574ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsHPROFILE hProfile, 1575ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number Intent, 1576ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number dwFlags, 1577ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov void* Buffer, 1578ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number dwBufferLen) 1579ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1580ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsIOHANDLER* mem; 1581ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number dwBytesUsed; 1582ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1583ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (Buffer == NULL) 1584ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mem = cmsOpenIOhandlerFromNULL(ContextID); 1585ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 1586ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mem = cmsOpenIOhandlerFromMem(ContextID, Buffer, dwBufferLen, "w"); 1587ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1588ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!mem) return 0; 1589ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1590ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dwBytesUsed = cmsGetPostScriptColorResource(ContextID, cmsPS_RESOURCE_CSA, hProfile, Intent, dwFlags, mem); 1591ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1592ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Get rid of memory stream 1593ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsCloseIOhandler(mem); 1594ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1595ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return dwBytesUsed; 1596ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1597ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1598