Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/lcms2/src/cmsxform.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 //--------------------------------------------------------------------------------- | |
| 2 // | |
| 3 // Little Color Management System | |
| 4 // Copyright (c) 1998-2023 Marti Maria Saguer | |
| 5 // | |
| 6 // Permission is hereby granted, free of charge, to any person obtaining | |
| 7 // a copy of this software and associated documentation files (the "Software"), | |
| 8 // to deal in the Software without restriction, including without limitation | |
| 9 // the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 10 // and/or sell copies of the Software, and to permit persons to whom the Software | |
| 11 // is furnished to do so, subject to the following conditions: | |
| 12 // | |
| 13 // The above copyright notice and this permission notice shall be included in | |
| 14 // all copies or substantial portions of the Software. | |
| 15 // | |
| 16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
| 17 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO | |
| 18 // THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
| 19 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | |
| 20 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |
| 21 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |
| 22 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
| 23 // | |
| 24 //--------------------------------------------------------------------------------- | |
| 25 // | |
| 26 | |
| 27 #include "lcms2_internal.h" | |
| 28 | |
| 29 // Transformations stuff | |
| 30 // ----------------------------------------------------------------------- | |
| 31 | |
| 32 #define DEFAULT_OBSERVER_ADAPTATION_STATE 1.0 | |
| 33 | |
| 34 // The Context0 observer adaptation state. | |
| 35 _cmsAdaptationStateChunkType _cmsAdaptationStateChunk = { DEFAULT_OBSERVER_ADAPTATION_STATE }; | |
| 36 | |
| 37 // Init and duplicate observer adaptation state | |
| 38 void _cmsAllocAdaptationStateChunk(struct _cmsContext_struct* ctx, | |
| 39 const struct _cmsContext_struct* src) | |
| 40 { | |
| 41 static _cmsAdaptationStateChunkType AdaptationStateChunk = { DEFAULT_OBSERVER_ADAPTATION_STATE }; | |
| 42 void* from; | |
| 43 | |
| 44 if (src != NULL) { | |
| 45 from = src ->chunks[AdaptationStateContext]; | |
| 46 } | |
| 47 else { | |
| 48 from = &AdaptationStateChunk; | |
| 49 } | |
| 50 | |
| 51 ctx ->chunks[AdaptationStateContext] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsAdaptationStateChunkType)); | |
| 52 } | |
| 53 | |
| 54 | |
| 55 // Sets adaptation state for absolute colorimetric intent in the given context. Adaptation state applies on all | |
| 56 // but cmsCreateExtendedTransform(). Little CMS can handle incomplete adaptation states. | |
| 57 // The adaptation state may be defaulted by this function. If you don't like it, use the extended transform routine | |
| 58 cmsFloat64Number CMSEXPORT cmsSetAdaptationState(cmsContext ContextID, cmsFloat64Number d) | |
| 59 { | |
| 60 cmsFloat64Number prev; | |
| 61 _cmsAdaptationStateChunkType* ptr = (_cmsAdaptationStateChunkType*) _cmsContextGetClientChunk(ContextID, AdaptationStateContext); | |
| 62 | |
| 63 // Get previous value for return | |
| 64 prev = ptr ->AdaptationState; | |
| 65 | |
| 66 // Set the value if d is positive or zero | |
| 67 if (d >= 0.0) { | |
| 68 | |
| 69 ptr ->AdaptationState = d; | |
| 70 } | |
| 71 | |
| 72 // Always return previous value | |
| 73 return prev; | |
| 74 } | |
| 75 | |
| 76 | |
| 77 // ----------------------------------------------------------------------- | |
| 78 | |
| 79 // Alarm codes for 16-bit transformations, because the fixed range of containers there are | |
| 80 // no values left to mark out of gamut. | |
| 81 | |
| 82 #define DEFAULT_ALARM_CODES_VALUE {0x7F00, 0x7F00, 0x7F00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} | |
| 83 | |
| 84 _cmsAlarmCodesChunkType _cmsAlarmCodesChunk = { DEFAULT_ALARM_CODES_VALUE }; | |
| 85 | |
| 86 // Sets the codes used to mark out-out-gamut on Proofing transforms for a given context. Values are meant to be | |
| 87 // encoded in 16 bits. | |
| 88 void CMSEXPORT cmsSetAlarmCodes(cmsContext ContextID, const cmsUInt16Number AlarmCodesP[cmsMAXCHANNELS]) | |
| 89 { | |
| 90 _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(ContextID, AlarmCodesContext); | |
| 91 | |
| 92 _cmsAssert(ContextAlarmCodes != NULL); // Can't happen | |
| 93 | |
| 94 memcpy(ContextAlarmCodes->AlarmCodes, AlarmCodesP, sizeof(ContextAlarmCodes->AlarmCodes)); | |
| 95 } | |
| 96 | |
| 97 // Gets the current codes used to mark out-out-gamut on Proofing transforms for the given context. | |
| 98 // Values are meant to be encoded in 16 bits. | |
| 99 void CMSEXPORT cmsGetAlarmCodes(cmsContext ContextID, cmsUInt16Number AlarmCodesP[cmsMAXCHANNELS]) | |
| 100 { | |
| 101 _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(ContextID, AlarmCodesContext); | |
| 102 | |
| 103 _cmsAssert(ContextAlarmCodes != NULL); // Can't happen | |
| 104 | |
| 105 memcpy(AlarmCodesP, ContextAlarmCodes->AlarmCodes, sizeof(ContextAlarmCodes->AlarmCodes)); | |
| 106 } | |
| 107 | |
| 108 | |
| 109 // Init and duplicate alarm codes | |
| 110 void _cmsAllocAlarmCodesChunk(struct _cmsContext_struct* ctx, | |
| 111 const struct _cmsContext_struct* src) | |
| 112 { | |
| 113 static _cmsAlarmCodesChunkType AlarmCodesChunk = { DEFAULT_ALARM_CODES_VALUE }; | |
| 114 void* from; | |
| 115 | |
| 116 if (src != NULL) { | |
| 117 from = src ->chunks[AlarmCodesContext]; | |
| 118 } | |
| 119 else { | |
| 120 from = &AlarmCodesChunk; | |
| 121 } | |
| 122 | |
| 123 ctx ->chunks[AlarmCodesContext] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsAlarmCodesChunkType)); | |
| 124 } | |
| 125 | |
| 126 // ----------------------------------------------------------------------- | |
| 127 | |
| 128 // Get rid of transform resources | |
| 129 void CMSEXPORT cmsDeleteTransform(cmsContext ContextID, cmsHTRANSFORM hTransform) | |
| 130 { | |
| 131 _cmsTRANSFORM* p = (_cmsTRANSFORM*) hTransform; | |
| 132 _cmsTRANSFORMCORE *core; | |
| 133 cmsUInt32Number refs; | |
| 134 | |
| 135 if (p == NULL) | |
| 136 return; | |
| 137 | |
| 138 core = p->core; | |
| 139 | |
| 140 _cmsAssert(core != NULL); | |
| 141 | |
| 142 refs = _cmsAdjustReferenceCount(&core->refs, -1); | |
| 143 _cmsFree(ContextID, (void *) p); | |
| 144 | |
| 145 if (refs != 0) | |
| 146 return; | |
| 147 | |
| 148 if (core->GamutCheck) | |
| 149 cmsPipelineFree(ContextID, core->GamutCheck); | |
| 150 | |
| 151 if (core->Lut) | |
| 152 cmsPipelineFree(ContextID, core->Lut); | |
| 153 | |
| 154 if (core->InputColorant) | |
| 155 cmsFreeNamedColorList(ContextID, core->InputColorant); | |
| 156 | |
| 157 if (core->OutputColorant) | |
| 158 cmsFreeNamedColorList(ContextID, core->OutputColorant); | |
| 159 | |
| 160 if (core->Sequence) | |
| 161 cmsFreeProfileSequenceDescription(ContextID, core->Sequence); | |
| 162 | |
| 163 if (core->UserData) | |
| 164 core->FreeUserData(ContextID, core->UserData); | |
| 165 | |
| 166 _cmsFree(ContextID, (void *)core); | |
| 167 } | |
| 168 | |
| 169 | |
| 170 static | |
| 171 cmsUInt32Number PixelSize(cmsUInt32Number Format) | |
| 172 { | |
| 173 cmsUInt32Number fmt_bytes = T_BYTES(Format); | |
| 174 | |
| 175 // For double, the T_BYTES field is zero | |
| 176 if (fmt_bytes == 0) | |
| 177 return sizeof(cmsUInt64Number); | |
| 178 | |
| 179 // Otherwise, it is already correct for all formats | |
| 180 return fmt_bytes; | |
| 181 } | |
| 182 | |
| 183 | |
| 184 | |
| 185 | |
| 186 // Apply transform. | |
| 187 void CMSEXPORT cmsDoTransform(cmsContext ContextID, cmsHTRANSFORM Transform, | |
| 188 const void* InputBuffer, | |
| 189 void* OutputBuffer, | |
| 190 cmsUInt32Number Size) | |
| 191 | |
| 192 { | |
| 193 _cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform; | |
| 194 cmsStride stride; | |
| 195 | |
| 196 stride.BytesPerLineIn = 0; // Not used | |
| 197 stride.BytesPerLineOut = 0; | |
| 198 stride.BytesPerPlaneIn = Size * PixelSize(p->InputFormat); | |
| 199 stride.BytesPerPlaneOut = Size * PixelSize(p->OutputFormat); | |
| 200 | |
| 201 p -> xform(ContextID, p, InputBuffer, OutputBuffer, Size, 1, &stride); | |
| 202 } | |
| 203 | |
| 204 | |
| 205 // This is a legacy stride for planar | |
| 206 void CMSEXPORT cmsDoTransformStride(cmsContext ContextID, cmsHTRANSFORM Transform, | |
| 207 const void* InputBuffer, | |
| 208 void* OutputBuffer, | |
| 209 cmsUInt32Number Size, cmsUInt32Number Stride) | |
| 210 | |
| 211 { | |
| 212 _cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform; | |
| 213 cmsStride stride; | |
| 214 | |
| 215 stride.BytesPerLineIn = 0; | |
| 216 stride.BytesPerLineOut = 0; | |
| 217 stride.BytesPerPlaneIn = Stride; | |
| 218 stride.BytesPerPlaneOut = Stride; | |
| 219 | |
| 220 p -> xform(ContextID, p, InputBuffer, OutputBuffer, Size, 1, &stride); | |
| 221 } | |
| 222 | |
| 223 // This is the "fast" function for plugins | |
| 224 void CMSEXPORT cmsDoTransformLineStride(cmsContext ContextID, cmsHTRANSFORM Transform, | |
| 225 const void* InputBuffer, | |
| 226 void* OutputBuffer, | |
| 227 cmsUInt32Number PixelsPerLine, | |
| 228 cmsUInt32Number LineCount, | |
| 229 cmsUInt32Number BytesPerLineIn, | |
| 230 cmsUInt32Number BytesPerLineOut, | |
| 231 cmsUInt32Number BytesPerPlaneIn, | |
| 232 cmsUInt32Number BytesPerPlaneOut) | |
| 233 | |
| 234 { | |
| 235 _cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform; | |
| 236 cmsStride stride; | |
| 237 | |
| 238 stride.BytesPerLineIn = BytesPerLineIn; | |
| 239 stride.BytesPerLineOut = BytesPerLineOut; | |
| 240 stride.BytesPerPlaneIn = BytesPerPlaneIn; | |
| 241 stride.BytesPerPlaneOut = BytesPerPlaneOut; | |
| 242 | |
| 243 p->xform(ContextID, p, InputBuffer, OutputBuffer, PixelsPerLine, LineCount, &stride); | |
| 244 } | |
| 245 | |
| 246 | |
| 247 | |
| 248 // Transform routines ---------------------------------------------------------------------------------------------------------- | |
| 249 | |
| 250 // Float xform converts floats. Since there are no performance issues, one routine does all job, including gamut check. | |
| 251 // Note that because extended range, we can use a -1.0 value for out of gamut in this case. | |
| 252 static | |
| 253 void FloatXFORM(cmsContext ContextID, _cmsTRANSFORM* p, | |
| 254 const void* in, | |
| 255 void* out, | |
| 256 cmsUInt32Number PixelsPerLine, | |
| 257 cmsUInt32Number LineCount, | |
| 258 const cmsStride* Stride) | |
| 259 { | |
| 260 cmsUInt8Number* accum; | |
| 261 cmsUInt8Number* output; | |
| 262 cmsFloat32Number fIn[cmsMAXCHANNELS], fOut[cmsMAXCHANNELS]; | |
| 263 cmsFloat32Number OutOfGamut; | |
| 264 cmsUInt32Number i, j, c, strideIn, strideOut; | |
| 265 _cmsTRANSFORMCORE *core = p->core; | |
| 266 | |
| 267 _cmsHandleExtraChannels(ContextID, p, in, out, PixelsPerLine, LineCount, Stride); | |
| 268 | |
| 269 strideIn = 0; | |
| 270 strideOut = 0; | |
| 271 memset(fIn, 0, sizeof(fIn)); | |
| 272 memset(fOut, 0, sizeof(fOut)); | |
| 273 | |
| 274 for (i = 0; i < LineCount; i++) { | |
| 275 | |
| 276 accum = (cmsUInt8Number*)in + strideIn; | |
| 277 output = (cmsUInt8Number*)out + strideOut; | |
| 278 | |
| 279 for (j = 0; j < PixelsPerLine; j++) { | |
| 280 | |
| 281 accum = p->FromInputFloat(ContextID, p, fIn, accum, Stride->BytesPerPlaneIn); | |
| 282 | |
| 283 // Any gamut chack to do? | |
| 284 if (core->GamutCheck != NULL) { | |
| 285 | |
| 286 // Evaluate gamut marker. | |
| 287 cmsPipelineEvalFloat(ContextID, fIn, &OutOfGamut, core->GamutCheck); | |
| 288 | |
| 289 // Is current color out of gamut? | |
| 290 if (OutOfGamut > 0.0) { | |
| 291 | |
| 292 // Certainly, out of gamut | |
| 293 for (c = 0; c < cmsMAXCHANNELS; c++) | |
| 294 fOut[c] = -1.0; | |
| 295 | |
| 296 } | |
| 297 else { | |
| 298 // No, proceed normally | |
| 299 cmsPipelineEvalFloat(ContextID, fIn, fOut, core->Lut); | |
| 300 } | |
| 301 } | |
| 302 else { | |
| 303 | |
| 304 // No gamut check at all | |
| 305 cmsPipelineEvalFloat(ContextID, fIn, fOut, core->Lut); | |
| 306 } | |
| 307 | |
| 308 | |
| 309 output = p->ToOutputFloat(ContextID, p, fOut, output, Stride->BytesPerPlaneOut); | |
| 310 } | |
| 311 | |
| 312 strideIn += Stride->BytesPerLineIn; | |
| 313 strideOut += Stride->BytesPerLineOut; | |
| 314 } | |
| 315 | |
| 316 } | |
| 317 | |
| 318 | |
| 319 static | |
| 320 void NullFloatXFORM(cmsContext ContextID, _cmsTRANSFORM* p, | |
| 321 const void* in, | |
| 322 void* out, | |
| 323 cmsUInt32Number PixelsPerLine, | |
| 324 cmsUInt32Number LineCount, | |
| 325 const cmsStride* Stride) | |
| 326 | |
| 327 { | |
| 328 cmsUInt8Number* accum; | |
| 329 cmsUInt8Number* output; | |
| 330 cmsFloat32Number fIn[cmsMAXCHANNELS]; | |
| 331 cmsUInt32Number i, j, strideIn, strideOut; | |
| 332 | |
| 333 _cmsHandleExtraChannels(ContextID, p, in, out, PixelsPerLine, LineCount, Stride); | |
| 334 | |
| 335 strideIn = 0; | |
| 336 strideOut = 0; | |
| 337 memset(fIn, 0, sizeof(fIn)); | |
| 338 | |
| 339 for (i = 0; i < LineCount; i++) { | |
| 340 | |
| 341 accum = (cmsUInt8Number*) in + strideIn; | |
| 342 output = (cmsUInt8Number*) out + strideOut; | |
| 343 | |
| 344 for (j = 0; j < PixelsPerLine; j++) { | |
| 345 | |
| 346 accum = p->FromInputFloat(ContextID, p, fIn, accum, Stride ->BytesPerPlaneIn); | |
| 347 output = p->ToOutputFloat(ContextID, p, fIn, output, Stride->BytesPerPlaneOut); | |
| 348 } | |
| 349 | |
| 350 strideIn += Stride->BytesPerLineIn; | |
| 351 strideOut += Stride->BytesPerLineOut; | |
| 352 } | |
| 353 } | |
| 354 | |
| 355 static inline int mul255(cmsUInt32Number a, cmsUInt32Number b) | |
| 356 { | |
| 357 /* see Jim Blinn's book "Dirty Pixels" for how this works */ | |
| 358 cmsUInt32Number x = a * b + 128; | |
| 359 x += x >> 8; | |
| 360 return x >> 8; | |
| 361 } | |
| 362 | |
| 363 static inline cmsUInt32Number mul65535(cmsUInt32Number a, cmsUInt32Number b) | |
| 364 { | |
| 365 /* see Jim Blinn's book "Dirty Pixels" for how this works */ | |
| 366 cmsUInt32Number x = a * b + 0x8000; | |
| 367 x += x >> 16; | |
| 368 return x >> 16; | |
| 369 } | |
| 370 | |
| 371 // 16 bit precision ----------------------------------------------------------------------------------------------------------- | |
| 372 | |
| 373 // Null transformation, only applies formatters. No cache | |
| 374 static | |
| 375 void NullXFORM(cmsContext ContextID, | |
| 376 _cmsTRANSFORM* p, | |
| 377 const void* in, | |
| 378 void* out, | |
| 379 cmsUInt32Number PixelsPerLine, | |
| 380 cmsUInt32Number LineCount, | |
| 381 const cmsStride* Stride) | |
| 382 { | |
| 383 cmsUInt8Number* accum; | |
| 384 cmsUInt8Number* output; | |
| 385 cmsUInt16Number wIn[cmsMAXCHANNELS]; | |
| 386 cmsUInt32Number i, j, strideIn, strideOut; | |
| 387 | |
| 388 _cmsHandleExtraChannels(ContextID, p, in, out, PixelsPerLine, LineCount, Stride); | |
| 389 | |
| 390 strideIn = 0; | |
| 391 strideOut = 0; | |
| 392 memset(wIn, 0, sizeof(wIn)); | |
| 393 | |
| 394 for (i = 0; i < LineCount; i++) { | |
| 395 | |
| 396 accum = (cmsUInt8Number*)in + strideIn; | |
| 397 output = (cmsUInt8Number*)out + strideOut; | |
| 398 | |
| 399 for (j = 0; j < PixelsPerLine; j++) { | |
| 400 | |
| 401 accum = p->FromInput(ContextID, p, wIn, accum, Stride->BytesPerPlaneIn); | |
| 402 output = p->ToOutput(ContextID, p, wIn, output, Stride->BytesPerPlaneOut); | |
| 403 } | |
| 404 | |
| 405 strideIn += Stride->BytesPerLineIn; | |
| 406 strideOut += Stride->BytesPerLineOut; | |
| 407 } | |
| 408 | |
| 409 } | |
| 410 | |
| 411 | |
| 412 // No gamut check, no cache, 16 bits | |
| 413 #define FUNCTION_NAME PrecalculatedXFORM | |
| 414 #include "extra_xform.h" | |
| 415 | |
| 416 // No gamut check, no cache, 16 bits | |
| 417 #define PREALPHA | |
| 418 #define FUNCTION_NAME PrecalculatedXFORM_P | |
| 419 #include "extra_xform.h" | |
| 420 | |
| 421 // No gamut check, no cache, Identity transform, including pack/unpack | |
| 422 static | |
| 423 void PrecalculatedXFORMIdentity(cmsContext ContextID, | |
| 424 _cmsTRANSFORM* p, | |
| 425 const void* in, | |
| 426 void* out, | |
| 427 cmsUInt32Number PixelsPerLine, | |
| 428 cmsUInt32Number LineCount, | |
| 429 const cmsStride* Stride) | |
| 430 { | |
| 431 cmsUInt32Number bpli = Stride->BytesPerLineIn; | |
| 432 cmsUInt32Number bplo = Stride->BytesPerLineOut; | |
| 433 int bpp; | |
| 434 cmsUNUSED_PARAMETER(ContextID); | |
| 435 | |
| 436 /* Silence some warnings */ | |
| 437 (void)bpli; | |
| 438 (void)bplo; | |
| 439 | |
| 440 if ((in == out && bpli == bplo) || PixelsPerLine == 0) | |
| 441 return; | |
| 442 | |
| 443 bpp = T_BYTES(p->InputFormat); | |
| 444 if (bpp == 0) | |
| 445 bpp = sizeof(double); | |
| 446 bpp *= T_CHANNELS(p->InputFormat) + T_EXTRA(p->InputFormat); | |
| 447 PixelsPerLine *= bpp; /* Convert to BytesPerLine */ | |
| 448 while (LineCount-- > 0) | |
| 449 { | |
| 450 memmove(out, in, PixelsPerLine); | |
| 451 in = (void *)((cmsUInt8Number *)in + bpli); | |
| 452 out = (void *)((cmsUInt8Number *)out + bplo); | |
| 453 } | |
| 454 } | |
| 455 | |
| 456 static | |
| 457 void PrecalculatedXFORMIdentityPlanar(cmsContext ContextID, | |
| 458 _cmsTRANSFORM* p, | |
| 459 const void* in, | |
| 460 void* out, | |
| 461 cmsUInt32Number PixelsPerLine, | |
| 462 cmsUInt32Number LineCount, | |
| 463 const cmsStride* Stride) | |
| 464 { | |
| 465 cmsUInt32Number bpli = Stride->BytesPerLineIn; | |
| 466 cmsUInt32Number bplo = Stride->BytesPerLineOut; | |
| 467 cmsUInt32Number bppi = Stride->BytesPerPlaneIn; | |
| 468 cmsUInt32Number bppo = Stride->BytesPerPlaneOut; | |
| 469 int bpp; | |
| 470 int planes; | |
| 471 const void *plane_in; | |
| 472 void *plane_out; | |
| 473 cmsUNUSED_PARAMETER(ContextID); | |
| 474 | |
| 475 /* Silence some warnings */ | |
| 476 (void)bpli; | |
| 477 (void)bplo; | |
| 478 (void)bppi; | |
| 479 (void)bppo; | |
| 480 | |
| 481 if ((in == out && bpli == bplo && bppi == bppo) || PixelsPerLine == 0) | |
| 482 return; | |
| 483 | |
| 484 bpp = T_BYTES(p->InputFormat); | |
| 485 if (bpp == 0) | |
| 486 bpp = sizeof(double); | |
| 487 PixelsPerLine *= bpp; /* Convert to BytesPerLine */ | |
| 488 planes = T_CHANNELS(p->InputFormat) + T_EXTRA(p->InputFormat); | |
| 489 while (planes-- > 0) | |
| 490 { | |
| 491 plane_in = in; | |
| 492 plane_out = out; | |
| 493 while (LineCount-- > 0) | |
| 494 { | |
| 495 memmove(plane_out, plane_in, PixelsPerLine); | |
| 496 plane_in = (void *)((cmsUInt8Number *)plane_in + bpli); | |
| 497 plane_out = (void *)((cmsUInt8Number *)plane_out + bplo); | |
| 498 } | |
| 499 in = (void *)((cmsUInt8Number *)in + bppi); | |
| 500 out = (void *)((cmsUInt8Number *)out + bppo); | |
| 501 } | |
| 502 } | |
| 503 | |
| 504 // Auxiliary: Handle precalculated gamut check. The retrieval of context may be alittle bit slow, but this function is not critical. | |
| 505 static | |
| 506 void TransformOnePixelWithGamutCheck(cmsContext ContextID, _cmsTRANSFORM* p, | |
| 507 const cmsUInt16Number wIn[], | |
| 508 cmsUInt16Number wOut[]) | |
| 509 { | |
| 510 cmsUInt16Number wOutOfGamut; | |
| 511 _cmsTRANSFORMCORE *core = p->core; | |
| 512 | |
| 513 core->GamutCheck->Eval16Fn(ContextID, wIn, &wOutOfGamut, core->GamutCheck->Data); | |
| 514 if (wOutOfGamut >= 1) { | |
| 515 | |
| 516 cmsUInt32Number i; | |
| 517 cmsUInt32Number n = core->Lut->OutputChannels; | |
| 518 _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(ContextID, AlarmCodesContext); | |
| 519 | |
| 520 for (i=0; i < n; i++) { | |
| 521 | |
| 522 wOut[i] = ContextAlarmCodes ->AlarmCodes[i]; | |
| 523 } | |
| 524 } | |
| 525 else | |
| 526 core->Lut->Eval16Fn(ContextID, wIn, wOut, core->Lut->Data); | |
| 527 } | |
| 528 | |
| 529 // Gamut check, No cache, 16 bits. | |
| 530 #define FUNCTION_NAME PrecalculatedXFORMGamutCheck | |
| 531 #define GAMUTCHECK | |
| 532 #include "extra_xform.h" | |
| 533 | |
| 534 // Gamut check, No cache, 16 bits. | |
| 535 #define FUNCTION_NAME PrecalculatedXFORMGamutCheck_P | |
| 536 #define PREALPHA | |
| 537 #define GAMUTCHECK | |
| 538 #include "extra_xform.h" | |
| 539 | |
| 540 // No gamut check, Cache, 16 bits, | |
| 541 #define FUNCTION_NAME CachedXFORM | |
| 542 #define CACHED | |
| 543 #include "extra_xform.h" | |
| 544 | |
| 545 // All those nice features together | |
| 546 #define FUNCTION_NAME CachedXFORMGamutCheck | |
| 547 #define CACHED | |
| 548 #define GAMUTCHECK | |
| 549 #include "extra_xform.h" | |
| 550 | |
| 551 // All those nice features together | |
| 552 #define FUNCTION_NAME CachedXFORMGamutCheck_P | |
| 553 #define CACHED | |
| 554 #define PREALPHA | |
| 555 #define GAMUTCHECK | |
| 556 #include "extra_xform.h" | |
| 557 | |
| 558 // No gamut check, Cache, 16 bits, <= 4 bytes | |
| 559 #define FUNCTION_NAME CachedXFORM4 | |
| 560 #define CACHED | |
| 561 #define CMPBYTES 4 | |
| 562 #define NUMEXTRAS 0 | |
| 563 #include "extra_xform.h" | |
| 564 | |
| 565 // No gamut check, Cache, 16 bits, <= 8 bytes total | |
| 566 #define FUNCTION_NAME CachedXFORM8 | |
| 567 #define CACHED | |
| 568 #define CMPBYTES 8 | |
| 569 #define NUMEXTRAS 0 | |
| 570 #include "extra_xform.h" | |
| 571 | |
| 572 // Special ones for common cases. | |
| 573 #define FUNCTION_NAME CachedXFORM1to1 | |
| 574 #define CACHED | |
| 575 #define INPACKEDSAMPLESIZE 1 | |
| 576 #define OUTPACKEDSAMPLESIZE 1 | |
| 577 #define NUMINCHANNELS 1 | |
| 578 #define NUMOUTCHANNELS 1 | |
| 579 #define NUMEXTRAS 0 | |
| 580 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 581 do { \ | |
| 582 (D)[0] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 583 } while (0) | |
| 584 #define PACK(CTX,T,S,D,Z,A) \ | |
| 585 do { \ | |
| 586 *(D)++ = FROM_16_TO_8((S)[0]); \ | |
| 587 } while (0) | |
| 588 #include "extra_xform.h" | |
| 589 | |
| 590 #define FUNCTION_NAME CachedXFORM1x2to1x2 | |
| 591 #define CACHED | |
| 592 #define INPACKEDSAMPLESIZE 2 | |
| 593 #define OUTPACKEDSAMPLESIZE 2 | |
| 594 #define NUMINCHANNELS 1 | |
| 595 #define NUMOUTCHANNELS 1 | |
| 596 #define NUMEXTRAS 0 | |
| 597 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 598 do { \ | |
| 599 (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 600 } while (0) | |
| 601 #define PACK(CTX,T,S,D,Z,A) \ | |
| 602 do { \ | |
| 603 *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \ | |
| 604 } while (0) | |
| 605 #include "extra_xform.h" | |
| 606 | |
| 607 #define FUNCTION_NAME CachedXFORM1to3 | |
| 608 #define CACHED | |
| 609 #define INPACKEDSAMPLESIZE 1 | |
| 610 #define OUTPACKEDSAMPLESIZE 1 | |
| 611 #define NUMINCHANNELS 1 | |
| 612 #define NUMOUTCHANNELS 3 | |
| 613 #define NUMEXTRAS 0 | |
| 614 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 615 do { \ | |
| 616 (D)[0] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 617 } while (0) | |
| 618 #define PACK(CTX,T,S,D,Z,A) \ | |
| 619 do { \ | |
| 620 *(D)++ = FROM_16_TO_8((S)[0]); \ | |
| 621 *(D)++ = FROM_16_TO_8((S)[1]); \ | |
| 622 *(D)++ = FROM_16_TO_8((S)[2]); \ | |
| 623 } while (0) | |
| 624 #include "extra_xform.h" | |
| 625 | |
| 626 #define FUNCTION_NAME CachedXFORM1x2to3x2 | |
| 627 #define CACHED | |
| 628 #define INPACKEDSAMPLESIZE 2 | |
| 629 #define OUTPACKEDSAMPLESIZE 2 | |
| 630 #define NUMINCHANNELS 1 | |
| 631 #define NUMOUTCHANNELS 3 | |
| 632 #define NUMEXTRAS 0 | |
| 633 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 634 do { \ | |
| 635 (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 636 } while (0) | |
| 637 #define PACK(CTX,T,S,D,Z,A) \ | |
| 638 do { \ | |
| 639 *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \ | |
| 640 *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \ | |
| 641 *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \ | |
| 642 } while (0) | |
| 643 #include "extra_xform.h" | |
| 644 | |
| 645 #define FUNCTION_NAME CachedXFORM1to4 | |
| 646 #define CACHED | |
| 647 #define INPACKEDSAMPLESIZE 1 | |
| 648 #define OUTPACKEDSAMPLESIZE 1 | |
| 649 #define NUMINCHANNELS 1 | |
| 650 #define NUMOUTCHANNELS 4 | |
| 651 #define NUMEXTRAS 0 | |
| 652 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 653 do { \ | |
| 654 (D)[0] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 655 } while (0) | |
| 656 #define PACK(CTX,T,S,D,Z,A) \ | |
| 657 do { \ | |
| 658 *(D)++ = FROM_16_TO_8((S)[0]); \ | |
| 659 *(D)++ = FROM_16_TO_8((S)[1]); \ | |
| 660 *(D)++ = FROM_16_TO_8((S)[2]); \ | |
| 661 *(D)++ = FROM_16_TO_8((S)[3]); \ | |
| 662 } while (0) | |
| 663 #include "extra_xform.h" | |
| 664 | |
| 665 #define FUNCTION_NAME CachedXFORM1x2to4x2 | |
| 666 #define CACHED | |
| 667 #define INPACKEDSAMPLESIZE 2 | |
| 668 #define OUTPACKEDSAMPLESIZE 2 | |
| 669 #define NUMINCHANNELS 1 | |
| 670 #define NUMOUTCHANNELS 4 | |
| 671 #define NUMEXTRAS 0 | |
| 672 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 673 do { \ | |
| 674 (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 675 } while (0) | |
| 676 #define PACK(CTX,T,S,D,Z,A) \ | |
| 677 do { \ | |
| 678 *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \ | |
| 679 *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \ | |
| 680 *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \ | |
| 681 *(cmsUInt16Number *)(D) = (S)[3]; (D) += 2; \ | |
| 682 } while (0) | |
| 683 #include "extra_xform.h" | |
| 684 | |
| 685 #define FUNCTION_NAME CachedXFORM3to1 | |
| 686 #define CACHED | |
| 687 #define INPACKEDSAMPLESIZE 1 | |
| 688 #define OUTPACKEDSAMPLESIZE 1 | |
| 689 #define NUMINCHANNELS 3 | |
| 690 #define NUMOUTCHANNELS 1 | |
| 691 #define NUMEXTRAS 0 | |
| 692 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 693 do { \ | |
| 694 (D)[0] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 695 (D)[1] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 696 (D)[2] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 697 } while (0) | |
| 698 #define PACK(CTX,T,S,D,Z,A) \ | |
| 699 do { \ | |
| 700 *(D)++ = FROM_16_TO_8((S)[0]); \ | |
| 701 } while (0) | |
| 702 #include "extra_xform.h" | |
| 703 | |
| 704 #define FUNCTION_NAME CachedXFORM3x2to1x2 | |
| 705 #define CACHED | |
| 706 #define INPACKEDSAMPLESIZE 2 | |
| 707 #define OUTPACKEDSAMPLESIZE 2 | |
| 708 #define NUMINCHANNELS 3 | |
| 709 #define NUMOUTCHANNELS 1 | |
| 710 #define NUMEXTRAS 0 | |
| 711 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 712 do { \ | |
| 713 (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 714 (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 715 (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 716 } while (0) | |
| 717 #define PACK(CTX,T,S,D,Z,A) \ | |
| 718 do { \ | |
| 719 *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \ | |
| 720 } while (0) | |
| 721 #include "extra_xform.h" | |
| 722 | |
| 723 #define FUNCTION_NAME CachedXFORM3to3 | |
| 724 #define CACHED | |
| 725 #define INPACKEDSAMPLESIZE 1 | |
| 726 #define OUTPACKEDSAMPLESIZE 1 | |
| 727 #define NUMINCHANNELS 3 | |
| 728 #define NUMOUTCHANNELS 3 | |
| 729 #define NUMEXTRAS 0 | |
| 730 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 731 do { \ | |
| 732 (D)[0] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 733 (D)[1] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 734 (D)[2] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 735 } while (0) | |
| 736 #define PACK(CTX,T,S,D,Z,A) \ | |
| 737 do { \ | |
| 738 *(D)++ = FROM_16_TO_8((S)[0]); \ | |
| 739 *(D)++ = FROM_16_TO_8((S)[1]); \ | |
| 740 *(D)++ = FROM_16_TO_8((S)[2]); \ | |
| 741 } while (0) | |
| 742 #include "extra_xform.h" | |
| 743 | |
| 744 #define FUNCTION_NAME CachedXFORM3x2to3x2 | |
| 745 #define CACHED | |
| 746 #define INPACKEDSAMPLESIZE 2 | |
| 747 #define OUTPACKEDSAMPLESIZE 2 | |
| 748 #define NUMINCHANNELS 3 | |
| 749 #define NUMOUTCHANNELS 3 | |
| 750 #define NUMEXTRAS 0 | |
| 751 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 752 do { \ | |
| 753 (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 754 (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 755 (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 756 } while (0) | |
| 757 #define PACK(CTX,T,S,D,Z,A) \ | |
| 758 do { \ | |
| 759 *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \ | |
| 760 *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \ | |
| 761 *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \ | |
| 762 } while (0) | |
| 763 #include "extra_xform.h" | |
| 764 | |
| 765 #define FUNCTION_NAME CachedXFORM3to4 | |
| 766 #define CACHED | |
| 767 #define INPACKEDSAMPLESIZE 1 | |
| 768 #define OUTPACKEDSAMPLESIZE 1 | |
| 769 #define NUMINCHANNELS 3 | |
| 770 #define NUMOUTCHANNELS 4 | |
| 771 #define NUMEXTRAS 0 | |
| 772 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 773 do { \ | |
| 774 (D)[0] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 775 (D)[1] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 776 (D)[2] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 777 } while (0) | |
| 778 #define PACK(CTX,T,S,D,Z,A) \ | |
| 779 do { \ | |
| 780 *(D)++ = FROM_16_TO_8((S)[0]); \ | |
| 781 *(D)++ = FROM_16_TO_8((S)[1]); \ | |
| 782 *(D)++ = FROM_16_TO_8((S)[2]); \ | |
| 783 *(D)++ = FROM_16_TO_8((S)[3]); \ | |
| 784 } while (0) | |
| 785 #include "extra_xform.h" | |
| 786 | |
| 787 #define FUNCTION_NAME CachedXFORM3x2to4x2 | |
| 788 #define CACHED | |
| 789 #define INPACKEDSAMPLESIZE 2 | |
| 790 #define OUTPACKEDSAMPLESIZE 2 | |
| 791 #define NUMINCHANNELS 3 | |
| 792 #define NUMOUTCHANNELS 4 | |
| 793 #define NUMEXTRAS 0 | |
| 794 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 795 do { \ | |
| 796 (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 797 (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 798 (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 799 } while (0) | |
| 800 #define PACK(CTX,T,S,D,Z,A) \ | |
| 801 do { \ | |
| 802 *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \ | |
| 803 *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \ | |
| 804 *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \ | |
| 805 *(cmsUInt16Number *)(D) = (S)[3]; (D) += 2; \ | |
| 806 } while (0) | |
| 807 #include "extra_xform.h" | |
| 808 | |
| 809 #define FUNCTION_NAME CachedXFORM4to1 | |
| 810 #define CACHED | |
| 811 #define INPACKEDSAMPLESIZE 1 | |
| 812 #define OUTPACKEDSAMPLESIZE 1 | |
| 813 #define NUMINCHANNELS 4 | |
| 814 #define NUMOUTCHANNELS 1 | |
| 815 #define NUMEXTRAS 0 | |
| 816 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 817 do { \ | |
| 818 (D)[0] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 819 (D)[1] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 820 (D)[2] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 821 (D)[3] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 822 } while (0) | |
| 823 #define PACK(CTX,T,S,D,Z,A) \ | |
| 824 do { \ | |
| 825 *(D)++ = FROM_16_TO_8((S)[0]); \ | |
| 826 } while (0) | |
| 827 #include "extra_xform.h" | |
| 828 | |
| 829 #define FUNCTION_NAME CachedXFORM4x2to1x2 | |
| 830 #define CACHED | |
| 831 #define INPACKEDSAMPLESIZE 2 | |
| 832 #define OUTPACKEDSAMPLESIZE 2 | |
| 833 #define NUMINCHANNELS 4 | |
| 834 #define NUMOUTCHANNELS 1 | |
| 835 #define NUMEXTRAS 0 | |
| 836 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 837 do { \ | |
| 838 (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 839 (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 840 (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 841 (D)[3] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 842 } while (0) | |
| 843 #define PACK(CTX,T,S,D,Z,A) \ | |
| 844 do { \ | |
| 845 *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \ | |
| 846 } while (0) | |
| 847 #include "extra_xform.h" | |
| 848 | |
| 849 #define FUNCTION_NAME CachedXFORM4to3 | |
| 850 #define CACHED | |
| 851 #define INPACKEDSAMPLESIZE 1 | |
| 852 #define OUTPACKEDSAMPLESIZE 1 | |
| 853 #define NUMINCHANNELS 4 | |
| 854 #define NUMOUTCHANNELS 3 | |
| 855 #define NUMEXTRAS 0 | |
| 856 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 857 do { \ | |
| 858 (D)[0] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 859 (D)[1] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 860 (D)[2] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 861 (D)[3] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 862 } while (0) | |
| 863 #define PACK(CTX,T,S,D,Z,A) \ | |
| 864 do { \ | |
| 865 *(D)++ = FROM_16_TO_8((S)[0]); \ | |
| 866 *(D)++ = FROM_16_TO_8((S)[1]); \ | |
| 867 *(D)++ = FROM_16_TO_8((S)[2]); \ | |
| 868 } while (0) | |
| 869 #include "extra_xform.h" | |
| 870 | |
| 871 #define FUNCTION_NAME CachedXFORM4x2to3x2 | |
| 872 #define CACHED | |
| 873 #define INPACKEDSAMPLESIZE 2 | |
| 874 #define OUTPACKEDSAMPLESIZE 2 | |
| 875 #define NUMINCHANNELS 4 | |
| 876 #define NUMOUTCHANNELS 3 | |
| 877 #define NUMEXTRAS 0 | |
| 878 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 879 do { \ | |
| 880 (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 881 (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 882 (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 883 (D)[3] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 884 } while (0) | |
| 885 #define PACK(CTX,T,S,D,Z,A) \ | |
| 886 do { \ | |
| 887 *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \ | |
| 888 *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \ | |
| 889 *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \ | |
| 890 } while (0) | |
| 891 #include "extra_xform.h" | |
| 892 | |
| 893 #define FUNCTION_NAME CachedXFORM4to4 | |
| 894 #define CACHED | |
| 895 #define INPACKEDSAMPLESIZE 1 | |
| 896 #define OUTPACKEDSAMPLESIZE 1 | |
| 897 #define NUMINCHANNELS 4 | |
| 898 #define NUMOUTCHANNELS 4 | |
| 899 #define NUMEXTRAS 0 | |
| 900 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 901 do { \ | |
| 902 (D)[0] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 903 (D)[1] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 904 (D)[2] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 905 (D)[3] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 906 } while (0) | |
| 907 #define PACK(CTX,T,S,D,Z,A) \ | |
| 908 do { \ | |
| 909 *(D)++ = FROM_16_TO_8((S)[0]); \ | |
| 910 *(D)++ = FROM_16_TO_8((S)[1]); \ | |
| 911 *(D)++ = FROM_16_TO_8((S)[2]); \ | |
| 912 *(D)++ = FROM_16_TO_8((S)[3]); \ | |
| 913 } while (0) | |
| 914 #include "extra_xform.h" | |
| 915 | |
| 916 #define FUNCTION_NAME CachedXFORM4x2to4x2 | |
| 917 #define CACHED | |
| 918 #define INPACKEDSAMPLESIZE 2 | |
| 919 #define OUTPACKEDSAMPLESIZE 2 | |
| 920 #define NUMINCHANNELS 4 | |
| 921 #define NUMOUTCHANNELS 4 | |
| 922 #define NUMEXTRAS 0 | |
| 923 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 924 do { \ | |
| 925 (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 926 (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 927 (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 928 (D)[3] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 929 } while (0) | |
| 930 #define PACK(CTX,T,S,D,Z,A) \ | |
| 931 do { \ | |
| 932 *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \ | |
| 933 *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \ | |
| 934 *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \ | |
| 935 *(cmsUInt16Number *)(D) = (S)[3]; (D) += 2; \ | |
| 936 } while (0) | |
| 937 #include "extra_xform.h" | |
| 938 | |
| 939 // Same again, but with alpha | |
| 940 // Special ones for common cases. | |
| 941 #define FUNCTION_NAME CachedXFORM1to1_1 | |
| 942 #define CACHED | |
| 943 #define INPACKEDSAMPLESIZE 1 | |
| 944 #define OUTPACKEDSAMPLESIZE 1 | |
| 945 #define NUMINCHANNELS 1 | |
| 946 #define NUMOUTCHANNELS 1 | |
| 947 #define NUMEXTRAS 1 | |
| 948 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 949 do { \ | |
| 950 (D)[0] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 951 } while (0) | |
| 952 #define PACK(CTX,T,S,D,Z,A) \ | |
| 953 do { \ | |
| 954 *(D)++ = FROM_16_TO_8((S)[0]); \ | |
| 955 } while (0) | |
| 956 #include "extra_xform.h" | |
| 957 | |
| 958 #define FUNCTION_NAME CachedXFORM1x2to1x2_2 | |
| 959 #define CACHED | |
| 960 #define INPACKEDSAMPLESIZE 2 | |
| 961 #define OUTPACKEDSAMPLESIZE 2 | |
| 962 #define NUMINCHANNELS 1 | |
| 963 #define NUMOUTCHANNELS 1 | |
| 964 #define NUMEXTRAS 1 | |
| 965 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 966 do { \ | |
| 967 (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 968 } while (0) | |
| 969 #define PACK(CTX,T,S,D,Z,A) \ | |
| 970 do { \ | |
| 971 *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \ | |
| 972 } while (0) | |
| 973 #include "extra_xform.h" | |
| 974 | |
| 975 #define FUNCTION_NAME CachedXFORM1to3_1 | |
| 976 #define CACHED | |
| 977 #define INPACKEDSAMPLESIZE 1 | |
| 978 #define OUTPACKEDSAMPLESIZE 3 | |
| 979 #define NUMINCHANNELS 1 | |
| 980 #define NUMOUTCHANNELS 1 | |
| 981 #define NUMEXTRAS 1 | |
| 982 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 983 do { \ | |
| 984 (D)[0] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 985 } while (0) | |
| 986 #define PACK(CTX,T,S,D,Z,A) \ | |
| 987 do { \ | |
| 988 *(D)++ = FROM_16_TO_8((S)[0]); \ | |
| 989 *(D)++ = FROM_16_TO_8((S)[1]); \ | |
| 990 *(D)++ = FROM_16_TO_8((S)[2]); \ | |
| 991 } while (0) | |
| 992 #include "extra_xform.h" | |
| 993 | |
| 994 #define FUNCTION_NAME CachedXFORM1x2to3x2_2 | |
| 995 #define CACHED | |
| 996 #define INPACKEDSAMPLESIZE 2 | |
| 997 #define OUTPACKEDSAMPLESIZE 2 | |
| 998 #define NUMINCHANNELS 1 | |
| 999 #define NUMOUTCHANNELS 3 | |
| 1000 #define NUMEXTRAS 1 | |
| 1001 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 1002 do { \ | |
| 1003 (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 1004 } while (0) | |
| 1005 #define PACK(CTX,T,S,D,Z,A) \ | |
| 1006 do { \ | |
| 1007 *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \ | |
| 1008 *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \ | |
| 1009 *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \ | |
| 1010 } while (0) | |
| 1011 #include "extra_xform.h" | |
| 1012 | |
| 1013 #define FUNCTION_NAME CachedXFORM1to4_1 | |
| 1014 #define CACHED | |
| 1015 #define INPACKEDSAMPLESIZE 1 | |
| 1016 #define OUTPACKEDSAMPLESIZE 1 | |
| 1017 #define NUMINCHANNELS 1 | |
| 1018 #define NUMOUTCHANNELS 4 | |
| 1019 #define NUMEXTRAS 1 | |
| 1020 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 1021 do { \ | |
| 1022 (D)[0] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 1023 } while (0) | |
| 1024 #define PACK(CTX,T,S,D,Z,A) \ | |
| 1025 do { \ | |
| 1026 *(D)++ = FROM_16_TO_8((S)[0]); \ | |
| 1027 *(D)++ = FROM_16_TO_8((S)[1]); \ | |
| 1028 *(D)++ = FROM_16_TO_8((S)[2]); \ | |
| 1029 *(D)++ = FROM_16_TO_8((S)[3]); \ | |
| 1030 } while (0) | |
| 1031 #include "extra_xform.h" | |
| 1032 | |
| 1033 #define FUNCTION_NAME CachedXFORM1x2to4x2_2 | |
| 1034 #define CACHED | |
| 1035 #define INPACKEDSAMPLESIZE 2 | |
| 1036 #define OUTPACKEDSAMPLESIZE 2 | |
| 1037 #define NUMINCHANNELS 1 | |
| 1038 #define NUMOUTCHANNELS 4 | |
| 1039 #define NUMEXTRAS 1 | |
| 1040 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 1041 do { \ | |
| 1042 (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 1043 } while (0) | |
| 1044 #define PACK(CTX,T,S,D,Z,A) \ | |
| 1045 do { \ | |
| 1046 *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \ | |
| 1047 *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \ | |
| 1048 *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \ | |
| 1049 *(cmsUInt16Number *)(D) = (S)[3]; (D) += 2; \ | |
| 1050 } while (0) | |
| 1051 #include "extra_xform.h" | |
| 1052 | |
| 1053 #define FUNCTION_NAME CachedXFORM3to1_1 | |
| 1054 #define CACHED | |
| 1055 #define INPACKEDSAMPLESIZE 1 | |
| 1056 #define OUTPACKEDSAMPLESIZE 1 | |
| 1057 #define NUMINCHANNELS 3 | |
| 1058 #define NUMOUTCHANNELS 1 | |
| 1059 #define NUMEXTRAS 1 | |
| 1060 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 1061 do { \ | |
| 1062 (D)[0] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 1063 (D)[1] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 1064 (D)[2] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 1065 } while (0) | |
| 1066 #define PACK(CTX,T,S,D,Z,A) \ | |
| 1067 do { \ | |
| 1068 *(D)++ = FROM_16_TO_8((S)[0]); \ | |
| 1069 } while (0) | |
| 1070 #include "extra_xform.h" | |
| 1071 | |
| 1072 #define FUNCTION_NAME CachedXFORM3x2to1x2_2 | |
| 1073 #define CACHED | |
| 1074 #define INPACKEDSAMPLESIZE 2 | |
| 1075 #define OUTPACKEDSAMPLESIZE 2 | |
| 1076 #define NUMINCHANNELS 3 | |
| 1077 #define NUMOUTCHANNELS 1 | |
| 1078 #define NUMEXTRAS 1 | |
| 1079 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 1080 do { \ | |
| 1081 (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 1082 (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 1083 (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 1084 } while (0) | |
| 1085 #define PACK(CTX,T,S,D,Z,A) \ | |
| 1086 do { \ | |
| 1087 *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \ | |
| 1088 } while (0) | |
| 1089 #include "extra_xform.h" | |
| 1090 | |
| 1091 #define FUNCTION_NAME CachedXFORM3to3_1 | |
| 1092 #define CACHED | |
| 1093 #define INPACKEDSAMPLESIZE 1 | |
| 1094 #define OUTPACKEDSAMPLESIZE 1 | |
| 1095 #define NUMINCHANNELS 3 | |
| 1096 #define NUMOUTCHANNELS 3 | |
| 1097 #define NUMEXTRAS 1 | |
| 1098 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 1099 do { \ | |
| 1100 (D)[0] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 1101 (D)[1] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 1102 (D)[2] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 1103 } while (0) | |
| 1104 #define PACK(CTX,T,S,D,Z,A) \ | |
| 1105 do { \ | |
| 1106 *(D)++ = FROM_16_TO_8((S)[0]); \ | |
| 1107 *(D)++ = FROM_16_TO_8((S)[1]); \ | |
| 1108 *(D)++ = FROM_16_TO_8((S)[2]); \ | |
| 1109 } while (0) | |
| 1110 #include "extra_xform.h" | |
| 1111 | |
| 1112 #define FUNCTION_NAME CachedXFORM3x2to3x2_2 | |
| 1113 #define CACHED | |
| 1114 #define INPACKEDSAMPLESIZE 2 | |
| 1115 #define OUTPACKEDSAMPLESIZE 2 | |
| 1116 #define NUMINCHANNELS 3 | |
| 1117 #define NUMOUTCHANNELS 3 | |
| 1118 #define NUMEXTRAS 1 | |
| 1119 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 1120 do { \ | |
| 1121 (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 1122 (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 1123 (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 1124 } while (0) | |
| 1125 #define PACK(CTX,T,S,D,Z,A) \ | |
| 1126 do { \ | |
| 1127 *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \ | |
| 1128 *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \ | |
| 1129 *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \ | |
| 1130 } while (0) | |
| 1131 #include "extra_xform.h" | |
| 1132 | |
| 1133 #define FUNCTION_NAME CachedXFORM3to4_1 | |
| 1134 #define CACHED | |
| 1135 #define INPACKEDSAMPLESIZE 1 | |
| 1136 #define OUTPACKEDSAMPLESIZE 1 | |
| 1137 #define NUMINCHANNELS 3 | |
| 1138 #define NUMOUTCHANNELS 4 | |
| 1139 #define NUMEXTRAS 1 | |
| 1140 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 1141 do { \ | |
| 1142 (D)[0] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 1143 (D)[1] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 1144 (D)[2] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 1145 } while (0) | |
| 1146 #define PACK(CTX,T,S,D,Z,A) \ | |
| 1147 do { \ | |
| 1148 *(D)++ = FROM_16_TO_8((S)[0]); \ | |
| 1149 *(D)++ = FROM_16_TO_8((S)[1]); \ | |
| 1150 *(D)++ = FROM_16_TO_8((S)[2]); \ | |
| 1151 *(D)++ = FROM_16_TO_8((S)[3]); \ | |
| 1152 } while (0) | |
| 1153 #include "extra_xform.h" | |
| 1154 | |
| 1155 #define FUNCTION_NAME CachedXFORM3x2to4x2_2 | |
| 1156 #define CACHED | |
| 1157 #define INPACKEDSAMPLESIZE 2 | |
| 1158 #define OUTPACKEDSAMPLESIZE 2 | |
| 1159 #define NUMINCHANNELS 3 | |
| 1160 #define NUMOUTCHANNELS 4 | |
| 1161 #define NUMEXTRAS 1 | |
| 1162 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 1163 do { \ | |
| 1164 (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 1165 (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 1166 (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 1167 } while (0) | |
| 1168 #define PACK(CTX,T,S,D,Z,A) \ | |
| 1169 do { \ | |
| 1170 *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \ | |
| 1171 *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \ | |
| 1172 *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \ | |
| 1173 *(cmsUInt16Number *)(D) = (S)[3]; (D) += 2; \ | |
| 1174 } while (0) | |
| 1175 #include "extra_xform.h" | |
| 1176 | |
| 1177 #define FUNCTION_NAME CachedXFORM4to1_1 | |
| 1178 #define CACHED | |
| 1179 #define INPACKEDSAMPLESIZE 1 | |
| 1180 #define OUTPACKEDSAMPLESIZE 1 | |
| 1181 #define NUMINCHANNELS 4 | |
| 1182 #define NUMOUTCHANNELS 1 | |
| 1183 #define NUMEXTRAS 1 | |
| 1184 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 1185 do { \ | |
| 1186 (D)[0] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 1187 (D)[1] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 1188 (D)[2] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 1189 (D)[3] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 1190 } while (0) | |
| 1191 #define PACK(CTX,T,S,D,Z,A) \ | |
| 1192 do { \ | |
| 1193 *(D)++ = FROM_16_TO_8((S)[0]); \ | |
| 1194 } while (0) | |
| 1195 #include "extra_xform.h" | |
| 1196 | |
| 1197 #define FUNCTION_NAME CachedXFORM4x2to1x2_2 | |
| 1198 #define CACHED | |
| 1199 #define INPACKEDSAMPLESIZE 2 | |
| 1200 #define OUTPACKEDSAMPLESIZE 2 | |
| 1201 #define NUMINCHANNELS 1 | |
| 1202 #define NUMOUTCHANNELS 1 | |
| 1203 #define NUMEXTRAS 1 | |
| 1204 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 1205 do { \ | |
| 1206 (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 1207 (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 1208 (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 1209 (D)[3] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 1210 } while (0) | |
| 1211 #define PACK(CTX,T,S,D,Z,A) \ | |
| 1212 do { \ | |
| 1213 *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \ | |
| 1214 } while (0) | |
| 1215 #include "extra_xform.h" | |
| 1216 | |
| 1217 #define FUNCTION_NAME CachedXFORM4to3_1 | |
| 1218 #define CACHED | |
| 1219 #define INPACKEDSAMPLESIZE 1 | |
| 1220 #define OUTPACKEDSAMPLESIZE 1 | |
| 1221 #define NUMINCHANNELS 4 | |
| 1222 #define NUMOUTCHANNELS 3 | |
| 1223 #define NUMEXTRAS 1 | |
| 1224 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 1225 do { \ | |
| 1226 (D)[0] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 1227 (D)[1] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 1228 (D)[2] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 1229 (D)[3] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 1230 } while (0) | |
| 1231 #define PACK(CTX,T,S,D,Z,A) \ | |
| 1232 do { \ | |
| 1233 *(D)++ = FROM_16_TO_8((S)[0]); \ | |
| 1234 *(D)++ = FROM_16_TO_8((S)[1]); \ | |
| 1235 *(D)++ = FROM_16_TO_8((S)[2]); \ | |
| 1236 } while (0) | |
| 1237 #include "extra_xform.h" | |
| 1238 | |
| 1239 #define FUNCTION_NAME CachedXFORM4x2to3x2_2 | |
| 1240 #define CACHED | |
| 1241 #define INPACKEDSAMPLESIZE 2 | |
| 1242 #define OUTPACKEDSAMPLESIZE 2 | |
| 1243 #define NUMINCHANNELS 4 | |
| 1244 #define NUMOUTCHANNELS 3 | |
| 1245 #define NUMEXTRAS 1 | |
| 1246 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 1247 do { \ | |
| 1248 (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 1249 (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 1250 (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 1251 (D)[3] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 1252 } while (0) | |
| 1253 #define PACK(CTX,T,S,D,Z,A) \ | |
| 1254 do { \ | |
| 1255 *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \ | |
| 1256 *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \ | |
| 1257 *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \ | |
| 1258 } while (0) | |
| 1259 #include "extra_xform.h" | |
| 1260 | |
| 1261 #define FUNCTION_NAME CachedXFORM4to4_1 | |
| 1262 #define CACHED | |
| 1263 #define INPACKEDSAMPLESIZE 1 | |
| 1264 #define OUTPACKEDSAMPLESIZE 1 | |
| 1265 #define NUMINCHANNELS 4 | |
| 1266 #define NUMOUTCHANNELS 4 | |
| 1267 #define NUMEXTRAS 1 | |
| 1268 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 1269 do { \ | |
| 1270 (D)[0] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 1271 (D)[1] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 1272 (D)[2] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 1273 (D)[3] = FROM_8_TO_16(*(S)); (S)++; \ | |
| 1274 } while (0) | |
| 1275 #define PACK(CTX,T,S,D,Z,A) \ | |
| 1276 do { \ | |
| 1277 *(D)++ = FROM_16_TO_8((S)[0]); \ | |
| 1278 *(D)++ = FROM_16_TO_8((S)[1]); \ | |
| 1279 *(D)++ = FROM_16_TO_8((S)[2]); \ | |
| 1280 *(D)++ = FROM_16_TO_8((S)[3]); \ | |
| 1281 } while (0) | |
| 1282 #include "extra_xform.h" | |
| 1283 | |
| 1284 #define FUNCTION_NAME CachedXFORM4x2to4x2_2 | |
| 1285 #define CACHED | |
| 1286 #define INPACKEDSAMPLESIZE 2 | |
| 1287 #define OUTPACKEDSAMPLESIZE 2 | |
| 1288 #define NUMINCHANNELS 4 | |
| 1289 #define NUMOUTCHANNELS 4 | |
| 1290 #define NUMEXTRAS 1 | |
| 1291 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 1292 do { \ | |
| 1293 (D)[0] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 1294 (D)[1] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 1295 (D)[2] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 1296 (D)[3] = *(cmsUInt16Number *)(S); (S) += 2; \ | |
| 1297 } while (0) | |
| 1298 #define PACK(CTX,T,S,D,Z,A) \ | |
| 1299 do { \ | |
| 1300 *(cmsUInt16Number *)(D) = (S)[0]; (D) += 2; \ | |
| 1301 *(cmsUInt16Number *)(D) = (S)[1]; (D) += 2; \ | |
| 1302 *(cmsUInt16Number *)(D) = (S)[2]; (D) += 2; \ | |
| 1303 *(cmsUInt16Number *)(D) = (S)[3]; (D) += 2; \ | |
| 1304 } while (0) | |
| 1305 #include "extra_xform.h" | |
| 1306 | |
| 1307 | |
| 1308 // Same again, but with premultiplied alpha | |
| 1309 // | |
| 1310 // No gamut check, Cache, 16 bits, | |
| 1311 #define FUNCTION_NAME CachedXFORM_P1 | |
| 1312 #define CACHED | |
| 1313 #define INPACKEDSAMPLESIZE 1 | |
| 1314 #define OUTPACKEDSAMPLESIZE 1 | |
| 1315 #define PREALPHA | |
| 1316 #include "extra_xform.h" | |
| 1317 | |
| 1318 // No gamut check, Cache, 16 bits, | |
| 1319 #define FUNCTION_NAME CachedXFORM_P2 | |
| 1320 #define CACHED | |
| 1321 #define INPACKEDSAMPLESIZE 2 | |
| 1322 #define OUTPACKEDSAMPLESIZE 2 | |
| 1323 #define PREALPHA | |
| 1324 #include "extra_xform.h" | |
| 1325 | |
| 1326 // Special ones for common cases. | |
| 1327 #define FUNCTION_NAME CachedXFORM1to1_P1 | |
| 1328 #define CACHED | |
| 1329 #define INPACKEDSAMPLESIZE 1 | |
| 1330 #define OUTPACKEDSAMPLESIZE 1 | |
| 1331 #define NUMINCHANNELS 1 | |
| 1332 #define NUMOUTCHANNELS 1 | |
| 1333 #define NUMEXTRAS 1 | |
| 1334 #define PREALPHA | |
| 1335 #define UNPACKINCLUDESPREALPHA | |
| 1336 #define PACKINCLUDESPREALPHA | |
| 1337 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 1338 do { \ | |
| 1339 cmsUInt32Number inva = 0xFFFFU / (A); \ | |
| 1340 (D)[0] = (cmsUInt16Number)(*(S) * inva); (S)++; \ | |
| 1341 } while (0) | |
| 1342 #define PACK(CTX,T,S,D,Z,A) \ | |
| 1343 do { \ | |
| 1344 *(D)++ = mul255(FROM_16_TO_8((S)[0]),(A)); \ | |
| 1345 } while (0) | |
| 1346 #include "extra_xform.h" | |
| 1347 | |
| 1348 #define FUNCTION_NAME CachedXFORM1x2to1x2_P2 | |
| 1349 #define CACHED | |
| 1350 #define INPACKEDSAMPLESIZE 2 | |
| 1351 #define OUTPACKEDSAMPLESIZE 2 | |
| 1352 #define NUMINCHANNELS 1 | |
| 1353 #define NUMOUTCHANNELS 1 | |
| 1354 #define NUMEXTRAS 1 | |
| 1355 #define PREALPHA | |
| 1356 #define UNPACKINCLUDESPREALPHA | |
| 1357 #define PACKINCLUDESPREALPHA | |
| 1358 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 1359 do { \ | |
| 1360 cmsUInt32Number inva = 0xffff0000U / (A); \ | |
| 1361 (D)[0] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ | |
| 1362 } while (0) | |
| 1363 #define PACK(CTX,T,S,D,Z,A) \ | |
| 1364 do { \ | |
| 1365 *(cmsUInt16Number *)(D) = mul65535((S)[0],A); (D) += 2; \ | |
| 1366 } while (0) | |
| 1367 #include "extra_xform.h" | |
| 1368 | |
| 1369 #define FUNCTION_NAME CachedXFORM1to3_P1 | |
| 1370 #define CACHED | |
| 1371 #define INPACKEDSAMPLESIZE 1 | |
| 1372 #define OUTPACKEDSAMPLESIZE 1 | |
| 1373 #define NUMINCHANNELS 1 | |
| 1374 #define NUMOUTCHANNELS 3 | |
| 1375 #define NUMEXTRAS 1 | |
| 1376 #define PREALPHA | |
| 1377 #define UNPACKINCLUDESPREALPHA | |
| 1378 #define PACKINCLUDESPREALPHA | |
| 1379 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 1380 do { \ | |
| 1381 cmsUInt32Number inva = 0xFFFFU / (A); \ | |
| 1382 (D)[0] = (cmsUInt16Number)(*(S) * inva); (S)++; \ | |
| 1383 } while (0) | |
| 1384 #define PACK(CTX,T,S,D,Z,A) \ | |
| 1385 do { \ | |
| 1386 *(D)++ = mul255(FROM_16_TO_8((S)[0]),(A)); \ | |
| 1387 *(D)++ = mul255(FROM_16_TO_8((S)[1]),(A)); \ | |
| 1388 *(D)++ = mul255(FROM_16_TO_8((S)[2]),(A)); \ | |
| 1389 } while (0) | |
| 1390 #include "extra_xform.h" | |
| 1391 | |
| 1392 #define FUNCTION_NAME CachedXFORM1x2to3x2_P2 | |
| 1393 #define CACHED | |
| 1394 #define INPACKEDSAMPLESIZE 2 | |
| 1395 #define OUTPACKEDSAMPLESIZE 2 | |
| 1396 #define NUMINCHANNELS 1 | |
| 1397 #define NUMOUTCHANNELS 3 | |
| 1398 #define NUMEXTRAS 1 | |
| 1399 #define PREALPHA | |
| 1400 #define UNPACKINCLUDESPREALPHA | |
| 1401 #define PACKINCLUDESPREALPHA | |
| 1402 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 1403 do { \ | |
| 1404 cmsUInt32Number inva = 0xffff0000U / (A); \ | |
| 1405 (D)[0] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ | |
| 1406 } while (0) | |
| 1407 #define PACK(CTX,T,S,D,Z,A) \ | |
| 1408 do { \ | |
| 1409 *(cmsUInt16Number *)(D) = mul65535((S)[0],A); (D) += 2; \ | |
| 1410 *(cmsUInt16Number *)(D) = mul65535((S)[1],A); (D) += 2; \ | |
| 1411 *(cmsUInt16Number *)(D) = mul65535((S)[2],A); (D) += 2; \ | |
| 1412 } while (0) | |
| 1413 #include "extra_xform.h" | |
| 1414 | |
| 1415 #define FUNCTION_NAME CachedXFORM1to4_P1 | |
| 1416 #define CACHED | |
| 1417 #define INPACKEDSAMPLESIZE 1 | |
| 1418 #define OUTPACKEDSAMPLESIZE 1 | |
| 1419 #define NUMINCHANNELS 1 | |
| 1420 #define NUMOUTCHANNELS 4 | |
| 1421 #define NUMEXTRAS 1 | |
| 1422 #define PREALPHA | |
| 1423 #define UNPACKINCLUDESPREALPHA | |
| 1424 #define PACKINCLUDESPREALPHA | |
| 1425 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 1426 do { \ | |
| 1427 cmsUInt32Number inva = 0xFFFFU / (A); \ | |
| 1428 (D)[0] = (cmsUInt16Number)(*(S) * inva); (S)++; \ | |
| 1429 } while (0) | |
| 1430 #define PACK(CTX,T,S,D,Z,A) \ | |
| 1431 do { \ | |
| 1432 *(D)++ = mul255(FROM_16_TO_8((S)[0]),(A)); \ | |
| 1433 *(D)++ = mul255(FROM_16_TO_8((S)[1]),(A)); \ | |
| 1434 *(D)++ = mul255(FROM_16_TO_8((S)[2]),(A)); \ | |
| 1435 *(D)++ = mul255(FROM_16_TO_8((S)[3]),(A)); \ | |
| 1436 } while (0) | |
| 1437 #include "extra_xform.h" | |
| 1438 | |
| 1439 #define FUNCTION_NAME CachedXFORM1x2to4x2_P2 | |
| 1440 #define CACHED | |
| 1441 #define INPACKEDSAMPLESIZE 2 | |
| 1442 #define OUTPACKEDSAMPLESIZE 2 | |
| 1443 #define NUMINCHANNELS 1 | |
| 1444 #define NUMOUTCHANNELS 4 | |
| 1445 #define NUMEXTRAS 1 | |
| 1446 #define PREALPHA | |
| 1447 #define UNPACKINCLUDESPREALPHA | |
| 1448 #define PACKINCLUDESPREALPHA | |
| 1449 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 1450 do { \ | |
| 1451 cmsUInt32Number inva = 0xffff0000U / (A); \ | |
| 1452 (D)[0] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ | |
| 1453 } while (0) | |
| 1454 #define PACK(CTX,T,S,D,Z,A) \ | |
| 1455 do { \ | |
| 1456 *(cmsUInt16Number *)(D) = mul65535((S)[0],A); (D) += 2; \ | |
| 1457 *(cmsUInt16Number *)(D) = mul65535((S)[1],A); (D) += 2; \ | |
| 1458 *(cmsUInt16Number *)(D) = mul65535((S)[2],A); (D) += 2; \ | |
| 1459 *(cmsUInt16Number *)(D) = mul65535((S)[3],A); (D) += 2; \ | |
| 1460 } while (0) | |
| 1461 #include "extra_xform.h" | |
| 1462 | |
| 1463 #define FUNCTION_NAME CachedXFORM3to1_P1 | |
| 1464 #define CACHED | |
| 1465 #define INPACKEDSAMPLESIZE 1 | |
| 1466 #define OUTPACKEDSAMPLESIZE 1 | |
| 1467 #define NUMINCHANNELS 3 | |
| 1468 #define NUMOUTCHANNELS 1 | |
| 1469 #define NUMEXTRAS 1 | |
| 1470 #define PREALPHA | |
| 1471 #define UNPACKINCLUDESPREALPHA | |
| 1472 #define PACKINCLUDESPREALPHA | |
| 1473 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 1474 do { \ | |
| 1475 cmsUInt32Number inva = 0xFFFFU / (A); \ | |
| 1476 (D)[0] = (cmsUInt16Number)((*(S) * inva)); (S)++; \ | |
| 1477 (D)[1] = (cmsUInt16Number)((*(S) * inva)); (S)++; \ | |
| 1478 (D)[2] = (cmsUInt16Number)((*(S) * inva)); (S)++; \ | |
| 1479 } while (0) | |
| 1480 #define PACK(CTX,T,S,D,Z,A) \ | |
| 1481 do { \ | |
| 1482 *(D)++ = mul255(FROM_16_TO_8((S)[0]),(A)); \ | |
| 1483 } while (0) | |
| 1484 #include "extra_xform.h" | |
| 1485 | |
| 1486 #define FUNCTION_NAME CachedXFORM3x2to1x2_P2 | |
| 1487 #define CACHED | |
| 1488 #define INPACKEDSAMPLESIZE 2 | |
| 1489 #define OUTPACKEDSAMPLESIZE 2 | |
| 1490 #define NUMINCHANNELS 3 | |
| 1491 #define NUMOUTCHANNELS 1 | |
| 1492 #define NUMEXTRAS 1 | |
| 1493 #define PREALPHA | |
| 1494 #define UNPACKINCLUDESPREALPHA | |
| 1495 #define PACKINCLUDESPREALPHA | |
| 1496 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 1497 do { \ | |
| 1498 cmsUInt32Number inva = 0xffff0000U / (A); \ | |
| 1499 (D)[0] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ | |
| 1500 (D)[1] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ | |
| 1501 (D)[2] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ | |
| 1502 } while (0) | |
| 1503 #define PACK(CTX,T,S,D,Z,A) \ | |
| 1504 do { \ | |
| 1505 *(cmsUInt16Number *)(D) = mul65535((S)[0],A); (D) += 2; \ | |
| 1506 } while (0) | |
| 1507 #include "extra_xform.h" | |
| 1508 | |
| 1509 #define FUNCTION_NAME CachedXFORM3to3_P1 | |
| 1510 #define CACHED | |
| 1511 #define INPACKEDSAMPLESIZE 1 | |
| 1512 #define OUTPACKEDSAMPLESIZE 1 | |
| 1513 #define NUMINCHANNELS 3 | |
| 1514 #define NUMOUTCHANNELS 3 | |
| 1515 #define NUMEXTRAS 1 | |
| 1516 #define PREALPHA | |
| 1517 #define UNPACKINCLUDESPREALPHA | |
| 1518 #define PACKINCLUDESPREALPHA | |
| 1519 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 1520 do { \ | |
| 1521 cmsUInt32Number inva = 0xFFFFU / (A); \ | |
| 1522 (D)[0] = (cmsUInt16Number)(*(S) * inva); (S)++; \ | |
| 1523 (D)[1] = (cmsUInt16Number)(*(S) * inva); (S)++; \ | |
| 1524 (D)[2] = (cmsUInt16Number)(*(S) * inva); (S)++; \ | |
| 1525 } while (0) | |
| 1526 #define PACK(CTX,T,S,D,Z,A) \ | |
| 1527 do { \ | |
| 1528 *(D)++ = mul255(FROM_16_TO_8((S)[0]),(A)); \ | |
| 1529 *(D)++ = mul255(FROM_16_TO_8((S)[1]),(A)); \ | |
| 1530 *(D)++ = mul255(FROM_16_TO_8((S)[2]),(A)); \ | |
| 1531 } while (0) | |
| 1532 #include "extra_xform.h" | |
| 1533 | |
| 1534 #define FUNCTION_NAME CachedXFORM3x2to3x2_P2 | |
| 1535 #define CACHED | |
| 1536 #define INPACKEDSAMPLESIZE 2 | |
| 1537 #define OUTPACKEDSAMPLESIZE 2 | |
| 1538 #define NUMINCHANNELS 3 | |
| 1539 #define NUMOUTCHANNELS 3 | |
| 1540 #define NUMEXTRAS 1 | |
| 1541 #define PREALPHA | |
| 1542 #define UNPACKINCLUDESPREALPHA | |
| 1543 #define PACKINCLUDESPREALPHA | |
| 1544 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 1545 do { \ | |
| 1546 cmsUInt32Number inva = 0xffff0000U / (A); \ | |
| 1547 (D)[0] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ | |
| 1548 (D)[1] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ | |
| 1549 (D)[2] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ | |
| 1550 } while (0) | |
| 1551 #define PACK(CTX,T,S,D,Z,A) \ | |
| 1552 do { \ | |
| 1553 *(cmsUInt16Number *)(D) = mul65535((S)[0],A); (D) += 2; \ | |
| 1554 *(cmsUInt16Number *)(D) = mul65535((S)[1],A); (D) += 2; \ | |
| 1555 *(cmsUInt16Number *)(D) = mul65535((S)[2],A); (D) += 2; \ | |
| 1556 } while (0) | |
| 1557 #include "extra_xform.h" | |
| 1558 | |
| 1559 #define FUNCTION_NAME CachedXFORM3to4_P1 | |
| 1560 #define CACHED | |
| 1561 #define INPACKEDSAMPLESIZE 1 | |
| 1562 #define OUTPACKEDSAMPLESIZE 1 | |
| 1563 #define NUMINCHANNELS 3 | |
| 1564 #define NUMOUTCHANNELS 4 | |
| 1565 #define NUMEXTRAS 1 | |
| 1566 #define PREALPHA | |
| 1567 #define UNPACKINCLUDESPREALPHA | |
| 1568 #define PACKINCLUDESPREALPHA | |
| 1569 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 1570 do { \ | |
| 1571 cmsUInt32Number inva = 0xFFFFU / (A); \ | |
| 1572 (D)[0] = (cmsUInt16Number)(*(S) * inva); (S)++; \ | |
| 1573 (D)[1] = (cmsUInt16Number)(*(S) * inva); (S)++; \ | |
| 1574 (D)[2] = (cmsUInt16Number)(*(S) * inva); (S)++; \ | |
| 1575 } while (0) | |
| 1576 #define PACK(CTX,T,S,D,Z,A) \ | |
| 1577 do { \ | |
| 1578 *(D)++ = mul255(FROM_16_TO_8((S)[0]),(A)); \ | |
| 1579 *(D)++ = mul255(FROM_16_TO_8((S)[1]),(A)); \ | |
| 1580 *(D)++ = mul255(FROM_16_TO_8((S)[2]),(A)); \ | |
| 1581 *(D)++ = mul255(FROM_16_TO_8((S)[3]),(A)); \ | |
| 1582 } while (0) | |
| 1583 #include "extra_xform.h" | |
| 1584 | |
| 1585 #define FUNCTION_NAME CachedXFORM3x2to4x2_P2 | |
| 1586 #define CACHED | |
| 1587 #define INPACKEDSAMPLESIZE 2 | |
| 1588 #define OUTPACKEDSAMPLESIZE 2 | |
| 1589 #define NUMINCHANNELS 3 | |
| 1590 #define NUMOUTCHANNELS 4 | |
| 1591 #define NUMEXTRAS 1 | |
| 1592 #define PREALPHA | |
| 1593 #define UNPACKINCLUDESPREALPHA | |
| 1594 #define PACKINCLUDESPREALPHA | |
| 1595 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 1596 do { \ | |
| 1597 cmsUInt32Number inva = 0xffff0000U / (A); \ | |
| 1598 (D)[0] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ | |
| 1599 (D)[1] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ | |
| 1600 (D)[2] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ | |
| 1601 } while (0) | |
| 1602 #define PACK(CTX,T,S,D,Z,A) \ | |
| 1603 do { \ | |
| 1604 *(cmsUInt16Number *)(D) = mul65535((S)[0],A); (D) += 2; \ | |
| 1605 *(cmsUInt16Number *)(D) = mul65535((S)[1],A); (D) += 2; \ | |
| 1606 *(cmsUInt16Number *)(D) = mul65535((S)[2],A); (D) += 2; \ | |
| 1607 *(cmsUInt16Number *)(D) = mul65535((S)[3],A); (D) += 2; \ | |
| 1608 } while (0) | |
| 1609 #include "extra_xform.h" | |
| 1610 | |
| 1611 #define FUNCTION_NAME CachedXFORM4to1_P1 | |
| 1612 #define CACHED | |
| 1613 #define INPACKEDSAMPLESIZE 1 | |
| 1614 #define OUTPACKEDSAMPLESIZE 1 | |
| 1615 #define NUMINCHANNELS 4 | |
| 1616 #define NUMOUTCHANNELS 1 | |
| 1617 #define NUMEXTRAS 1 | |
| 1618 #define PREALPHA | |
| 1619 #define UNPACKINCLUDESPREALPHA | |
| 1620 #define PACKINCLUDESPREALPHA | |
| 1621 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 1622 do { \ | |
| 1623 cmsUInt32Number inva = 0xFFFFU / (A); \ | |
| 1624 (D)[0] = (cmsUInt16Number)(*(S) * inva); (S)++; \ | |
| 1625 (D)[1] = (cmsUInt16Number)(*(S) * inva); (S)++; \ | |
| 1626 (D)[2] = (cmsUInt16Number)(*(S) * inva); (S)++; \ | |
| 1627 (D)[3] = (cmsUInt16Number)(*(S) * inva); (S)++; \ | |
| 1628 } while (0) | |
| 1629 #define PACK(CTX,T,S,D,Z,A) \ | |
| 1630 do { \ | |
| 1631 *(D)++ = mul255(FROM_16_TO_8((S)[0]),(A)); \ | |
| 1632 } while (0) | |
| 1633 #include "extra_xform.h" | |
| 1634 | |
| 1635 #define FUNCTION_NAME CachedXFORM4x2to1x2_P2 | |
| 1636 #define CACHED | |
| 1637 #define INPACKEDSAMPLESIZE 2 | |
| 1638 #define OUTPACKEDSAMPLESIZE 2 | |
| 1639 #define NUMINCHANNELS 4 | |
| 1640 #define NUMOUTCHANNELS 1 | |
| 1641 #define NUMEXTRAS 1 | |
| 1642 #define PREALPHA | |
| 1643 #define UNPACKINCLUDESPREALPHA | |
| 1644 #define PACKINCLUDESPREALPHA | |
| 1645 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 1646 do { \ | |
| 1647 cmsUInt32Number inva = 0xffff0000U / (A); \ | |
| 1648 (D)[0] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ | |
| 1649 (D)[1] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ | |
| 1650 (D)[2] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ | |
| 1651 (D)[3] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ | |
| 1652 } while (0) | |
| 1653 #define PACK(CTX,T,S,D,Z,A) \ | |
| 1654 do { \ | |
| 1655 *(cmsUInt16Number *)(D) = mul65535((S)[0],A); (D) += 2; \ | |
| 1656 } while (0) | |
| 1657 #include "extra_xform.h" | |
| 1658 | |
| 1659 #define FUNCTION_NAME CachedXFORM4to3_P1 | |
| 1660 #define CACHED | |
| 1661 #define INPACKEDSAMPLESIZE 1 | |
| 1662 #define OUTPACKEDSAMPLESIZE 1 | |
| 1663 #define NUMINCHANNELS 4 | |
| 1664 #define NUMOUTCHANNELS 3 | |
| 1665 #define NUMEXTRAS 1 | |
| 1666 #define PREALPHA | |
| 1667 #define UNPACKINCLUDESPREALPHA | |
| 1668 #define PACKINCLUDESPREALPHA | |
| 1669 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 1670 do { \ | |
| 1671 cmsUInt32Number inva = 0xFFFFU / (A); \ | |
| 1672 (D)[0] = (cmsUInt16Number)(*(S) * inva); (S)++; \ | |
| 1673 (D)[1] = (cmsUInt16Number)(*(S) * inva); (S)++; \ | |
| 1674 (D)[2] = (cmsUInt16Number)(*(S) * inva); (S)++; \ | |
| 1675 (D)[3] = (cmsUInt16Number)(*(S) * inva); (S)++; \ | |
| 1676 } while (0) | |
| 1677 #define PACK(CTX,T,S,D,Z,A) \ | |
| 1678 do { \ | |
| 1679 *(D)++ = mul255(FROM_16_TO_8((S)[0]),(A)); \ | |
| 1680 *(D)++ = mul255(FROM_16_TO_8((S)[1]),(A)); \ | |
| 1681 *(D)++ = mul255(FROM_16_TO_8((S)[2]),(A)); \ | |
| 1682 } while (0) | |
| 1683 #include "extra_xform.h" | |
| 1684 | |
| 1685 #define FUNCTION_NAME CachedXFORM4x2to3x2_P2 | |
| 1686 #define CACHED | |
| 1687 #define INPACKEDSAMPLESIZE 2 | |
| 1688 #define OUTPACKEDSAMPLESIZE 2 | |
| 1689 #define NUMINCHANNELS 4 | |
| 1690 #define NUMOUTCHANNELS 3 | |
| 1691 #define NUMEXTRAS 1 | |
| 1692 #define PREALPHA | |
| 1693 #define UNPACKINCLUDESPREALPHA | |
| 1694 #define PACKINCLUDESPREALPHA | |
| 1695 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 1696 do { \ | |
| 1697 cmsUInt32Number inva = 0xffff0000U / (A); \ | |
| 1698 (D)[0] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ | |
| 1699 (D)[1] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ | |
| 1700 (D)[2] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ | |
| 1701 (D)[3] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ | |
| 1702 } while (0) | |
| 1703 #define PACK(CTX,T,S,D,Z,A) \ | |
| 1704 do { \ | |
| 1705 *(cmsUInt16Number *)(D) = mul65535((S)[0],A); (D) += 2; \ | |
| 1706 *(cmsUInt16Number *)(D) = mul65535((S)[1],A); (D) += 2; \ | |
| 1707 *(cmsUInt16Number *)(D) = mul65535((S)[2],A); (D) += 2; \ | |
| 1708 } while (0) | |
| 1709 #include "extra_xform.h" | |
| 1710 | |
| 1711 #define FUNCTION_NAME CachedXFORM4to4_P1 | |
| 1712 #define CACHED | |
| 1713 #define INPACKEDSAMPLESIZE 1 | |
| 1714 #define OUTPACKEDSAMPLESIZE 1 | |
| 1715 #define NUMINCHANNELS 4 | |
| 1716 #define NUMOUTCHANNELS 4 | |
| 1717 #define NUMEXTRAS 1 | |
| 1718 #define PREALPHA | |
| 1719 #define UNPACKINCLUDESPREALPHA | |
| 1720 #define PACKINCLUDESPREALPHA | |
| 1721 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 1722 do { \ | |
| 1723 cmsUInt32Number inva = 0xFFFFU / (A); \ | |
| 1724 (D)[0] = (cmsUInt16Number)(*(S) * inva); (S)++; \ | |
| 1725 (D)[1] = (cmsUInt16Number)(*(S) * inva); (S)++; \ | |
| 1726 (D)[2] = (cmsUInt16Number)(*(S) * inva); (S)++; \ | |
| 1727 (D)[3] = (cmsUInt16Number)(*(S) * inva); (S)++; \ | |
| 1728 } while (0) | |
| 1729 #define PACK(CTX,T,S,D,Z,A) \ | |
| 1730 do { \ | |
| 1731 *(D)++ = mul255(FROM_16_TO_8((S)[0]),(A)); \ | |
| 1732 *(D)++ = mul255(FROM_16_TO_8((S)[1]),(A)); \ | |
| 1733 *(D)++ = mul255(FROM_16_TO_8((S)[2]),(A)); \ | |
| 1734 *(D)++ = mul255(FROM_16_TO_8((S)[3]),(A)); \ | |
| 1735 } while (0) | |
| 1736 #include "extra_xform.h" | |
| 1737 | |
| 1738 #define FUNCTION_NAME CachedXFORM4x2to4x2_P2 | |
| 1739 #define CACHED | |
| 1740 #define INPACKEDSAMPLESIZE 2 | |
| 1741 #define OUTPACKEDSAMPLESIZE 2 | |
| 1742 #define NUMINCHANNELS 4 | |
| 1743 #define NUMOUTCHANNELS 4 | |
| 1744 #define NUMEXTRAS 1 | |
| 1745 #define PREALPHA | |
| 1746 #define UNPACKINCLUDESPREALPHA | |
| 1747 #define PACKINCLUDESPREALPHA | |
| 1748 #define UNPACK(CTX,T,D,S,Z,A) \ | |
| 1749 do { \ | |
| 1750 cmsUInt32Number inva = 0xffff0000U / (A); \ | |
| 1751 (D)[0] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ | |
| 1752 (D)[1] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ | |
| 1753 (D)[2] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ | |
| 1754 (D)[3] = (cmsUInt16Number)(((*(cmsUInt16Number *)(S)) * inva)>>16); (S) += 2; \ | |
| 1755 } while (0) | |
| 1756 #define PACK(CTX,T,S,D,Z,A) \ | |
| 1757 do { \ | |
| 1758 *(cmsUInt16Number *)(D) = mul65535((S)[0],A); (D) += 2; \ | |
| 1759 *(cmsUInt16Number *)(D) = mul65535((S)[1],A); (D) += 2; \ | |
| 1760 *(cmsUInt16Number *)(D) = mul65535((S)[2],A); (D) += 2; \ | |
| 1761 *(cmsUInt16Number *)(D) = mul65535((S)[3],A); (D) += 2; \ | |
| 1762 } while (0) | |
| 1763 #include "extra_xform.h" | |
| 1764 | |
| 1765 | |
| 1766 // Transform plug-ins ---------------------------------------------------------------------------------------------------- | |
| 1767 | |
| 1768 // List of used-defined transform factories | |
| 1769 typedef struct _cmsTransformCollection_st { | |
| 1770 | |
| 1771 _cmsTransform2Factory Factory; | |
| 1772 cmsBool OldXform; // Factory returns xform function in the old style | |
| 1773 | |
| 1774 struct _cmsTransformCollection_st *Next; | |
| 1775 | |
| 1776 } _cmsTransformCollection; | |
| 1777 | |
| 1778 // The linked list head | |
| 1779 _cmsTransformPluginChunkType _cmsTransformPluginChunk = { NULL }; | |
| 1780 | |
| 1781 | |
| 1782 // Duplicates the zone of memory used by the plug-in in the new context | |
| 1783 static | |
| 1784 void DupPluginTransformList(struct _cmsContext_struct* ctx, | |
| 1785 const struct _cmsContext_struct* src) | |
| 1786 { | |
| 1787 _cmsTransformPluginChunkType newHead = { NULL }; | |
| 1788 _cmsTransformCollection* entry; | |
| 1789 _cmsTransformCollection* Anterior = NULL; | |
| 1790 _cmsTransformPluginChunkType* head = (_cmsTransformPluginChunkType*) src->chunks[TransformPlugin]; | |
| 1791 | |
| 1792 // Walk the list copying all nodes | |
| 1793 for (entry = head->TransformCollection; | |
| 1794 entry != NULL; | |
| 1795 entry = entry ->Next) { | |
| 1796 | |
| 1797 _cmsTransformCollection *newEntry = ( _cmsTransformCollection *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(_cmsTransformCollection)); | |
| 1798 | |
| 1799 if (newEntry == NULL) | |
| 1800 return; | |
| 1801 | |
| 1802 // We want to keep the linked list order, so this is a little bit tricky | |
| 1803 newEntry -> Next = NULL; | |
| 1804 if (Anterior) | |
| 1805 Anterior -> Next = newEntry; | |
| 1806 | |
| 1807 Anterior = newEntry; | |
| 1808 | |
| 1809 if (newHead.TransformCollection == NULL) | |
| 1810 newHead.TransformCollection = newEntry; | |
| 1811 } | |
| 1812 | |
| 1813 ctx ->chunks[TransformPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsTransformPluginChunkType)); | |
| 1814 } | |
| 1815 | |
| 1816 // Allocates memory for transform plugin factory | |
| 1817 void _cmsAllocTransformPluginChunk(struct _cmsContext_struct* ctx, | |
| 1818 const struct _cmsContext_struct* src) | |
| 1819 { | |
| 1820 if (src != NULL) { | |
| 1821 | |
| 1822 // Copy all linked list | |
| 1823 DupPluginTransformList(ctx, src); | |
| 1824 } | |
| 1825 else { | |
| 1826 static _cmsTransformPluginChunkType TransformPluginChunkType = { NULL }; | |
| 1827 ctx ->chunks[TransformPlugin] = _cmsSubAllocDup(ctx ->MemPool, &TransformPluginChunkType, sizeof(_cmsTransformPluginChunkType)); | |
| 1828 } | |
| 1829 } | |
| 1830 | |
| 1831 // Adaptor for old versions of plug-in | |
| 1832 static | |
| 1833 void _cmsTransform2toTransformAdaptor(cmsContext ContextID, struct _cmstransform_struct *CMMcargo, | |
| 1834 const void* InputBuffer, | |
| 1835 void* OutputBuffer, | |
| 1836 cmsUInt32Number PixelsPerLine, | |
| 1837 cmsUInt32Number LineCount, | |
| 1838 const cmsStride* Stride) | |
| 1839 { | |
| 1840 | |
| 1841 cmsUInt32Number i, strideIn, strideOut; | |
| 1842 | |
| 1843 _cmsHandleExtraChannels(ContextID, CMMcargo, InputBuffer, OutputBuffer, PixelsPerLine, LineCount, Stride); | |
| 1844 | |
| 1845 strideIn = 0; | |
| 1846 strideOut = 0; | |
| 1847 | |
| 1848 for (i = 0; i < LineCount; i++) { | |
| 1849 | |
| 1850 void *accum = (cmsUInt8Number*)InputBuffer + strideIn; | |
| 1851 void *output = (cmsUInt8Number*)OutputBuffer + strideOut; | |
| 1852 | |
| 1853 CMMcargo->OldXform(ContextID, CMMcargo, accum, output, PixelsPerLine, Stride->BytesPerPlaneIn); | |
| 1854 | |
| 1855 strideIn += Stride->BytesPerLineIn; | |
| 1856 strideOut += Stride->BytesPerLineOut; | |
| 1857 } | |
| 1858 } | |
| 1859 | |
| 1860 | |
| 1861 | |
| 1862 // Register new ways to transform | |
| 1863 cmsBool _cmsRegisterTransformPlugin(cmsContext ContextID, cmsPluginBase* Data) | |
| 1864 { | |
| 1865 cmsPluginTransform* Plugin = (cmsPluginTransform*) Data; | |
| 1866 _cmsTransformCollection* fl; | |
| 1867 _cmsTransformPluginChunkType* ctx = ( _cmsTransformPluginChunkType*) _cmsContextGetClientChunk(ContextID,TransformPlugin); | |
| 1868 | |
| 1869 if (Data == NULL) { | |
| 1870 | |
| 1871 // Free the chain. Memory is safely freed at exit | |
| 1872 ctx->TransformCollection = NULL; | |
| 1873 return TRUE; | |
| 1874 } | |
| 1875 | |
| 1876 // Factory callback is required | |
| 1877 if (Plugin->factories.xform == NULL) return FALSE; | |
| 1878 | |
| 1879 | |
| 1880 fl = (_cmsTransformCollection*) _cmsPluginMalloc(ContextID, sizeof(_cmsTransformCollection)); | |
| 1881 if (fl == NULL) return FALSE; | |
| 1882 | |
| 1883 // Check for full xform plug-ins previous to 2.8, we would need an adapter in that case | |
| 1884 if (Plugin->base.ExpectedVersion < 2080) { | |
| 1885 | |
| 1886 fl->OldXform = TRUE; | |
| 1887 } | |
| 1888 else | |
| 1889 fl->OldXform = FALSE; | |
| 1890 | |
| 1891 // Copy the parameters | |
| 1892 fl->Factory = Plugin->factories.xform; | |
| 1893 | |
| 1894 // Keep linked list | |
| 1895 fl ->Next = ctx->TransformCollection; | |
| 1896 ctx->TransformCollection = fl; | |
| 1897 | |
| 1898 // All is ok | |
| 1899 return TRUE; | |
| 1900 } | |
| 1901 | |
| 1902 | |
| 1903 void CMSEXPORT _cmsSetTransformUserData(struct _cmstransform_struct *CMMcargo, void* ptr, _cmsFreeUserDataFn FreePrivateDataFn) | |
| 1904 { | |
| 1905 _cmsAssert(CMMcargo != NULL && CMMcargo->core != NULL); | |
| 1906 CMMcargo->core->UserData = ptr; | |
| 1907 CMMcargo->core->FreeUserData = FreePrivateDataFn; | |
| 1908 } | |
| 1909 | |
| 1910 // returns the pointer defined by the plug-in to store private data | |
| 1911 void * CMSEXPORT _cmsGetTransformUserData(struct _cmstransform_struct *CMMcargo) | |
| 1912 { | |
| 1913 _cmsAssert(CMMcargo != NULL && CMMcargo->core != NULL); | |
| 1914 return CMMcargo->core->UserData; | |
| 1915 } | |
| 1916 | |
| 1917 // returns the current formatters | |
| 1918 void CMSEXPORT _cmsGetTransformFormatters16(struct _cmstransform_struct *CMMcargo, cmsFormatter16* FromInput, cmsFormatter16* ToOutput) | |
| 1919 { | |
| 1920 _cmsAssert(CMMcargo != NULL); | |
| 1921 if (FromInput) *FromInput = CMMcargo ->FromInput; | |
| 1922 if (ToOutput) *ToOutput = CMMcargo ->ToOutput; | |
| 1923 } | |
| 1924 | |
| 1925 void CMSEXPORT _cmsGetTransformFormattersFloat(struct _cmstransform_struct *CMMcargo, cmsFormatterFloat* FromInput, cmsFormatterFloat* ToOutput) | |
| 1926 { | |
| 1927 _cmsAssert(CMMcargo != NULL); | |
| 1928 if (FromInput) *FromInput = CMMcargo ->FromInputFloat; | |
| 1929 if (ToOutput) *ToOutput = CMMcargo ->ToOutputFloat; | |
| 1930 } | |
| 1931 | |
| 1932 // returns original flags | |
| 1933 cmsUInt32Number CMSEXPORT _cmsGetTransformFlags(struct _cmstransform_struct* CMMcargo) | |
| 1934 { | |
| 1935 _cmsAssert(CMMcargo != NULL); | |
| 1936 return CMMcargo->core->dwOriginalFlags; | |
| 1937 } | |
| 1938 | |
| 1939 void | |
| 1940 _cmsFindFormatter(_cmsTRANSFORM* p, cmsUInt32Number InputFormat, cmsUInt32Number OutputFormat, cmsUInt32Number dwFlags) | |
| 1941 { | |
| 1942 if (dwFlags & cmsFLAGS_NULLTRANSFORM) { | |
| 1943 p ->xform = NullXFORM; | |
| 1944 return; | |
| 1945 } | |
| 1946 if (dwFlags & cmsFLAGS_PREMULT) { | |
| 1947 if (dwFlags & cmsFLAGS_NOCACHE) { | |
| 1948 if (dwFlags & cmsFLAGS_GAMUTCHECK) | |
| 1949 p ->xform = PrecalculatedXFORMGamutCheck_P; // Gamut check, no cache | |
| 1950 else if ((InputFormat & ~COLORSPACE_SH(31)) == (OutputFormat & ~COLORSPACE_SH(31)) && | |
| 1951 _cmsLutIsIdentity(p->core->Lut)) { | |
| 1952 if (T_PLANAR(InputFormat)) | |
| 1953 p ->xform = PrecalculatedXFORMIdentityPlanar; | |
| 1954 else | |
| 1955 p ->xform = PrecalculatedXFORMIdentity; | |
| 1956 } else | |
| 1957 p ->xform = PrecalculatedXFORM_P; // No cache, no gamut check | |
| 1958 return; | |
| 1959 } | |
| 1960 if (dwFlags & cmsFLAGS_GAMUTCHECK) { | |
| 1961 p ->xform = CachedXFORMGamutCheck_P; // Gamut check, cache | |
| 1962 return; | |
| 1963 } | |
| 1964 if ((InputFormat & ~COLORSPACE_SH(31)) == (OutputFormat & ~COLORSPACE_SH(31)) && | |
| 1965 _cmsLutIsIdentity(p->core->Lut)) { | |
| 1966 /* No point in a cache here! */ | |
| 1967 if (T_PLANAR(InputFormat)) | |
| 1968 p ->xform = PrecalculatedXFORMIdentityPlanar; | |
| 1969 else | |
| 1970 p ->xform = PrecalculatedXFORMIdentity; | |
| 1971 return; | |
| 1972 } | |
| 1973 } | |
| 1974 if (dwFlags & cmsFLAGS_NOCACHE) { | |
| 1975 if (dwFlags & cmsFLAGS_GAMUTCHECK) | |
| 1976 p ->xform = PrecalculatedXFORMGamutCheck; // Gamut check, no cache | |
| 1977 else if ((InputFormat & ~COLORSPACE_SH(31)) == (OutputFormat & ~COLORSPACE_SH(31)) && | |
| 1978 _cmsLutIsIdentity(p->core->Lut)) { | |
| 1979 if (T_PLANAR(InputFormat)) | |
| 1980 p ->xform = PrecalculatedXFORMIdentityPlanar; | |
| 1981 else | |
| 1982 p ->xform = PrecalculatedXFORMIdentity; | |
| 1983 } else | |
| 1984 p ->xform = PrecalculatedXFORM; // No cache, no gamut check | |
| 1985 return; | |
| 1986 } | |
| 1987 if (dwFlags & cmsFLAGS_GAMUTCHECK) { | |
| 1988 p ->xform = CachedXFORMGamutCheck; // Gamut check, cache | |
| 1989 return; | |
| 1990 } | |
| 1991 if ((InputFormat & ~COLORSPACE_SH(31)) == (OutputFormat & ~COLORSPACE_SH(31)) && | |
| 1992 _cmsLutIsIdentity(p->core->Lut)) { | |
| 1993 /* No point in a cache here! */ | |
| 1994 if (T_PLANAR(InputFormat)) | |
| 1995 p ->xform = PrecalculatedXFORMIdentityPlanar; | |
| 1996 else | |
| 1997 p ->xform = PrecalculatedXFORMIdentity; | |
| 1998 return; | |
| 1999 } | |
| 2000 if (T_EXTRA(InputFormat) == 1 && T_EXTRA(OutputFormat) == 1) { | |
| 2001 if (dwFlags & cmsFLAGS_PREMULT) { | |
| 2002 if ((InputFormat & ~(COLORSPACE_SH(31)|CHANNELS_SH(7)|BYTES_SH(3)|EXTRA_SH(1))) == 0 && | |
| 2003 (OutputFormat & ~(COLORSPACE_SH(31)|CHANNELS_SH(7)|BYTES_SH(3)|EXTRA_SH(1))) == 0) { | |
| 2004 switch ((InputFormat & (CHANNELS_SH(7)|BYTES_SH(3)))| | |
| 2005 ((OutputFormat & (CHANNELS_SH(7)|BYTES_SH(3)))<<6)) { | |
| 2006 case CHANNELS_SH(1) | BYTES_SH(1) | ((CHANNELS_SH(1) | BYTES_SH(1))<<6): | |
| 2007 p->xform = CachedXFORM1to1_P1; | |
| 2008 return; | |
| 2009 case CHANNELS_SH(1) | BYTES_SH(2) | ((CHANNELS_SH(1) | BYTES_SH(2))<<6): | |
| 2010 p->xform = CachedXFORM1x2to1x2_P2; | |
| 2011 return; | |
| 2012 case CHANNELS_SH(1) | BYTES_SH(1) | ((CHANNELS_SH(3) | BYTES_SH(1))<<6): | |
| 2013 p->xform = CachedXFORM1to3_P1; | |
| 2014 return; | |
| 2015 case CHANNELS_SH(1) | BYTES_SH(2) | ((CHANNELS_SH(3) | BYTES_SH(2))<<6): | |
| 2016 p->xform = CachedXFORM1x2to3x2_P2; | |
| 2017 return; | |
| 2018 case CHANNELS_SH(1) | BYTES_SH(1) | ((CHANNELS_SH(4) | BYTES_SH(1))<<6): | |
| 2019 p->xform = CachedXFORM1to4_P1; | |
| 2020 return; | |
| 2021 case CHANNELS_SH(1) | BYTES_SH(2) | ((CHANNELS_SH(4) | BYTES_SH(2))<<6): | |
| 2022 p->xform = CachedXFORM1x2to4x2_P2; | |
| 2023 return; | |
| 2024 case CHANNELS_SH(3) | BYTES_SH(1) | ((CHANNELS_SH(1) | BYTES_SH(1))<<6): | |
| 2025 p ->xform = CachedXFORM3to1_P1; | |
| 2026 return; | |
| 2027 case CHANNELS_SH(3) | BYTES_SH(2) | ((CHANNELS_SH(1) | BYTES_SH(2))<<6): | |
| 2028 p ->xform = CachedXFORM3x2to1x2_P2; | |
| 2029 return; | |
| 2030 case CHANNELS_SH(3) | BYTES_SH(1) | ((CHANNELS_SH(3) | BYTES_SH(1))<<6): | |
| 2031 p->xform = CachedXFORM3to3_P1; | |
| 2032 return; | |
| 2033 case CHANNELS_SH(3) | BYTES_SH(2) | ((CHANNELS_SH(3) | BYTES_SH(2))<<6): | |
| 2034 p->xform = CachedXFORM3x2to3x2_P2; | |
| 2035 return; | |
| 2036 case CHANNELS_SH(3) | BYTES_SH(1) | ((CHANNELS_SH(4) | BYTES_SH(1))<<6): | |
| 2037 p->xform = CachedXFORM3to4_P1; | |
| 2038 return; | |
| 2039 case CHANNELS_SH(3) | BYTES_SH(2) | ((CHANNELS_SH(4) | BYTES_SH(2))<<6): | |
| 2040 p->xform = CachedXFORM3x2to4x2_P2; | |
| 2041 return; | |
| 2042 case CHANNELS_SH(4) | BYTES_SH(1) | ((CHANNELS_SH(1) | BYTES_SH(1))<<6): | |
| 2043 p->xform = CachedXFORM4to1_P1; | |
| 2044 return; | |
| 2045 case CHANNELS_SH(4) | BYTES_SH(2) | ((CHANNELS_SH(1) | BYTES_SH(2))<<6): | |
| 2046 p->xform = CachedXFORM4x2to1x2_P2; | |
| 2047 return; | |
| 2048 case CHANNELS_SH(4) | BYTES_SH(1) | ((CHANNELS_SH(3) | BYTES_SH(1))<<6): | |
| 2049 p->xform = CachedXFORM4to3_P1; | |
| 2050 return; | |
| 2051 case CHANNELS_SH(4) | BYTES_SH(2) | ((CHANNELS_SH(3) | BYTES_SH(2))<<6): | |
| 2052 p->xform = CachedXFORM4x2to3x2_P2; | |
| 2053 return; | |
| 2054 case CHANNELS_SH(4) | BYTES_SH(1) | ((CHANNELS_SH(4) | BYTES_SH(1))<<6): | |
| 2055 p->xform = CachedXFORM4to4_P1; | |
| 2056 return; | |
| 2057 case CHANNELS_SH(4) | BYTES_SH(2) | ((CHANNELS_SH(4) | BYTES_SH(2))<<6): | |
| 2058 p->xform = CachedXFORM4x2to4x2_P2; | |
| 2059 return; | |
| 2060 } | |
| 2061 } | |
| 2062 } else { | |
| 2063 if ((InputFormat & ~(COLORSPACE_SH(31)|CHANNELS_SH(7)|BYTES_SH(3)|EXTRA_SH(1))) == 0 && | |
| 2064 (OutputFormat & ~(COLORSPACE_SH(31)|CHANNELS_SH(7)|BYTES_SH(3)|EXTRA_SH(1))) == 0) { | |
| 2065 switch ((InputFormat & (CHANNELS_SH(7)|BYTES_SH(3)))| | |
| 2066 ((OutputFormat & (CHANNELS_SH(7)|BYTES_SH(3)))<<6)) { | |
| 2067 case CHANNELS_SH(1) | BYTES_SH(1) | ((CHANNELS_SH(1) | BYTES_SH(1))<<6): | |
| 2068 p->xform = CachedXFORM1to1_1; | |
| 2069 return; | |
| 2070 case CHANNELS_SH(1) | BYTES_SH(2) | ((CHANNELS_SH(1) | BYTES_SH(2))<<6): | |
| 2071 p->xform = CachedXFORM1x2to1x2_2; | |
| 2072 return; | |
| 2073 case CHANNELS_SH(1) | BYTES_SH(1) | ((CHANNELS_SH(3) | BYTES_SH(1))<<6): | |
| 2074 p->xform = CachedXFORM1to3_1; | |
| 2075 return; | |
| 2076 case CHANNELS_SH(1) | BYTES_SH(2) | ((CHANNELS_SH(3) | BYTES_SH(2))<<6): | |
| 2077 p->xform = CachedXFORM1x2to3x2_2; | |
| 2078 return; | |
| 2079 case CHANNELS_SH(1) | BYTES_SH(1) | ((CHANNELS_SH(4) | BYTES_SH(1))<<6): | |
| 2080 p->xform = CachedXFORM1to4_1; | |
| 2081 return; | |
| 2082 case CHANNELS_SH(1) | BYTES_SH(2) | ((CHANNELS_SH(4) | BYTES_SH(2))<<6): | |
| 2083 p->xform = CachedXFORM1x2to4x2_2; | |
| 2084 return; | |
| 2085 case CHANNELS_SH(3) | BYTES_SH(1) | ((CHANNELS_SH(1) | BYTES_SH(1))<<6): | |
| 2086 p ->xform = CachedXFORM3to1_1; | |
| 2087 return; | |
| 2088 case CHANNELS_SH(3) | BYTES_SH(2) | ((CHANNELS_SH(1) | BYTES_SH(2))<<6): | |
| 2089 p ->xform = CachedXFORM3x2to1x2_2; | |
| 2090 return; | |
| 2091 case CHANNELS_SH(3) | BYTES_SH(1) | ((CHANNELS_SH(3) | BYTES_SH(1))<<6): | |
| 2092 p->xform = CachedXFORM3to3_1; | |
| 2093 return; | |
| 2094 case CHANNELS_SH(3) | BYTES_SH(2) | ((CHANNELS_SH(3) | BYTES_SH(2))<<6): | |
| 2095 p->xform = CachedXFORM3x2to3x2_2; | |
| 2096 return; | |
| 2097 case CHANNELS_SH(3) | BYTES_SH(1) | ((CHANNELS_SH(4) | BYTES_SH(1))<<6): | |
| 2098 p->xform = CachedXFORM3to4_1; | |
| 2099 return; | |
| 2100 case CHANNELS_SH(3) | BYTES_SH(2) | ((CHANNELS_SH(4) | BYTES_SH(2))<<6): | |
| 2101 p->xform = CachedXFORM3x2to4x2_2; | |
| 2102 return; | |
| 2103 case CHANNELS_SH(4) | BYTES_SH(1) | ((CHANNELS_SH(1) | BYTES_SH(1))<<6): | |
| 2104 p->xform = CachedXFORM4to1_1; | |
| 2105 return; | |
| 2106 case CHANNELS_SH(4) | BYTES_SH(2) | ((CHANNELS_SH(1) | BYTES_SH(2))<<6): | |
| 2107 p->xform = CachedXFORM4x2to1x2_2; | |
| 2108 return; | |
| 2109 case CHANNELS_SH(4) | BYTES_SH(1) | ((CHANNELS_SH(3) | BYTES_SH(1))<<6): | |
| 2110 p->xform = CachedXFORM4to3_1; | |
| 2111 return; | |
| 2112 case CHANNELS_SH(4) | BYTES_SH(2) | ((CHANNELS_SH(3) | BYTES_SH(2))<<6): | |
| 2113 p->xform = CachedXFORM4x2to3x2_2; | |
| 2114 return; | |
| 2115 case CHANNELS_SH(4) | BYTES_SH(1) | ((CHANNELS_SH(4) | BYTES_SH(1))<<6): | |
| 2116 p->xform = CachedXFORM4to4_1; | |
| 2117 return; | |
| 2118 case CHANNELS_SH(4) | BYTES_SH(2) | ((CHANNELS_SH(4) | BYTES_SH(2))<<6): | |
| 2119 p->xform = CachedXFORM4x2to4x2_2; | |
| 2120 return; | |
| 2121 } | |
| 2122 } | |
| 2123 } | |
| 2124 } | |
| 2125 if (T_EXTRA(InputFormat) != 0) { | |
| 2126 if (dwFlags & cmsFLAGS_PREMULT) { | |
| 2127 if (T_BYTES(InputFormat) == 1) | |
| 2128 p ->xform = CachedXFORM_P1;// No gamut check, cache | |
| 2129 else | |
| 2130 p ->xform = CachedXFORM_P2;// No gamut check, cache | |
| 2131 } else { | |
| 2132 p ->xform = CachedXFORM; // No gamut check, cache | |
| 2133 } | |
| 2134 return; | |
| 2135 } | |
| 2136 if ((InputFormat & ~(COLORSPACE_SH(31)|CHANNELS_SH(7)|BYTES_SH(3))) == 0 && | |
| 2137 (OutputFormat & ~(COLORSPACE_SH(31)|CHANNELS_SH(7)|BYTES_SH(3))) == 0) { | |
| 2138 switch ((InputFormat & (CHANNELS_SH(7)|BYTES_SH(3)))| | |
| 2139 ((OutputFormat & (CHANNELS_SH(7)|BYTES_SH(3)))<<6)) { | |
| 2140 case CHANNELS_SH(1) | BYTES_SH(1) | ((CHANNELS_SH(1) | BYTES_SH(1))<<6): | |
| 2141 p->xform = CachedXFORM1to1; | |
| 2142 return; | |
| 2143 case CHANNELS_SH(1) | BYTES_SH(2) | ((CHANNELS_SH(1) | BYTES_SH(2))<<6): | |
| 2144 p->xform = CachedXFORM1x2to1x2; | |
| 2145 return; | |
| 2146 case CHANNELS_SH(1) | BYTES_SH(1) | ((CHANNELS_SH(3) | BYTES_SH(1))<<6): | |
| 2147 p->xform = CachedXFORM1to3; | |
| 2148 return; | |
| 2149 case CHANNELS_SH(1) | BYTES_SH(2) | ((CHANNELS_SH(3) | BYTES_SH(2))<<6): | |
| 2150 p->xform = CachedXFORM1x2to3x2; | |
| 2151 return; | |
| 2152 case CHANNELS_SH(1) | BYTES_SH(1) | ((CHANNELS_SH(4) | BYTES_SH(1))<<6): | |
| 2153 p->xform = CachedXFORM1to4; | |
| 2154 return; | |
| 2155 case CHANNELS_SH(1) | BYTES_SH(2) | ((CHANNELS_SH(4) | BYTES_SH(2))<<6): | |
| 2156 p->xform = CachedXFORM1x2to4x2; | |
| 2157 return; | |
| 2158 case CHANNELS_SH(3) | BYTES_SH(1) | ((CHANNELS_SH(1) | BYTES_SH(1))<<6): | |
| 2159 p ->xform = CachedXFORM3to1; | |
| 2160 return; | |
| 2161 case CHANNELS_SH(3) | BYTES_SH(2) | ((CHANNELS_SH(1) | BYTES_SH(2))<<6): | |
| 2162 p ->xform = CachedXFORM3x2to1x2; | |
| 2163 return; | |
| 2164 case CHANNELS_SH(3) | BYTES_SH(1) | ((CHANNELS_SH(3) | BYTES_SH(1))<<6): | |
| 2165 p->xform = CachedXFORM3to3; | |
| 2166 return; | |
| 2167 case CHANNELS_SH(3) | BYTES_SH(2) | ((CHANNELS_SH(3) | BYTES_SH(2))<<6): | |
| 2168 p->xform = CachedXFORM3x2to3x2; | |
| 2169 return; | |
| 2170 case CHANNELS_SH(3) | BYTES_SH(1) | ((CHANNELS_SH(4) | BYTES_SH(1))<<6): | |
| 2171 p->xform = CachedXFORM3to4; | |
| 2172 return; | |
| 2173 case CHANNELS_SH(3) | BYTES_SH(2) | ((CHANNELS_SH(4) | BYTES_SH(2))<<6): | |
| 2174 p->xform = CachedXFORM3x2to4x2; | |
| 2175 return; | |
| 2176 case CHANNELS_SH(4) | BYTES_SH(1) | ((CHANNELS_SH(1) | BYTES_SH(1))<<6): | |
| 2177 p->xform = CachedXFORM4to1; | |
| 2178 return; | |
| 2179 case CHANNELS_SH(4) | BYTES_SH(2) | ((CHANNELS_SH(1) | BYTES_SH(2))<<6): | |
| 2180 p->xform = CachedXFORM4x2to1x2; | |
| 2181 return; | |
| 2182 case CHANNELS_SH(4) | BYTES_SH(1) | ((CHANNELS_SH(3) | BYTES_SH(1))<<6): | |
| 2183 p->xform = CachedXFORM4to3; | |
| 2184 return; | |
| 2185 case CHANNELS_SH(4) | BYTES_SH(2) | ((CHANNELS_SH(3) | BYTES_SH(2))<<6): | |
| 2186 p->xform = CachedXFORM4x2to3x2; | |
| 2187 return; | |
| 2188 case CHANNELS_SH(4) | BYTES_SH(1) | ((CHANNELS_SH(4) | BYTES_SH(1))<<6): | |
| 2189 p->xform = CachedXFORM4to4; | |
| 2190 return; | |
| 2191 case CHANNELS_SH(4) | BYTES_SH(2) | ((CHANNELS_SH(4) | BYTES_SH(2))<<6): | |
| 2192 p->xform = CachedXFORM4x2to4x2; | |
| 2193 return; | |
| 2194 } | |
| 2195 } | |
| 2196 { | |
| 2197 int inwords = T_CHANNELS(InputFormat); | |
| 2198 if (inwords <= 2) | |
| 2199 p ->xform = CachedXFORM4; | |
| 2200 else if (inwords <= 4) | |
| 2201 p ->xform = CachedXFORM8; | |
| 2202 else | |
| 2203 p ->xform = CachedXFORM; // No gamut check, cache | |
| 2204 } | |
| 2205 } | |
| 2206 | |
| 2207 // Returns the worker callback for parallelization plug-ins | |
| 2208 _cmsTransform2Fn CMSEXPORT _cmsGetTransformWorker(struct _cmstransform_struct* CMMcargo) | |
| 2209 { | |
| 2210 _cmsAssert(CMMcargo != NULL); | |
| 2211 return CMMcargo->Worker; | |
| 2212 } | |
| 2213 | |
| 2214 // This field holds maximum number of workers or -1 to auto | |
| 2215 cmsInt32Number CMSEXPORT _cmsGetTransformMaxWorkers(struct _cmstransform_struct* CMMcargo) | |
| 2216 { | |
| 2217 _cmsAssert(CMMcargo != NULL); | |
| 2218 return CMMcargo->MaxWorkers; | |
| 2219 } | |
| 2220 | |
| 2221 // This field is actually unused and reserved | |
| 2222 cmsUInt32Number CMSEXPORT _cmsGetTransformWorkerFlags(struct _cmstransform_struct* CMMcargo) | |
| 2223 { | |
| 2224 _cmsAssert(CMMcargo != NULL); | |
| 2225 return CMMcargo->WorkerFlags; | |
| 2226 } | |
| 2227 | |
| 2228 // In the case there is a parallelization plug-in, let it to do its job | |
| 2229 static | |
| 2230 void ParalellizeIfSuitable(cmsContext ContextID, _cmsTRANSFORM* p) | |
| 2231 { | |
| 2232 _cmsParallelizationPluginChunkType* ctx = (_cmsParallelizationPluginChunkType*)_cmsContextGetClientChunk(ContextID, ParallelizationPlugin); | |
| 2233 | |
| 2234 _cmsAssert(p != NULL); | |
| 2235 if (ctx != NULL && ctx->SchedulerFn != NULL) { | |
| 2236 | |
| 2237 p->Worker = p->xform; | |
| 2238 p->xform = ctx->SchedulerFn; | |
| 2239 p->MaxWorkers = ctx->MaxWorkers; | |
| 2240 p->WorkerFlags = ctx->WorkerFlags; | |
| 2241 } | |
| 2242 } | |
| 2243 | |
| 2244 | |
| 2245 /** | |
| 2246 * An empty unroll to avoid a check with NULL on cmsDoTransform() | |
| 2247 */ | |
| 2248 static | |
| 2249 cmsUInt8Number* UnrollNothing(cmsContext ContextID, | |
| 2250 CMSREGISTER _cmsTRANSFORM* info, | |
| 2251 CMSREGISTER cmsUInt16Number wIn[], | |
| 2252 CMSREGISTER cmsUInt8Number* accum, | |
| 2253 CMSREGISTER cmsUInt32Number Stride) | |
| 2254 { | |
| 2255 return accum; | |
| 2256 | |
| 2257 cmsUNUSED_PARAMETER(ContextID); | |
| 2258 cmsUNUSED_PARAMETER(info); | |
| 2259 cmsUNUSED_PARAMETER(wIn); | |
| 2260 cmsUNUSED_PARAMETER(Stride); | |
| 2261 } | |
| 2262 | |
| 2263 static | |
| 2264 cmsUInt8Number* PackNothing(cmsContext ContextID, | |
| 2265 CMSREGISTER _cmsTRANSFORM* info, | |
| 2266 CMSREGISTER cmsUInt16Number wOut[], | |
| 2267 CMSREGISTER cmsUInt8Number* output, | |
| 2268 CMSREGISTER cmsUInt32Number Stride) | |
| 2269 { | |
| 2270 return output; | |
| 2271 | |
| 2272 cmsUNUSED_PARAMETER(ContextID); | |
| 2273 cmsUNUSED_PARAMETER(info); | |
| 2274 cmsUNUSED_PARAMETER(wOut); | |
| 2275 cmsUNUSED_PARAMETER(Stride); | |
| 2276 } | |
| 2277 | |
| 2278 // Allocate transform struct and set it to defaults. Ask the optimization plug-in about if those formats are proper | |
| 2279 // for separated transforms. If this is the case, | |
| 2280 static | |
| 2281 _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut, | |
| 2282 cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags) | |
| 2283 { | |
| 2284 _cmsTransformPluginChunkType* ctx = ( _cmsTransformPluginChunkType*) _cmsContextGetClientChunk(ContextID, TransformPlugin); | |
| 2285 _cmsTransformCollection* Plugin; | |
| 2286 _cmsTRANSFORMCORE *core; | |
| 2287 | |
| 2288 // Allocate needed memory | |
| 2289 _cmsTRANSFORM* p = (_cmsTRANSFORM*)_cmsMallocZero(ContextID, sizeof(_cmsTRANSFORM)); | |
| 2290 if (!p) { | |
| 2291 cmsPipelineFree(ContextID, lut); | |
| 2292 return NULL; | |
| 2293 } | |
| 2294 | |
| 2295 core = (_cmsTRANSFORMCORE*)_cmsMallocZero(ContextID, sizeof(*core)); | |
| 2296 if (!core) { | |
| 2297 _cmsFree(ContextID, p); | |
| 2298 cmsPipelineFree(ContextID, lut); | |
| 2299 return NULL; | |
| 2300 } | |
| 2301 | |
| 2302 p->core = core; | |
| 2303 core->refs = 1; | |
| 2304 // Store the proposed pipeline | |
| 2305 p->core->Lut = lut; | |
| 2306 | |
| 2307 // Let's see if any plug-in want to do the transform by itself | |
| 2308 if (core->Lut != NULL) { | |
| 2309 if (!(*dwFlags & cmsFLAGS_NOOPTIMIZE)) { | |
| 2310 | |
| 2311 for (Plugin = ctx->TransformCollection; | |
| 2312 Plugin != NULL; | |
| 2313 Plugin = Plugin->Next) { | |
| 2314 | |
| 2315 if (Plugin->Factory(ContextID, &p->xform, &core->UserData, &core->FreeUserData, &core->Lut, InputFormat, OutputFormat, dwFlags)) { | |
| 2316 | |
| 2317 // Last plugin in the declaration order takes control. We just keep | |
| 2318 // the original parameters as a logging. | |
| 2319 // Note that cmsFLAGS_CAN_CHANGE_FORMATTER is not set, so by default | |
| 2320 // an optimized transform is not reusable. The plug-in can, however, change | |
| 2321 // the flags and make it suitable. | |
| 2322 | |
| 2323 p->InputFormat = *InputFormat; | |
| 2324 p->OutputFormat = *OutputFormat; | |
| 2325 core->dwOriginalFlags = *dwFlags; | |
| 2326 | |
| 2327 // Fill the formatters just in case the optimized routine is interested. | |
| 2328 // No error is thrown if the formatter doesn't exist. It is up to the optimization | |
| 2329 // factory to decide what to do in those cases. | |
| 2330 p->FromInput = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16; | |
| 2331 p->ToOutput = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16; | |
| 2332 p->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat; | |
| 2333 p->ToOutputFloat = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat; | |
| 2334 | |
| 2335 // Save the day? (Ignore the warning) | |
| 2336 if (Plugin->OldXform) { | |
| 2337 p->OldXform = (_cmsTransformFn)(void*) p->xform; | |
| 2338 p->xform = _cmsTransform2toTransformAdaptor; | |
| 2339 } | |
| 2340 | |
| 2341 ParalellizeIfSuitable(ContextID, p); | |
| 2342 return p; | |
| 2343 } | |
| 2344 } | |
| 2345 } | |
| 2346 | |
| 2347 // Not suitable for the transform plug-in, let's check the pipeline plug-in | |
| 2348 _cmsOptimizePipeline(ContextID, &core->Lut, Intent, InputFormat, OutputFormat, dwFlags); | |
| 2349 } | |
| 2350 | |
| 2351 // Check whatever this is a true floating point transform | |
| 2352 if (_cmsFormatterIsFloat(*InputFormat) || _cmsFormatterIsFloat(*OutputFormat)) { | |
| 2353 | |
| 2354 // Get formatter function always return a valid union, but the contents of this union may be NULL. | |
| 2355 p ->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat; | |
| 2356 p ->ToOutputFloat = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat; | |
| 2357 *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER; | |
| 2358 | |
| 2359 if (p ->FromInputFloat == NULL || p ->ToOutputFloat == NULL) { | |
| 2360 | |
| 2361 cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format"); | |
| 2362 cmsDeleteTransform(ContextID, p); | |
| 2363 return NULL; | |
| 2364 } | |
| 2365 | |
| 2366 if (*dwFlags & cmsFLAGS_NULLTRANSFORM) { | |
| 2367 | |
| 2368 p ->xform = NullFloatXFORM; | |
| 2369 } | |
| 2370 else { | |
| 2371 // Float transforms don't use cache, always are non-NULL | |
| 2372 p ->xform = FloatXFORM; | |
| 2373 } | |
| 2374 | |
| 2375 } | |
| 2376 else { | |
| 2377 | |
| 2378 // Formats are intended to be changed before use | |
| 2379 if (*InputFormat == 0 && *OutputFormat == 0) { | |
| 2380 p->FromInput = UnrollNothing; | |
| 2381 p->ToOutput = PackNothing; | |
| 2382 *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER; | |
| 2383 } | |
| 2384 else { | |
| 2385 | |
| 2386 cmsUInt32Number BytesPerPixelInput; | |
| 2387 | |
| 2388 p ->FromInput = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16; | |
| 2389 p ->ToOutput = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16; | |
| 2390 | |
| 2391 if (p ->FromInput == NULL || p ->ToOutput == NULL) { | |
| 2392 | |
| 2393 cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format"); | |
| 2394 cmsDeleteTransform(ContextID, p); | |
| 2395 return NULL; | |
| 2396 } | |
| 2397 | |
| 2398 BytesPerPixelInput = T_BYTES(*InputFormat); | |
| 2399 if (BytesPerPixelInput == 0 || BytesPerPixelInput >= 2) | |
| 2400 *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER; | |
| 2401 | |
| 2402 } | |
| 2403 | |
| 2404 _cmsFindFormatter(p, *InputFormat, *OutputFormat, *dwFlags); | |
| 2405 } | |
| 2406 | |
| 2407 /** | |
| 2408 * Check consistency for alpha channel copy | |
| 2409 */ | |
| 2410 if (*dwFlags & cmsFLAGS_COPY_ALPHA) | |
| 2411 { | |
| 2412 if (T_EXTRA(*InputFormat) != T_EXTRA(*OutputFormat)) | |
| 2413 { | |
| 2414 cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Mismatched alpha channels"); | |
| 2415 cmsDeleteTransform(ContextID, p); | |
| 2416 return NULL; | |
| 2417 } | |
| 2418 } | |
| 2419 | |
| 2420 p ->InputFormat = *InputFormat; | |
| 2421 p ->OutputFormat = *OutputFormat; | |
| 2422 core->dwOriginalFlags = *dwFlags; | |
| 2423 core->UserData = NULL; | |
| 2424 ParalellizeIfSuitable(ContextID, p); | |
| 2425 return p; | |
| 2426 } | |
| 2427 | |
| 2428 static | |
| 2429 cmsBool GetXFormColorSpaces(cmsContext ContextID, cmsUInt32Number nProfiles, cmsHPROFILE hProfiles[], cmsColorSpaceSignature* Input, cmsColorSpaceSignature* Output) | |
| 2430 { | |
| 2431 cmsColorSpaceSignature ColorSpaceIn, ColorSpaceOut; | |
| 2432 cmsColorSpaceSignature PostColorSpace; | |
| 2433 cmsUInt32Number i; | |
| 2434 | |
| 2435 if (nProfiles == 0) return FALSE; | |
| 2436 if (hProfiles[0] == NULL) return FALSE; | |
| 2437 | |
| 2438 *Input = PostColorSpace = cmsGetColorSpace(ContextID, hProfiles[0]); | |
| 2439 | |
| 2440 for (i=0; i < nProfiles; i++) { | |
| 2441 | |
| 2442 cmsProfileClassSignature cls; | |
| 2443 cmsHPROFILE hProfile = hProfiles[i]; | |
| 2444 | |
| 2445 int lIsInput = (PostColorSpace != cmsSigXYZData) && | |
| 2446 (PostColorSpace != cmsSigLabData); | |
| 2447 | |
| 2448 if (hProfile == NULL) return FALSE; | |
| 2449 | |
| 2450 cls = cmsGetDeviceClass(ContextID, hProfile); | |
| 2451 | |
| 2452 if (cls == cmsSigNamedColorClass) { | |
| 2453 | |
| 2454 ColorSpaceIn = cmsSig1colorData; | |
| 2455 ColorSpaceOut = (nProfiles > 1) ? cmsGetPCS(ContextID, hProfile) : cmsGetColorSpace(ContextID, hProfile); | |
| 2456 } | |
| 2457 else | |
| 2458 if (lIsInput || (cls == cmsSigLinkClass)) { | |
| 2459 | |
| 2460 ColorSpaceIn = cmsGetColorSpace(ContextID, hProfile); | |
| 2461 ColorSpaceOut = cmsGetPCS(ContextID, hProfile); | |
| 2462 } | |
| 2463 else | |
| 2464 { | |
| 2465 ColorSpaceIn = cmsGetPCS(ContextID, hProfile); | |
| 2466 ColorSpaceOut = cmsGetColorSpace(ContextID, hProfile); | |
| 2467 } | |
| 2468 | |
| 2469 if (i==0) | |
| 2470 *Input = ColorSpaceIn; | |
| 2471 | |
| 2472 PostColorSpace = ColorSpaceOut; | |
| 2473 } | |
| 2474 | |
| 2475 *Output = PostColorSpace; | |
| 2476 | |
| 2477 return TRUE; | |
| 2478 } | |
| 2479 | |
| 2480 // Check colorspace | |
| 2481 static | |
| 2482 cmsBool IsProperColorSpace(cmsContext ContextID, cmsColorSpaceSignature Check, cmsUInt32Number dwFormat) | |
| 2483 { | |
| 2484 int Space1 = (int) T_COLORSPACE(dwFormat); | |
| 2485 int Space2 = _cmsLCMScolorSpace(ContextID, Check); | |
| 2486 | |
| 2487 if (Space1 == PT_ANY) return TRUE; | |
| 2488 if (Space1 == Space2) return TRUE; | |
| 2489 | |
| 2490 if (Space1 == PT_LabV2 && Space2 == PT_Lab) return TRUE; | |
| 2491 if (Space1 == PT_Lab && Space2 == PT_LabV2) return TRUE; | |
| 2492 | |
| 2493 return FALSE; | |
| 2494 } | |
| 2495 | |
| 2496 // ---------------------------------------------------------------------------------------------------------------- | |
| 2497 | |
| 2498 // Jun-21-2000: Some profiles (those that comes with W2K) comes | |
| 2499 // with the media white (media black?) x 100. Add a sanity check | |
| 2500 | |
| 2501 static | |
| 2502 void NormalizeXYZ(cmsCIEXYZ* Dest) | |
| 2503 { | |
| 2504 while (Dest -> X > 2. && | |
| 2505 Dest -> Y > 2. && | |
| 2506 Dest -> Z > 2.) { | |
| 2507 | |
| 2508 Dest -> X /= 10.; | |
| 2509 Dest -> Y /= 10.; | |
| 2510 Dest -> Z /= 10.; | |
| 2511 } | |
| 2512 } | |
| 2513 | |
| 2514 static | |
| 2515 void SetWhitePoint(cmsCIEXYZ* wtPt, const cmsCIEXYZ* src) | |
| 2516 { | |
| 2517 if (src == NULL) { | |
| 2518 wtPt ->X = cmsD50X; | |
| 2519 wtPt ->Y = cmsD50Y; | |
| 2520 wtPt ->Z = cmsD50Z; | |
| 2521 } | |
| 2522 else { | |
| 2523 wtPt ->X = src->X; | |
| 2524 wtPt ->Y = src->Y; | |
| 2525 wtPt ->Z = src->Z; | |
| 2526 | |
| 2527 NormalizeXYZ(wtPt); | |
| 2528 } | |
| 2529 | |
| 2530 } | |
| 2531 | |
| 2532 // New to lcms 2.0 -- have all parameters available. | |
| 2533 cmsHTRANSFORM CMSEXPORT cmsCreateExtendedTransform(cmsContext ContextID, | |
| 2534 cmsUInt32Number nProfiles, cmsHPROFILE hProfiles[], | |
| 2535 cmsBool BPC[], | |
| 2536 cmsUInt32Number Intents[], | |
| 2537 cmsFloat64Number AdaptationStates[], | |
| 2538 cmsHPROFILE hGamutProfile, | |
| 2539 cmsUInt32Number nGamutPCSposition, | |
| 2540 cmsUInt32Number InputFormat, | |
| 2541 cmsUInt32Number OutputFormat, | |
| 2542 cmsUInt32Number dwFlags) | |
| 2543 { | |
| 2544 _cmsTRANSFORM* xform; | |
| 2545 cmsColorSpaceSignature EntryColorSpace; | |
| 2546 cmsColorSpaceSignature ExitColorSpace; | |
| 2547 cmsPipeline* Lut; | |
| 2548 cmsUInt32Number LastIntent = Intents[nProfiles-1]; | |
| 2549 | |
| 2550 // If it is a fake transform | |
| 2551 if (dwFlags & cmsFLAGS_NULLTRANSFORM) | |
| 2552 { | |
| 2553 return AllocEmptyTransform(ContextID, NULL, INTENT_PERCEPTUAL, &InputFormat, &OutputFormat, &dwFlags); | |
| 2554 } | |
| 2555 | |
| 2556 // If gamut check is requested, make sure we have a gamut profile | |
| 2557 if (dwFlags & cmsFLAGS_GAMUTCHECK) { | |
| 2558 if (hGamutProfile == NULL) dwFlags &= ~cmsFLAGS_GAMUTCHECK; | |
| 2559 } | |
| 2560 | |
| 2561 // On floating point transforms, inhibit cache | |
| 2562 if (_cmsFormatterIsFloat(InputFormat) || _cmsFormatterIsFloat(OutputFormat)) | |
| 2563 dwFlags |= cmsFLAGS_NOCACHE; | |
| 2564 | |
| 2565 // Mark entry/exit spaces | |
| 2566 if (!GetXFormColorSpaces(ContextID, nProfiles, hProfiles, &EntryColorSpace, &ExitColorSpace)) { | |
| 2567 cmsSignalError(ContextID, cmsERROR_NULL, "NULL input profiles on transform"); | |
| 2568 return NULL; | |
| 2569 } | |
| 2570 | |
| 2571 // Check if proper colorspaces | |
| 2572 if (!IsProperColorSpace(ContextID, EntryColorSpace, InputFormat)) { | |
| 2573 cmsSignalError(ContextID, cmsERROR_COLORSPACE_CHECK, "Wrong input color space on transform"); | |
| 2574 return NULL; | |
| 2575 } | |
| 2576 | |
| 2577 if (!IsProperColorSpace(ContextID, ExitColorSpace, OutputFormat)) { | |
| 2578 cmsSignalError(ContextID, cmsERROR_COLORSPACE_CHECK, "Wrong output color space on transform"); | |
| 2579 return NULL; | |
| 2580 } | |
| 2581 | |
| 2582 // Check whatever the transform is 16 bits and involves linear RGB in first profile. If so, disable optimizations | |
| 2583 if (EntryColorSpace == cmsSigRgbData && T_BYTES(InputFormat) == 2 && !(dwFlags & cmsFLAGS_NOOPTIMIZE)) | |
| 2584 { | |
| 2585 cmsFloat64Number gamma = cmsDetectRGBProfileGamma(ContextID, hProfiles[0], 0.1); | |
| 2586 | |
| 2587 if (gamma > 0 && gamma < 1.6) | |
| 2588 dwFlags |= cmsFLAGS_NOOPTIMIZE; | |
| 2589 } | |
| 2590 | |
| 2591 // Create a pipeline with all transformations | |
| 2592 Lut = _cmsLinkProfiles(ContextID, nProfiles, Intents, hProfiles, BPC, AdaptationStates, dwFlags); | |
| 2593 if (Lut == NULL) { | |
| 2594 cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Couldn't link the profiles"); | |
| 2595 return NULL; | |
| 2596 } | |
| 2597 | |
| 2598 // Check channel count | |
| 2599 if ((cmsChannelsOfColorSpace(ContextID, EntryColorSpace) != (cmsInt32Number) cmsPipelineInputChannels(ContextID, Lut)) || | |
| 2600 (cmsChannelsOfColorSpace(ContextID, ExitColorSpace) != (cmsInt32Number) cmsPipelineOutputChannels(ContextID, Lut))) { | |
| 2601 cmsPipelineFree(ContextID, Lut); | |
| 2602 cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Channel count doesn't match. Profile is corrupted"); | |
| 2603 return NULL; | |
| 2604 } | |
| 2605 | |
| 2606 // Check premultiplication requirements | |
| 2607 if (dwFlags & cmsFLAGS_PREMULT) { | |
| 2608 if (T_BYTES(InputFormat) != T_BYTES(OutputFormat)) { | |
| 2609 cmsPipelineFree(ContextID, Lut); | |
| 2610 cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Premultiplication requires input and output to be in the same format."); | |
| 2611 return NULL; | |
| 2612 } | |
| 2613 | |
| 2614 if (T_EXTRA(InputFormat) < 1 || T_EXTRA(OutputFormat) < 1 || T_EXTRA(InputFormat) != T_EXTRA(OutputFormat) || (dwFlags & cmsFLAGS_COPY_ALPHA) == 0) { | |
| 2615 cmsPipelineFree(ContextID, Lut); | |
| 2616 cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Premultiplication must preserve the extra channels"); | |
| 2617 return NULL; | |
| 2618 } | |
| 2619 } | |
| 2620 | |
| 2621 | |
| 2622 // All seems ok | |
| 2623 xform = AllocEmptyTransform(ContextID, Lut, LastIntent, &InputFormat, &OutputFormat, &dwFlags); | |
| 2624 if (xform == NULL) { | |
| 2625 return NULL; | |
| 2626 } | |
| 2627 | |
| 2628 // Keep values | |
| 2629 xform->core->EntryColorSpace = EntryColorSpace; | |
| 2630 xform->core->ExitColorSpace = ExitColorSpace; | |
| 2631 xform->core->RenderingIntent = Intents[nProfiles-1]; | |
| 2632 | |
| 2633 // Take white points | |
| 2634 SetWhitePoint(&xform->core->EntryWhitePoint, (cmsCIEXYZ*) cmsReadTag(ContextID, hProfiles[0], cmsSigMediaWhitePointTag)); | |
| 2635 SetWhitePoint(&xform->core->ExitWhitePoint, (cmsCIEXYZ*) cmsReadTag(ContextID, hProfiles[nProfiles-1], cmsSigMediaWhitePointTag)); | |
| 2636 | |
| 2637 | |
| 2638 // Create a gamut check LUT if requested | |
| 2639 if (hGamutProfile != NULL && (dwFlags & cmsFLAGS_GAMUTCHECK)) | |
| 2640 xform->core->GamutCheck = _cmsCreateGamutCheckPipeline(ContextID, hProfiles, | |
| 2641 BPC, Intents, | |
| 2642 AdaptationStates, | |
| 2643 nGamutPCSposition, | |
| 2644 hGamutProfile); | |
| 2645 | |
| 2646 | |
| 2647 // Try to read input and output colorant table | |
| 2648 if (cmsIsTag(ContextID, hProfiles[0], cmsSigColorantTableTag)) { | |
| 2649 | |
| 2650 // Input table can only come in this way. | |
| 2651 xform->core->InputColorant = cmsDupNamedColorList(ContextID, (cmsNAMEDCOLORLIST*) cmsReadTag(ContextID, hProfiles[0], cmsSigColorantTableTag)); | |
| 2652 } | |
| 2653 | |
| 2654 // Output is a little bit more complex. | |
| 2655 if (cmsGetDeviceClass(ContextID, hProfiles[nProfiles-1]) == cmsSigLinkClass) { | |
| 2656 | |
| 2657 // This tag may exist only on devicelink profiles. | |
| 2658 if (cmsIsTag(ContextID, hProfiles[nProfiles-1], cmsSigColorantTableOutTag)) { | |
| 2659 | |
| 2660 // It may be NULL if error | |
| 2661 xform->core->OutputColorant = cmsDupNamedColorList(ContextID, (cmsNAMEDCOLORLIST*) cmsReadTag(ContextID, hProfiles[nProfiles-1], cmsSigColorantTableOutTag)); | |
| 2662 } | |
| 2663 | |
| 2664 } else { | |
| 2665 | |
| 2666 if (cmsIsTag(ContextID, hProfiles[nProfiles-1], cmsSigColorantTableTag)) { | |
| 2667 | |
| 2668 xform->core->OutputColorant = cmsDupNamedColorList(ContextID, (cmsNAMEDCOLORLIST*) cmsReadTag(ContextID, hProfiles[nProfiles-1], cmsSigColorantTableTag)); | |
| 2669 } | |
| 2670 } | |
| 2671 | |
| 2672 // Store the sequence of profiles | |
| 2673 if (dwFlags & cmsFLAGS_KEEP_SEQUENCE) { | |
| 2674 xform->core->Sequence = _cmsCompileProfileSequence(ContextID, nProfiles, hProfiles); | |
| 2675 } | |
| 2676 else | |
| 2677 xform->core->Sequence = NULL; | |
| 2678 | |
| 2679 // If this is a cached transform, init first value, which is zero (16 bits only) | |
| 2680 if (!(dwFlags & cmsFLAGS_NOCACHE)) { | |
| 2681 | |
| 2682 memset(&xform ->Cache.CacheIn, 0, sizeof(xform ->Cache.CacheIn)); | |
| 2683 | |
| 2684 if (xform->core->GamutCheck != NULL) { | |
| 2685 TransformOnePixelWithGamutCheck(ContextID, xform, xform->Cache.CacheIn, xform->Cache.CacheOut); | |
| 2686 } | |
| 2687 else { | |
| 2688 | |
| 2689 xform->core->Lut->Eval16Fn(ContextID, xform ->Cache.CacheIn, xform->Cache.CacheOut, xform->core->Lut->Data); | |
| 2690 } | |
| 2691 | |
| 2692 } | |
| 2693 | |
| 2694 return (cmsHTRANSFORM) xform; | |
| 2695 } | |
| 2696 | |
| 2697 // Multiprofile transforms: Gamut check is not available here, as it is unclear from which profile the gamut comes. | |
| 2698 cmsHTRANSFORM CMSEXPORT cmsCreateMultiprofileTransform(cmsContext ContextID, | |
| 2699 cmsHPROFILE hProfiles[], | |
| 2700 cmsUInt32Number nProfiles, | |
| 2701 cmsUInt32Number InputFormat, | |
| 2702 cmsUInt32Number OutputFormat, | |
| 2703 cmsUInt32Number Intent, | |
| 2704 cmsUInt32Number dwFlags) | |
| 2705 { | |
| 2706 cmsUInt32Number i; | |
| 2707 cmsBool BPC[256]; | |
| 2708 cmsUInt32Number Intents[256]; | |
| 2709 cmsFloat64Number AdaptationStates[256]; | |
| 2710 | |
| 2711 if (nProfiles <= 0 || nProfiles > 255) { | |
| 2712 cmsSignalError(ContextID, cmsERROR_RANGE, "Wrong number of profiles. 1..255 expected, %d found.", nProfiles); | |
| 2713 return NULL; | |
| 2714 } | |
| 2715 | |
| 2716 for (i=0; i < nProfiles; i++) { | |
| 2717 BPC[i] = dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION ? TRUE : FALSE; | |
| 2718 Intents[i] = Intent; | |
| 2719 AdaptationStates[i] = cmsSetAdaptationState(ContextID, -1); | |
| 2720 } | |
| 2721 | |
| 2722 | |
| 2723 return cmsCreateExtendedTransform(ContextID, nProfiles, hProfiles, BPC, Intents, AdaptationStates, NULL, 0, InputFormat, OutputFormat, dwFlags); | |
| 2724 } | |
| 2725 | |
| 2726 | |
| 2727 | |
| 2728 cmsHTRANSFORM CMSEXPORT cmsCreateTransform(cmsContext ContextID, | |
| 2729 cmsHPROFILE Input, | |
| 2730 cmsUInt32Number InputFormat, | |
| 2731 cmsHPROFILE Output, | |
| 2732 cmsUInt32Number OutputFormat, | |
| 2733 cmsUInt32Number Intent, | |
| 2734 cmsUInt32Number dwFlags) | |
| 2735 { | |
| 2736 | |
| 2737 cmsHPROFILE hArray[2]; | |
| 2738 | |
| 2739 hArray[0] = Input; | |
| 2740 hArray[1] = Output; | |
| 2741 | |
| 2742 return cmsCreateMultiprofileTransform(ContextID, hArray, Output == NULL ? 1U : 2U, InputFormat, OutputFormat, Intent, dwFlags); | |
| 2743 } | |
| 2744 | |
| 2745 | |
| 2746 cmsHTRANSFORM CMSEXPORT cmsCreateProofingTransform(cmsContext ContextID, | |
| 2747 cmsHPROFILE InputProfile, | |
| 2748 cmsUInt32Number InputFormat, | |
| 2749 cmsHPROFILE OutputProfile, | |
| 2750 cmsUInt32Number OutputFormat, | |
| 2751 cmsHPROFILE ProofingProfile, | |
| 2752 cmsUInt32Number nIntent, | |
| 2753 cmsUInt32Number ProofingIntent, | |
| 2754 cmsUInt32Number dwFlags) | |
| 2755 { | |
| 2756 cmsHPROFILE hArray[4]; | |
| 2757 cmsUInt32Number Intents[4]; | |
| 2758 cmsBool BPC[4]; | |
| 2759 cmsFloat64Number Adaptation[4]; | |
| 2760 cmsBool DoBPC = (dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION) ? TRUE : FALSE; | |
| 2761 | |
| 2762 | |
| 2763 hArray[0] = InputProfile; hArray[1] = ProofingProfile; hArray[2] = ProofingProfile; hArray[3] = OutputProfile; | |
| 2764 Intents[0] = nIntent; Intents[1] = nIntent; Intents[2] = INTENT_RELATIVE_COLORIMETRIC; Intents[3] = ProofingIntent; | |
| 2765 BPC[0] = DoBPC; BPC[1] = DoBPC; BPC[2] = 0; BPC[3] = 0; | |
| 2766 | |
| 2767 Adaptation[0] = Adaptation[1] = Adaptation[2] = Adaptation[3] = cmsSetAdaptationState(ContextID, -1); | |
| 2768 | |
| 2769 if (!(dwFlags & (cmsFLAGS_SOFTPROOFING|cmsFLAGS_GAMUTCHECK))) | |
| 2770 return cmsCreateTransform(ContextID, InputProfile, InputFormat, OutputProfile, OutputFormat, nIntent, dwFlags); | |
| 2771 | |
| 2772 return cmsCreateExtendedTransform(ContextID, 4, hArray, BPC, Intents, Adaptation, | |
| 2773 ProofingProfile, 1, InputFormat, OutputFormat, dwFlags); | |
| 2774 | |
| 2775 } | |
| 2776 | |
| 2777 | |
| 2778 | |
| 2779 // Grab the input/output formats | |
| 2780 cmsUInt32Number CMSEXPORT cmsGetTransformInputFormat(cmsContext ContextID, cmsHTRANSFORM hTransform) | |
| 2781 { | |
| 2782 _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform; | |
| 2783 cmsUNUSED_PARAMETER(ContextID); | |
| 2784 | |
| 2785 if (xform == NULL) return 0; | |
| 2786 return xform->InputFormat; | |
| 2787 } | |
| 2788 | |
| 2789 cmsUInt32Number CMSEXPORT cmsGetTransformOutputFormat(cmsContext ContextID, cmsHTRANSFORM hTransform) | |
| 2790 { | |
| 2791 _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform; | |
| 2792 cmsUNUSED_PARAMETER(ContextID); | |
| 2793 | |
| 2794 if (xform == NULL) return 0; | |
| 2795 return xform->OutputFormat; | |
| 2796 } | |
| 2797 | |
| 2798 cmsHTRANSFORM cmsCloneTransformChangingFormats(cmsContext ContextID, | |
| 2799 const cmsHTRANSFORM hTransform, | |
| 2800 cmsUInt32Number InputFormat, | |
| 2801 cmsUInt32Number OutputFormat) | |
| 2802 { | |
| 2803 const _cmsTRANSFORM *oldXform = (const _cmsTRANSFORM *)hTransform; | |
| 2804 _cmsTRANSFORM *xform; | |
| 2805 cmsFormatter16 FromInput, ToOutput; | |
| 2806 | |
| 2807 _cmsAssert(oldXform != NULL && oldXform->core != NULL); | |
| 2808 | |
| 2809 // We only can afford to change formatters if previous transform is at least 16 bits | |
| 2810 if (!(oldXform->core->dwOriginalFlags & cmsFLAGS_CAN_CHANGE_FORMATTER)) { | |
| 2811 cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "cmsCloneTransformChangingFormats works only on transforms created originally with at least 16 bits of precision"); | |
| 2812 return NULL; | |
| 2813 } | |
| 2814 | |
| 2815 xform = _cmsMalloc(ContextID, sizeof(*xform)); | |
| 2816 if (xform == NULL) | |
| 2817 return NULL; | |
| 2818 | |
| 2819 memcpy(xform, oldXform, sizeof(*xform)); | |
| 2820 | |
| 2821 FromInput = _cmsGetFormatter(ContextID, InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16; | |
| 2822 ToOutput = _cmsGetFormatter(ContextID, OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16; | |
| 2823 | |
| 2824 if (FromInput == NULL || ToOutput == NULL) { | |
| 2825 | |
| 2826 cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format"); | |
| 2827 return NULL; | |
| 2828 } | |
| 2829 | |
| 2830 xform ->InputFormat = InputFormat; | |
| 2831 xform ->OutputFormat = OutputFormat; | |
| 2832 xform ->FromInput = FromInput; | |
| 2833 xform ->ToOutput = ToOutput; | |
| 2834 _cmsFindFormatter(xform, InputFormat, OutputFormat, xform->core->dwOriginalFlags); | |
| 2835 | |
| 2836 (void)_cmsAdjustReferenceCount(&xform->core->refs, 1); | |
| 2837 | |
| 2838 return xform; | |
| 2839 } |
