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