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