1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. Oracle designates this 7 * particular file as subject to the "Classpath" exception as provided 8 * by Oracle in the LICENSE file that accompanied this code. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 */ 24 25 // This file is available under and governed by the GNU General Public 26 // License version 2 only, as published by the Free Software Foundation. 27 // However, the following notice accompanied the original version of this 28 // file: 29 // 30 //--------------------------------------------------------------------------------- 31 // 32 // Little Color Management System 33 // Copyright (c) 1998-2016 Marti Maria Saguer 34 // 35 // Permission is hereby granted, free of charge, to any person obtaining 36 // a copy of this software and associated documentation files (the "Software"), 37 // to deal in the Software without restriction, including without limitation 38 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 39 // and/or sell copies of the Software, and to permit persons to whom the Software 40 // is furnished to do so, subject to the following conditions: 41 // 42 // The above copyright notice and this permission notice shall be included in 43 // all copies or substantial portions of the Software. 44 // 45 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 46 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 47 // THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 48 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 49 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 50 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 51 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 52 // 53 //--------------------------------------------------------------------------------- 54 // 55 56 #include "lcms2_internal.h" 57 58 59 // Alpha copy ------------------------------------------------------------------------------------------------------------------ 60 61 // Floor to byte, taking care of saturation 62 cmsINLINE cmsUInt8Number _cmsQuickSaturateByte(cmsFloat64Number d) 63 { 64 d += 0.5; 65 if (d <= 0) return 0; 66 if (d >= 255.0) return 255; 67 68 return (cmsUInt8Number) _cmsQuickFloorWord(d); 69 } 70 71 72 // Return the size in bytes of a given formatter 73 static 74 int trueBytesSize(cmsUInt32Number Format) 75 { 76 int fmt_bytes = T_BYTES(Format); 77 78 // For double, the T_BYTES field returns zero 79 if (fmt_bytes == 0) 80 return sizeof(double); 81 82 // Otherwise, it is already correct for all formats 83 return fmt_bytes; 84 } 85 86 87 // Several format converters 88 89 typedef void(*cmsFormatterAlphaFn)(void* dst, const void* src); 90 91 92 // From 8 93 94 static 95 void copy8(void* dst, const void* src) 96 { 97 memmove(dst, src, 1); 98 } 99 100 static 101 void from8to16(void* dst, const void* src) 102 { 103 cmsUInt8Number n = *(cmsUInt8Number*)src; 104 *(cmsUInt16Number*) dst = FROM_8_TO_16(n); 105 } 106 107 static 108 void from8toFLT(void* dst, const void* src) 109 { 110 *(cmsFloat32Number*)dst = (*(cmsUInt8Number*)src) / 255.0f; 111 } 112 113 static 114 void from8toDBL(void* dst, const void* src) 115 { 116 *(cmsFloat64Number*)dst = (*(cmsUInt8Number*)src) / 255.0; 117 } 118 119 static 120 void from8toHLF(void* dst, const void* src) 121 { 122 cmsFloat32Number n = (*(cmsUInt8Number*)src) / 255.0f; 123 *(cmsUInt16Number*)dst = _cmsFloat2Half(n); 124 } 125 126 // From 16 127 128 static 129 void from16to8(void* dst, const void* src) 130 { 131 cmsUInt16Number n = *(cmsUInt16Number*)src; 132 *(cmsUInt8Number*) dst = FROM_16_TO_8(n); 133 } 134 135 static 136 void copy16(void* dst, const void* src) 137 { 138 memmove(dst, src, 2); 139 } 140 141 void from16toFLT(void* dst, const void* src) 142 { 143 *(cmsFloat32Number*)dst = (*(cmsUInt16Number*)src) / 65535.0f; 144 } 145 146 void from16toDBL(void* dst, const void* src) 147 { 148 *(cmsFloat64Number*)dst = (*(cmsUInt16Number*)src) / 65535.0f; 149 } 150 151 static 152 void from16toHLF(void* dst, const void* src) 153 { 154 cmsFloat32Number n = (*(cmsUInt16Number*)src) / 65535.0f; 155 *(cmsUInt16Number*)dst = _cmsFloat2Half(n); 156 } 157 158 // From Float 159 160 static 161 void fromFLTto8(void* dst, const void* src) 162 { 163 cmsFloat32Number n = *(cmsFloat32Number*)src; 164 *(cmsUInt8Number*)dst = _cmsQuickSaturateByte(n * 255.0f); 165 } 166 167 static 168 void fromFLTto16(void* dst, const void* src) 169 { 170 cmsFloat32Number n = *(cmsFloat32Number*)src; 171 *(cmsUInt16Number*)dst = _cmsQuickSaturateWord(n * 65535.0f); 172 } 173 174 static 175 void copy32(void* dst, const void* src) 176 { 177 memmove(dst, src, sizeof(cmsFloat32Number)); 178 } 179 180 static 181 void fromFLTtoDBL(void* dst, const void* src) 182 { 183 cmsFloat32Number n = *(cmsFloat32Number*)src; 184 *(cmsFloat64Number*)dst = (cmsFloat64Number)n; 185 } 186 187 static 188 void fromFLTtoHLF(void* dst, const void* src) 189 { 190 cmsFloat32Number n = *(cmsFloat32Number*)src; 191 *(cmsUInt16Number*)dst = _cmsFloat2Half(n); 192 } 193 194 195 // From HALF 196 197 static 198 void fromHLFto8(void* dst, const void* src) 199 { 200 cmsFloat32Number n = _cmsHalf2Float(*(cmsUInt16Number*)src); 201 *(cmsUInt8Number*)dst = _cmsQuickSaturateByte(n * 255.0f); 202 } 203 204 static 205 void fromHLFto16(void* dst, const void* src) 206 { 207 cmsFloat32Number n = _cmsHalf2Float(*(cmsUInt16Number*)src); 208 *(cmsUInt16Number*)dst = _cmsQuickSaturateWord(n * 65535.0f); 209 } 210 211 static 212 void fromHLFtoFLT(void* dst, const void* src) 213 { 214 *(cmsFloat32Number*)dst = _cmsHalf2Float(*(cmsUInt16Number*)src); 215 } 216 217 static 218 void fromHLFtoDBL(void* dst, const void* src) 219 { 220 *(cmsFloat64Number*)dst = (cmsFloat64Number)_cmsHalf2Float(*(cmsUInt16Number*)src); 221 } 222 223 // From double 224 static 225 void fromDBLto8(void* dst, const void* src) 226 { 227 cmsFloat64Number n = *(cmsFloat64Number*)src; 228 *(cmsUInt8Number*)dst = _cmsQuickSaturateByte(n * 255.0); 229 } 230 231 static 232 void fromDBLto16(void* dst, const void* src) 233 { 234 cmsFloat64Number n = *(cmsFloat64Number*)src; 235 *(cmsUInt16Number*)dst = _cmsQuickSaturateWord(n * 65535.0f); 236 } 237 238 static 239 void fromDBLtoFLT(void* dst, const void* src) 240 { 241 cmsFloat64Number n = *(cmsFloat64Number*)src; 242 *(cmsFloat32Number*)dst = (cmsFloat32Number) n; 243 } 244 245 static 246 void fromDBLtoHLF(void* dst, const void* src) 247 { 248 cmsFloat32Number n = (cmsFloat32Number) *(cmsFloat64Number*)src; 249 *(cmsUInt16Number*)dst = _cmsFloat2Half(n); 250 } 251 252 static 253 void copy64(void* dst, const void* src) 254 { 255 memmove(dst, src, sizeof(cmsFloat64Number)); 256 } 257 258 259 // Returns the position (x or y) of the formatter in the table of functions 260 static 261 int FormatterPos(cmsUInt32Number frm) 262 { 263 int b = T_BYTES(frm); 264 265 if (b == 0 && T_FLOAT(frm)) 266 return 4; // DBL 267 if (b == 2 && T_FLOAT(frm)) 268 return 2; // HLF 269 if (b == 4 && T_FLOAT(frm)) 270 return 3; // FLT 271 if (b == 2 && !T_FLOAT(frm)) 272 return 1; // 16 273 if (b == 1 && !T_FLOAT(frm)) 274 return 0; // 8 275 276 return -1; // not recognized 277 278 } 279 280 // Obtains a alpha-to-alpha funmction formatter 281 static 282 cmsFormatterAlphaFn _cmsGetFormatterAlpha(cmsContext id, cmsUInt32Number in, cmsUInt32Number out) 283 { 284 static cmsFormatterAlphaFn FormattersAlpha[5][5] = { 285 286 /* from 8 */ { copy8, from8to16, from8toHLF, from8toFLT, from8toDBL }, 287 /* from 16*/ { from16to8, copy16, from16toHLF, from16toFLT, from16toDBL }, 288 /* from HLF*/ { fromHLFto8, fromHLFto16, copy16, fromHLFtoFLT, fromHLFtoDBL }, 289 /* from FLT*/ { fromFLTto8, fromFLTto16, fromFLTtoHLF, copy32, fromFLTtoDBL }, 290 /* from DBL*/ { fromDBLto8, fromDBLto16, fromDBLtoHLF, fromDBLtoFLT, copy64 }}; 291 292 int in_n = FormatterPos(in); 293 int out_n = FormatterPos(out); 294 295 if (in_n < 0 || out_n < 0 || in_n > 4 || out_n > 4) { 296 297 cmsSignalError(id, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized alpha channel width"); 298 return NULL; 299 } 300 301 return FormattersAlpha[in_n][out_n]; 302 } 303 304 305 306 // This function computes the distance from each component to the next one in bytes. 307 static 308 void ComputeIncrementsForChunky(cmsUInt32Number Format, 309 cmsUInt32Number ComponentStartingOrder[], 310 cmsUInt32Number ComponentPointerIncrements[]) 311 { 312 cmsUInt32Number channels[cmsMAXCHANNELS]; 313 int extra = T_EXTRA(Format); 314 int nchannels = T_CHANNELS(Format); 315 int total_chans = nchannels + extra; 316 int i; 317 int channelSize = trueBytesSize(Format); 318 int pixelSize = channelSize * total_chans; 319 320 // Sanity check 321 if (total_chans <= 0 || total_chans >= cmsMAXCHANNELS) 322 return; 323 324 memset(channels, 0, sizeof(channels)); 325 326 // Separation is independent of starting point and only depends on channel size 327 for (i = 0; i < extra; i++) 328 ComponentPointerIncrements[i] = pixelSize; 329 330 // Handle do swap 331 for (i = 0; i < total_chans; i++) 332 { 333 if (T_DOSWAP(Format)) { 334 channels[i] = total_chans - i - 1; 335 } 336 else { 337 channels[i] = i; 338 } 339 } 340 341 // Handle swap first (ROL of positions), example CMYK -> KCMY | 0123 -> 3012 342 if (T_SWAPFIRST(Format) && total_chans > 1) { 343 344 cmsUInt32Number tmp = channels[0]; 345 for (i = 0; i < total_chans-1; i++) 346 channels[i] = channels[i + 1]; 347 348 channels[total_chans - 1] = tmp; 349 } 350 351 // Handle size 352 if (channelSize > 1) 353 for (i = 0; i < total_chans; i++) { 354 channels[i] *= channelSize; 355 } 356 357 for (i = 0; i < extra; i++) 358 ComponentStartingOrder[i] = channels[i + nchannels]; 359 } 360 361 362 363 // On planar configurations, the distance is the stride added to any non-negative 364 static 365 void ComputeIncrementsForPlanar(cmsUInt32Number Format, 366 cmsUInt32Number BytesPerPlane, 367 cmsUInt32Number ComponentStartingOrder[], 368 cmsUInt32Number ComponentPointerIncrements[]) 369 { 370 cmsUInt32Number channels[cmsMAXCHANNELS]; 371 int extra = T_EXTRA(Format); 372 int nchannels = T_CHANNELS(Format); 373 int total_chans = nchannels + extra; 374 int i; 375 int channelSize = trueBytesSize(Format); 376 377 // Sanity check 378 if (total_chans <= 0 || total_chans >= cmsMAXCHANNELS) 379 return; 380 381 memset(channels, 0, sizeof(channels)); 382 383 // Separation is independent of starting point and only depends on channel size 384 for (i = 0; i < extra; i++) 385 ComponentPointerIncrements[i] = channelSize; 386 387 // Handle do swap 388 for (i = 0; i < total_chans; i++) 389 { 390 if (T_DOSWAP(Format)) { 391 channels[i] = total_chans - i - 1; 392 } 393 else { 394 channels[i] = i; 395 } 396 } 397 398 // Handle swap first (ROL of positions), example CMYK -> KCMY | 0123 -> 3012 399 if (T_SWAPFIRST(Format) && total_chans > 0) { 400 401 cmsUInt32Number tmp = channels[0]; 402 for (i = 0; i < total_chans - 1; i++) 403 channels[i] = channels[i + 1]; 404 405 channels[total_chans - 1] = tmp; 406 } 407 408 // Handle size 409 for (i = 0; i < total_chans; i++) { 410 channels[i] *= BytesPerPlane; 411 } 412 413 for (i = 0; i < extra; i++) 414 ComponentStartingOrder[i] = channels[i + nchannels]; 415 } 416 417 418 419 // Dispatcher por chunky and planar RGB 420 static 421 void ComputeComponentIncrements(cmsUInt32Number Format, 422 cmsUInt32Number BytesPerPlane, 423 cmsUInt32Number ComponentStartingOrder[], 424 cmsUInt32Number ComponentPointerIncrements[]) 425 { 426 if (T_PLANAR(Format)) { 427 428 ComputeIncrementsForPlanar(Format, BytesPerPlane, ComponentStartingOrder, ComponentPointerIncrements); 429 } 430 else { 431 ComputeIncrementsForChunky(Format, ComponentStartingOrder, ComponentPointerIncrements); 432 } 433 434 } 435 436 437 438 // Handles extra channels copying alpha if requested by the flags 439 void _cmsHandleExtraChannels(_cmsTRANSFORM* p, const void* in, 440 void* out, 441 cmsUInt32Number PixelsPerLine, 442 cmsUInt32Number LineCount, 443 const cmsStride* Stride) 444 { 445 cmsUInt32Number i, j, k; 446 cmsUInt32Number nExtra; 447 cmsUInt32Number SourceStartingOrder[cmsMAXCHANNELS]; 448 cmsUInt32Number SourceIncrements[cmsMAXCHANNELS]; 449 cmsUInt32Number DestStartingOrder[cmsMAXCHANNELS]; 450 cmsUInt32Number DestIncrements[cmsMAXCHANNELS]; 451 452 cmsFormatterAlphaFn copyValueFn; 453 454 // Make sure we need some copy 455 if (!(p->dwOriginalFlags & cmsFLAGS_COPY_ALPHA)) 456 return; 457 458 // Exit early if in-place color-management is occurring - no need to copy extra channels to themselves. 459 if (p->InputFormat == p->OutputFormat && in == out) 460 return; 461 462 // Make sure we have same number of alpha channels. If not, just return as this should be checked at transform creation time. 463 nExtra = T_EXTRA(p->InputFormat); 464 if (nExtra != T_EXTRA(p->OutputFormat)) 465 return; 466 467 // Anything to do? 468 if (nExtra == 0) 469 return; 470 471 // Compute the increments 472 ComputeComponentIncrements(p->InputFormat, Stride->BytesPerPlaneIn, SourceStartingOrder, SourceIncrements); 473 ComputeComponentIncrements(p->OutputFormat, Stride->BytesPerPlaneOut, DestStartingOrder, DestIncrements); 474 475 // Check for conversions 8, 16, half, float, dbl 476 copyValueFn = _cmsGetFormatterAlpha(p->ContextID, p->InputFormat, p->OutputFormat); 477 478 if (nExtra == 1) { // Optimized routine for copying a single extra channel quickly 479 480 cmsUInt8Number* SourcePtr; 481 cmsUInt8Number* DestPtr; 482 483 cmsUInt32Number SourceStrideIncrement = 0; 484 cmsUInt32Number DestStrideIncrement = 0; 485 486 // The loop itself 487 for (i = 0; i < LineCount; i++) { 488 489 // Prepare pointers for the loop 490 SourcePtr = (cmsUInt8Number*)in + SourceStartingOrder[0] + SourceStrideIncrement; 491 DestPtr = (cmsUInt8Number*)out + DestStartingOrder[0] + DestStrideIncrement; 492 493 for (j = 0; j < PixelsPerLine; j++) { 494 495 copyValueFn(DestPtr, SourcePtr); 496 497 SourcePtr += SourceIncrements[0]; 498 DestPtr += DestIncrements[0]; 499 } 500 501 SourceStrideIncrement += Stride->BytesPerLineIn; 502 DestStrideIncrement += Stride->BytesPerLineOut; 503 } 504 505 } 506 else { // General case with more than one extra channel 507 508 cmsUInt8Number* SourcePtr[cmsMAXCHANNELS]; 509 cmsUInt8Number* DestPtr[cmsMAXCHANNELS]; 510 511 cmsUInt32Number SourceStrideIncrements[cmsMAXCHANNELS]; 512 cmsUInt32Number DestStrideIncrements[cmsMAXCHANNELS]; 513 514 memset(SourceStrideIncrements, 0, sizeof(SourceStrideIncrements)); 515 memset(DestStrideIncrements, 0, sizeof(DestStrideIncrements)); 516 517 // The loop itself 518 for (i = 0; i < LineCount; i++) { 519 520 // Prepare pointers for the loop 521 for (j = 0; j < nExtra; j++) { 522 523 SourcePtr[j] = (cmsUInt8Number*)in + SourceStartingOrder[j] + SourceStrideIncrements[j]; 524 DestPtr[j] = (cmsUInt8Number*)out + DestStartingOrder[j] + DestStrideIncrements[j]; 525 } 526 527 for (j = 0; j < PixelsPerLine; j++) { 528 529 for (k = 0; k < nExtra; k++) { 530 531 copyValueFn(DestPtr[k], SourcePtr[k]); 532 533 SourcePtr[k] += SourceIncrements[k]; 534 DestPtr[k] += DestIncrements[k]; 535 } 536 } 537 538 for (j = 0; j < nExtra; j++) { 539 540 SourceStrideIncrements[j] += Stride->BytesPerLineIn; 541 DestStrideIncrements[j] += Stride->BytesPerLineOut; 542 } 543 } 544 } 545 } 546 547