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