OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkAtomics.h" | 8 #include "SkAtomics.h" |
9 #include "SkColorSpace.h" | 9 #include "SkColorSpace.h" |
10 #include "SkColorSpacePriv.h" | 10 #include "SkColorSpacePriv.h" |
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
355 switch (type) { | 355 switch (type) { |
356 case kTAG_CurveType: { | 356 case kTAG_CurveType: { |
357 uint32_t count = read_big_endian_uint(src + 8); | 357 uint32_t count = read_big_endian_uint(src + 8); |
358 tagBytes = 12 + count * 2; | 358 tagBytes = 12 + count * 2; |
359 if (0 == count) { | 359 if (0 == count) { |
360 // Some tags require a gamma curve, but the author doesn't a
ctually want | 360 // Some tags require a gamma curve, but the author doesn't a
ctually want |
361 // to transform the data. In this case, it is common to see
a curve with | 361 // to transform the data. In this case, it is common to see
a curve with |
362 // a count of 0. | 362 // a count of 0. |
363 gammas[i].fValue = 1.0f; | 363 gammas[i].fValue = 1.0f; |
364 break; | 364 break; |
365 } else if (len < 12 + 2 * count) { | 365 } else if (len < tagBytes) { |
366 SkColorSpacePrintf("gamma tag is too small (%d bytes)", len)
; | 366 SkColorSpacePrintf("gamma tag is too small (%d bytes)", len)
; |
367 return false; | 367 return false; |
368 } | 368 } |
369 | 369 |
370 const uint16_t* table = (const uint16_t*) (src + 12); | 370 const uint16_t* table = (const uint16_t*) (src + 12); |
371 if (1 == count) { | 371 if (1 == count) { |
372 // The table entry is the gamma (with a bias of 256). | 372 // The table entry is the gamma (with a bias of 256). |
373 uint16_t value = read_big_endian_short((const uint8_t*) tabl
e); | 373 uint16_t value = read_big_endian_short((const uint8_t*) tabl
e); |
374 gammas[i].fValue = value / 256.0f; | 374 gammas[i].fValue = value / 256.0f; |
375 SkColorSpacePrintf("gamma %d %g\n", value, gammas[i].fValue)
; | 375 SkColorSpacePrintf("gamma %d %g\n", value, gammas[i].fValue)
; |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
422 // Otherwise, fill in the interpolation table. | 422 // Otherwise, fill in the interpolation table. |
423 gammas[i].fTableSize = count; | 423 gammas[i].fTableSize = count; |
424 gammas[i].fTable = std::unique_ptr<float[]>(new float[count]); | 424 gammas[i].fTable = std::unique_ptr<float[]>(new float[count]); |
425 for (uint32_t j = 0; j < count; j++) { | 425 for (uint32_t j = 0; j < count; j++) { |
426 gammas[i].fTable[j] = | 426 gammas[i].fTable[j] = |
427 (read_big_endian_short((const uint8_t*) &table[j]))
/ 65535.0f; | 427 (read_big_endian_short((const uint8_t*) &table[j]))
/ 65535.0f; |
428 } | 428 } |
429 break; | 429 break; |
430 } | 430 } |
431 case kTAG_ParaCurveType: | 431 case kTAG_ParaCurveType: |
432 // Guess 2.2f. | 432 // Determine the format of the parametric curve tag. |
433 // FIXME (msarett): Handle parametric curves. | 433 switch(read_big_endian_short(src + 8)) { |
434 SkColorSpacePrintf("parametric curve\n"); | 434 case 0: { |
435 gammas[i].fValue = 2.2f; | 435 tagBytes = 12 + 4; |
| 436 if (len < tagBytes) { |
| 437 SkColorSpacePrintf("gamma tag is too small (%d bytes
)", len); |
| 438 return false; |
| 439 } |
436 | 440 |
437 // Determine the size of the parametric curve tag. | 441 // Y = X^g |
438 switch(read_big_endian_short(src + 8)) { | 442 int32_t g = read_big_endian_int(src + 12); |
439 case 0: | 443 gammas[i].fValue = SkFixedToFloat(g); |
440 tagBytes = 12 + 4; | |
441 break; | 444 break; |
442 case 1: | 445 } |
| 446 |
| 447 // Here's where the real parametric gammas start. There are
many |
| 448 // permutations of the same equations. |
| 449 // |
| 450 // Y = (aX + b)^g + c for X >= d |
| 451 // Y = eX + f otherwise |
| 452 // |
| 453 // We will fill in with zeros as necessary to always match t
he above form. |
| 454 // Note that there is no need to actually write zero, since
the struct is |
| 455 // zero initialized. |
| 456 case 1: { |
443 tagBytes = 12 + 12; | 457 tagBytes = 12 + 12; |
| 458 if (len < tagBytes) { |
| 459 SkColorSpacePrintf("gamma tag is too small (%d bytes
)", len); |
| 460 return false; |
| 461 } |
| 462 |
| 463 // Y = (aX + b)^g for X >= -b/a |
| 464 // Y = 0 otherwise |
| 465 gammas[i].fG = SkFixedToFloat(read_big_endian_int(src +
12)); |
| 466 gammas[i].fA = SkFixedToFloat(read_big_endian_int(src +
16)); |
| 467 gammas[i].fB = SkFixedToFloat(read_big_endian_int(src +
20)); |
| 468 gammas[i].fD = -gammas[i].fB / gammas[i].fA; |
444 break; | 469 break; |
| 470 } |
445 case 2: | 471 case 2: |
446 tagBytes = 12 + 16; | 472 tagBytes = 12 + 16; |
| 473 if (len < tagBytes) { |
| 474 SkColorSpacePrintf("gamma tag is too small (%d bytes
)", len); |
| 475 return false; |
| 476 } |
| 477 |
| 478 // Y = (aX + b)^g + c for X >= -b/a |
| 479 // Y = c otherwise |
| 480 gammas[i].fG = SkFixedToFloat(read_big_endian_int(src +
12)); |
| 481 gammas[i].fA = SkFixedToFloat(read_big_endian_int(src +
16)); |
| 482 gammas[i].fB = SkFixedToFloat(read_big_endian_int(src +
20)); |
| 483 gammas[i].fC = SkFixedToFloat(read_big_endian_int(src +
24)); |
| 484 gammas[i].fD = -gammas[i].fB / gammas[i].fA; |
| 485 gammas[i].fF = gammas[i].fC; |
447 break; | 486 break; |
448 case 3: | 487 case 3: |
449 tagBytes = 12 + 20; | 488 tagBytes = 12 + 20; |
| 489 if (len < tagBytes) { |
| 490 SkColorSpacePrintf("gamma tag is too small (%d bytes
)", len); |
| 491 return false; |
| 492 } |
| 493 |
| 494 // Y = (aX + b)^g for X >= d |
| 495 // Y = cX otherwise |
| 496 gammas[i].fG = SkFixedToFloat(read_big_endian_int(src +
12)); |
| 497 gammas[i].fA = SkFixedToFloat(read_big_endian_int(src +
16)); |
| 498 gammas[i].fB = SkFixedToFloat(read_big_endian_int(src +
20)); |
| 499 gammas[i].fD = SkFixedToFloat(read_big_endian_int(src +
28)); |
| 500 gammas[i].fE = SkFixedToFloat(read_big_endian_int(src +
24)); |
450 break; | 501 break; |
451 case 4: | 502 case 4: |
452 tagBytes = 12 + 28; | 503 tagBytes = 12 + 28; |
| 504 if (len < tagBytes) { |
| 505 SkColorSpacePrintf("gamma tag is too small (%d bytes
)", len); |
| 506 return false; |
| 507 } |
| 508 |
| 509 // Y = (aX + b)^g + c for X >= d |
| 510 // Y = eX + f otherwise |
| 511 // NOTE: The ICC spec writes "cX" instead of "eX" but I
think it's a typo. |
| 512 gammas[i].fG = SkFixedToFloat(read_big_endian_int(src +
12)); |
| 513 gammas[i].fA = SkFixedToFloat(read_big_endian_int(src +
16)); |
| 514 gammas[i].fB = SkFixedToFloat(read_big_endian_int(src +
20)); |
| 515 gammas[i].fC = SkFixedToFloat(read_big_endian_int(src +
24)); |
| 516 gammas[i].fD = SkFixedToFloat(read_big_endian_int(src +
28)); |
| 517 gammas[i].fE = SkFixedToFloat(read_big_endian_int(src +
32)); |
| 518 gammas[i].fF = SkFixedToFloat(read_big_endian_int(src +
36)); |
453 break; | 519 break; |
454 default: | 520 default: |
455 SkColorSpacePrintf("Invalid parametric curve type\n"); | 521 SkColorSpacePrintf("Invalid parametric curve type\n"); |
456 return false; | 522 return false; |
457 } | 523 } |
458 break; | 524 break; |
459 default: | 525 default: |
460 SkColorSpacePrintf("Unsupported gamma tag type %d\n", type); | 526 SkColorSpacePrintf("Unsupported gamma tag type %d\n", type); |
461 return false; | 527 return false; |
462 } | 528 } |
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
742 } | 808 } |
743 } | 809 } |
744 | 810 |
745 } | 811 } |
746 default: | 812 default: |
747 break; | 813 break; |
748 } | 814 } |
749 | 815 |
750 return_null("ICC profile contains unsupported colorspace"); | 816 return_null("ICC profile contains unsupported colorspace"); |
751 } | 817 } |
OLD | NEW |