1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. Oracle designates this 7 * particular file as subject to the "Classpath" exception as provided 8 * by Oracle in the LICENSE file that accompanied this code. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 */ 24 25 // This file is available under and governed by the GNU General Public 26 // License version 2 only, as published by the Free Software Foundation. 27 // However, the following notice accompanied the original version of this 28 // file: 29 // 30 //--------------------------------------------------------------------------------- 31 // 32 // Little Color Management System 33 // Copyright (c) 1998-2020 Marti Maria Saguer 34 // 35 // Permission is hereby granted, free of charge, to any person obtaining 36 // a copy of this software and associated documentation files (the "Software"), 37 // to deal in the Software without restriction, including without limitation 38 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 39 // and/or sell copies of the Software, and to permit persons to whom the Software 40 // is furnished to do so, subject to the following conditions: 41 // 42 // The above copyright notice and this permission notice shall be included in 43 // all copies or substantial portions of the Software. 44 // 45 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 46 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 47 // THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 48 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 49 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 50 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 51 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 52 // 53 //--------------------------------------------------------------------------------- 54 // 55 56 #include "lcms2_internal.h" 57 58 // This module handles all formats supported by lcms. There are two flavors, 16 bits and 59 // floating point. Floating point is supported only in a subset, those formats holding 60 // cmsFloat32Number (4 bytes per component) and double (marked as 0 bytes per component 61 // as special case) 62 63 // --------------------------------------------------------------------------- 64 65 66 // This macro return words stored as big endian 67 #define CHANGE_ENDIAN(w) (cmsUInt16Number) ((cmsUInt16Number) ((w)<<8)|((w)>>8)) 68 69 // These macros handles reversing (negative) 70 #define REVERSE_FLAVOR_8(x) ((cmsUInt8Number) (0xff-(x))) 71 #define REVERSE_FLAVOR_16(x) ((cmsUInt16Number)(0xffff-(x))) 72 73 // * 0xffff / 0xff00 = (255 * 257) / (255 * 256) = 257 / 256 74 cmsINLINE cmsUInt16Number FomLabV2ToLabV4(cmsUInt16Number x) 75 { 76 int a = (x << 8 | x) >> 8; // * 257 / 256 77 if ( a > 0xffff) return 0xffff; 78 return (cmsUInt16Number) a; 79 } 80 81 // * 0xf00 / 0xffff = * 256 / 257 82 cmsINLINE cmsUInt16Number FomLabV4ToLabV2(cmsUInt16Number x) 83 { 84 return (cmsUInt16Number) (((x << 8) + 0x80) / 257); 85 } 86 87 88 typedef struct { 89 cmsUInt32Number Type; 90 cmsUInt32Number Mask; 91 cmsFormatter16 Frm; 92 93 } cmsFormatters16; 94 95 typedef struct { 96 cmsUInt32Number Type; 97 cmsUInt32Number Mask; 98 cmsFormatterFloat Frm; 99 100 } cmsFormattersFloat; 101 102 103 #define ANYSPACE COLORSPACE_SH(31) 104 #define ANYCHANNELS CHANNELS_SH(15) 105 #define ANYEXTRA EXTRA_SH(7) 106 #define ANYPLANAR PLANAR_SH(1) 107 #define ANYENDIAN ENDIAN16_SH(1) 108 #define ANYSWAP DOSWAP_SH(1) 109 #define ANYSWAPFIRST SWAPFIRST_SH(1) 110 #define ANYFLAVOR FLAVOR_SH(1) 111 112 113 // Suppress waning about info never being used 114 115 #ifdef _MSC_VER 116 #pragma warning(disable : 4100) 117 #endif 118 119 // Unpacking routines (16 bits) ---------------------------------------------------------------------------------------- 120 121 122 // Does almost everything but is slow 123 static 124 cmsUInt8Number* UnrollChunkyBytes(CMSREGISTER _cmsTRANSFORM* info, 125 CMSREGISTER cmsUInt16Number wIn[], 126 CMSREGISTER cmsUInt8Number* accum, 127 CMSREGISTER cmsUInt32Number Stride) 128 { 129 cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat); 130 cmsUInt32Number DoSwap = T_DOSWAP(info ->InputFormat); 131 cmsUInt32Number Reverse = T_FLAVOR(info ->InputFormat); 132 cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> InputFormat); 133 cmsUInt32Number Extra = T_EXTRA(info -> InputFormat); 134 cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst; 135 cmsUInt16Number v; 136 cmsUInt32Number i; 137 138 if (ExtraFirst) { 139 accum += Extra; 140 } 141 142 for (i=0; i < nChan; i++) { 143 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i; 144 145 v = FROM_8_TO_16(*accum); 146 v = Reverse ? REVERSE_FLAVOR_16(v) : v; 147 wIn[index] = v; 148 accum++; 149 } 150 151 if (!ExtraFirst) { 152 accum += Extra; 153 } 154 155 if (Extra == 0 && SwapFirst) { 156 cmsUInt16Number tmp = wIn[0]; 157 158 memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsUInt16Number)); 159 wIn[nChan-1] = tmp; 160 } 161 162 return accum; 163 164 cmsUNUSED_PARAMETER(info); 165 cmsUNUSED_PARAMETER(Stride); 166 167 } 168 169 // Extra channels are just ignored because come in the next planes 170 static 171 cmsUInt8Number* UnrollPlanarBytes(CMSREGISTER _cmsTRANSFORM* info, 172 CMSREGISTER cmsUInt16Number wIn[], 173 CMSREGISTER cmsUInt8Number* accum, 174 CMSREGISTER cmsUInt32Number Stride) 175 { 176 cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat); 177 cmsUInt32Number DoSwap = T_DOSWAP(info ->InputFormat); 178 cmsUInt32Number SwapFirst = T_SWAPFIRST(info ->InputFormat); 179 cmsUInt32Number Reverse = T_FLAVOR(info ->InputFormat); 180 cmsUInt32Number i; 181 cmsUInt8Number* Init = accum; 182 183 if (DoSwap ^ SwapFirst) { 184 accum += T_EXTRA(info -> InputFormat) * Stride; 185 } 186 187 for (i=0; i < nChan; i++) { 188 189 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i; 190 cmsUInt16Number v = FROM_8_TO_16(*accum); 191 192 wIn[index] = Reverse ? REVERSE_FLAVOR_16(v) : v; 193 accum += Stride; 194 } 195 196 return (Init + 1); 197 } 198 199 // Special cases, provided for performance 200 static 201 cmsUInt8Number* Unroll4Bytes(CMSREGISTER _cmsTRANSFORM* info, 202 CMSREGISTER cmsUInt16Number wIn[], 203 CMSREGISTER cmsUInt8Number* accum, 204 CMSREGISTER cmsUInt32Number Stride) 205 { 206 wIn[0] = FROM_8_TO_16(*accum); accum++; // C 207 wIn[1] = FROM_8_TO_16(*accum); accum++; // M 208 wIn[2] = FROM_8_TO_16(*accum); accum++; // Y 209 wIn[3] = FROM_8_TO_16(*accum); accum++; // K 210 211 return accum; 212 213 cmsUNUSED_PARAMETER(info); 214 cmsUNUSED_PARAMETER(Stride); 215 } 216 217 static 218 cmsUInt8Number* Unroll4BytesReverse(CMSREGISTER _cmsTRANSFORM* info, 219 CMSREGISTER cmsUInt16Number wIn[], 220 CMSREGISTER cmsUInt8Number* accum, 221 CMSREGISTER cmsUInt32Number Stride) 222 { 223 wIn[0] = FROM_8_TO_16(REVERSE_FLAVOR_8(*accum)); accum++; // C 224 wIn[1] = FROM_8_TO_16(REVERSE_FLAVOR_8(*accum)); accum++; // M 225 wIn[2] = FROM_8_TO_16(REVERSE_FLAVOR_8(*accum)); accum++; // Y 226 wIn[3] = FROM_8_TO_16(REVERSE_FLAVOR_8(*accum)); accum++; // K 227 228 return accum; 229 230 cmsUNUSED_PARAMETER(info); 231 cmsUNUSED_PARAMETER(Stride); 232 } 233 234 static 235 cmsUInt8Number* Unroll4BytesSwapFirst(CMSREGISTER _cmsTRANSFORM* info, 236 CMSREGISTER cmsUInt16Number wIn[], 237 CMSREGISTER cmsUInt8Number* accum, 238 CMSREGISTER cmsUInt32Number Stride) 239 { 240 wIn[3] = FROM_8_TO_16(*accum); accum++; // K 241 wIn[0] = FROM_8_TO_16(*accum); accum++; // C 242 wIn[1] = FROM_8_TO_16(*accum); accum++; // M 243 wIn[2] = FROM_8_TO_16(*accum); accum++; // Y 244 245 return accum; 246 247 cmsUNUSED_PARAMETER(info); 248 cmsUNUSED_PARAMETER(Stride); 249 } 250 251 // KYMC 252 static 253 cmsUInt8Number* Unroll4BytesSwap(CMSREGISTER _cmsTRANSFORM* info, 254 CMSREGISTER cmsUInt16Number wIn[], 255 CMSREGISTER cmsUInt8Number* accum, 256 CMSREGISTER cmsUInt32Number Stride) 257 { 258 wIn[3] = FROM_8_TO_16(*accum); accum++; // K 259 wIn[2] = FROM_8_TO_16(*accum); accum++; // Y 260 wIn[1] = FROM_8_TO_16(*accum); accum++; // M 261 wIn[0] = FROM_8_TO_16(*accum); accum++; // C 262 263 return accum; 264 265 cmsUNUSED_PARAMETER(info); 266 cmsUNUSED_PARAMETER(Stride); 267 } 268 269 static 270 cmsUInt8Number* Unroll4BytesSwapSwapFirst(CMSREGISTER _cmsTRANSFORM* info, 271 CMSREGISTER cmsUInt16Number wIn[], 272 CMSREGISTER cmsUInt8Number* accum, 273 CMSREGISTER cmsUInt32Number Stride) 274 { 275 wIn[2] = FROM_8_TO_16(*accum); accum++; // K 276 wIn[1] = FROM_8_TO_16(*accum); accum++; // Y 277 wIn[0] = FROM_8_TO_16(*accum); accum++; // M 278 wIn[3] = FROM_8_TO_16(*accum); accum++; // C 279 280 return accum; 281 282 cmsUNUSED_PARAMETER(info); 283 cmsUNUSED_PARAMETER(Stride); 284 } 285 286 static 287 cmsUInt8Number* Unroll3Bytes(CMSREGISTER _cmsTRANSFORM* info, 288 CMSREGISTER cmsUInt16Number wIn[], 289 CMSREGISTER cmsUInt8Number* accum, 290 CMSREGISTER cmsUInt32Number Stride) 291 { 292 wIn[0] = FROM_8_TO_16(*accum); accum++; // R 293 wIn[1] = FROM_8_TO_16(*accum); accum++; // G 294 wIn[2] = FROM_8_TO_16(*accum); accum++; // B 295 296 return accum; 297 298 cmsUNUSED_PARAMETER(info); 299 cmsUNUSED_PARAMETER(Stride); 300 } 301 302 static 303 cmsUInt8Number* Unroll3BytesSkip1Swap(CMSREGISTER _cmsTRANSFORM* info, 304 CMSREGISTER cmsUInt16Number wIn[], 305 CMSREGISTER cmsUInt8Number* accum, 306 CMSREGISTER cmsUInt32Number Stride) 307 { 308 accum++; // A 309 wIn[2] = FROM_8_TO_16(*accum); accum++; // B 310 wIn[1] = FROM_8_TO_16(*accum); accum++; // G 311 wIn[0] = FROM_8_TO_16(*accum); accum++; // R 312 313 return accum; 314 315 cmsUNUSED_PARAMETER(info); 316 cmsUNUSED_PARAMETER(Stride); 317 } 318 319 static 320 cmsUInt8Number* Unroll3BytesSkip1SwapSwapFirst(CMSREGISTER _cmsTRANSFORM* info, 321 CMSREGISTER cmsUInt16Number wIn[], 322 CMSREGISTER cmsUInt8Number* accum, 323 CMSREGISTER cmsUInt32Number Stride) 324 { 325 wIn[2] = FROM_8_TO_16(*accum); accum++; // B 326 wIn[1] = FROM_8_TO_16(*accum); accum++; // G 327 wIn[0] = FROM_8_TO_16(*accum); accum++; // R 328 accum++; // A 329 330 return accum; 331 332 cmsUNUSED_PARAMETER(info); 333 cmsUNUSED_PARAMETER(Stride); 334 } 335 336 static 337 cmsUInt8Number* Unroll3BytesSkip1SwapFirst(CMSREGISTER _cmsTRANSFORM* info, 338 CMSREGISTER cmsUInt16Number wIn[], 339 CMSREGISTER cmsUInt8Number* accum, 340 CMSREGISTER cmsUInt32Number Stride) 341 { 342 accum++; // A 343 wIn[0] = FROM_8_TO_16(*accum); accum++; // R 344 wIn[1] = FROM_8_TO_16(*accum); accum++; // G 345 wIn[2] = FROM_8_TO_16(*accum); accum++; // B 346 347 return accum; 348 349 cmsUNUSED_PARAMETER(info); 350 cmsUNUSED_PARAMETER(Stride); 351 } 352 353 354 // BRG 355 static 356 cmsUInt8Number* Unroll3BytesSwap(CMSREGISTER _cmsTRANSFORM* info, 357 CMSREGISTER cmsUInt16Number wIn[], 358 CMSREGISTER cmsUInt8Number* accum, 359 CMSREGISTER cmsUInt32Number Stride) 360 { 361 wIn[2] = FROM_8_TO_16(*accum); accum++; // B 362 wIn[1] = FROM_8_TO_16(*accum); accum++; // G 363 wIn[0] = FROM_8_TO_16(*accum); accum++; // R 364 365 return accum; 366 367 cmsUNUSED_PARAMETER(info); 368 cmsUNUSED_PARAMETER(Stride); 369 } 370 371 static 372 cmsUInt8Number* UnrollLabV2_8(CMSREGISTER _cmsTRANSFORM* info, 373 CMSREGISTER cmsUInt16Number wIn[], 374 CMSREGISTER cmsUInt8Number* accum, 375 CMSREGISTER cmsUInt32Number Stride) 376 { 377 wIn[0] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // L 378 wIn[1] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // a 379 wIn[2] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // b 380 381 return accum; 382 383 cmsUNUSED_PARAMETER(info); 384 cmsUNUSED_PARAMETER(Stride); 385 } 386 387 static 388 cmsUInt8Number* UnrollALabV2_8(CMSREGISTER _cmsTRANSFORM* info, 389 CMSREGISTER cmsUInt16Number wIn[], 390 CMSREGISTER cmsUInt8Number* accum, 391 CMSREGISTER cmsUInt32Number Stride) 392 { 393 accum++; // A 394 wIn[0] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // L 395 wIn[1] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // a 396 wIn[2] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // b 397 398 return accum; 399 400 cmsUNUSED_PARAMETER(info); 401 cmsUNUSED_PARAMETER(Stride); 402 } 403 404 static 405 cmsUInt8Number* UnrollLabV2_16(CMSREGISTER _cmsTRANSFORM* info, 406 CMSREGISTER cmsUInt16Number wIn[], 407 CMSREGISTER cmsUInt8Number* accum, 408 CMSREGISTER cmsUInt32Number Stride) 409 { 410 wIn[0] = FomLabV2ToLabV4(*(cmsUInt16Number*) accum); accum += 2; // L 411 wIn[1] = FomLabV2ToLabV4(*(cmsUInt16Number*) accum); accum += 2; // a 412 wIn[2] = FomLabV2ToLabV4(*(cmsUInt16Number*) accum); accum += 2; // b 413 414 return accum; 415 416 cmsUNUSED_PARAMETER(info); 417 cmsUNUSED_PARAMETER(Stride); 418 } 419 420 // for duplex 421 static 422 cmsUInt8Number* Unroll2Bytes(CMSREGISTER _cmsTRANSFORM* info, 423 CMSREGISTER cmsUInt16Number wIn[], 424 CMSREGISTER cmsUInt8Number* accum, 425 CMSREGISTER cmsUInt32Number Stride) 426 { 427 wIn[0] = FROM_8_TO_16(*accum); accum++; // ch1 428 wIn[1] = FROM_8_TO_16(*accum); accum++; // ch2 429 430 return accum; 431 432 cmsUNUSED_PARAMETER(info); 433 cmsUNUSED_PARAMETER(Stride); 434 } 435 436 437 438 439 // Monochrome duplicates L into RGB for null-transforms 440 static 441 cmsUInt8Number* Unroll1Byte(CMSREGISTER _cmsTRANSFORM* info, 442 CMSREGISTER cmsUInt16Number wIn[], 443 CMSREGISTER cmsUInt8Number* accum, 444 CMSREGISTER cmsUInt32Number Stride) 445 { 446 wIn[0] = wIn[1] = wIn[2] = FROM_8_TO_16(*accum); accum++; // L 447 448 return accum; 449 450 cmsUNUSED_PARAMETER(info); 451 cmsUNUSED_PARAMETER(Stride); 452 } 453 454 455 static 456 cmsUInt8Number* Unroll1ByteSkip1(CMSREGISTER _cmsTRANSFORM* info, 457 CMSREGISTER cmsUInt16Number wIn[], 458 CMSREGISTER cmsUInt8Number* accum, 459 CMSREGISTER cmsUInt32Number Stride) 460 { 461 wIn[0] = wIn[1] = wIn[2] = FROM_8_TO_16(*accum); accum++; // L 462 accum += 1; 463 464 return accum; 465 466 cmsUNUSED_PARAMETER(info); 467 cmsUNUSED_PARAMETER(Stride); 468 } 469 470 static 471 cmsUInt8Number* Unroll1ByteSkip2(CMSREGISTER _cmsTRANSFORM* info, 472 CMSREGISTER cmsUInt16Number wIn[], 473 CMSREGISTER cmsUInt8Number* accum, 474 CMSREGISTER cmsUInt32Number Stride) 475 { 476 wIn[0] = wIn[1] = wIn[2] = FROM_8_TO_16(*accum); accum++; // L 477 accum += 2; 478 479 return accum; 480 481 cmsUNUSED_PARAMETER(info); 482 cmsUNUSED_PARAMETER(Stride); 483 } 484 485 static 486 cmsUInt8Number* Unroll1ByteReversed(CMSREGISTER _cmsTRANSFORM* info, 487 CMSREGISTER cmsUInt16Number wIn[], 488 CMSREGISTER cmsUInt8Number* accum, 489 CMSREGISTER cmsUInt32Number Stride) 490 { 491 wIn[0] = wIn[1] = wIn[2] = REVERSE_FLAVOR_16(FROM_8_TO_16(*accum)); accum++; // L 492 493 return accum; 494 495 cmsUNUSED_PARAMETER(info); 496 cmsUNUSED_PARAMETER(Stride); 497 } 498 499 500 static 501 cmsUInt8Number* UnrollAnyWords(CMSREGISTER _cmsTRANSFORM* info, 502 CMSREGISTER cmsUInt16Number wIn[], 503 CMSREGISTER cmsUInt8Number* accum, 504 CMSREGISTER cmsUInt32Number Stride) 505 { 506 cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat); 507 cmsUInt32Number SwapEndian = T_ENDIAN16(info -> InputFormat); 508 cmsUInt32Number DoSwap = T_DOSWAP(info ->InputFormat); 509 cmsUInt32Number Reverse = T_FLAVOR(info ->InputFormat); 510 cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> InputFormat); 511 cmsUInt32Number Extra = T_EXTRA(info -> InputFormat); 512 cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst; 513 cmsUInt32Number i; 514 515 if (ExtraFirst) { 516 accum += Extra * sizeof(cmsUInt16Number); 517 } 518 519 for (i=0; i < nChan; i++) { 520 521 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i; 522 cmsUInt16Number v = *(cmsUInt16Number*) accum; 523 524 if (SwapEndian) 525 v = CHANGE_ENDIAN(v); 526 527 wIn[index] = Reverse ? REVERSE_FLAVOR_16(v) : v; 528 529 accum += sizeof(cmsUInt16Number); 530 } 531 532 if (!ExtraFirst) { 533 accum += Extra * sizeof(cmsUInt16Number); 534 } 535 536 if (Extra == 0 && SwapFirst) { 537 538 cmsUInt16Number tmp = wIn[0]; 539 540 memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsUInt16Number)); 541 wIn[nChan-1] = tmp; 542 } 543 544 return accum; 545 546 cmsUNUSED_PARAMETER(Stride); 547 } 548 549 static 550 cmsUInt8Number* UnrollPlanarWords(CMSREGISTER _cmsTRANSFORM* info, 551 CMSREGISTER cmsUInt16Number wIn[], 552 CMSREGISTER cmsUInt8Number* accum, 553 CMSREGISTER cmsUInt32Number Stride) 554 { 555 cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat); 556 cmsUInt32Number DoSwap= T_DOSWAP(info ->InputFormat); 557 cmsUInt32Number Reverse= T_FLAVOR(info ->InputFormat); 558 cmsUInt32Number SwapEndian = T_ENDIAN16(info -> InputFormat); 559 cmsUInt32Number i; 560 cmsUInt8Number* Init = accum; 561 562 if (DoSwap) { 563 accum += T_EXTRA(info -> InputFormat) * Stride; 564 } 565 566 for (i=0; i < nChan; i++) { 567 568 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i; 569 cmsUInt16Number v = *(cmsUInt16Number*) accum; 570 571 if (SwapEndian) 572 v = CHANGE_ENDIAN(v); 573 574 wIn[index] = Reverse ? REVERSE_FLAVOR_16(v) : v; 575 576 accum += Stride; 577 } 578 579 return (Init + sizeof(cmsUInt16Number)); 580 } 581 582 583 static 584 cmsUInt8Number* Unroll4Words(CMSREGISTER _cmsTRANSFORM* info, 585 CMSREGISTER cmsUInt16Number wIn[], 586 CMSREGISTER cmsUInt8Number* accum, 587 CMSREGISTER cmsUInt32Number Stride) 588 { 589 wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // C 590 wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // M 591 wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // Y 592 wIn[3] = *(cmsUInt16Number*) accum; accum+= 2; // K 593 594 return accum; 595 596 cmsUNUSED_PARAMETER(info); 597 cmsUNUSED_PARAMETER(Stride); 598 } 599 600 static 601 cmsUInt8Number* Unroll4WordsReverse(CMSREGISTER _cmsTRANSFORM* info, 602 CMSREGISTER cmsUInt16Number wIn[], 603 CMSREGISTER cmsUInt8Number* accum, 604 CMSREGISTER cmsUInt32Number Stride) 605 { 606 wIn[0] = REVERSE_FLAVOR_16(*(cmsUInt16Number*) accum); accum+= 2; // C 607 wIn[1] = REVERSE_FLAVOR_16(*(cmsUInt16Number*) accum); accum+= 2; // M 608 wIn[2] = REVERSE_FLAVOR_16(*(cmsUInt16Number*) accum); accum+= 2; // Y 609 wIn[3] = REVERSE_FLAVOR_16(*(cmsUInt16Number*) accum); accum+= 2; // K 610 611 return accum; 612 613 cmsUNUSED_PARAMETER(info); 614 cmsUNUSED_PARAMETER(Stride); 615 } 616 617 static 618 cmsUInt8Number* Unroll4WordsSwapFirst(CMSREGISTER _cmsTRANSFORM* info, 619 CMSREGISTER cmsUInt16Number wIn[], 620 CMSREGISTER cmsUInt8Number* accum, 621 CMSREGISTER cmsUInt32Number Stride) 622 { 623 wIn[3] = *(cmsUInt16Number*) accum; accum+= 2; // K 624 wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // C 625 wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // M 626 wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // Y 627 628 return accum; 629 630 cmsUNUSED_PARAMETER(info); 631 cmsUNUSED_PARAMETER(Stride); 632 } 633 634 // KYMC 635 static 636 cmsUInt8Number* Unroll4WordsSwap(CMSREGISTER _cmsTRANSFORM* info, 637 CMSREGISTER cmsUInt16Number wIn[], 638 CMSREGISTER cmsUInt8Number* accum, 639 CMSREGISTER cmsUInt32Number Stride) 640 { 641 wIn[3] = *(cmsUInt16Number*) accum; accum+= 2; // K 642 wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // Y 643 wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // M 644 wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // C 645 646 return accum; 647 648 cmsUNUSED_PARAMETER(info); 649 cmsUNUSED_PARAMETER(Stride); 650 } 651 652 static 653 cmsUInt8Number* Unroll4WordsSwapSwapFirst(CMSREGISTER _cmsTRANSFORM* info, 654 CMSREGISTER cmsUInt16Number wIn[], 655 CMSREGISTER cmsUInt8Number* accum, 656 CMSREGISTER cmsUInt32Number Stride) 657 { 658 wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // K 659 wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // Y 660 wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // M 661 wIn[3] = *(cmsUInt16Number*) accum; accum+= 2; // C 662 663 return accum; 664 665 cmsUNUSED_PARAMETER(info); 666 cmsUNUSED_PARAMETER(Stride); 667 } 668 669 static 670 cmsUInt8Number* Unroll3Words(CMSREGISTER _cmsTRANSFORM* info, 671 CMSREGISTER cmsUInt16Number wIn[], 672 CMSREGISTER cmsUInt8Number* accum, 673 CMSREGISTER cmsUInt32Number Stride) 674 { 675 wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // C R 676 wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // M G 677 wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // Y B 678 679 return accum; 680 681 cmsUNUSED_PARAMETER(info); 682 cmsUNUSED_PARAMETER(Stride); 683 } 684 685 static 686 cmsUInt8Number* Unroll3WordsSwap(CMSREGISTER _cmsTRANSFORM* info, 687 CMSREGISTER cmsUInt16Number wIn[], 688 CMSREGISTER cmsUInt8Number* accum, 689 CMSREGISTER cmsUInt32Number Stride) 690 { 691 wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // C R 692 wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // M G 693 wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // Y B 694 695 return accum; 696 697 cmsUNUSED_PARAMETER(info); 698 cmsUNUSED_PARAMETER(Stride); 699 } 700 701 static 702 cmsUInt8Number* Unroll3WordsSkip1Swap(CMSREGISTER _cmsTRANSFORM* info, 703 CMSREGISTER cmsUInt16Number wIn[], 704 CMSREGISTER cmsUInt8Number* accum, 705 CMSREGISTER cmsUInt32Number Stride) 706 { 707 accum += 2; // A 708 wIn[2] = *(cmsUInt16Number*) accum; accum += 2; // R 709 wIn[1] = *(cmsUInt16Number*) accum; accum += 2; // G 710 wIn[0] = *(cmsUInt16Number*) accum; accum += 2; // B 711 712 return accum; 713 714 cmsUNUSED_PARAMETER(info); 715 cmsUNUSED_PARAMETER(Stride); 716 } 717 718 static 719 cmsUInt8Number* Unroll3WordsSkip1SwapFirst(CMSREGISTER _cmsTRANSFORM* info, 720 CMSREGISTER cmsUInt16Number wIn[], 721 CMSREGISTER cmsUInt8Number* accum, 722 CMSREGISTER cmsUInt32Number Stride) 723 { 724 accum += 2; // A 725 wIn[0] = *(cmsUInt16Number*) accum; accum += 2; // R 726 wIn[1] = *(cmsUInt16Number*) accum; accum += 2; // G 727 wIn[2] = *(cmsUInt16Number*) accum; accum += 2; // B 728 729 return accum; 730 731 cmsUNUSED_PARAMETER(info); 732 cmsUNUSED_PARAMETER(Stride); 733 } 734 735 static 736 cmsUInt8Number* Unroll1Word(CMSREGISTER _cmsTRANSFORM* info, 737 CMSREGISTER cmsUInt16Number wIn[], 738 CMSREGISTER cmsUInt8Number* accum, 739 CMSREGISTER cmsUInt32Number Stride) 740 { 741 wIn[0] = wIn[1] = wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // L 742 743 return accum; 744 745 cmsUNUSED_PARAMETER(info); 746 cmsUNUSED_PARAMETER(Stride); 747 } 748 749 static 750 cmsUInt8Number* Unroll1WordReversed(CMSREGISTER _cmsTRANSFORM* info, 751 CMSREGISTER cmsUInt16Number wIn[], 752 CMSREGISTER cmsUInt8Number* accum, 753 CMSREGISTER cmsUInt32Number Stride) 754 { 755 wIn[0] = wIn[1] = wIn[2] = REVERSE_FLAVOR_16(*(cmsUInt16Number*) accum); accum+= 2; 756 757 return accum; 758 759 cmsUNUSED_PARAMETER(info); 760 cmsUNUSED_PARAMETER(Stride); 761 } 762 763 static 764 cmsUInt8Number* Unroll1WordSkip3(CMSREGISTER _cmsTRANSFORM* info, 765 CMSREGISTER cmsUInt16Number wIn[], 766 CMSREGISTER cmsUInt8Number* accum, 767 CMSREGISTER cmsUInt32Number Stride) 768 { 769 wIn[0] = wIn[1] = wIn[2] = *(cmsUInt16Number*) accum; 770 771 accum += 8; 772 773 return accum; 774 775 cmsUNUSED_PARAMETER(info); 776 cmsUNUSED_PARAMETER(Stride); 777 } 778 779 static 780 cmsUInt8Number* Unroll2Words(CMSREGISTER _cmsTRANSFORM* info, 781 CMSREGISTER cmsUInt16Number wIn[], 782 CMSREGISTER cmsUInt8Number* accum, 783 CMSREGISTER cmsUInt32Number Stride) 784 { 785 wIn[0] = *(cmsUInt16Number*) accum; accum += 2; // ch1 786 wIn[1] = *(cmsUInt16Number*) accum; accum += 2; // ch2 787 788 return accum; 789 790 cmsUNUSED_PARAMETER(info); 791 cmsUNUSED_PARAMETER(Stride); 792 } 793 794 795 // This is a conversion of Lab double to 16 bits 796 static 797 cmsUInt8Number* UnrollLabDoubleTo16(CMSREGISTER _cmsTRANSFORM* info, 798 CMSREGISTER cmsUInt16Number wIn[], 799 CMSREGISTER cmsUInt8Number* accum, 800 CMSREGISTER cmsUInt32Number Stride) 801 { 802 if (T_PLANAR(info -> InputFormat)) { 803 804 cmsCIELab Lab; 805 cmsUInt8Number* pos_L; 806 cmsUInt8Number* pos_a; 807 cmsUInt8Number* pos_b; 808 809 pos_L = accum; 810 pos_a = accum + Stride; 811 pos_b = accum + Stride * 2; 812 813 Lab.L = *(cmsFloat64Number*) pos_L; 814 Lab.a = *(cmsFloat64Number*) pos_a; 815 Lab.b = *(cmsFloat64Number*) pos_b; 816 817 cmsFloat2LabEncoded(wIn, &Lab); 818 return accum + sizeof(cmsFloat64Number); 819 } 820 else { 821 822 cmsFloat2LabEncoded(wIn, (cmsCIELab*) accum); 823 accum += sizeof(cmsCIELab) + T_EXTRA(info ->InputFormat) * sizeof(cmsFloat64Number); 824 return accum; 825 } 826 } 827 828 829 // This is a conversion of Lab float to 16 bits 830 static 831 cmsUInt8Number* UnrollLabFloatTo16(CMSREGISTER _cmsTRANSFORM* info, 832 CMSREGISTER cmsUInt16Number wIn[], 833 CMSREGISTER cmsUInt8Number* accum, 834 CMSREGISTER cmsUInt32Number Stride) 835 { 836 cmsCIELab Lab; 837 838 if (T_PLANAR(info -> InputFormat)) { 839 840 cmsUInt8Number* pos_L; 841 cmsUInt8Number* pos_a; 842 cmsUInt8Number* pos_b; 843 844 pos_L = accum; 845 pos_a = accum + Stride; 846 pos_b = accum + Stride * 2; 847 848 Lab.L = *(cmsFloat32Number*)pos_L; 849 Lab.a = *(cmsFloat32Number*)pos_a; 850 Lab.b = *(cmsFloat32Number*)pos_b; 851 852 cmsFloat2LabEncoded(wIn, &Lab); 853 return accum + sizeof(cmsFloat32Number); 854 } 855 else { 856 857 Lab.L = ((cmsFloat32Number*) accum)[0]; 858 Lab.a = ((cmsFloat32Number*) accum)[1]; 859 Lab.b = ((cmsFloat32Number*) accum)[2]; 860 861 cmsFloat2LabEncoded(wIn, &Lab); 862 accum += (3 + T_EXTRA(info ->InputFormat)) * sizeof(cmsFloat32Number); 863 return accum; 864 } 865 } 866 867 // This is a conversion of XYZ double to 16 bits 868 static 869 cmsUInt8Number* UnrollXYZDoubleTo16(CMSREGISTER _cmsTRANSFORM* info, 870 CMSREGISTER cmsUInt16Number wIn[], 871 CMSREGISTER cmsUInt8Number* accum, 872 CMSREGISTER cmsUInt32Number Stride) 873 { 874 if (T_PLANAR(info -> InputFormat)) { 875 876 cmsCIEXYZ XYZ; 877 cmsUInt8Number* pos_X; 878 cmsUInt8Number* pos_Y; 879 cmsUInt8Number* pos_Z; 880 881 pos_X = accum; 882 pos_Y = accum + Stride; 883 pos_Z = accum + Stride * 2; 884 885 XYZ.X = *(cmsFloat64Number*)pos_X; 886 XYZ.Y = *(cmsFloat64Number*)pos_Y; 887 XYZ.Z = *(cmsFloat64Number*)pos_Z; 888 889 cmsFloat2XYZEncoded(wIn, &XYZ); 890 891 return accum + sizeof(cmsFloat64Number); 892 893 } 894 895 else { 896 cmsFloat2XYZEncoded(wIn, (cmsCIEXYZ*) accum); 897 accum += sizeof(cmsCIEXYZ) + T_EXTRA(info ->InputFormat) * sizeof(cmsFloat64Number); 898 899 return accum; 900 } 901 } 902 903 // This is a conversion of XYZ float to 16 bits 904 static 905 cmsUInt8Number* UnrollXYZFloatTo16(CMSREGISTER _cmsTRANSFORM* info, 906 CMSREGISTER cmsUInt16Number wIn[], 907 CMSREGISTER cmsUInt8Number* accum, 908 CMSREGISTER cmsUInt32Number Stride) 909 { 910 if (T_PLANAR(info -> InputFormat)) { 911 912 cmsCIEXYZ XYZ; 913 cmsUInt8Number* pos_X; 914 cmsUInt8Number* pos_Y; 915 cmsUInt8Number* pos_Z; 916 917 pos_X = accum; 918 pos_Y = accum + Stride; 919 pos_Z = accum + Stride * 2; 920 921 XYZ.X = *(cmsFloat32Number*)pos_X; 922 XYZ.Y = *(cmsFloat32Number*)pos_Y; 923 XYZ.Z = *(cmsFloat32Number*)pos_Z; 924 925 cmsFloat2XYZEncoded(wIn, &XYZ); 926 927 return accum + sizeof(cmsFloat32Number); 928 929 } 930 931 else { 932 cmsFloat32Number* Pt = (cmsFloat32Number*) accum; 933 cmsCIEXYZ XYZ; 934 935 XYZ.X = Pt[0]; 936 XYZ.Y = Pt[1]; 937 XYZ.Z = Pt[2]; 938 cmsFloat2XYZEncoded(wIn, &XYZ); 939 940 accum += 3 * sizeof(cmsFloat32Number) + T_EXTRA(info ->InputFormat) * sizeof(cmsFloat32Number); 941 942 return accum; 943 } 944 } 945 946 // Check if space is marked as ink 947 cmsINLINE cmsBool IsInkSpace(cmsUInt32Number Type) 948 { 949 switch (T_COLORSPACE(Type)) { 950 951 case PT_CMY: 952 case PT_CMYK: 953 case PT_MCH5: 954 case PT_MCH6: 955 case PT_MCH7: 956 case PT_MCH8: 957 case PT_MCH9: 958 case PT_MCH10: 959 case PT_MCH11: 960 case PT_MCH12: 961 case PT_MCH13: 962 case PT_MCH14: 963 case PT_MCH15: return TRUE; 964 965 default: return FALSE; 966 } 967 } 968 969 // Return the size in bytes of a given formatter 970 static 971 cmsUInt32Number PixelSize(cmsUInt32Number Format) 972 { 973 cmsUInt32Number fmt_bytes = T_BYTES(Format); 974 975 // For double, the T_BYTES field is zero 976 if (fmt_bytes == 0) 977 return sizeof(cmsUInt64Number); 978 979 // Otherwise, it is already correct for all formats 980 return fmt_bytes; 981 } 982 983 // Inks does come in percentage, remaining cases are between 0..1.0, again to 16 bits 984 static 985 cmsUInt8Number* UnrollDoubleTo16(CMSREGISTER _cmsTRANSFORM* info, 986 CMSREGISTER cmsUInt16Number wIn[], 987 CMSREGISTER cmsUInt8Number* accum, 988 CMSREGISTER cmsUInt32Number Stride) 989 { 990 991 cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat); 992 cmsUInt32Number DoSwap = T_DOSWAP(info ->InputFormat); 993 cmsUInt32Number Reverse = T_FLAVOR(info ->InputFormat); 994 cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> InputFormat); 995 cmsUInt32Number Extra = T_EXTRA(info -> InputFormat); 996 cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst; 997 cmsUInt32Number Planar = T_PLANAR(info -> InputFormat); 998 cmsFloat64Number v; 999 cmsUInt16Number vi; 1000 cmsUInt32Number i, start = 0; 1001 cmsFloat64Number maximum = IsInkSpace(info ->InputFormat) ? 655.35 : 65535.0; 1002 1003 1004 Stride /= PixelSize(info->InputFormat); 1005 1006 if (ExtraFirst) 1007 start = Extra; 1008 1009 for (i=0; i < nChan; i++) { 1010 1011 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i; 1012 1013 if (Planar) 1014 v = (cmsFloat32Number) ((cmsFloat64Number*) accum)[(i + start) * Stride]; 1015 else 1016 v = (cmsFloat32Number) ((cmsFloat64Number*) accum)[i + start]; 1017 1018 vi = _cmsQuickSaturateWord(v * maximum); 1019 1020 if (Reverse) 1021 vi = REVERSE_FLAVOR_16(vi); 1022 1023 wIn[index] = vi; 1024 } 1025 1026 1027 if (Extra == 0 && SwapFirst) { 1028 cmsUInt16Number tmp = wIn[0]; 1029 1030 memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsUInt16Number)); 1031 wIn[nChan-1] = tmp; 1032 } 1033 1034 if (T_PLANAR(info -> InputFormat)) 1035 return accum + sizeof(cmsFloat64Number); 1036 else 1037 return accum + (nChan + Extra) * sizeof(cmsFloat64Number); 1038 } 1039 1040 1041 1042 static 1043 cmsUInt8Number* UnrollFloatTo16(CMSREGISTER _cmsTRANSFORM* info, 1044 CMSREGISTER cmsUInt16Number wIn[], 1045 CMSREGISTER cmsUInt8Number* accum, 1046 CMSREGISTER cmsUInt32Number Stride) 1047 { 1048 1049 cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat); 1050 cmsUInt32Number DoSwap = T_DOSWAP(info ->InputFormat); 1051 cmsUInt32Number Reverse = T_FLAVOR(info ->InputFormat); 1052 cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> InputFormat); 1053 cmsUInt32Number Extra = T_EXTRA(info -> InputFormat); 1054 cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst; 1055 cmsUInt32Number Planar = T_PLANAR(info -> InputFormat); 1056 cmsFloat32Number v; 1057 cmsUInt16Number vi; 1058 cmsUInt32Number i, start = 0; 1059 cmsFloat64Number maximum = IsInkSpace(info ->InputFormat) ? 655.35 : 65535.0; 1060 1061 Stride /= PixelSize(info->InputFormat); 1062 1063 if (ExtraFirst) 1064 start = Extra; 1065 1066 for (i=0; i < nChan; i++) { 1067 1068 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i; 1069 1070 if (Planar) 1071 v = (cmsFloat32Number) ((cmsFloat32Number*) accum)[(i + start) * Stride]; 1072 else 1073 v = (cmsFloat32Number) ((cmsFloat32Number*) accum)[i + start]; 1074 1075 vi = _cmsQuickSaturateWord(v * maximum); 1076 1077 if (Reverse) 1078 vi = REVERSE_FLAVOR_16(vi); 1079 1080 wIn[index] = vi; 1081 } 1082 1083 1084 if (Extra == 0 && SwapFirst) { 1085 cmsUInt16Number tmp = wIn[0]; 1086 1087 memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsUInt16Number)); 1088 wIn[nChan-1] = tmp; 1089 } 1090 1091 if (T_PLANAR(info -> InputFormat)) 1092 return accum + sizeof(cmsFloat32Number); 1093 else 1094 return accum + (nChan + Extra) * sizeof(cmsFloat32Number); 1095 } 1096 1097 1098 1099 1100 // For 1 channel, we need to duplicate data (it comes in 0..1.0 range) 1101 static 1102 cmsUInt8Number* UnrollDouble1Chan(CMSREGISTER _cmsTRANSFORM* info, 1103 CMSREGISTER cmsUInt16Number wIn[], 1104 CMSREGISTER cmsUInt8Number* accum, 1105 CMSREGISTER cmsUInt32Number Stride) 1106 { 1107 cmsFloat64Number* Inks = (cmsFloat64Number*) accum; 1108 1109 wIn[0] = wIn[1] = wIn[2] = _cmsQuickSaturateWord(Inks[0] * 65535.0); 1110 1111 return accum + sizeof(cmsFloat64Number); 1112 1113 cmsUNUSED_PARAMETER(info); 1114 cmsUNUSED_PARAMETER(Stride); 1115 } 1116 1117 //------------------------------------------------------------------------------------------------------------------- 1118 1119 // For anything going from cmsFloat32Number 1120 static 1121 cmsUInt8Number* UnrollFloatsToFloat(_cmsTRANSFORM* info, 1122 cmsFloat32Number wIn[], 1123 cmsUInt8Number* accum, 1124 cmsUInt32Number Stride) 1125 { 1126 1127 cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat); 1128 cmsUInt32Number DoSwap = T_DOSWAP(info ->InputFormat); 1129 cmsUInt32Number Reverse = T_FLAVOR(info ->InputFormat); 1130 cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> InputFormat); 1131 cmsUInt32Number Extra = T_EXTRA(info -> InputFormat); 1132 cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst; 1133 cmsUInt32Number Planar = T_PLANAR(info -> InputFormat); 1134 cmsFloat32Number v; 1135 cmsUInt32Number i, start = 0; 1136 cmsFloat32Number maximum = IsInkSpace(info ->InputFormat) ? 100.0F : 1.0F; 1137 1138 Stride /= PixelSize(info->InputFormat); 1139 1140 if (ExtraFirst) 1141 start = Extra; 1142 1143 for (i=0; i < nChan; i++) { 1144 1145 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i; 1146 1147 if (Planar) 1148 v = (cmsFloat32Number) ((cmsFloat32Number*) accum)[(i + start) * Stride]; 1149 else 1150 v = (cmsFloat32Number) ((cmsFloat32Number*) accum)[i + start]; 1151 1152 v /= maximum; 1153 1154 wIn[index] = Reverse ? 1 - v : v; 1155 } 1156 1157 1158 if (Extra == 0 && SwapFirst) { 1159 cmsFloat32Number tmp = wIn[0]; 1160 1161 memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsFloat32Number)); 1162 wIn[nChan-1] = tmp; 1163 } 1164 1165 if (T_PLANAR(info -> InputFormat)) 1166 return accum + sizeof(cmsFloat32Number); 1167 else 1168 return accum + (nChan + Extra) * sizeof(cmsFloat32Number); 1169 } 1170 1171 // For anything going from double 1172 1173 static 1174 cmsUInt8Number* UnrollDoublesToFloat(_cmsTRANSFORM* info, 1175 cmsFloat32Number wIn[], 1176 cmsUInt8Number* accum, 1177 cmsUInt32Number Stride) 1178 { 1179 1180 cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat); 1181 cmsUInt32Number DoSwap = T_DOSWAP(info ->InputFormat); 1182 cmsUInt32Number Reverse = T_FLAVOR(info ->InputFormat); 1183 cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> InputFormat); 1184 cmsUInt32Number Extra = T_EXTRA(info -> InputFormat); 1185 cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst; 1186 cmsUInt32Number Planar = T_PLANAR(info -> InputFormat); 1187 cmsFloat64Number v; 1188 cmsUInt32Number i, start = 0; 1189 cmsFloat64Number maximum = IsInkSpace(info ->InputFormat) ? 100.0 : 1.0; 1190 1191 Stride /= PixelSize(info->InputFormat); 1192 1193 if (ExtraFirst) 1194 start = Extra; 1195 1196 for (i=0; i < nChan; i++) { 1197 1198 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i; 1199 1200 if (Planar) 1201 v = (cmsFloat64Number) ((cmsFloat64Number*) accum)[(i + start) * Stride]; 1202 else 1203 v = (cmsFloat64Number) ((cmsFloat64Number*) accum)[i + start]; 1204 1205 v /= maximum; 1206 1207 wIn[index] = (cmsFloat32Number) (Reverse ? 1.0 - v : v); 1208 } 1209 1210 1211 if (Extra == 0 && SwapFirst) { 1212 cmsFloat32Number tmp = wIn[0]; 1213 1214 memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsFloat32Number)); 1215 wIn[nChan-1] = tmp; 1216 } 1217 1218 if (T_PLANAR(info -> InputFormat)) 1219 return accum + sizeof(cmsFloat64Number); 1220 else 1221 return accum + (nChan + Extra) * sizeof(cmsFloat64Number); 1222 } 1223 1224 1225 1226 // From Lab double to cmsFloat32Number 1227 static 1228 cmsUInt8Number* UnrollLabDoubleToFloat(_cmsTRANSFORM* info, 1229 cmsFloat32Number wIn[], 1230 cmsUInt8Number* accum, 1231 cmsUInt32Number Stride) 1232 { 1233 cmsFloat64Number* Pt = (cmsFloat64Number*) accum; 1234 1235 if (T_PLANAR(info -> InputFormat)) { 1236 1237 Stride /= PixelSize(info->InputFormat); 1238 1239 wIn[0] = (cmsFloat32Number) (Pt[0] / 100.0); // from 0..100 to 0..1 1240 wIn[1] = (cmsFloat32Number) ((Pt[Stride] + 128) / 255.0); // form -128..+127 to 0..1 1241 wIn[2] = (cmsFloat32Number) ((Pt[Stride*2] + 128) / 255.0); 1242 1243 return accum + sizeof(cmsFloat64Number); 1244 } 1245 else { 1246 1247 wIn[0] = (cmsFloat32Number) (Pt[0] / 100.0); // from 0..100 to 0..1 1248 wIn[1] = (cmsFloat32Number) ((Pt[1] + 128) / 255.0); // form -128..+127 to 0..1 1249 wIn[2] = (cmsFloat32Number) ((Pt[2] + 128) / 255.0); 1250 1251 accum += sizeof(cmsFloat64Number)*(3 + T_EXTRA(info ->InputFormat)); 1252 return accum; 1253 } 1254 } 1255 1256 // From Lab double to cmsFloat32Number 1257 static 1258 cmsUInt8Number* UnrollLabFloatToFloat(_cmsTRANSFORM* info, 1259 cmsFloat32Number wIn[], 1260 cmsUInt8Number* accum, 1261 cmsUInt32Number Stride) 1262 { 1263 cmsFloat32Number* Pt = (cmsFloat32Number*) accum; 1264 1265 if (T_PLANAR(info -> InputFormat)) { 1266 1267 Stride /= PixelSize(info->InputFormat); 1268 1269 wIn[0] = (cmsFloat32Number) (Pt[0] / 100.0); // from 0..100 to 0..1 1270 wIn[1] = (cmsFloat32Number) ((Pt[Stride] + 128) / 255.0); // form -128..+127 to 0..1 1271 wIn[2] = (cmsFloat32Number) ((Pt[Stride*2] + 128) / 255.0); 1272 1273 return accum + sizeof(cmsFloat32Number); 1274 } 1275 else { 1276 1277 wIn[0] = (cmsFloat32Number) (Pt[0] / 100.0); // from 0..100 to 0..1 1278 wIn[1] = (cmsFloat32Number) ((Pt[1] + 128) / 255.0); // form -128..+127 to 0..1 1279 wIn[2] = (cmsFloat32Number) ((Pt[2] + 128) / 255.0); 1280 1281 accum += sizeof(cmsFloat32Number)*(3 + T_EXTRA(info ->InputFormat)); 1282 return accum; 1283 } 1284 } 1285 1286 1287 1288 // 1.15 fixed point, that means maximum value is MAX_ENCODEABLE_XYZ (0xFFFF) 1289 static 1290 cmsUInt8Number* UnrollXYZDoubleToFloat(_cmsTRANSFORM* info, 1291 cmsFloat32Number wIn[], 1292 cmsUInt8Number* accum, 1293 cmsUInt32Number Stride) 1294 { 1295 cmsFloat64Number* Pt = (cmsFloat64Number*) accum; 1296 1297 if (T_PLANAR(info -> InputFormat)) { 1298 1299 Stride /= PixelSize(info->InputFormat); 1300 1301 wIn[0] = (cmsFloat32Number) (Pt[0] / MAX_ENCODEABLE_XYZ); 1302 wIn[1] = (cmsFloat32Number) (Pt[Stride] / MAX_ENCODEABLE_XYZ); 1303 wIn[2] = (cmsFloat32Number) (Pt[Stride*2] / MAX_ENCODEABLE_XYZ); 1304 1305 return accum + sizeof(cmsFloat64Number); 1306 } 1307 else { 1308 1309 wIn[0] = (cmsFloat32Number) (Pt[0] / MAX_ENCODEABLE_XYZ); 1310 wIn[1] = (cmsFloat32Number) (Pt[1] / MAX_ENCODEABLE_XYZ); 1311 wIn[2] = (cmsFloat32Number) (Pt[2] / MAX_ENCODEABLE_XYZ); 1312 1313 accum += sizeof(cmsFloat64Number)*(3 + T_EXTRA(info ->InputFormat)); 1314 return accum; 1315 } 1316 } 1317 1318 static 1319 cmsUInt8Number* UnrollXYZFloatToFloat(_cmsTRANSFORM* info, 1320 cmsFloat32Number wIn[], 1321 cmsUInt8Number* accum, 1322 cmsUInt32Number Stride) 1323 { 1324 cmsFloat32Number* Pt = (cmsFloat32Number*) accum; 1325 1326 if (T_PLANAR(info -> InputFormat)) { 1327 1328 Stride /= PixelSize(info->InputFormat); 1329 1330 wIn[0] = (cmsFloat32Number) (Pt[0] / MAX_ENCODEABLE_XYZ); 1331 wIn[1] = (cmsFloat32Number) (Pt[Stride] / MAX_ENCODEABLE_XYZ); 1332 wIn[2] = (cmsFloat32Number) (Pt[Stride*2] / MAX_ENCODEABLE_XYZ); 1333 1334 return accum + sizeof(cmsFloat32Number); 1335 } 1336 else { 1337 1338 wIn[0] = (cmsFloat32Number) (Pt[0] / MAX_ENCODEABLE_XYZ); 1339 wIn[1] = (cmsFloat32Number) (Pt[1] / MAX_ENCODEABLE_XYZ); 1340 wIn[2] = (cmsFloat32Number) (Pt[2] / MAX_ENCODEABLE_XYZ); 1341 1342 accum += sizeof(cmsFloat32Number)*(3 + T_EXTRA(info ->InputFormat)); 1343 return accum; 1344 } 1345 } 1346 1347 1348 1349 // Packing routines ----------------------------------------------------------------------------------------------------------- 1350 1351 1352 // Generic chunky for byte 1353 1354 static 1355 cmsUInt8Number* PackAnyBytes(CMSREGISTER _cmsTRANSFORM* info, 1356 CMSREGISTER cmsUInt16Number wOut[], 1357 CMSREGISTER cmsUInt8Number* output, 1358 CMSREGISTER cmsUInt32Number Stride) 1359 { 1360 cmsUInt32Number nChan = T_CHANNELS(info -> OutputFormat); 1361 cmsUInt32Number DoSwap = T_DOSWAP(info ->OutputFormat); 1362 cmsUInt32Number Reverse = T_FLAVOR(info ->OutputFormat); 1363 cmsUInt32Number Extra = T_EXTRA(info -> OutputFormat); 1364 cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> OutputFormat); 1365 cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst; 1366 cmsUInt8Number* swap1; 1367 cmsUInt8Number v = 0; 1368 cmsUInt32Number i; 1369 1370 swap1 = output; 1371 1372 if (ExtraFirst) { 1373 output += Extra; 1374 } 1375 1376 for (i=0; i < nChan; i++) { 1377 1378 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i; 1379 1380 v = FROM_16_TO_8(wOut[index]); 1381 1382 if (Reverse) 1383 v = REVERSE_FLAVOR_8(v); 1384 1385 *output++ = v; 1386 } 1387 1388 if (!ExtraFirst) { 1389 output += Extra; 1390 } 1391 1392 if (Extra == 0 && SwapFirst) { 1393 1394 memmove(swap1 + 1, swap1, nChan-1); 1395 *swap1 = v; 1396 } 1397 1398 1399 return output; 1400 1401 cmsUNUSED_PARAMETER(Stride); 1402 } 1403 1404 1405 1406 static 1407 cmsUInt8Number* PackAnyWords(CMSREGISTER _cmsTRANSFORM* info, 1408 CMSREGISTER cmsUInt16Number wOut[], 1409 CMSREGISTER cmsUInt8Number* output, 1410 CMSREGISTER cmsUInt32Number Stride) 1411 { 1412 cmsUInt32Number nChan = T_CHANNELS(info -> OutputFormat); 1413 cmsUInt32Number SwapEndian = T_ENDIAN16(info -> OutputFormat); 1414 cmsUInt32Number DoSwap = T_DOSWAP(info ->OutputFormat); 1415 cmsUInt32Number Reverse = T_FLAVOR(info ->OutputFormat); 1416 cmsUInt32Number Extra = T_EXTRA(info -> OutputFormat); 1417 cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> OutputFormat); 1418 cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst; 1419 cmsUInt16Number* swap1; 1420 cmsUInt16Number v = 0; 1421 cmsUInt32Number i; 1422 1423 swap1 = (cmsUInt16Number*) output; 1424 1425 if (ExtraFirst) { 1426 output += Extra * sizeof(cmsUInt16Number); 1427 } 1428 1429 for (i=0; i < nChan; i++) { 1430 1431 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i; 1432 1433 v = wOut[index]; 1434 1435 if (SwapEndian) 1436 v = CHANGE_ENDIAN(v); 1437 1438 if (Reverse) 1439 v = REVERSE_FLAVOR_16(v); 1440 1441 *(cmsUInt16Number*) output = v; 1442 1443 output += sizeof(cmsUInt16Number); 1444 } 1445 1446 if (!ExtraFirst) { 1447 output += Extra * sizeof(cmsUInt16Number); 1448 } 1449 1450 if (Extra == 0 && SwapFirst) { 1451 1452 memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsUInt16Number)); 1453 *swap1 = v; 1454 } 1455 1456 1457 return output; 1458 1459 cmsUNUSED_PARAMETER(Stride); 1460 } 1461 1462 1463 static 1464 cmsUInt8Number* PackPlanarBytes(CMSREGISTER _cmsTRANSFORM* info, 1465 CMSREGISTER cmsUInt16Number wOut[], 1466 CMSREGISTER cmsUInt8Number* output, 1467 CMSREGISTER cmsUInt32Number Stride) 1468 { 1469 cmsUInt32Number nChan = T_CHANNELS(info -> OutputFormat); 1470 cmsUInt32Number DoSwap = T_DOSWAP(info ->OutputFormat); 1471 cmsUInt32Number SwapFirst = T_SWAPFIRST(info ->OutputFormat); 1472 cmsUInt32Number Reverse = T_FLAVOR(info ->OutputFormat); 1473 cmsUInt32Number i; 1474 cmsUInt8Number* Init = output; 1475 1476 1477 if (DoSwap ^ SwapFirst) { 1478 output += T_EXTRA(info -> OutputFormat) * Stride; 1479 } 1480 1481 1482 for (i=0; i < nChan; i++) { 1483 1484 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i; 1485 cmsUInt8Number v = FROM_16_TO_8(wOut[index]); 1486 1487 *(cmsUInt8Number*) output = (cmsUInt8Number) (Reverse ? REVERSE_FLAVOR_8(v) : v); 1488 output += Stride; 1489 } 1490 1491 return (Init + 1); 1492 1493 cmsUNUSED_PARAMETER(Stride); 1494 } 1495 1496 1497 static 1498 cmsUInt8Number* PackPlanarWords(CMSREGISTER _cmsTRANSFORM* info, 1499 CMSREGISTER cmsUInt16Number wOut[], 1500 CMSREGISTER cmsUInt8Number* output, 1501 CMSREGISTER cmsUInt32Number Stride) 1502 { 1503 cmsUInt32Number nChan = T_CHANNELS(info -> OutputFormat); 1504 cmsUInt32Number DoSwap = T_DOSWAP(info ->OutputFormat); 1505 cmsUInt32Number Reverse = T_FLAVOR(info ->OutputFormat); 1506 cmsUInt32Number SwapEndian = T_ENDIAN16(info -> OutputFormat); 1507 cmsUInt32Number i; 1508 cmsUInt8Number* Init = output; 1509 cmsUInt16Number v; 1510 1511 if (DoSwap) { 1512 output += T_EXTRA(info -> OutputFormat) * Stride; 1513 } 1514 1515 for (i=0; i < nChan; i++) { 1516 1517 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i; 1518 1519 v = wOut[index]; 1520 1521 if (SwapEndian) 1522 v = CHANGE_ENDIAN(v); 1523 1524 if (Reverse) 1525 v = REVERSE_FLAVOR_16(v); 1526 1527 *(cmsUInt16Number*) output = v; 1528 output += Stride; 1529 } 1530 1531 return (Init + sizeof(cmsUInt16Number)); 1532 } 1533 1534 // CMYKcm (unrolled for speed) 1535 1536 static 1537 cmsUInt8Number* Pack6Bytes(CMSREGISTER _cmsTRANSFORM* info, 1538 CMSREGISTER cmsUInt16Number wOut[], 1539 CMSREGISTER cmsUInt8Number* output, 1540 CMSREGISTER cmsUInt32Number Stride) 1541 { 1542 *output++ = FROM_16_TO_8(wOut[0]); 1543 *output++ = FROM_16_TO_8(wOut[1]); 1544 *output++ = FROM_16_TO_8(wOut[2]); 1545 *output++ = FROM_16_TO_8(wOut[3]); 1546 *output++ = FROM_16_TO_8(wOut[4]); 1547 *output++ = FROM_16_TO_8(wOut[5]); 1548 1549 return output; 1550 1551 cmsUNUSED_PARAMETER(info); 1552 cmsUNUSED_PARAMETER(Stride); 1553 } 1554 1555 // KCMYcm 1556 1557 static 1558 cmsUInt8Number* Pack6BytesSwap(CMSREGISTER _cmsTRANSFORM* info, 1559 CMSREGISTER cmsUInt16Number wOut[], 1560 CMSREGISTER cmsUInt8Number* output, 1561 CMSREGISTER cmsUInt32Number Stride) 1562 { 1563 *output++ = FROM_16_TO_8(wOut[5]); 1564 *output++ = FROM_16_TO_8(wOut[4]); 1565 *output++ = FROM_16_TO_8(wOut[3]); 1566 *output++ = FROM_16_TO_8(wOut[2]); 1567 *output++ = FROM_16_TO_8(wOut[1]); 1568 *output++ = FROM_16_TO_8(wOut[0]); 1569 1570 return output; 1571 1572 cmsUNUSED_PARAMETER(info); 1573 cmsUNUSED_PARAMETER(Stride); 1574 } 1575 1576 // CMYKcm 1577 static 1578 cmsUInt8Number* Pack6Words(CMSREGISTER _cmsTRANSFORM* info, 1579 CMSREGISTER cmsUInt16Number wOut[], 1580 CMSREGISTER cmsUInt8Number* output, 1581 CMSREGISTER cmsUInt32Number Stride) 1582 { 1583 *(cmsUInt16Number*) output = wOut[0]; 1584 output+= 2; 1585 *(cmsUInt16Number*) output = wOut[1]; 1586 output+= 2; 1587 *(cmsUInt16Number*) output = wOut[2]; 1588 output+= 2; 1589 *(cmsUInt16Number*) output = wOut[3]; 1590 output+= 2; 1591 *(cmsUInt16Number*) output = wOut[4]; 1592 output+= 2; 1593 *(cmsUInt16Number*) output = wOut[5]; 1594 output+= 2; 1595 1596 return output; 1597 1598 cmsUNUSED_PARAMETER(info); 1599 cmsUNUSED_PARAMETER(Stride); 1600 } 1601 1602 // KCMYcm 1603 static 1604 cmsUInt8Number* Pack6WordsSwap(CMSREGISTER _cmsTRANSFORM* info, 1605 CMSREGISTER cmsUInt16Number wOut[], 1606 CMSREGISTER cmsUInt8Number* output, 1607 CMSREGISTER cmsUInt32Number Stride) 1608 { 1609 *(cmsUInt16Number*) output = wOut[5]; 1610 output+= 2; 1611 *(cmsUInt16Number*) output = wOut[4]; 1612 output+= 2; 1613 *(cmsUInt16Number*) output = wOut[3]; 1614 output+= 2; 1615 *(cmsUInt16Number*) output = wOut[2]; 1616 output+= 2; 1617 *(cmsUInt16Number*) output = wOut[1]; 1618 output+= 2; 1619 *(cmsUInt16Number*) output = wOut[0]; 1620 output+= 2; 1621 1622 return output; 1623 1624 cmsUNUSED_PARAMETER(info); 1625 cmsUNUSED_PARAMETER(Stride); 1626 } 1627 1628 1629 static 1630 cmsUInt8Number* Pack4Bytes(CMSREGISTER _cmsTRANSFORM* info, 1631 CMSREGISTER cmsUInt16Number wOut[], 1632 CMSREGISTER cmsUInt8Number* output, 1633 CMSREGISTER cmsUInt32Number Stride) 1634 { 1635 *output++ = FROM_16_TO_8(wOut[0]); 1636 *output++ = FROM_16_TO_8(wOut[1]); 1637 *output++ = FROM_16_TO_8(wOut[2]); 1638 *output++ = FROM_16_TO_8(wOut[3]); 1639 1640 return output; 1641 1642 cmsUNUSED_PARAMETER(info); 1643 cmsUNUSED_PARAMETER(Stride); 1644 } 1645 1646 static 1647 cmsUInt8Number* Pack4BytesReverse(CMSREGISTER _cmsTRANSFORM* info, 1648 CMSREGISTER cmsUInt16Number wOut[], 1649 CMSREGISTER cmsUInt8Number* output, 1650 CMSREGISTER cmsUInt32Number Stride) 1651 { 1652 *output++ = REVERSE_FLAVOR_8(FROM_16_TO_8(wOut[0])); 1653 *output++ = REVERSE_FLAVOR_8(FROM_16_TO_8(wOut[1])); 1654 *output++ = REVERSE_FLAVOR_8(FROM_16_TO_8(wOut[2])); 1655 *output++ = REVERSE_FLAVOR_8(FROM_16_TO_8(wOut[3])); 1656 1657 return output; 1658 1659 cmsUNUSED_PARAMETER(info); 1660 cmsUNUSED_PARAMETER(Stride); 1661 } 1662 1663 1664 static 1665 cmsUInt8Number* Pack4BytesSwapFirst(CMSREGISTER _cmsTRANSFORM* info, 1666 CMSREGISTER cmsUInt16Number wOut[], 1667 CMSREGISTER cmsUInt8Number* output, 1668 CMSREGISTER cmsUInt32Number Stride) 1669 { 1670 *output++ = FROM_16_TO_8(wOut[3]); 1671 *output++ = FROM_16_TO_8(wOut[0]); 1672 *output++ = FROM_16_TO_8(wOut[1]); 1673 *output++ = FROM_16_TO_8(wOut[2]); 1674 1675 return output; 1676 1677 cmsUNUSED_PARAMETER(info); 1678 cmsUNUSED_PARAMETER(Stride); 1679 } 1680 1681 // ABGR 1682 static 1683 cmsUInt8Number* Pack4BytesSwap(CMSREGISTER _cmsTRANSFORM* info, 1684 CMSREGISTER cmsUInt16Number wOut[], 1685 CMSREGISTER cmsUInt8Number* output, 1686 CMSREGISTER cmsUInt32Number Stride) 1687 { 1688 *output++ = FROM_16_TO_8(wOut[3]); 1689 *output++ = FROM_16_TO_8(wOut[2]); 1690 *output++ = FROM_16_TO_8(wOut[1]); 1691 *output++ = FROM_16_TO_8(wOut[0]); 1692 1693 return output; 1694 1695 cmsUNUSED_PARAMETER(info); 1696 cmsUNUSED_PARAMETER(Stride); 1697 } 1698 1699 static 1700 cmsUInt8Number* Pack4BytesSwapSwapFirst(CMSREGISTER _cmsTRANSFORM* info, 1701 CMSREGISTER cmsUInt16Number wOut[], 1702 CMSREGISTER cmsUInt8Number* output, 1703 CMSREGISTER cmsUInt32Number Stride) 1704 { 1705 *output++ = FROM_16_TO_8(wOut[2]); 1706 *output++ = FROM_16_TO_8(wOut[1]); 1707 *output++ = FROM_16_TO_8(wOut[0]); 1708 *output++ = FROM_16_TO_8(wOut[3]); 1709 1710 return output; 1711 1712 cmsUNUSED_PARAMETER(info); 1713 cmsUNUSED_PARAMETER(Stride); 1714 } 1715 1716 static 1717 cmsUInt8Number* Pack4Words(CMSREGISTER _cmsTRANSFORM* info, 1718 CMSREGISTER cmsUInt16Number wOut[], 1719 CMSREGISTER cmsUInt8Number* output, 1720 CMSREGISTER cmsUInt32Number Stride) 1721 { 1722 *(cmsUInt16Number*) output = wOut[0]; 1723 output+= 2; 1724 *(cmsUInt16Number*) output = wOut[1]; 1725 output+= 2; 1726 *(cmsUInt16Number*) output = wOut[2]; 1727 output+= 2; 1728 *(cmsUInt16Number*) output = wOut[3]; 1729 output+= 2; 1730 1731 return output; 1732 1733 cmsUNUSED_PARAMETER(info); 1734 cmsUNUSED_PARAMETER(Stride); 1735 } 1736 1737 static 1738 cmsUInt8Number* Pack4WordsReverse(CMSREGISTER _cmsTRANSFORM* info, 1739 CMSREGISTER cmsUInt16Number wOut[], 1740 CMSREGISTER cmsUInt8Number* output, 1741 CMSREGISTER cmsUInt32Number Stride) 1742 { 1743 *(cmsUInt16Number*) output = REVERSE_FLAVOR_16(wOut[0]); 1744 output+= 2; 1745 *(cmsUInt16Number*) output = REVERSE_FLAVOR_16(wOut[1]); 1746 output+= 2; 1747 *(cmsUInt16Number*) output = REVERSE_FLAVOR_16(wOut[2]); 1748 output+= 2; 1749 *(cmsUInt16Number*) output = REVERSE_FLAVOR_16(wOut[3]); 1750 output+= 2; 1751 1752 return output; 1753 1754 cmsUNUSED_PARAMETER(info); 1755 cmsUNUSED_PARAMETER(Stride); 1756 } 1757 1758 // ABGR 1759 static 1760 cmsUInt8Number* Pack4WordsSwap(CMSREGISTER _cmsTRANSFORM* info, 1761 CMSREGISTER cmsUInt16Number wOut[], 1762 CMSREGISTER cmsUInt8Number* output, 1763 CMSREGISTER cmsUInt32Number Stride) 1764 { 1765 *(cmsUInt16Number*) output = wOut[3]; 1766 output+= 2; 1767 *(cmsUInt16Number*) output = wOut[2]; 1768 output+= 2; 1769 *(cmsUInt16Number*) output = wOut[1]; 1770 output+= 2; 1771 *(cmsUInt16Number*) output = wOut[0]; 1772 output+= 2; 1773 1774 return output; 1775 1776 cmsUNUSED_PARAMETER(info); 1777 cmsUNUSED_PARAMETER(Stride); 1778 } 1779 1780 // CMYK 1781 static 1782 cmsUInt8Number* Pack4WordsBigEndian(CMSREGISTER _cmsTRANSFORM* info, 1783 CMSREGISTER cmsUInt16Number wOut[], 1784 CMSREGISTER cmsUInt8Number* output, 1785 CMSREGISTER cmsUInt32Number Stride) 1786 { 1787 *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[0]); 1788 output+= 2; 1789 *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[1]); 1790 output+= 2; 1791 *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[2]); 1792 output+= 2; 1793 *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[3]); 1794 output+= 2; 1795 1796 return output; 1797 1798 cmsUNUSED_PARAMETER(info); 1799 cmsUNUSED_PARAMETER(Stride); 1800 } 1801 1802 1803 static 1804 cmsUInt8Number* PackLabV2_8(CMSREGISTER _cmsTRANSFORM* info, 1805 CMSREGISTER cmsUInt16Number wOut[], 1806 CMSREGISTER cmsUInt8Number* output, 1807 CMSREGISTER cmsUInt32Number Stride) 1808 { 1809 *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[0])); 1810 *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[1])); 1811 *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[2])); 1812 1813 return output; 1814 1815 cmsUNUSED_PARAMETER(info); 1816 cmsUNUSED_PARAMETER(Stride); 1817 } 1818 1819 static 1820 cmsUInt8Number* PackALabV2_8(CMSREGISTER _cmsTRANSFORM* info, 1821 CMSREGISTER cmsUInt16Number wOut[], 1822 CMSREGISTER cmsUInt8Number* output, 1823 CMSREGISTER cmsUInt32Number Stride) 1824 { 1825 output++; 1826 *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[0])); 1827 *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[1])); 1828 *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[2])); 1829 1830 return output; 1831 1832 cmsUNUSED_PARAMETER(info); 1833 cmsUNUSED_PARAMETER(Stride); 1834 } 1835 1836 static 1837 cmsUInt8Number* PackLabV2_16(CMSREGISTER _cmsTRANSFORM* info, 1838 CMSREGISTER cmsUInt16Number wOut[], 1839 CMSREGISTER cmsUInt8Number* output, 1840 CMSREGISTER cmsUInt32Number Stride) 1841 { 1842 *(cmsUInt16Number*) output = FomLabV4ToLabV2(wOut[0]); 1843 output += 2; 1844 *(cmsUInt16Number*) output = FomLabV4ToLabV2(wOut[1]); 1845 output += 2; 1846 *(cmsUInt16Number*) output = FomLabV4ToLabV2(wOut[2]); 1847 output += 2; 1848 1849 return output; 1850 1851 cmsUNUSED_PARAMETER(info); 1852 cmsUNUSED_PARAMETER(Stride); 1853 } 1854 1855 static 1856 cmsUInt8Number* Pack3Bytes(CMSREGISTER _cmsTRANSFORM* info, 1857 CMSREGISTER cmsUInt16Number wOut[], 1858 CMSREGISTER cmsUInt8Number* output, 1859 CMSREGISTER cmsUInt32Number Stride) 1860 { 1861 *output++ = FROM_16_TO_8(wOut[0]); 1862 *output++ = FROM_16_TO_8(wOut[1]); 1863 *output++ = FROM_16_TO_8(wOut[2]); 1864 1865 return output; 1866 1867 cmsUNUSED_PARAMETER(info); 1868 cmsUNUSED_PARAMETER(Stride); 1869 } 1870 1871 static 1872 cmsUInt8Number* Pack3BytesOptimized(CMSREGISTER _cmsTRANSFORM* info, 1873 CMSREGISTER cmsUInt16Number wOut[], 1874 CMSREGISTER cmsUInt8Number* output, 1875 CMSREGISTER cmsUInt32Number Stride) 1876 { 1877 *output++ = (wOut[0] & 0xFFU); 1878 *output++ = (wOut[1] & 0xFFU); 1879 *output++ = (wOut[2] & 0xFFU); 1880 1881 return output; 1882 1883 cmsUNUSED_PARAMETER(info); 1884 cmsUNUSED_PARAMETER(Stride); 1885 } 1886 1887 static 1888 cmsUInt8Number* Pack3BytesSwap(CMSREGISTER _cmsTRANSFORM* info, 1889 CMSREGISTER cmsUInt16Number wOut[], 1890 CMSREGISTER cmsUInt8Number* output, 1891 CMSREGISTER cmsUInt32Number Stride) 1892 { 1893 *output++ = FROM_16_TO_8(wOut[2]); 1894 *output++ = FROM_16_TO_8(wOut[1]); 1895 *output++ = FROM_16_TO_8(wOut[0]); 1896 1897 return output; 1898 1899 cmsUNUSED_PARAMETER(info); 1900 cmsUNUSED_PARAMETER(Stride); 1901 } 1902 1903 static 1904 cmsUInt8Number* Pack3BytesSwapOptimized(CMSREGISTER _cmsTRANSFORM* info, 1905 CMSREGISTER cmsUInt16Number wOut[], 1906 CMSREGISTER cmsUInt8Number* output, 1907 CMSREGISTER cmsUInt32Number Stride) 1908 { 1909 *output++ = (wOut[2] & 0xFFU); 1910 *output++ = (wOut[1] & 0xFFU); 1911 *output++ = (wOut[0] & 0xFFU); 1912 1913 return output; 1914 1915 cmsUNUSED_PARAMETER(info); 1916 cmsUNUSED_PARAMETER(Stride); 1917 } 1918 1919 1920 static 1921 cmsUInt8Number* Pack3Words(CMSREGISTER _cmsTRANSFORM* info, 1922 CMSREGISTER cmsUInt16Number wOut[], 1923 CMSREGISTER cmsUInt8Number* output, 1924 CMSREGISTER cmsUInt32Number Stride) 1925 { 1926 *(cmsUInt16Number*) output = wOut[0]; 1927 output+= 2; 1928 *(cmsUInt16Number*) output = wOut[1]; 1929 output+= 2; 1930 *(cmsUInt16Number*) output = wOut[2]; 1931 output+= 2; 1932 1933 return output; 1934 1935 cmsUNUSED_PARAMETER(info); 1936 cmsUNUSED_PARAMETER(Stride); 1937 } 1938 1939 static 1940 cmsUInt8Number* Pack3WordsSwap(CMSREGISTER _cmsTRANSFORM* info, 1941 CMSREGISTER cmsUInt16Number wOut[], 1942 CMSREGISTER cmsUInt8Number* output, 1943 CMSREGISTER cmsUInt32Number Stride) 1944 { 1945 *(cmsUInt16Number*) output = wOut[2]; 1946 output+= 2; 1947 *(cmsUInt16Number*) output = wOut[1]; 1948 output+= 2; 1949 *(cmsUInt16Number*) output = wOut[0]; 1950 output+= 2; 1951 1952 return output; 1953 1954 cmsUNUSED_PARAMETER(info); 1955 cmsUNUSED_PARAMETER(Stride); 1956 } 1957 1958 static 1959 cmsUInt8Number* Pack3WordsBigEndian(CMSREGISTER _cmsTRANSFORM* info, 1960 CMSREGISTER cmsUInt16Number wOut[], 1961 CMSREGISTER cmsUInt8Number* output, 1962 CMSREGISTER cmsUInt32Number Stride) 1963 { 1964 *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[0]); 1965 output+= 2; 1966 *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[1]); 1967 output+= 2; 1968 *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[2]); 1969 output+= 2; 1970 1971 return output; 1972 1973 cmsUNUSED_PARAMETER(info); 1974 cmsUNUSED_PARAMETER(Stride); 1975 } 1976 1977 static 1978 cmsUInt8Number* Pack3BytesAndSkip1(CMSREGISTER _cmsTRANSFORM* info, 1979 CMSREGISTER cmsUInt16Number wOut[], 1980 CMSREGISTER cmsUInt8Number* output, 1981 CMSREGISTER cmsUInt32Number Stride) 1982 { 1983 *output++ = FROM_16_TO_8(wOut[0]); 1984 *output++ = FROM_16_TO_8(wOut[1]); 1985 *output++ = FROM_16_TO_8(wOut[2]); 1986 output++; 1987 1988 return output; 1989 1990 cmsUNUSED_PARAMETER(info); 1991 cmsUNUSED_PARAMETER(Stride); 1992 } 1993 1994 static 1995 cmsUInt8Number* Pack3BytesAndSkip1Optimized(CMSREGISTER _cmsTRANSFORM* info, 1996 CMSREGISTER cmsUInt16Number wOut[], 1997 CMSREGISTER cmsUInt8Number* output, 1998 CMSREGISTER cmsUInt32Number Stride) 1999 { 2000 *output++ = (wOut[0] & 0xFFU); 2001 *output++ = (wOut[1] & 0xFFU); 2002 *output++ = (wOut[2] & 0xFFU); 2003 output++; 2004 2005 return output; 2006 2007 cmsUNUSED_PARAMETER(info); 2008 cmsUNUSED_PARAMETER(Stride); 2009 } 2010 2011 2012 static 2013 cmsUInt8Number* Pack3BytesAndSkip1SwapFirst(CMSREGISTER _cmsTRANSFORM* info, 2014 CMSREGISTER cmsUInt16Number wOut[], 2015 CMSREGISTER cmsUInt8Number* output, 2016 CMSREGISTER cmsUInt32Number Stride) 2017 { 2018 output++; 2019 *output++ = FROM_16_TO_8(wOut[0]); 2020 *output++ = FROM_16_TO_8(wOut[1]); 2021 *output++ = FROM_16_TO_8(wOut[2]); 2022 2023 return output; 2024 2025 cmsUNUSED_PARAMETER(info); 2026 cmsUNUSED_PARAMETER(Stride); 2027 } 2028 2029 static 2030 cmsUInt8Number* Pack3BytesAndSkip1SwapFirstOptimized(CMSREGISTER _cmsTRANSFORM* info, 2031 CMSREGISTER cmsUInt16Number wOut[], 2032 CMSREGISTER cmsUInt8Number* output, 2033 CMSREGISTER cmsUInt32Number Stride) 2034 { 2035 output++; 2036 *output++ = (wOut[0] & 0xFFU); 2037 *output++ = (wOut[1] & 0xFFU); 2038 *output++ = (wOut[2] & 0xFFU); 2039 2040 return output; 2041 2042 cmsUNUSED_PARAMETER(info); 2043 cmsUNUSED_PARAMETER(Stride); 2044 } 2045 2046 static 2047 cmsUInt8Number* Pack3BytesAndSkip1Swap(CMSREGISTER _cmsTRANSFORM* info, 2048 CMSREGISTER cmsUInt16Number wOut[], 2049 CMSREGISTER cmsUInt8Number* output, 2050 CMSREGISTER cmsUInt32Number Stride) 2051 { 2052 output++; 2053 *output++ = FROM_16_TO_8(wOut[2]); 2054 *output++ = FROM_16_TO_8(wOut[1]); 2055 *output++ = FROM_16_TO_8(wOut[0]); 2056 2057 return output; 2058 2059 cmsUNUSED_PARAMETER(info); 2060 cmsUNUSED_PARAMETER(Stride); 2061 } 2062 2063 static 2064 cmsUInt8Number* Pack3BytesAndSkip1SwapOptimized(CMSREGISTER _cmsTRANSFORM* info, 2065 CMSREGISTER cmsUInt16Number wOut[], 2066 CMSREGISTER cmsUInt8Number* output, 2067 CMSREGISTER cmsUInt32Number Stride) 2068 { 2069 output++; 2070 *output++ = (wOut[2] & 0xFFU); 2071 *output++ = (wOut[1] & 0xFFU); 2072 *output++ = (wOut[0] & 0xFFU); 2073 2074 return output; 2075 2076 cmsUNUSED_PARAMETER(info); 2077 cmsUNUSED_PARAMETER(Stride); 2078 } 2079 2080 2081 static 2082 cmsUInt8Number* Pack3BytesAndSkip1SwapSwapFirst(CMSREGISTER _cmsTRANSFORM* info, 2083 CMSREGISTER cmsUInt16Number wOut[], 2084 CMSREGISTER cmsUInt8Number* output, 2085 CMSREGISTER cmsUInt32Number Stride) 2086 { 2087 *output++ = FROM_16_TO_8(wOut[2]); 2088 *output++ = FROM_16_TO_8(wOut[1]); 2089 *output++ = FROM_16_TO_8(wOut[0]); 2090 output++; 2091 2092 return output; 2093 2094 cmsUNUSED_PARAMETER(info); 2095 cmsUNUSED_PARAMETER(Stride); 2096 } 2097 2098 static 2099 cmsUInt8Number* Pack3BytesAndSkip1SwapSwapFirstOptimized(CMSREGISTER _cmsTRANSFORM* info, 2100 CMSREGISTER cmsUInt16Number wOut[], 2101 CMSREGISTER cmsUInt8Number* output, 2102 CMSREGISTER cmsUInt32Number Stride) 2103 { 2104 *output++ = (wOut[2] & 0xFFU); 2105 *output++ = (wOut[1] & 0xFFU); 2106 *output++ = (wOut[0] & 0xFFU); 2107 output++; 2108 2109 return output; 2110 2111 cmsUNUSED_PARAMETER(info); 2112 cmsUNUSED_PARAMETER(Stride); 2113 } 2114 2115 static 2116 cmsUInt8Number* Pack3WordsAndSkip1(CMSREGISTER _cmsTRANSFORM* info, 2117 CMSREGISTER cmsUInt16Number wOut[], 2118 CMSREGISTER cmsUInt8Number* output, 2119 CMSREGISTER cmsUInt32Number Stride) 2120 { 2121 *(cmsUInt16Number*) output = wOut[0]; 2122 output+= 2; 2123 *(cmsUInt16Number*) output = wOut[1]; 2124 output+= 2; 2125 *(cmsUInt16Number*) output = wOut[2]; 2126 output+= 2; 2127 output+= 2; 2128 2129 return output; 2130 2131 cmsUNUSED_PARAMETER(info); 2132 cmsUNUSED_PARAMETER(Stride); 2133 } 2134 2135 static 2136 cmsUInt8Number* Pack3WordsAndSkip1Swap(CMSREGISTER _cmsTRANSFORM* info, 2137 CMSREGISTER cmsUInt16Number wOut[], 2138 CMSREGISTER cmsUInt8Number* output, 2139 CMSREGISTER cmsUInt32Number Stride) 2140 { 2141 output+= 2; 2142 *(cmsUInt16Number*) output = wOut[2]; 2143 output+= 2; 2144 *(cmsUInt16Number*) output = wOut[1]; 2145 output+= 2; 2146 *(cmsUInt16Number*) output = wOut[0]; 2147 output+= 2; 2148 2149 return output; 2150 2151 cmsUNUSED_PARAMETER(info); 2152 cmsUNUSED_PARAMETER(Stride); 2153 } 2154 2155 2156 static 2157 cmsUInt8Number* Pack3WordsAndSkip1SwapFirst(CMSREGISTER _cmsTRANSFORM* info, 2158 CMSREGISTER cmsUInt16Number wOut[], 2159 CMSREGISTER cmsUInt8Number* output, 2160 CMSREGISTER cmsUInt32Number Stride) 2161 { 2162 output+= 2; 2163 *(cmsUInt16Number*) output = wOut[0]; 2164 output+= 2; 2165 *(cmsUInt16Number*) output = wOut[1]; 2166 output+= 2; 2167 *(cmsUInt16Number*) output = wOut[2]; 2168 output+= 2; 2169 2170 return output; 2171 2172 cmsUNUSED_PARAMETER(info); 2173 cmsUNUSED_PARAMETER(Stride); 2174 } 2175 2176 2177 static 2178 cmsUInt8Number* Pack3WordsAndSkip1SwapSwapFirst(CMSREGISTER _cmsTRANSFORM* info, 2179 CMSREGISTER cmsUInt16Number wOut[], 2180 CMSREGISTER cmsUInt8Number* output, 2181 CMSREGISTER cmsUInt32Number Stride) 2182 { 2183 *(cmsUInt16Number*) output = wOut[2]; 2184 output+= 2; 2185 *(cmsUInt16Number*) output = wOut[1]; 2186 output+= 2; 2187 *(cmsUInt16Number*) output = wOut[0]; 2188 output+= 2; 2189 output+= 2; 2190 2191 return output; 2192 2193 cmsUNUSED_PARAMETER(info); 2194 cmsUNUSED_PARAMETER(Stride); 2195 } 2196 2197 2198 2199 static 2200 cmsUInt8Number* Pack1Byte(CMSREGISTER _cmsTRANSFORM* info, 2201 CMSREGISTER cmsUInt16Number wOut[], 2202 CMSREGISTER cmsUInt8Number* output, 2203 CMSREGISTER cmsUInt32Number Stride) 2204 { 2205 *output++ = FROM_16_TO_8(wOut[0]); 2206 2207 return output; 2208 2209 cmsUNUSED_PARAMETER(info); 2210 cmsUNUSED_PARAMETER(Stride); 2211 } 2212 2213 2214 static 2215 cmsUInt8Number* Pack1ByteReversed(CMSREGISTER _cmsTRANSFORM* info, 2216 CMSREGISTER cmsUInt16Number wOut[], 2217 CMSREGISTER cmsUInt8Number* output, 2218 CMSREGISTER cmsUInt32Number Stride) 2219 { 2220 *output++ = FROM_16_TO_8(REVERSE_FLAVOR_16(wOut[0])); 2221 2222 return output; 2223 2224 cmsUNUSED_PARAMETER(info); 2225 cmsUNUSED_PARAMETER(Stride); 2226 } 2227 2228 2229 static 2230 cmsUInt8Number* Pack1ByteSkip1(CMSREGISTER _cmsTRANSFORM* info, 2231 CMSREGISTER cmsUInt16Number wOut[], 2232 CMSREGISTER cmsUInt8Number* output, 2233 CMSREGISTER cmsUInt32Number Stride) 2234 { 2235 *output++ = FROM_16_TO_8(wOut[0]); 2236 output++; 2237 2238 return output; 2239 2240 cmsUNUSED_PARAMETER(info); 2241 cmsUNUSED_PARAMETER(Stride); 2242 } 2243 2244 2245 static 2246 cmsUInt8Number* Pack1ByteSkip1SwapFirst(CMSREGISTER _cmsTRANSFORM* info, 2247 CMSREGISTER cmsUInt16Number wOut[], 2248 CMSREGISTER cmsUInt8Number* output, 2249 CMSREGISTER cmsUInt32Number Stride) 2250 { 2251 output++; 2252 *output++ = FROM_16_TO_8(wOut[0]); 2253 2254 return output; 2255 2256 cmsUNUSED_PARAMETER(info); 2257 cmsUNUSED_PARAMETER(Stride); 2258 } 2259 2260 static 2261 cmsUInt8Number* Pack1Word(CMSREGISTER _cmsTRANSFORM* info, 2262 CMSREGISTER cmsUInt16Number wOut[], 2263 CMSREGISTER cmsUInt8Number* output, 2264 CMSREGISTER cmsUInt32Number Stride) 2265 { 2266 *(cmsUInt16Number*) output = wOut[0]; 2267 output+= 2; 2268 2269 return output; 2270 2271 cmsUNUSED_PARAMETER(info); 2272 cmsUNUSED_PARAMETER(Stride); 2273 } 2274 2275 2276 static 2277 cmsUInt8Number* Pack1WordReversed(CMSREGISTER _cmsTRANSFORM* info, 2278 CMSREGISTER cmsUInt16Number wOut[], 2279 CMSREGISTER cmsUInt8Number* output, 2280 CMSREGISTER cmsUInt32Number Stride) 2281 { 2282 *(cmsUInt16Number*) output = REVERSE_FLAVOR_16(wOut[0]); 2283 output+= 2; 2284 2285 return output; 2286 2287 cmsUNUSED_PARAMETER(info); 2288 cmsUNUSED_PARAMETER(Stride); 2289 } 2290 2291 static 2292 cmsUInt8Number* Pack1WordBigEndian(CMSREGISTER _cmsTRANSFORM* info, 2293 CMSREGISTER cmsUInt16Number wOut[], 2294 CMSREGISTER cmsUInt8Number* output, 2295 CMSREGISTER cmsUInt32Number Stride) 2296 { 2297 *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[0]); 2298 output+= 2; 2299 2300 return output; 2301 2302 cmsUNUSED_PARAMETER(info); 2303 cmsUNUSED_PARAMETER(Stride); 2304 } 2305 2306 2307 static 2308 cmsUInt8Number* Pack1WordSkip1(CMSREGISTER _cmsTRANSFORM* info, 2309 CMSREGISTER cmsUInt16Number wOut[], 2310 CMSREGISTER cmsUInt8Number* output, 2311 CMSREGISTER cmsUInt32Number Stride) 2312 { 2313 *(cmsUInt16Number*) output = wOut[0]; 2314 output+= 4; 2315 2316 return output; 2317 2318 cmsUNUSED_PARAMETER(info); 2319 cmsUNUSED_PARAMETER(Stride); 2320 } 2321 2322 static 2323 cmsUInt8Number* Pack1WordSkip1SwapFirst(CMSREGISTER _cmsTRANSFORM* info, 2324 CMSREGISTER cmsUInt16Number wOut[], 2325 CMSREGISTER cmsUInt8Number* output, 2326 CMSREGISTER cmsUInt32Number Stride) 2327 { 2328 output += 2; 2329 *(cmsUInt16Number*) output = wOut[0]; 2330 output+= 2; 2331 2332 return output; 2333 2334 cmsUNUSED_PARAMETER(info); 2335 cmsUNUSED_PARAMETER(Stride); 2336 } 2337 2338 2339 // Unencoded Float values -- don't try optimize speed 2340 static 2341 cmsUInt8Number* PackLabDoubleFrom16(CMSREGISTER _cmsTRANSFORM* info, 2342 CMSREGISTER cmsUInt16Number wOut[], 2343 CMSREGISTER cmsUInt8Number* output, 2344 CMSREGISTER cmsUInt32Number Stride) 2345 { 2346 2347 if (T_PLANAR(info -> OutputFormat)) { 2348 2349 cmsCIELab Lab; 2350 cmsFloat64Number* Out = (cmsFloat64Number*) output; 2351 cmsLabEncoded2Float(&Lab, wOut); 2352 2353 Out[0] = Lab.L; 2354 Out[Stride] = Lab.a; 2355 Out[Stride*2] = Lab.b; 2356 2357 return output + sizeof(cmsFloat64Number); 2358 } 2359 else { 2360 2361 cmsLabEncoded2Float((cmsCIELab*) output, wOut); 2362 return output + (sizeof(cmsCIELab) + T_EXTRA(info ->OutputFormat) * sizeof(cmsFloat64Number)); 2363 } 2364 } 2365 2366 2367 static 2368 cmsUInt8Number* PackLabFloatFrom16(CMSREGISTER _cmsTRANSFORM* info, 2369 CMSREGISTER cmsUInt16Number wOut[], 2370 CMSREGISTER cmsUInt8Number* output, 2371 CMSREGISTER cmsUInt32Number Stride) 2372 { 2373 cmsCIELab Lab; 2374 cmsLabEncoded2Float(&Lab, wOut); 2375 2376 if (T_PLANAR(info -> OutputFormat)) { 2377 2378 cmsFloat32Number* Out = (cmsFloat32Number*) output; 2379 2380 Stride /= PixelSize(info->OutputFormat); 2381 2382 Out[0] = (cmsFloat32Number)Lab.L; 2383 Out[Stride] = (cmsFloat32Number)Lab.a; 2384 Out[Stride*2] = (cmsFloat32Number)Lab.b; 2385 2386 return output + sizeof(cmsFloat32Number); 2387 } 2388 else { 2389 2390 ((cmsFloat32Number*) output)[0] = (cmsFloat32Number) Lab.L; 2391 ((cmsFloat32Number*) output)[1] = (cmsFloat32Number) Lab.a; 2392 ((cmsFloat32Number*) output)[2] = (cmsFloat32Number) Lab.b; 2393 2394 return output + (3 + T_EXTRA(info ->OutputFormat)) * sizeof(cmsFloat32Number); 2395 } 2396 } 2397 2398 static 2399 cmsUInt8Number* PackXYZDoubleFrom16(CMSREGISTER _cmsTRANSFORM* Info, 2400 CMSREGISTER cmsUInt16Number wOut[], 2401 CMSREGISTER cmsUInt8Number* output, 2402 CMSREGISTER cmsUInt32Number Stride) 2403 { 2404 if (T_PLANAR(Info -> OutputFormat)) { 2405 2406 cmsCIEXYZ XYZ; 2407 cmsFloat64Number* Out = (cmsFloat64Number*) output; 2408 cmsXYZEncoded2Float(&XYZ, wOut); 2409 2410 Stride /= PixelSize(Info->OutputFormat); 2411 2412 Out[0] = XYZ.X; 2413 Out[Stride] = XYZ.Y; 2414 Out[Stride*2] = XYZ.Z; 2415 2416 return output + sizeof(cmsFloat64Number); 2417 2418 } 2419 else { 2420 2421 cmsXYZEncoded2Float((cmsCIEXYZ*) output, wOut); 2422 2423 return output + (sizeof(cmsCIEXYZ) + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat64Number)); 2424 } 2425 } 2426 2427 static 2428 cmsUInt8Number* PackXYZFloatFrom16(CMSREGISTER _cmsTRANSFORM* Info, 2429 CMSREGISTER cmsUInt16Number wOut[], 2430 CMSREGISTER cmsUInt8Number* output, 2431 CMSREGISTER cmsUInt32Number Stride) 2432 { 2433 if (T_PLANAR(Info -> OutputFormat)) { 2434 2435 cmsCIEXYZ XYZ; 2436 cmsFloat32Number* Out = (cmsFloat32Number*) output; 2437 cmsXYZEncoded2Float(&XYZ, wOut); 2438 2439 Stride /= PixelSize(Info->OutputFormat); 2440 2441 Out[0] = (cmsFloat32Number) XYZ.X; 2442 Out[Stride] = (cmsFloat32Number) XYZ.Y; 2443 Out[Stride*2] = (cmsFloat32Number) XYZ.Z; 2444 2445 return output + sizeof(cmsFloat32Number); 2446 2447 } 2448 else { 2449 2450 cmsCIEXYZ XYZ; 2451 cmsFloat32Number* Out = (cmsFloat32Number*) output; 2452 cmsXYZEncoded2Float(&XYZ, wOut); 2453 2454 Out[0] = (cmsFloat32Number) XYZ.X; 2455 Out[1] = (cmsFloat32Number) XYZ.Y; 2456 Out[2] = (cmsFloat32Number) XYZ.Z; 2457 2458 return output + (3 * sizeof(cmsFloat32Number) + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat32Number)); 2459 } 2460 } 2461 2462 static 2463 cmsUInt8Number* PackDoubleFrom16(CMSREGISTER _cmsTRANSFORM* info, 2464 CMSREGISTER cmsUInt16Number wOut[], 2465 CMSREGISTER cmsUInt8Number* output, 2466 CMSREGISTER cmsUInt32Number Stride) 2467 { 2468 cmsUInt32Number nChan = T_CHANNELS(info -> OutputFormat); 2469 cmsUInt32Number DoSwap = T_DOSWAP(info ->OutputFormat); 2470 cmsUInt32Number Reverse = T_FLAVOR(info ->OutputFormat); 2471 cmsUInt32Number Extra = T_EXTRA(info -> OutputFormat); 2472 cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> OutputFormat); 2473 cmsUInt32Number Planar = T_PLANAR(info -> OutputFormat); 2474 cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst; 2475 cmsFloat64Number maximum = IsInkSpace(info ->OutputFormat) ? 655.35 : 65535.0; 2476 cmsFloat64Number v = 0; 2477 cmsFloat64Number* swap1 = (cmsFloat64Number*) output; 2478 cmsUInt32Number i, start = 0; 2479 2480 Stride /= PixelSize(info->OutputFormat); 2481 2482 if (ExtraFirst) 2483 start = Extra; 2484 2485 for (i=0; i < nChan; i++) { 2486 2487 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i; 2488 2489 v = (cmsFloat64Number) wOut[index] / maximum; 2490 2491 if (Reverse) 2492 v = maximum - v; 2493 2494 if (Planar) 2495 ((cmsFloat64Number*) output)[(i + start) * Stride]= v; 2496 else 2497 ((cmsFloat64Number*) output)[i + start] = v; 2498 } 2499 2500 2501 if (Extra == 0 && SwapFirst) { 2502 2503 memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsFloat64Number)); 2504 *swap1 = v; 2505 } 2506 2507 if (T_PLANAR(info -> OutputFormat)) 2508 return output + sizeof(cmsFloat64Number); 2509 else 2510 return output + (nChan + Extra) * sizeof(cmsFloat64Number); 2511 2512 } 2513 2514 2515 static 2516 cmsUInt8Number* PackFloatFrom16(CMSREGISTER _cmsTRANSFORM* info, 2517 CMSREGISTER cmsUInt16Number wOut[], 2518 CMSREGISTER cmsUInt8Number* output, 2519 CMSREGISTER cmsUInt32Number Stride) 2520 { 2521 cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat); 2522 cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat); 2523 cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat); 2524 cmsUInt32Number Extra = T_EXTRA(info->OutputFormat); 2525 cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat); 2526 cmsUInt32Number Planar = T_PLANAR(info->OutputFormat); 2527 cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst; 2528 cmsFloat64Number maximum = IsInkSpace(info->OutputFormat) ? 655.35 : 65535.0; 2529 cmsFloat64Number v = 0; 2530 cmsFloat32Number* swap1 = (cmsFloat32Number*)output; 2531 cmsUInt32Number i, start = 0; 2532 2533 Stride /= PixelSize(info->OutputFormat); 2534 2535 if (ExtraFirst) 2536 start = Extra; 2537 2538 for (i = 0; i < nChan; i++) { 2539 2540 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i; 2541 2542 v = (cmsFloat64Number)wOut[index] / maximum; 2543 2544 if (Reverse) 2545 v = maximum - v; 2546 2547 if (Planar) 2548 ((cmsFloat32Number*)output)[(i + start) * Stride] = (cmsFloat32Number)v; 2549 else 2550 ((cmsFloat32Number*)output)[i + start] = (cmsFloat32Number)v; 2551 } 2552 2553 2554 if (Extra == 0 && SwapFirst) { 2555 2556 memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsFloat32Number)); 2557 *swap1 = (cmsFloat32Number)v; 2558 } 2559 2560 if (T_PLANAR(info->OutputFormat)) 2561 return output + sizeof(cmsFloat32Number); 2562 else 2563 return output + (nChan + Extra) * sizeof(cmsFloat32Number); 2564 } 2565 2566 2567 2568 // -------------------------------------------------------------------------------------------------------- 2569 2570 static 2571 cmsUInt8Number* PackFloatsFromFloat(_cmsTRANSFORM* info, 2572 cmsFloat32Number wOut[], 2573 cmsUInt8Number* output, 2574 cmsUInt32Number Stride) 2575 { 2576 cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat); 2577 cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat); 2578 cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat); 2579 cmsUInt32Number Extra = T_EXTRA(info->OutputFormat); 2580 cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat); 2581 cmsUInt32Number Planar = T_PLANAR(info->OutputFormat); 2582 cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst; 2583 cmsFloat64Number maximum = IsInkSpace(info->OutputFormat) ? 100.0 : 1.0; 2584 cmsFloat32Number* swap1 = (cmsFloat32Number*)output; 2585 cmsFloat64Number v = 0; 2586 cmsUInt32Number i, start = 0; 2587 2588 Stride /= PixelSize(info->OutputFormat); 2589 2590 if (ExtraFirst) 2591 start = Extra; 2592 2593 for (i = 0; i < nChan; i++) { 2594 2595 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i; 2596 2597 v = wOut[index] * maximum; 2598 2599 if (Reverse) 2600 v = maximum - v; 2601 2602 if (Planar) 2603 ((cmsFloat32Number*)output)[(i + start)* Stride] = (cmsFloat32Number)v; 2604 else 2605 ((cmsFloat32Number*)output)[i + start] = (cmsFloat32Number)v; 2606 } 2607 2608 2609 if (Extra == 0 && SwapFirst) { 2610 2611 memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsFloat32Number)); 2612 *swap1 = (cmsFloat32Number)v; 2613 } 2614 2615 if (T_PLANAR(info->OutputFormat)) 2616 return output + sizeof(cmsFloat32Number); 2617 else 2618 return output + (nChan + Extra) * sizeof(cmsFloat32Number); 2619 } 2620 2621 static 2622 cmsUInt8Number* PackDoublesFromFloat(_cmsTRANSFORM* info, 2623 cmsFloat32Number wOut[], 2624 cmsUInt8Number* output, 2625 cmsUInt32Number Stride) 2626 { 2627 cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat); 2628 cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat); 2629 cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat); 2630 cmsUInt32Number Extra = T_EXTRA(info->OutputFormat); 2631 cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat); 2632 cmsUInt32Number Planar = T_PLANAR(info->OutputFormat); 2633 cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst; 2634 cmsFloat64Number maximum = IsInkSpace(info->OutputFormat) ? 100.0 : 1.0; 2635 cmsFloat64Number v = 0; 2636 cmsFloat64Number* swap1 = (cmsFloat64Number*)output; 2637 cmsUInt32Number i, start = 0; 2638 2639 Stride /= PixelSize(info->OutputFormat); 2640 2641 if (ExtraFirst) 2642 start = Extra; 2643 2644 for (i = 0; i < nChan; i++) { 2645 2646 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i; 2647 2648 v = wOut[index] * maximum; 2649 2650 if (Reverse) 2651 v = maximum - v; 2652 2653 if (Planar) 2654 ((cmsFloat64Number*)output)[(i + start) * Stride] = v; 2655 else 2656 ((cmsFloat64Number*)output)[i + start] = v; 2657 } 2658 2659 if (Extra == 0 && SwapFirst) { 2660 2661 memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsFloat64Number)); 2662 *swap1 = v; 2663 } 2664 2665 2666 if (T_PLANAR(info->OutputFormat)) 2667 return output + sizeof(cmsFloat64Number); 2668 else 2669 return output + (nChan + Extra) * sizeof(cmsFloat64Number); 2670 2671 } 2672 2673 2674 2675 2676 2677 static 2678 cmsUInt8Number* PackLabFloatFromFloat(_cmsTRANSFORM* Info, 2679 cmsFloat32Number wOut[], 2680 cmsUInt8Number* output, 2681 cmsUInt32Number Stride) 2682 { 2683 cmsFloat32Number* Out = (cmsFloat32Number*) output; 2684 2685 if (T_PLANAR(Info -> OutputFormat)) { 2686 2687 Stride /= PixelSize(Info->OutputFormat); 2688 2689 Out[0] = (cmsFloat32Number) (wOut[0] * 100.0); 2690 Out[Stride] = (cmsFloat32Number) (wOut[1] * 255.0 - 128.0); 2691 Out[Stride*2] = (cmsFloat32Number) (wOut[2] * 255.0 - 128.0); 2692 2693 return output + sizeof(cmsFloat32Number); 2694 } 2695 else { 2696 2697 Out[0] = (cmsFloat32Number) (wOut[0] * 100.0); 2698 Out[1] = (cmsFloat32Number) (wOut[1] * 255.0 - 128.0); 2699 Out[2] = (cmsFloat32Number) (wOut[2] * 255.0 - 128.0); 2700 2701 return output + (sizeof(cmsFloat32Number)*3 + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat32Number)); 2702 } 2703 2704 } 2705 2706 2707 static 2708 cmsUInt8Number* PackLabDoubleFromFloat(_cmsTRANSFORM* Info, 2709 cmsFloat32Number wOut[], 2710 cmsUInt8Number* output, 2711 cmsUInt32Number Stride) 2712 { 2713 cmsFloat64Number* Out = (cmsFloat64Number*) output; 2714 2715 if (T_PLANAR(Info -> OutputFormat)) { 2716 2717 Stride /= PixelSize(Info->OutputFormat); 2718 2719 Out[0] = (cmsFloat64Number) (wOut[0] * 100.0); 2720 Out[Stride] = (cmsFloat64Number) (wOut[1] * 255.0 - 128.0); 2721 Out[Stride*2] = (cmsFloat64Number) (wOut[2] * 255.0 - 128.0); 2722 2723 return output + sizeof(cmsFloat64Number); 2724 } 2725 else { 2726 2727 Out[0] = (cmsFloat64Number) (wOut[0] * 100.0); 2728 Out[1] = (cmsFloat64Number) (wOut[1] * 255.0 - 128.0); 2729 Out[2] = (cmsFloat64Number) (wOut[2] * 255.0 - 128.0); 2730 2731 return output + (sizeof(cmsFloat64Number)*3 + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat64Number)); 2732 } 2733 2734 } 2735 2736 2737 // From 0..1 range to 0..MAX_ENCODEABLE_XYZ 2738 static 2739 cmsUInt8Number* PackXYZFloatFromFloat(_cmsTRANSFORM* Info, 2740 cmsFloat32Number wOut[], 2741 cmsUInt8Number* output, 2742 cmsUInt32Number Stride) 2743 { 2744 cmsFloat32Number* Out = (cmsFloat32Number*) output; 2745 2746 if (T_PLANAR(Info -> OutputFormat)) { 2747 2748 Stride /= PixelSize(Info->OutputFormat); 2749 2750 Out[0] = (cmsFloat32Number) (wOut[0] * MAX_ENCODEABLE_XYZ); 2751 Out[Stride] = (cmsFloat32Number) (wOut[1] * MAX_ENCODEABLE_XYZ); 2752 Out[Stride*2] = (cmsFloat32Number) (wOut[2] * MAX_ENCODEABLE_XYZ); 2753 2754 return output + sizeof(cmsFloat32Number); 2755 } 2756 else { 2757 2758 Out[0] = (cmsFloat32Number) (wOut[0] * MAX_ENCODEABLE_XYZ); 2759 Out[1] = (cmsFloat32Number) (wOut[1] * MAX_ENCODEABLE_XYZ); 2760 Out[2] = (cmsFloat32Number) (wOut[2] * MAX_ENCODEABLE_XYZ); 2761 2762 return output + (sizeof(cmsFloat32Number)*3 + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat32Number)); 2763 } 2764 2765 } 2766 2767 // Same, but convert to double 2768 static 2769 cmsUInt8Number* PackXYZDoubleFromFloat(_cmsTRANSFORM* Info, 2770 cmsFloat32Number wOut[], 2771 cmsUInt8Number* output, 2772 cmsUInt32Number Stride) 2773 { 2774 cmsFloat64Number* Out = (cmsFloat64Number*) output; 2775 2776 if (T_PLANAR(Info -> OutputFormat)) { 2777 2778 Stride /= PixelSize(Info->OutputFormat); 2779 2780 Out[0] = (cmsFloat64Number) (wOut[0] * MAX_ENCODEABLE_XYZ); 2781 Out[Stride] = (cmsFloat64Number) (wOut[1] * MAX_ENCODEABLE_XYZ); 2782 Out[Stride*2] = (cmsFloat64Number) (wOut[2] * MAX_ENCODEABLE_XYZ); 2783 2784 return output + sizeof(cmsFloat64Number); 2785 } 2786 else { 2787 2788 Out[0] = (cmsFloat64Number) (wOut[0] * MAX_ENCODEABLE_XYZ); 2789 Out[1] = (cmsFloat64Number) (wOut[1] * MAX_ENCODEABLE_XYZ); 2790 Out[2] = (cmsFloat64Number) (wOut[2] * MAX_ENCODEABLE_XYZ); 2791 2792 return output + (sizeof(cmsFloat64Number)*3 + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat64Number)); 2793 } 2794 2795 } 2796 2797 2798 // ---------------------------------------------------------------------------------------------------------------- 2799 2800 #ifndef CMS_NO_HALF_SUPPORT 2801 2802 // Decodes an stream of half floats to wIn[] described by input format 2803 2804 static 2805 cmsUInt8Number* UnrollHalfTo16(CMSREGISTER _cmsTRANSFORM* info, 2806 CMSREGISTER cmsUInt16Number wIn[], 2807 CMSREGISTER cmsUInt8Number* accum, 2808 CMSREGISTER cmsUInt32Number Stride) 2809 { 2810 2811 cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat); 2812 cmsUInt32Number DoSwap = T_DOSWAP(info ->InputFormat); 2813 cmsUInt32Number Reverse = T_FLAVOR(info ->InputFormat); 2814 cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> InputFormat); 2815 cmsUInt32Number Extra = T_EXTRA(info -> InputFormat); 2816 cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst; 2817 cmsUInt32Number Planar = T_PLANAR(info -> InputFormat); 2818 cmsFloat32Number v; 2819 cmsUInt32Number i, start = 0; 2820 cmsFloat32Number maximum = IsInkSpace(info ->InputFormat) ? 655.35F : 65535.0F; 2821 2822 2823 Stride /= PixelSize(info->OutputFormat); 2824 2825 if (ExtraFirst) 2826 start = Extra; 2827 2828 for (i=0; i < nChan; i++) { 2829 2830 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i; 2831 2832 if (Planar) 2833 v = _cmsHalf2Float ( ((cmsUInt16Number*) accum)[(i + start) * Stride] ); 2834 else 2835 v = _cmsHalf2Float ( ((cmsUInt16Number*) accum)[i + start] ) ; 2836 2837 if (Reverse) v = maximum - v; 2838 2839 wIn[index] = _cmsQuickSaturateWord(v * maximum); 2840 } 2841 2842 2843 if (Extra == 0 && SwapFirst) { 2844 cmsUInt16Number tmp = wIn[0]; 2845 2846 memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsUInt16Number)); 2847 wIn[nChan-1] = tmp; 2848 } 2849 2850 if (T_PLANAR(info -> InputFormat)) 2851 return accum + sizeof(cmsUInt16Number); 2852 else 2853 return accum + (nChan + Extra) * sizeof(cmsUInt16Number); 2854 } 2855 2856 // Decodes an stream of half floats to wIn[] described by input format 2857 2858 static 2859 cmsUInt8Number* UnrollHalfToFloat(_cmsTRANSFORM* info, 2860 cmsFloat32Number wIn[], 2861 cmsUInt8Number* accum, 2862 cmsUInt32Number Stride) 2863 { 2864 2865 cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat); 2866 cmsUInt32Number DoSwap = T_DOSWAP(info ->InputFormat); 2867 cmsUInt32Number Reverse = T_FLAVOR(info ->InputFormat); 2868 cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> InputFormat); 2869 cmsUInt32Number Extra = T_EXTRA(info -> InputFormat); 2870 cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst; 2871 cmsUInt32Number Planar = T_PLANAR(info -> InputFormat); 2872 cmsFloat32Number v; 2873 cmsUInt32Number i, start = 0; 2874 cmsFloat32Number maximum = IsInkSpace(info ->InputFormat) ? 100.0F : 1.0F; 2875 2876 Stride /= PixelSize(info->OutputFormat); 2877 2878 if (ExtraFirst) 2879 start = Extra; 2880 2881 for (i=0; i < nChan; i++) { 2882 2883 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i; 2884 2885 if (Planar) 2886 v = _cmsHalf2Float ( ((cmsUInt16Number*) accum)[(i + start) * Stride] ); 2887 else 2888 v = _cmsHalf2Float ( ((cmsUInt16Number*) accum)[i + start] ) ; 2889 2890 v /= maximum; 2891 2892 wIn[index] = Reverse ? 1 - v : v; 2893 } 2894 2895 2896 if (Extra == 0 && SwapFirst) { 2897 cmsFloat32Number tmp = wIn[0]; 2898 2899 memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsFloat32Number)); 2900 wIn[nChan-1] = tmp; 2901 } 2902 2903 if (T_PLANAR(info -> InputFormat)) 2904 return accum + sizeof(cmsUInt16Number); 2905 else 2906 return accum + (nChan + Extra) * sizeof(cmsUInt16Number); 2907 } 2908 2909 2910 static 2911 cmsUInt8Number* PackHalfFrom16(CMSREGISTER _cmsTRANSFORM* info, 2912 CMSREGISTER cmsUInt16Number wOut[], 2913 CMSREGISTER cmsUInt8Number* output, 2914 CMSREGISTER cmsUInt32Number Stride) 2915 { 2916 cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat); 2917 cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat); 2918 cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat); 2919 cmsUInt32Number Extra = T_EXTRA(info->OutputFormat); 2920 cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat); 2921 cmsUInt32Number Planar = T_PLANAR(info->OutputFormat); 2922 cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst; 2923 cmsFloat32Number maximum = IsInkSpace(info->OutputFormat) ? 655.35F : 65535.0F; 2924 cmsFloat32Number v = 0; 2925 cmsUInt16Number* swap1 = (cmsUInt16Number*)output; 2926 cmsUInt32Number i, start = 0; 2927 2928 Stride /= PixelSize(info->OutputFormat); 2929 2930 if (ExtraFirst) 2931 start = Extra; 2932 2933 for (i = 0; i < nChan; i++) { 2934 2935 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i; 2936 2937 v = (cmsFloat32Number)wOut[index] / maximum; 2938 2939 if (Reverse) 2940 v = maximum - v; 2941 2942 if (Planar) 2943 ((cmsUInt16Number*)output)[(i + start) * Stride] = _cmsFloat2Half(v); 2944 else 2945 ((cmsUInt16Number*)output)[i + start] = _cmsFloat2Half(v); 2946 } 2947 2948 2949 if (Extra == 0 && SwapFirst) { 2950 2951 memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsUInt16Number)); 2952 *swap1 = _cmsFloat2Half(v); 2953 } 2954 2955 if (T_PLANAR(info->OutputFormat)) 2956 return output + sizeof(cmsUInt16Number); 2957 else 2958 return output + (nChan + Extra) * sizeof(cmsUInt16Number); 2959 } 2960 2961 2962 2963 static 2964 cmsUInt8Number* PackHalfFromFloat(_cmsTRANSFORM* info, 2965 cmsFloat32Number wOut[], 2966 cmsUInt8Number* output, 2967 cmsUInt32Number Stride) 2968 { 2969 cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat); 2970 cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat); 2971 cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat); 2972 cmsUInt32Number Extra = T_EXTRA(info->OutputFormat); 2973 cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat); 2974 cmsUInt32Number Planar = T_PLANAR(info->OutputFormat); 2975 cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst; 2976 cmsFloat32Number maximum = IsInkSpace(info->OutputFormat) ? 100.0F : 1.0F; 2977 cmsUInt16Number* swap1 = (cmsUInt16Number*)output; 2978 cmsFloat32Number v = 0; 2979 cmsUInt32Number i, start = 0; 2980 2981 Stride /= PixelSize(info->OutputFormat); 2982 2983 if (ExtraFirst) 2984 start = Extra; 2985 2986 for (i = 0; i < nChan; i++) { 2987 2988 cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i; 2989 2990 v = wOut[index] * maximum; 2991 2992 if (Reverse) 2993 v = maximum - v; 2994 2995 if (Planar) 2996 ((cmsUInt16Number*)output)[(i + start)* Stride] = _cmsFloat2Half(v); 2997 else 2998 ((cmsUInt16Number*)output)[i + start] = _cmsFloat2Half(v); 2999 } 3000 3001 3002 if (Extra == 0 && SwapFirst) { 3003 3004 memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsUInt16Number)); 3005 *swap1 = (cmsUInt16Number)_cmsFloat2Half(v); 3006 } 3007 3008 if (T_PLANAR(info->OutputFormat)) 3009 return output + sizeof(cmsUInt16Number); 3010 else 3011 return output + (nChan + Extra)* sizeof(cmsUInt16Number); 3012 } 3013 3014 #endif 3015 3016 // ---------------------------------------------------------------------------------------------------------------- 3017 3018 3019 static const cmsFormatters16 InputFormatters16[] = { 3020 3021 // Type Mask Function 3022 // ---------------------------- ------------------------------------ ---------------------------- 3023 { TYPE_Lab_DBL, ANYPLANAR|ANYEXTRA, UnrollLabDoubleTo16}, 3024 { TYPE_XYZ_DBL, ANYPLANAR|ANYEXTRA, UnrollXYZDoubleTo16}, 3025 { TYPE_Lab_FLT, ANYPLANAR|ANYEXTRA, UnrollLabFloatTo16}, 3026 { TYPE_XYZ_FLT, ANYPLANAR|ANYEXTRA, UnrollXYZFloatTo16}, 3027 { TYPE_GRAY_DBL, 0, UnrollDouble1Chan}, 3028 { FLOAT_SH(1)|BYTES_SH(0), ANYCHANNELS|ANYPLANAR|ANYSWAPFIRST|ANYFLAVOR| 3029 ANYSWAP|ANYEXTRA|ANYSPACE, UnrollDoubleTo16}, 3030 { FLOAT_SH(1)|BYTES_SH(4), ANYCHANNELS|ANYPLANAR|ANYSWAPFIRST|ANYFLAVOR| 3031 ANYSWAP|ANYEXTRA|ANYSPACE, UnrollFloatTo16}, 3032 #ifndef CMS_NO_HALF_SUPPORT 3033 { FLOAT_SH(1)|BYTES_SH(2), ANYCHANNELS|ANYPLANAR|ANYSWAPFIRST|ANYFLAVOR| 3034 ANYEXTRA|ANYSWAP|ANYSPACE, UnrollHalfTo16}, 3035 #endif 3036 3037 { CHANNELS_SH(1)|BYTES_SH(1), ANYSPACE, Unroll1Byte}, 3038 { CHANNELS_SH(1)|BYTES_SH(1)|EXTRA_SH(1), ANYSPACE, Unroll1ByteSkip1}, 3039 { CHANNELS_SH(1)|BYTES_SH(1)|EXTRA_SH(2), ANYSPACE, Unroll1ByteSkip2}, 3040 { CHANNELS_SH(1)|BYTES_SH(1)|FLAVOR_SH(1), ANYSPACE, Unroll1ByteReversed}, 3041 { COLORSPACE_SH(PT_MCH2)|CHANNELS_SH(2)|BYTES_SH(1), 0, Unroll2Bytes}, 3042 3043 { TYPE_LabV2_8, 0, UnrollLabV2_8 }, 3044 { TYPE_ALabV2_8, 0, UnrollALabV2_8 }, 3045 { TYPE_LabV2_16, 0, UnrollLabV2_16 }, 3046 3047 { CHANNELS_SH(3)|BYTES_SH(1), ANYSPACE, Unroll3Bytes}, 3048 { CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1), ANYSPACE, Unroll3BytesSwap}, 3049 { CHANNELS_SH(3)|EXTRA_SH(1)|BYTES_SH(1)|DOSWAP_SH(1), ANYSPACE, Unroll3BytesSkip1Swap}, 3050 { CHANNELS_SH(3)|EXTRA_SH(1)|BYTES_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Unroll3BytesSkip1SwapFirst}, 3051 3052 { CHANNELS_SH(3)|EXTRA_SH(1)|BYTES_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1), 3053 ANYSPACE, Unroll3BytesSkip1SwapSwapFirst}, 3054 3055 { CHANNELS_SH(4)|BYTES_SH(1), ANYSPACE, Unroll4Bytes}, 3056 { CHANNELS_SH(4)|BYTES_SH(1)|FLAVOR_SH(1), ANYSPACE, Unroll4BytesReverse}, 3057 { CHANNELS_SH(4)|BYTES_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Unroll4BytesSwapFirst}, 3058 { CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1), ANYSPACE, Unroll4BytesSwap}, 3059 { CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Unroll4BytesSwapSwapFirst}, 3060 3061 { BYTES_SH(1)|PLANAR_SH(1), ANYFLAVOR|ANYSWAPFIRST| 3062 ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, UnrollPlanarBytes}, 3063 3064 { BYTES_SH(1), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP| 3065 ANYEXTRA|ANYCHANNELS|ANYSPACE, UnrollChunkyBytes}, 3066 3067 { CHANNELS_SH(1)|BYTES_SH(2), ANYSPACE, Unroll1Word}, 3068 { CHANNELS_SH(1)|BYTES_SH(2)|FLAVOR_SH(1), ANYSPACE, Unroll1WordReversed}, 3069 { CHANNELS_SH(1)|BYTES_SH(2)|EXTRA_SH(3), ANYSPACE, Unroll1WordSkip3}, 3070 3071 { CHANNELS_SH(2)|BYTES_SH(2), ANYSPACE, Unroll2Words}, 3072 { CHANNELS_SH(3)|BYTES_SH(2), ANYSPACE, Unroll3Words}, 3073 { CHANNELS_SH(4)|BYTES_SH(2), ANYSPACE, Unroll4Words}, 3074 3075 { CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1), ANYSPACE, Unroll3WordsSwap}, 3076 { CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Unroll3WordsSkip1SwapFirst}, 3077 { CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1)|DOSWAP_SH(1), ANYSPACE, Unroll3WordsSkip1Swap}, 3078 { CHANNELS_SH(4)|BYTES_SH(2)|FLAVOR_SH(1), ANYSPACE, Unroll4WordsReverse}, 3079 { CHANNELS_SH(4)|BYTES_SH(2)|SWAPFIRST_SH(1), ANYSPACE, Unroll4WordsSwapFirst}, 3080 { CHANNELS_SH(4)|BYTES_SH(2)|DOSWAP_SH(1), ANYSPACE, Unroll4WordsSwap}, 3081 { CHANNELS_SH(4)|BYTES_SH(2)|DOSWAP_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Unroll4WordsSwapSwapFirst}, 3082 3083 3084 { BYTES_SH(2)|PLANAR_SH(1), ANYFLAVOR|ANYSWAP|ANYENDIAN|ANYEXTRA|ANYCHANNELS|ANYSPACE, UnrollPlanarWords}, 3085 { BYTES_SH(2), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYENDIAN|ANYEXTRA|ANYCHANNELS|ANYSPACE, UnrollAnyWords}, 3086 }; 3087 3088 3089 3090 static const cmsFormattersFloat InputFormattersFloat[] = { 3091 3092 // Type Mask Function 3093 // ---------------------------- ------------------------------------ ---------------------------- 3094 { TYPE_Lab_DBL, ANYPLANAR|ANYEXTRA, UnrollLabDoubleToFloat}, 3095 { TYPE_Lab_FLT, ANYPLANAR|ANYEXTRA, UnrollLabFloatToFloat}, 3096 3097 { TYPE_XYZ_DBL, ANYPLANAR|ANYEXTRA, UnrollXYZDoubleToFloat}, 3098 { TYPE_XYZ_FLT, ANYPLANAR|ANYEXTRA, UnrollXYZFloatToFloat}, 3099 3100 { FLOAT_SH(1)|BYTES_SH(4), ANYPLANAR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA| 3101 ANYCHANNELS|ANYSPACE, UnrollFloatsToFloat}, 3102 3103 { FLOAT_SH(1)|BYTES_SH(0), ANYPLANAR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA| 3104 ANYCHANNELS|ANYSPACE, UnrollDoublesToFloat}, 3105 #ifndef CMS_NO_HALF_SUPPORT 3106 { FLOAT_SH(1)|BYTES_SH(2), ANYPLANAR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA| 3107 ANYCHANNELS|ANYSPACE, UnrollHalfToFloat}, 3108 #endif 3109 }; 3110 3111 3112 // Bit fields set to one in the mask are not compared 3113 static 3114 cmsFormatter _cmsGetStockInputFormatter(cmsUInt32Number dwInput, cmsUInt32Number dwFlags) 3115 { 3116 cmsUInt32Number i; 3117 cmsFormatter fr; 3118 3119 switch (dwFlags) { 3120 3121 case CMS_PACK_FLAGS_16BITS: { 3122 for (i=0; i < sizeof(InputFormatters16) / sizeof(cmsFormatters16); i++) { 3123 const cmsFormatters16* f = InputFormatters16 + i; 3124 3125 if ((dwInput & ~f ->Mask) == f ->Type) { 3126 fr.Fmt16 = f ->Frm; 3127 return fr; 3128 } 3129 } 3130 } 3131 break; 3132 3133 case CMS_PACK_FLAGS_FLOAT: { 3134 for (i=0; i < sizeof(InputFormattersFloat) / sizeof(cmsFormattersFloat); i++) { 3135 const cmsFormattersFloat* f = InputFormattersFloat + i; 3136 3137 if ((dwInput & ~f ->Mask) == f ->Type) { 3138 fr.FmtFloat = f ->Frm; 3139 return fr; 3140 } 3141 } 3142 } 3143 break; 3144 3145 default:; 3146 3147 } 3148 3149 fr.Fmt16 = NULL; 3150 return fr; 3151 } 3152 3153 static const cmsFormatters16 OutputFormatters16[] = { 3154 // Type Mask Function 3155 // ---------------------------- ------------------------------------ ---------------------------- 3156 3157 { TYPE_Lab_DBL, ANYPLANAR|ANYEXTRA, PackLabDoubleFrom16}, 3158 { TYPE_XYZ_DBL, ANYPLANAR|ANYEXTRA, PackXYZDoubleFrom16}, 3159 3160 { TYPE_Lab_FLT, ANYPLANAR|ANYEXTRA, PackLabFloatFrom16}, 3161 { TYPE_XYZ_FLT, ANYPLANAR|ANYEXTRA, PackXYZFloatFrom16}, 3162 3163 { FLOAT_SH(1)|BYTES_SH(0), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP| 3164 ANYCHANNELS|ANYPLANAR|ANYEXTRA|ANYSPACE, PackDoubleFrom16}, 3165 { FLOAT_SH(1)|BYTES_SH(4), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP| 3166 ANYCHANNELS|ANYPLANAR|ANYEXTRA|ANYSPACE, PackFloatFrom16}, 3167 #ifndef CMS_NO_HALF_SUPPORT 3168 { FLOAT_SH(1)|BYTES_SH(2), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP| 3169 ANYCHANNELS|ANYPLANAR|ANYEXTRA|ANYSPACE, PackHalfFrom16}, 3170 #endif 3171 3172 { CHANNELS_SH(1)|BYTES_SH(1), ANYSPACE, Pack1Byte}, 3173 { CHANNELS_SH(1)|BYTES_SH(1)|EXTRA_SH(1), ANYSPACE, Pack1ByteSkip1}, 3174 { CHANNELS_SH(1)|BYTES_SH(1)|EXTRA_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Pack1ByteSkip1SwapFirst}, 3175 3176 { CHANNELS_SH(1)|BYTES_SH(1)|FLAVOR_SH(1), ANYSPACE, Pack1ByteReversed}, 3177 3178 { TYPE_LabV2_8, 0, PackLabV2_8 }, 3179 { TYPE_ALabV2_8, 0, PackALabV2_8 }, 3180 { TYPE_LabV2_16, 0, PackLabV2_16 }, 3181 3182 { CHANNELS_SH(3)|BYTES_SH(1)|OPTIMIZED_SH(1), ANYSPACE, Pack3BytesOptimized}, 3183 { CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|OPTIMIZED_SH(1), ANYSPACE, Pack3BytesAndSkip1Optimized}, 3184 { CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|SWAPFIRST_SH(1)|OPTIMIZED_SH(1), 3185 ANYSPACE, Pack3BytesAndSkip1SwapFirstOptimized}, 3186 { CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1)|OPTIMIZED_SH(1), 3187 ANYSPACE, Pack3BytesAndSkip1SwapSwapFirstOptimized}, 3188 { CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1)|EXTRA_SH(1)|OPTIMIZED_SH(1), 3189 ANYSPACE, Pack3BytesAndSkip1SwapOptimized}, 3190 { CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1)|OPTIMIZED_SH(1), ANYSPACE, Pack3BytesSwapOptimized}, 3191 3192 3193 3194 { CHANNELS_SH(3)|BYTES_SH(1), ANYSPACE, Pack3Bytes}, 3195 { CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1), ANYSPACE, Pack3BytesAndSkip1}, 3196 { CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Pack3BytesAndSkip1SwapFirst}, 3197 { CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1), 3198 ANYSPACE, Pack3BytesAndSkip1SwapSwapFirst}, 3199 { CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1)|EXTRA_SH(1), ANYSPACE, Pack3BytesAndSkip1Swap}, 3200 { CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1), ANYSPACE, Pack3BytesSwap}, 3201 { CHANNELS_SH(6)|BYTES_SH(1), ANYSPACE, Pack6Bytes}, 3202 { CHANNELS_SH(6)|BYTES_SH(1)|DOSWAP_SH(1), ANYSPACE, Pack6BytesSwap}, 3203 { CHANNELS_SH(4)|BYTES_SH(1), ANYSPACE, Pack4Bytes}, 3204 { CHANNELS_SH(4)|BYTES_SH(1)|FLAVOR_SH(1), ANYSPACE, Pack4BytesReverse}, 3205 { CHANNELS_SH(4)|BYTES_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Pack4BytesSwapFirst}, 3206 { CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1), ANYSPACE, Pack4BytesSwap}, 3207 { CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Pack4BytesSwapSwapFirst}, 3208 3209 { BYTES_SH(1), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackAnyBytes}, 3210 { BYTES_SH(1)|PLANAR_SH(1), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackPlanarBytes}, 3211 3212 { CHANNELS_SH(1)|BYTES_SH(2), ANYSPACE, Pack1Word}, 3213 { CHANNELS_SH(1)|BYTES_SH(2)|EXTRA_SH(1), ANYSPACE, Pack1WordSkip1}, 3214 { CHANNELS_SH(1)|BYTES_SH(2)|EXTRA_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Pack1WordSkip1SwapFirst}, 3215 { CHANNELS_SH(1)|BYTES_SH(2)|FLAVOR_SH(1), ANYSPACE, Pack1WordReversed}, 3216 { CHANNELS_SH(1)|BYTES_SH(2)|ENDIAN16_SH(1), ANYSPACE, Pack1WordBigEndian}, 3217 { CHANNELS_SH(3)|BYTES_SH(2), ANYSPACE, Pack3Words}, 3218 { CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1), ANYSPACE, Pack3WordsSwap}, 3219 { CHANNELS_SH(3)|BYTES_SH(2)|ENDIAN16_SH(1), ANYSPACE, Pack3WordsBigEndian}, 3220 { CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1), ANYSPACE, Pack3WordsAndSkip1}, 3221 { CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1)|DOSWAP_SH(1), ANYSPACE, Pack3WordsAndSkip1Swap}, 3222 { CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Pack3WordsAndSkip1SwapFirst}, 3223 3224 { CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1), 3225 ANYSPACE, Pack3WordsAndSkip1SwapSwapFirst}, 3226 3227 { CHANNELS_SH(4)|BYTES_SH(2), ANYSPACE, Pack4Words}, 3228 { CHANNELS_SH(4)|BYTES_SH(2)|FLAVOR_SH(1), ANYSPACE, Pack4WordsReverse}, 3229 { CHANNELS_SH(4)|BYTES_SH(2)|DOSWAP_SH(1), ANYSPACE, Pack4WordsSwap}, 3230 { CHANNELS_SH(4)|BYTES_SH(2)|ENDIAN16_SH(1), ANYSPACE, Pack4WordsBigEndian}, 3231 3232 { CHANNELS_SH(6)|BYTES_SH(2), ANYSPACE, Pack6Words}, 3233 { CHANNELS_SH(6)|BYTES_SH(2)|DOSWAP_SH(1), ANYSPACE, Pack6WordsSwap}, 3234 3235 { BYTES_SH(2)|PLANAR_SH(1), ANYFLAVOR|ANYENDIAN|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackPlanarWords}, 3236 { BYTES_SH(2), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYENDIAN|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackAnyWords} 3237 3238 }; 3239 3240 3241 static const cmsFormattersFloat OutputFormattersFloat[] = { 3242 // Type Mask Function 3243 // ---------------------------- --------------------------------------------------- ---------------------------- 3244 { TYPE_Lab_FLT, ANYPLANAR|ANYEXTRA, PackLabFloatFromFloat}, 3245 { TYPE_XYZ_FLT, ANYPLANAR|ANYEXTRA, PackXYZFloatFromFloat}, 3246 3247 { TYPE_Lab_DBL, ANYPLANAR|ANYEXTRA, PackLabDoubleFromFloat}, 3248 { TYPE_XYZ_DBL, ANYPLANAR|ANYEXTRA, PackXYZDoubleFromFloat}, 3249 3250 { FLOAT_SH(1)|BYTES_SH(4), ANYPLANAR| 3251 ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackFloatsFromFloat }, 3252 { FLOAT_SH(1)|BYTES_SH(0), ANYPLANAR| 3253 ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackDoublesFromFloat }, 3254 #ifndef CMS_NO_HALF_SUPPORT 3255 { FLOAT_SH(1)|BYTES_SH(2), 3256 ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackHalfFromFloat }, 3257 #endif 3258 3259 }; 3260 3261 3262 // Bit fields set to one in the mask are not compared 3263 static 3264 cmsFormatter _cmsGetStockOutputFormatter(cmsUInt32Number dwInput, cmsUInt32Number dwFlags) 3265 { 3266 cmsUInt32Number i; 3267 cmsFormatter fr; 3268 3269 // Optimization is only a hint 3270 dwInput &= ~OPTIMIZED_SH(1); 3271 3272 switch (dwFlags) 3273 { 3274 3275 case CMS_PACK_FLAGS_16BITS: { 3276 3277 for (i=0; i < sizeof(OutputFormatters16) / sizeof(cmsFormatters16); i++) { 3278 const cmsFormatters16* f = OutputFormatters16 + i; 3279 3280 if ((dwInput & ~f ->Mask) == f ->Type) { 3281 fr.Fmt16 = f ->Frm; 3282 return fr; 3283 } 3284 } 3285 } 3286 break; 3287 3288 case CMS_PACK_FLAGS_FLOAT: { 3289 3290 for (i=0; i < sizeof(OutputFormattersFloat) / sizeof(cmsFormattersFloat); i++) { 3291 const cmsFormattersFloat* f = OutputFormattersFloat + i; 3292 3293 if ((dwInput & ~f ->Mask) == f ->Type) { 3294 fr.FmtFloat = f ->Frm; 3295 return fr; 3296 } 3297 } 3298 } 3299 break; 3300 3301 default:; 3302 3303 } 3304 3305 fr.Fmt16 = NULL; 3306 return fr; 3307 } 3308 3309 3310 typedef struct _cms_formatters_factory_list { 3311 3312 cmsFormatterFactory Factory; 3313 struct _cms_formatters_factory_list *Next; 3314 3315 } cmsFormattersFactoryList; 3316 3317 _cmsFormattersPluginChunkType _cmsFormattersPluginChunk = { NULL }; 3318 3319 3320 // Duplicates the zone of memory used by the plug-in in the new context 3321 static 3322 void DupFormatterFactoryList(struct _cmsContext_struct* ctx, 3323 const struct _cmsContext_struct* src) 3324 { 3325 _cmsFormattersPluginChunkType newHead = { NULL }; 3326 cmsFormattersFactoryList* entry; 3327 cmsFormattersFactoryList* Anterior = NULL; 3328 _cmsFormattersPluginChunkType* head = (_cmsFormattersPluginChunkType*) src->chunks[FormattersPlugin]; 3329 3330 _cmsAssert(head != NULL); 3331 3332 // Walk the list copying all nodes 3333 for (entry = head->FactoryList; 3334 entry != NULL; 3335 entry = entry ->Next) { 3336 3337 cmsFormattersFactoryList *newEntry = ( cmsFormattersFactoryList *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(cmsFormattersFactoryList)); 3338 3339 if (newEntry == NULL) 3340 return; 3341 3342 // We want to keep the linked list order, so this is a little bit tricky 3343 newEntry -> Next = NULL; 3344 if (Anterior) 3345 Anterior -> Next = newEntry; 3346 3347 Anterior = newEntry; 3348 3349 if (newHead.FactoryList == NULL) 3350 newHead.FactoryList = newEntry; 3351 } 3352 3353 ctx ->chunks[FormattersPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsFormattersPluginChunkType)); 3354 } 3355 3356 // The interpolation plug-in memory chunk allocator/dup 3357 void _cmsAllocFormattersPluginChunk(struct _cmsContext_struct* ctx, 3358 const struct _cmsContext_struct* src) 3359 { 3360 _cmsAssert(ctx != NULL); 3361 3362 if (src != NULL) { 3363 3364 // Duplicate the LIST 3365 DupFormatterFactoryList(ctx, src); 3366 } 3367 else { 3368 static _cmsFormattersPluginChunkType FormattersPluginChunk = { NULL }; 3369 ctx ->chunks[FormattersPlugin] = _cmsSubAllocDup(ctx ->MemPool, &FormattersPluginChunk, sizeof(_cmsFormattersPluginChunkType)); 3370 } 3371 } 3372 3373 3374 3375 // Formatters management 3376 cmsBool _cmsRegisterFormattersPlugin(cmsContext ContextID, cmsPluginBase* Data) 3377 { 3378 _cmsFormattersPluginChunkType* ctx = ( _cmsFormattersPluginChunkType*) _cmsContextGetClientChunk(ContextID, FormattersPlugin); 3379 cmsPluginFormatters* Plugin = (cmsPluginFormatters*) Data; 3380 cmsFormattersFactoryList* fl ; 3381 3382 // Reset to built-in defaults 3383 if (Data == NULL) { 3384 3385 ctx ->FactoryList = NULL; 3386 return TRUE; 3387 } 3388 3389 fl = (cmsFormattersFactoryList*) _cmsPluginMalloc(ContextID, sizeof(cmsFormattersFactoryList)); 3390 if (fl == NULL) return FALSE; 3391 3392 fl ->Factory = Plugin ->FormattersFactory; 3393 3394 fl ->Next = ctx -> FactoryList; 3395 ctx ->FactoryList = fl; 3396 3397 return TRUE; 3398 } 3399 3400 cmsFormatter CMSEXPORT _cmsGetFormatter(cmsContext ContextID, 3401 cmsUInt32Number Type, // Specific type, i.e. TYPE_RGB_8 3402 cmsFormatterDirection Dir, 3403 cmsUInt32Number dwFlags) 3404 { 3405 _cmsFormattersPluginChunkType* ctx = ( _cmsFormattersPluginChunkType*) _cmsContextGetClientChunk(ContextID, FormattersPlugin); 3406 cmsFormattersFactoryList* f; 3407 3408 for (f =ctx->FactoryList; f != NULL; f = f ->Next) { 3409 3410 cmsFormatter fn = f ->Factory(Type, Dir, dwFlags); 3411 if (fn.Fmt16 != NULL) return fn; 3412 } 3413 3414 // Revert to default 3415 if (Dir == cmsFormatterInput) 3416 return _cmsGetStockInputFormatter(Type, dwFlags); 3417 else 3418 return _cmsGetStockOutputFormatter(Type, dwFlags); 3419 } 3420 3421 3422 // Return whatever given formatter refers to float values 3423 cmsBool _cmsFormatterIsFloat(cmsUInt32Number Type) 3424 { 3425 return T_FLOAT(Type) ? TRUE : FALSE; 3426 } 3427 3428 // Return whatever given formatter refers to 8 bits 3429 cmsBool _cmsFormatterIs8bit(cmsUInt32Number Type) 3430 { 3431 cmsUInt32Number Bytes = T_BYTES(Type); 3432 3433 return (Bytes == 1); 3434 } 3435 3436 // Build a suitable formatter for the colorspace of this profile 3437 cmsUInt32Number CMSEXPORT cmsFormatterForColorspaceOfProfile(cmsHPROFILE hProfile, cmsUInt32Number nBytes, cmsBool lIsFloat) 3438 { 3439 3440 cmsColorSpaceSignature ColorSpace = cmsGetColorSpace(hProfile); 3441 cmsUInt32Number ColorSpaceBits = (cmsUInt32Number) _cmsLCMScolorSpace(ColorSpace); 3442 cmsUInt32Number nOutputChans = cmsChannelsOf(ColorSpace); 3443 cmsUInt32Number Float = lIsFloat ? 1U : 0; 3444 3445 // Create a fake formatter for result 3446 return FLOAT_SH(Float) | COLORSPACE_SH(ColorSpaceBits) | BYTES_SH(nBytes) | CHANNELS_SH(nOutputChans); 3447 } 3448 3449 // Build a suitable formatter for the colorspace of this profile 3450 cmsUInt32Number CMSEXPORT cmsFormatterForPCSOfProfile(cmsHPROFILE hProfile, cmsUInt32Number nBytes, cmsBool lIsFloat) 3451 { 3452 3453 cmsColorSpaceSignature ColorSpace = cmsGetPCS(hProfile); 3454 3455 cmsUInt32Number ColorSpaceBits = (cmsUInt32Number) _cmsLCMScolorSpace(ColorSpace); 3456 cmsUInt32Number nOutputChans = cmsChannelsOf(ColorSpace); 3457 cmsUInt32Number Float = lIsFloat ? 1U : 0; 3458 3459 // Create a fake formatter for result 3460 return FLOAT_SH(Float) | COLORSPACE_SH(ColorSpaceBits) | BYTES_SH(nBytes) | CHANNELS_SH(nOutputChans); 3461 } 3462