Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/lcms2/src/cmsalpha.c @ 3:2c135c81b16c
MERGE: upstream PyMuPDF 1.26.4 with MuPDF 1.26.7
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:44:09 +0200 |
| parents | b50eed0cc0ef |
| children |
comparison
equal
deleted
inserted
replaced
| 0:6015a75abc2d | 3:2c135c81b16c |
|---|---|
| 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 // Alpha copy ------------------------------------------------------------------------------------------------------------------ | |
| 30 | |
| 31 // This macro return words stored as big endian | |
| 32 #define CHANGE_ENDIAN(w) (cmsUInt16Number) ((cmsUInt16Number) ((w)<<8)|((w)>>8)) | |
| 33 | |
| 34 | |
| 35 // Floor to byte, taking care of saturation | |
| 36 cmsINLINE cmsUInt8Number _cmsQuickSaturateByte(cmsFloat64Number d) | |
| 37 { | |
| 38 d += 0.5; | |
| 39 if (d <= 0) return 0; | |
| 40 if (d >= 255.0) return 255; | |
| 41 | |
| 42 return (cmsUInt8Number) _cmsQuickFloorWord(d); | |
| 43 } | |
| 44 | |
| 45 | |
| 46 // Return the size in bytes of a given formatter | |
| 47 static | |
| 48 cmsUInt32Number trueBytesSize(cmsUInt32Number Format) | |
| 49 { | |
| 50 cmsUInt32Number fmt_bytes = T_BYTES(Format); | |
| 51 | |
| 52 // For double, the T_BYTES field returns zero | |
| 53 if (fmt_bytes == 0) | |
| 54 return sizeof(double); | |
| 55 | |
| 56 // Otherwise, it is already correct for all formats | |
| 57 return fmt_bytes; | |
| 58 } | |
| 59 | |
| 60 | |
| 61 // Several format converters | |
| 62 | |
| 63 typedef void(*cmsFormatterAlphaFn)(void* dst, const void* src); | |
| 64 | |
| 65 | |
| 66 // From 8 | |
| 67 | |
| 68 static | |
| 69 void copy8(void* dst, const void* src) | |
| 70 { | |
| 71 memmove(dst, src, 1); | |
| 72 } | |
| 73 | |
| 74 static | |
| 75 void from8to16(void* dst, const void* src) | |
| 76 { | |
| 77 cmsUInt8Number n = *(cmsUInt8Number*)src; | |
| 78 *(cmsUInt16Number*) dst = (cmsUInt16Number) FROM_8_TO_16(n); | |
| 79 } | |
| 80 | |
| 81 static | |
| 82 void from8to16SE(void* dst, const void* src) | |
| 83 { | |
| 84 cmsUInt8Number n = *(cmsUInt8Number*)src; | |
| 85 *(cmsUInt16Number*)dst = CHANGE_ENDIAN(FROM_8_TO_16(n)); | |
| 86 } | |
| 87 | |
| 88 static | |
| 89 void from8toFLT(void* dst, const void* src) | |
| 90 { | |
| 91 *(cmsFloat32Number*)dst = (cmsFloat32Number) (*(cmsUInt8Number*)src) / 255.0f; | |
| 92 } | |
| 93 | |
| 94 static | |
| 95 void from8toDBL(void* dst, const void* src) | |
| 96 { | |
| 97 *(cmsFloat64Number*)dst = (cmsFloat64Number) (*(cmsUInt8Number*)src) / 255.0; | |
| 98 } | |
| 99 | |
| 100 static | |
| 101 void from8toHLF(void* dst, const void* src) | |
| 102 { | |
| 103 #ifndef CMS_NO_HALF_SUPPORT | |
| 104 cmsFloat32Number n = (*(cmsUInt8Number*)src) / 255.0f; | |
| 105 *(cmsUInt16Number*)dst = _cmsFloat2Half(n); | |
| 106 #else | |
| 107 cmsUNUSED_PARAMETER(dst); | |
| 108 cmsUNUSED_PARAMETER(src); | |
| 109 #endif | |
| 110 } | |
| 111 | |
| 112 // From 16 | |
| 113 | |
| 114 static | |
| 115 void from16to8(void* dst, const void* src) | |
| 116 { | |
| 117 cmsUInt16Number n = *(cmsUInt16Number*)src; | |
| 118 *(cmsUInt8Number*) dst = FROM_16_TO_8(n); | |
| 119 } | |
| 120 | |
| 121 static | |
| 122 void from16SEto8(void* dst, const void* src) | |
| 123 { | |
| 124 cmsUInt16Number n = *(cmsUInt16Number*)src; | |
| 125 *(cmsUInt8Number*)dst = FROM_16_TO_8(CHANGE_ENDIAN(n)); | |
| 126 } | |
| 127 | |
| 128 static | |
| 129 void copy16(void* dst, const void* src) | |
| 130 { | |
| 131 memmove(dst, src, 2); | |
| 132 } | |
| 133 | |
| 134 static | |
| 135 void from16to16(void* dst, const void* src) | |
| 136 { | |
| 137 cmsUInt16Number n = *(cmsUInt16Number*)src; | |
| 138 *(cmsUInt16Number*)dst = CHANGE_ENDIAN(n); | |
| 139 } | |
| 140 | |
| 141 static | |
| 142 void from16toFLT(void* dst, const void* src) | |
| 143 { | |
| 144 *(cmsFloat32Number*)dst = (*(cmsUInt16Number*)src) / 65535.0f; | |
| 145 } | |
| 146 | |
| 147 static | |
| 148 void from16SEtoFLT(void* dst, const void* src) | |
| 149 { | |
| 150 *(cmsFloat32Number*)dst = (CHANGE_ENDIAN(*(cmsUInt16Number*)src)) / 65535.0f; | |
| 151 } | |
| 152 | |
| 153 static | |
| 154 void from16toDBL(void* dst, const void* src) | |
| 155 { | |
| 156 *(cmsFloat64Number*)dst = (cmsFloat64Number) (*(cmsUInt16Number*)src) / 65535.0; | |
| 157 } | |
| 158 | |
| 159 static | |
| 160 void from16SEtoDBL(void* dst, const void* src) | |
| 161 { | |
| 162 *(cmsFloat64Number*)dst = (cmsFloat64Number) (CHANGE_ENDIAN(*(cmsUInt16Number*)src)) / 65535.0; | |
| 163 } | |
| 164 | |
| 165 static | |
| 166 void from16toHLF(void* dst, const void* src) | |
| 167 { | |
| 168 #ifndef CMS_NO_HALF_SUPPORT | |
| 169 cmsFloat32Number n = (*(cmsUInt16Number*)src) / 65535.0f; | |
| 170 *(cmsUInt16Number*)dst = _cmsFloat2Half(n); | |
| 171 #else | |
| 172 cmsUNUSED_PARAMETER(dst); | |
| 173 cmsUNUSED_PARAMETER(src); | |
| 174 #endif | |
| 175 } | |
| 176 | |
| 177 static | |
| 178 void from16SEtoHLF(void* dst, const void* src) | |
| 179 { | |
| 180 #ifndef CMS_NO_HALF_SUPPORT | |
| 181 cmsFloat32Number n = (CHANGE_ENDIAN(*(cmsUInt16Number*)src)) / 65535.0f; | |
| 182 *(cmsUInt16Number*)dst = _cmsFloat2Half(n); | |
| 183 #else | |
| 184 cmsUNUSED_PARAMETER(dst); | |
| 185 cmsUNUSED_PARAMETER(src); | |
| 186 #endif | |
| 187 } | |
| 188 // From Float | |
| 189 | |
| 190 static | |
| 191 void fromFLTto8(void* dst, const void* src) | |
| 192 { | |
| 193 cmsFloat32Number n = *(cmsFloat32Number*)src; | |
| 194 *(cmsUInt8Number*)dst = _cmsQuickSaturateByte(n * 255.0); | |
| 195 } | |
| 196 | |
| 197 static | |
| 198 void fromFLTto16(void* dst, const void* src) | |
| 199 { | |
| 200 cmsFloat32Number n = *(cmsFloat32Number*)src; | |
| 201 *(cmsUInt16Number*)dst = _cmsQuickSaturateWord(n * 65535.0); | |
| 202 } | |
| 203 | |
| 204 static | |
| 205 void fromFLTto16SE(void* dst, const void* src) | |
| 206 { | |
| 207 cmsFloat32Number n = *(cmsFloat32Number*)src; | |
| 208 cmsUInt16Number i = _cmsQuickSaturateWord(n * 65535.0); | |
| 209 | |
| 210 *(cmsUInt16Number*)dst = CHANGE_ENDIAN(i); | |
| 211 } | |
| 212 | |
| 213 static | |
| 214 void copy32(void* dst, const void* src) | |
| 215 { | |
| 216 memmove(dst, src, sizeof(cmsFloat32Number)); | |
| 217 } | |
| 218 | |
| 219 static | |
| 220 void fromFLTtoDBL(void* dst, const void* src) | |
| 221 { | |
| 222 cmsFloat32Number n = *(cmsFloat32Number*)src; | |
| 223 *(cmsFloat64Number*)dst = (cmsFloat64Number)n; | |
| 224 } | |
| 225 | |
| 226 static | |
| 227 void fromFLTtoHLF(void* dst, const void* src) | |
| 228 { | |
| 229 #ifndef CMS_NO_HALF_SUPPORT | |
| 230 cmsFloat32Number n = *(cmsFloat32Number*)src; | |
| 231 *(cmsUInt16Number*)dst = _cmsFloat2Half(n); | |
| 232 #else | |
| 233 cmsUNUSED_PARAMETER(dst); | |
| 234 cmsUNUSED_PARAMETER(src); | |
| 235 #endif | |
| 236 } | |
| 237 | |
| 238 | |
| 239 // From HALF | |
| 240 | |
| 241 static | |
| 242 void fromHLFto8(void* dst, const void* src) | |
| 243 { | |
| 244 #ifndef CMS_NO_HALF_SUPPORT | |
| 245 cmsFloat32Number n = _cmsHalf2Float(*(cmsUInt16Number*)src); | |
| 246 *(cmsUInt8Number*)dst = _cmsQuickSaturateByte(n * 255.0); | |
| 247 #else | |
| 248 cmsUNUSED_PARAMETER(dst); | |
| 249 cmsUNUSED_PARAMETER(src); | |
| 250 #endif | |
| 251 | |
| 252 } | |
| 253 | |
| 254 static | |
| 255 void fromHLFto16(void* dst, const void* src) | |
| 256 { | |
| 257 #ifndef CMS_NO_HALF_SUPPORT | |
| 258 cmsFloat32Number n = _cmsHalf2Float(*(cmsUInt16Number*)src); | |
| 259 *(cmsUInt16Number*)dst = _cmsQuickSaturateWord(n * 65535.0); | |
| 260 #else | |
| 261 cmsUNUSED_PARAMETER(dst); | |
| 262 cmsUNUSED_PARAMETER(src); | |
| 263 #endif | |
| 264 } | |
| 265 | |
| 266 static | |
| 267 void fromHLFto16SE(void* dst, const void* src) | |
| 268 { | |
| 269 #ifndef CMS_NO_HALF_SUPPORT | |
| 270 cmsFloat32Number n = _cmsHalf2Float(*(cmsUInt16Number*)src); | |
| 271 cmsUInt16Number i = _cmsQuickSaturateWord(n * 65535.0); | |
| 272 *(cmsUInt16Number*)dst = CHANGE_ENDIAN(i); | |
| 273 #else | |
| 274 cmsUNUSED_PARAMETER(dst); | |
| 275 cmsUNUSED_PARAMETER(src); | |
| 276 #endif | |
| 277 } | |
| 278 | |
| 279 static | |
| 280 void fromHLFtoFLT(void* dst, const void* src) | |
| 281 { | |
| 282 #ifndef CMS_NO_HALF_SUPPORT | |
| 283 *(cmsFloat32Number*)dst = _cmsHalf2Float(*(cmsUInt16Number*)src); | |
| 284 #else | |
| 285 cmsUNUSED_PARAMETER(dst); | |
| 286 cmsUNUSED_PARAMETER(src); | |
| 287 #endif | |
| 288 } | |
| 289 | |
| 290 static | |
| 291 void fromHLFtoDBL(void* dst, const void* src) | |
| 292 { | |
| 293 #ifndef CMS_NO_HALF_SUPPORT | |
| 294 *(cmsFloat64Number*)dst = (cmsFloat64Number)_cmsHalf2Float(*(cmsUInt16Number*)src); | |
| 295 #else | |
| 296 cmsUNUSED_PARAMETER(dst); | |
| 297 cmsUNUSED_PARAMETER(src); | |
| 298 #endif | |
| 299 } | |
| 300 | |
| 301 // From double | |
| 302 static | |
| 303 void fromDBLto8(void* dst, const void* src) | |
| 304 { | |
| 305 cmsFloat64Number n = *(cmsFloat64Number*)src; | |
| 306 *(cmsUInt8Number*)dst = _cmsQuickSaturateByte(n * 255.0); | |
| 307 } | |
| 308 | |
| 309 static | |
| 310 void fromDBLto16(void* dst, const void* src) | |
| 311 { | |
| 312 cmsFloat64Number n = *(cmsFloat64Number*)src; | |
| 313 *(cmsUInt16Number*)dst = _cmsQuickSaturateWord(n * 65535.0f); | |
| 314 } | |
| 315 | |
| 316 static | |
| 317 void fromDBLto16SE(void* dst, const void* src) | |
| 318 { | |
| 319 cmsFloat64Number n = *(cmsFloat64Number*)src; | |
| 320 cmsUInt16Number i = _cmsQuickSaturateWord(n * 65535.0f); | |
| 321 *(cmsUInt16Number*)dst = CHANGE_ENDIAN(i); | |
| 322 } | |
| 323 | |
| 324 static | |
| 325 void fromDBLtoFLT(void* dst, const void* src) | |
| 326 { | |
| 327 cmsFloat64Number n = *(cmsFloat64Number*)src; | |
| 328 *(cmsFloat32Number*)dst = (cmsFloat32Number) n; | |
| 329 } | |
| 330 | |
| 331 static | |
| 332 void fromDBLtoHLF(void* dst, const void* src) | |
| 333 { | |
| 334 #ifndef CMS_NO_HALF_SUPPORT | |
| 335 cmsFloat32Number n = (cmsFloat32Number) *(cmsFloat64Number*)src; | |
| 336 *(cmsUInt16Number*)dst = _cmsFloat2Half(n); | |
| 337 #else | |
| 338 cmsUNUSED_PARAMETER(dst); | |
| 339 cmsUNUSED_PARAMETER(src); | |
| 340 #endif | |
| 341 } | |
| 342 | |
| 343 static | |
| 344 void copy64(void* dst, const void* src) | |
| 345 { | |
| 346 memmove(dst, src, sizeof(cmsFloat64Number)); | |
| 347 } | |
| 348 | |
| 349 | |
| 350 // Returns the position (x or y) of the formatter in the table of functions | |
| 351 static | |
| 352 int FormatterPos(cmsUInt32Number frm) | |
| 353 { | |
| 354 cmsUInt32Number b = T_BYTES(frm); | |
| 355 | |
| 356 if (b == 0 && T_FLOAT(frm)) | |
| 357 return 5; // DBL | |
| 358 #ifndef CMS_NO_HALF_SUPPORT | |
| 359 if (b == 2 && T_FLOAT(frm)) | |
| 360 return 3; // HLF | |
| 361 #endif | |
| 362 if (b == 4 && T_FLOAT(frm)) | |
| 363 return 4; // FLT | |
| 364 if (b == 2 && !T_FLOAT(frm)) | |
| 365 { | |
| 366 if (T_ENDIAN16(frm)) | |
| 367 return 2; // 16SE | |
| 368 else | |
| 369 return 1; // 16 | |
| 370 } | |
| 371 if (b == 1 && !T_FLOAT(frm)) | |
| 372 return 0; // 8 | |
| 373 return -1; // not recognized | |
| 374 } | |
| 375 | |
| 376 // Obtains an alpha-to-alpha function formatter | |
| 377 static | |
| 378 cmsFormatterAlphaFn _cmsGetFormatterAlpha(cmsContext id, cmsUInt32Number in, cmsUInt32Number out) | |
| 379 { | |
| 380 static cmsFormatterAlphaFn FormattersAlpha[6][6] = { | |
| 381 | |
| 382 /* from 8 */ { copy8, from8to16, from8to16SE, from8toHLF, from8toFLT, from8toDBL }, | |
| 383 /* from 16*/ { from16to8, copy16, from16to16, from16toHLF, from16toFLT, from16toDBL }, | |
| 384 /* from 16SE*/{ from16SEto8, from16to16, copy16, from16SEtoHLF,from16SEtoFLT, from16SEtoDBL }, | |
| 385 /* from HLF*/ { fromHLFto8, fromHLFto16, fromHLFto16SE, copy16, fromHLFtoFLT, fromHLFtoDBL }, | |
| 386 /* from FLT*/ { fromFLTto8, fromFLTto16, fromFLTto16SE, fromFLTtoHLF, copy32, fromFLTtoDBL }, | |
| 387 /* from DBL*/ { fromDBLto8, fromDBLto16, fromDBLto16SE, fromDBLtoHLF, fromDBLtoFLT, copy64 }}; | |
| 388 | |
| 389 int in_n = FormatterPos(in); | |
| 390 int out_n = FormatterPos(out); | |
| 391 | |
| 392 if (in_n < 0 || out_n < 0 || in_n > 5 || out_n > 5) { | |
| 393 | |
| 394 cmsSignalError(id, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized alpha channel width"); | |
| 395 return NULL; | |
| 396 } | |
| 397 | |
| 398 return FormattersAlpha[in_n][out_n]; | |
| 399 } | |
| 400 | |
| 401 | |
| 402 | |
| 403 // This function computes the distance from each component to the next one in bytes. | |
| 404 static | |
| 405 cmsBool ComputeIncrementsForChunky(cmsUInt32Number Format, | |
| 406 cmsUInt32Number ComponentStartingOrder[], | |
| 407 cmsUInt32Number ComponentPointerIncrements[]) | |
| 408 { | |
| 409 cmsUInt32Number channels[cmsMAXEXTRACHANNELS]; | |
| 410 cmsUInt32Number extra = T_EXTRA(Format); | |
| 411 cmsUInt32Number nchannels = T_CHANNELS(Format); | |
| 412 cmsUInt32Number total_chans = nchannels + extra; | |
| 413 cmsUInt32Number i; | |
| 414 cmsUInt32Number channelSize = trueBytesSize(Format); | |
| 415 cmsUInt32Number pixelSize = channelSize * total_chans; | |
| 416 | |
| 417 // Sanity check | |
| 418 if (total_chans <= 0 || total_chans >= cmsMAXEXTRACHANNELS) | |
| 419 return FALSE; | |
| 420 | |
| 421 memset(channels, 0, sizeof(channels)); | |
| 422 | |
| 423 // Separation is independent of starting point and only depends on channel size | |
| 424 for (i = 0; i < extra; i++) | |
| 425 ComponentPointerIncrements[i] = pixelSize; | |
| 426 | |
| 427 // Handle do swap | |
| 428 for (i = 0; i < total_chans; i++) | |
| 429 { | |
| 430 if (T_DOSWAP(Format)) { | |
| 431 channels[i] = total_chans - i - 1; | |
| 432 } | |
| 433 else { | |
| 434 channels[i] = i; | |
| 435 } | |
| 436 } | |
| 437 | |
| 438 // Handle swap first (ROL of positions), example CMYK -> KCMY | 0123 -> 3012 | |
| 439 if (T_SWAPFIRST(Format) && total_chans > 1) { | |
| 440 | |
| 441 cmsUInt32Number tmp = channels[0]; | |
| 442 for (i = 0; i < total_chans-1; i++) | |
| 443 channels[i] = channels[i + 1]; | |
| 444 | |
| 445 channels[total_chans - 1] = tmp; | |
| 446 } | |
| 447 | |
| 448 // Handle size | |
| 449 if (channelSize > 1) | |
| 450 for (i = 0; i < total_chans; i++) { | |
| 451 channels[i] *= channelSize; | |
| 452 } | |
| 453 | |
| 454 for (i = 0; i < extra; i++) | |
| 455 ComponentStartingOrder[i] = channels[i + nchannels]; | |
| 456 | |
| 457 return TRUE; | |
| 458 } | |
| 459 | |
| 460 | |
| 461 | |
| 462 // On planar configurations, the distance is the stride added to any non-negative | |
| 463 static | |
| 464 cmsBool ComputeIncrementsForPlanar(cmsUInt32Number Format, | |
| 465 cmsUInt32Number BytesPerPlane, | |
| 466 cmsUInt32Number ComponentStartingOrder[], | |
| 467 cmsUInt32Number ComponentPointerIncrements[]) | |
| 468 { | |
| 469 cmsUInt32Number channels[cmsMAXEXTRACHANNELS]; | |
| 470 cmsUInt32Number extra = T_EXTRA(Format); | |
| 471 cmsUInt32Number nchannels = T_CHANNELS(Format); | |
| 472 cmsUInt32Number total_chans = nchannels + extra; | |
| 473 cmsUInt32Number i; | |
| 474 cmsUInt32Number channelSize = trueBytesSize(Format); | |
| 475 | |
| 476 // Sanity check | |
| 477 if (total_chans <= 0 || total_chans >= cmsMAXEXTRACHANNELS) | |
| 478 return FALSE; | |
| 479 | |
| 480 memset(channels, 0, sizeof(channels)); | |
| 481 | |
| 482 // Separation is independent of starting point and only depends on channel size | |
| 483 for (i = 0; i < extra; i++) | |
| 484 ComponentPointerIncrements[i] = channelSize; | |
| 485 | |
| 486 // Handle do swap | |
| 487 for (i = 0; i < total_chans; i++) | |
| 488 { | |
| 489 if (T_DOSWAP(Format)) { | |
| 490 channels[i] = total_chans - i - 1; | |
| 491 } | |
| 492 else { | |
| 493 channels[i] = i; | |
| 494 } | |
| 495 } | |
| 496 | |
| 497 // Handle swap first (ROL of positions), example CMYK -> KCMY | 0123 -> 3012 | |
| 498 if (T_SWAPFIRST(Format) && total_chans > 0) { | |
| 499 | |
| 500 cmsUInt32Number tmp = channels[0]; | |
| 501 for (i = 0; i < total_chans - 1; i++) | |
| 502 channels[i] = channels[i + 1]; | |
| 503 | |
| 504 channels[total_chans - 1] = tmp; | |
| 505 } | |
| 506 | |
| 507 // Handle size | |
| 508 for (i = 0; i < total_chans; i++) { | |
| 509 channels[i] *= BytesPerPlane; | |
| 510 } | |
| 511 | |
| 512 for (i = 0; i < extra; i++) | |
| 513 ComponentStartingOrder[i] = channels[i + nchannels]; | |
| 514 | |
| 515 return TRUE; | |
| 516 } | |
| 517 | |
| 518 | |
| 519 | |
| 520 // Dispatcher por chunky and planar RGB | |
| 521 static | |
| 522 cmsBool ComputeComponentIncrements(cmsUInt32Number Format, | |
| 523 cmsUInt32Number BytesPerPlane, | |
| 524 cmsUInt32Number ComponentStartingOrder[], | |
| 525 cmsUInt32Number ComponentPointerIncrements[]) | |
| 526 { | |
| 527 if (T_PLANAR(Format)) { | |
| 528 | |
| 529 return ComputeIncrementsForPlanar(Format, BytesPerPlane, ComponentStartingOrder, ComponentPointerIncrements); | |
| 530 } | |
| 531 else { | |
| 532 return ComputeIncrementsForChunky(Format, ComponentStartingOrder, ComponentPointerIncrements); | |
| 533 } | |
| 534 | |
| 535 } | |
| 536 | |
| 537 // Handles extra channels copying alpha if requested by the flags | |
| 538 void _cmsHandleExtraChannels(cmsContext ContextID, _cmsTRANSFORM* p, const void* in, | |
| 539 void* out, | |
| 540 cmsUInt32Number PixelsPerLine, | |
| 541 cmsUInt32Number LineCount, | |
| 542 const cmsStride* Stride) | |
| 543 { | |
| 544 cmsUInt32Number i, j, k; | |
| 545 cmsUInt32Number nExtra; | |
| 546 cmsUInt32Number SourceStartingOrder[cmsMAXEXTRACHANNELS]; | |
| 547 cmsUInt32Number SourceIncrements[cmsMAXEXTRACHANNELS]; | |
| 548 cmsUInt32Number DestStartingOrder[cmsMAXEXTRACHANNELS]; | |
| 549 cmsUInt32Number DestIncrements[cmsMAXEXTRACHANNELS]; | |
| 550 | |
| 551 cmsFormatterAlphaFn copyValueFn; | |
| 552 | |
| 553 // Make sure we need some copy | |
| 554 if (!(p->core->dwOriginalFlags & cmsFLAGS_COPY_ALPHA)) | |
| 555 return; | |
| 556 | |
| 557 // Exit early if in-place color-management is occurring - no need to copy extra channels to themselves. | |
| 558 if (p->InputFormat == p->OutputFormat && in == out) | |
| 559 return; | |
| 560 | |
| 561 // Make sure we have same number of alpha channels. If not, just return as this should be checked at transform creation time. | |
| 562 nExtra = T_EXTRA(p->InputFormat); | |
| 563 if (nExtra != T_EXTRA(p->OutputFormat)) | |
| 564 return; | |
| 565 | |
| 566 // Anything to do? | |
| 567 if (nExtra == 0) | |
| 568 return; | |
| 569 | |
| 570 // Compute the increments | |
| 571 if (!ComputeComponentIncrements(p->InputFormat, Stride->BytesPerPlaneIn, SourceStartingOrder, SourceIncrements)) | |
| 572 return; | |
| 573 if (!ComputeComponentIncrements(p->OutputFormat, Stride->BytesPerPlaneOut, DestStartingOrder, DestIncrements)) | |
| 574 return; | |
| 575 | |
| 576 // Check for conversions 8, 16, half, float, dbl | |
| 577 copyValueFn = _cmsGetFormatterAlpha(ContextID, p->InputFormat, p->OutputFormat); | |
| 578 if (copyValueFn == NULL) | |
| 579 return; | |
| 580 | |
| 581 if (nExtra == 1) { // Optimized routine for copying a single extra channel quickly | |
| 582 | |
| 583 cmsUInt8Number* SourcePtr; | |
| 584 cmsUInt8Number* DestPtr; | |
| 585 | |
| 586 cmsUInt32Number SourceStrideIncrement = 0; | |
| 587 cmsUInt32Number DestStrideIncrement = 0; | |
| 588 | |
| 589 // The loop itself | |
| 590 for (i = 0; i < LineCount; i++) { | |
| 591 | |
| 592 // Prepare pointers for the loop | |
| 593 SourcePtr = (cmsUInt8Number*)in + SourceStartingOrder[0] + SourceStrideIncrement; | |
| 594 DestPtr = (cmsUInt8Number*)out + DestStartingOrder[0] + DestStrideIncrement; | |
| 595 | |
| 596 for (j = 0; j < PixelsPerLine; j++) { | |
| 597 | |
| 598 copyValueFn(DestPtr, SourcePtr); | |
| 599 | |
| 600 SourcePtr += SourceIncrements[0]; | |
| 601 DestPtr += DestIncrements[0]; | |
| 602 } | |
| 603 | |
| 604 SourceStrideIncrement += Stride->BytesPerLineIn; | |
| 605 DestStrideIncrement += Stride->BytesPerLineOut; | |
| 606 } | |
| 607 | |
| 608 } | |
| 609 else { // General case with more than one extra channel | |
| 610 | |
| 611 cmsUInt8Number* SourcePtr[cmsMAXEXTRACHANNELS]; | |
| 612 cmsUInt8Number* DestPtr[cmsMAXEXTRACHANNELS]; | |
| 613 | |
| 614 cmsUInt32Number SourceStrideIncrements[cmsMAXEXTRACHANNELS]; | |
| 615 cmsUInt32Number DestStrideIncrements[cmsMAXEXTRACHANNELS]; | |
| 616 | |
| 617 memset(SourceStrideIncrements, 0, sizeof(SourceStrideIncrements)); | |
| 618 memset(DestStrideIncrements, 0, sizeof(DestStrideIncrements)); | |
| 619 | |
| 620 // The loop itself | |
| 621 for (i = 0; i < LineCount; i++) { | |
| 622 | |
| 623 // Prepare pointers for the loop | |
| 624 for (j = 0; j < nExtra; j++) { | |
| 625 | |
| 626 SourcePtr[j] = (cmsUInt8Number*)in + SourceStartingOrder[j] + SourceStrideIncrements[j]; | |
| 627 DestPtr[j] = (cmsUInt8Number*)out + DestStartingOrder[j] + DestStrideIncrements[j]; | |
| 628 } | |
| 629 | |
| 630 for (j = 0; j < PixelsPerLine; j++) { | |
| 631 | |
| 632 for (k = 0; k < nExtra; k++) { | |
| 633 | |
| 634 copyValueFn(DestPtr[k], SourcePtr[k]); | |
| 635 | |
| 636 SourcePtr[k] += SourceIncrements[k]; | |
| 637 DestPtr[k] += DestIncrements[k]; | |
| 638 } | |
| 639 } | |
| 640 | |
| 641 for (j = 0; j < nExtra; j++) { | |
| 642 | |
| 643 SourceStrideIncrements[j] += Stride->BytesPerLineIn; | |
| 644 DestStrideIncrements[j] += Stride->BytesPerLineOut; | |
| 645 } | |
| 646 } | |
| 647 } | |
| 648 } |
