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