OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 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 "SkCodecPriv.h" | 8 #include "SkCodecPriv.h" |
9 #include "SkColorPriv.h" | 9 #include "SkColorPriv.h" |
10 #include "SkSwizzler.h" | 10 #include "SkSwizzler.h" |
(...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
473 unsigned alpha = src[3]; | 473 unsigned alpha = src[3]; |
474 UPDATE_RESULT_ALPHA(alpha); | 474 UPDATE_RESULT_ALPHA(alpha); |
475 if (0 != alpha) { | 475 if (0 != alpha) { |
476 dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]); | 476 dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]); |
477 } | 477 } |
478 src += deltaSrc; | 478 src += deltaSrc; |
479 } | 479 } |
480 return COMPUTE_RESULT_ALPHA; | 480 return COMPUTE_RESULT_ALPHA; |
481 } | 481 } |
482 | 482 |
| 483 // kCMYK |
| 484 // |
| 485 // CMYK is stored as four bytes per pixel. |
| 486 // |
| 487 // We will implement a crude conversion from CMYK -> RGB using formulas |
| 488 // from easyrgb.com. |
| 489 // |
| 490 // CMYK -> CMY |
| 491 // C = C * (1 - K) + K |
| 492 // M = M * (1 - K) + K |
| 493 // Y = Y * (1 - K) + K |
| 494 // |
| 495 // libjpeg actually gives us inverted CMYK, so we must subtract the |
| 496 // original terms from 1. |
| 497 // CMYK -> CMY |
| 498 // C = (1 - C) * (1 - (1 - K)) + (1 - K) |
| 499 // M = (1 - M) * (1 - (1 - K)) + (1 - K) |
| 500 // Y = (1 - Y) * (1 - (1 - K)) + (1 - K) |
| 501 // |
| 502 // Simplifying the above expression. |
| 503 // CMYK -> CMY |
| 504 // C = 1 - CK |
| 505 // M = 1 - MK |
| 506 // Y = 1 - YK |
| 507 // |
| 508 // CMY -> RGB |
| 509 // R = (1 - C) * 255 |
| 510 // G = (1 - M) * 255 |
| 511 // B = (1 - Y) * 255 |
| 512 // |
| 513 // Therefore the full conversion is below. This can be verified at |
| 514 // www.rapidtables.com (assuming inverted CMYK). |
| 515 // CMYK -> RGB |
| 516 // R = C * K * 255 |
| 517 // G = M * K * 255 |
| 518 // B = Y * K * 255 |
| 519 // |
| 520 // As a final note, we have treated the CMYK values as if they were on |
| 521 // a scale from 0-1, when in fact they are 8-bit ints scaling from 0-255. |
| 522 // We must divide each CMYK component by 255 to obtain the true conversion |
| 523 // we should perform. |
| 524 // CMYK -> RGB |
| 525 // R = C * K / 255 |
| 526 // G = M * K / 255 |
| 527 // B = Y * K / 255 |
| 528 static SkSwizzler::ResultAlpha swizzle_cmyk_to_n32( |
| 529 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, |
| 530 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) { |
| 531 |
| 532 src += offset; |
| 533 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; |
| 534 for (int x = 0; x < dstWidth; x++) { |
| 535 const uint8_t r = SkMulDiv255Round(src[0], src[3]); |
| 536 const uint8_t g = SkMulDiv255Round(src[1], src[3]); |
| 537 const uint8_t b = SkMulDiv255Round(src[2], src[3]); |
| 538 |
| 539 dst[x] = SkPackARGB32NoCheck(0xFF, r, g, b); |
| 540 src += deltaSrc; |
| 541 } |
| 542 |
| 543 // CMYK is always opaque |
| 544 return SkSwizzler::kOpaque_ResultAlpha; |
| 545 } |
| 546 |
| 547 static SkSwizzler::ResultAlpha swizzle_cmyk_to_565( |
| 548 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, |
| 549 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) { |
| 550 |
| 551 src += offset; |
| 552 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; |
| 553 for (int x = 0; x < dstWidth; x++) { |
| 554 const uint8_t r = SkMulDiv255Round(src[0], src[3]); |
| 555 const uint8_t g = SkMulDiv255Round(src[1], src[3]); |
| 556 const uint8_t b = SkMulDiv255Round(src[2], src[3]); |
| 557 |
| 558 dst[x] = SkPack888ToRGB16(r, g, b); |
| 559 src += deltaSrc; |
| 560 } |
| 561 |
| 562 // CMYK is always opaque |
| 563 return SkSwizzler::kOpaque_ResultAlpha; |
| 564 } |
| 565 |
483 /** | 566 /** |
484 FIXME: This was my idea to cheat in order to continue taking advantage of sk
ipping zeroes. | 567 FIXME: This was my idea to cheat in order to continue taking advantage of sk
ipping zeroes. |
485 This would be fine for drawing normally, but not for drawing with transfer m
odes. Being | 568 This would be fine for drawing normally, but not for drawing with transfer m
odes. Being |
486 honest means we can draw correctly with transfer modes, with the cost of not
being able | 569 honest means we can draw correctly with transfer modes, with the cost of not
being able |
487 to take advantage of Android's free unwritten pages. Something to keep in mi
nd when we | 570 to take advantage of Android's free unwritten pages. Something to keep in mi
nd when we |
488 decide whether to switch to unpremul default. | 571 decide whether to switch to unpremul default. |
489 static bool swizzle_rgba_to_n32_unpremul_skipZ(void* SK_RESTRICT dstRow, | 572 static bool swizzle_rgba_to_n32_unpremul_skipZ(void* SK_RESTRICT dstRow, |
490 const uint8_t* SK_RESTRICT src, | 573 const uint8_t* SK_RESTRICT src, |
491 int dstWidth, int bitsPerPixel, i
nt offset, | 574 int dstWidth, int bitsPerPixel, i
nt offset, |
492 const SkPMColor[]) { | 575 const SkPMColor[]) { |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
665 } | 748 } |
666 break; | 749 break; |
667 case kRGB_565: | 750 case kRGB_565: |
668 switch (dstInfo.colorType()) { | 751 switch (dstInfo.colorType()) { |
669 case kRGB_565_SkColorType: | 752 case kRGB_565_SkColorType: |
670 proc = &sample565; | 753 proc = &sample565; |
671 break; | 754 break; |
672 default: | 755 default: |
673 break; | 756 break; |
674 } | 757 } |
| 758 break; |
| 759 case kCMYK: |
| 760 switch (dstInfo.colorType()) { |
| 761 case kN32_SkColorType: |
| 762 proc = &swizzle_cmyk_to_n32; |
| 763 break; |
| 764 case kRGB_565_SkColorType: |
| 765 proc = &swizzle_cmyk_to_565; |
| 766 break; |
| 767 default: |
| 768 break; |
| 769 } |
| 770 break; |
675 default: | 771 default: |
676 break; | 772 break; |
677 } | 773 } |
678 if (nullptr == proc) { | 774 if (nullptr == proc) { |
679 return nullptr; | 775 return nullptr; |
680 } | 776 } |
681 | 777 |
682 // Store bpp in bytes if it is an even multiple, otherwise use bits | 778 // Store bpp in bytes if it is an even multiple, otherwise use bits |
683 int bpp = SkIsAlign8(BitsPerPixel(sc)) ? BytesPerPixel(sc) : BitsPerPixel(sc
); | 779 int bpp = SkIsAlign8(BitsPerPixel(sc)) ? BytesPerPixel(sc) : BitsPerPixel(sc
); |
684 | 780 |
(...skipping 28 matching lines...) Expand all Loading... |
713 | 809 |
714 // check that fX0 is valid | 810 // check that fX0 is valid |
715 SkASSERT(fX0 >= 0); | 811 SkASSERT(fX0 >= 0); |
716 return fDstWidth; | 812 return fDstWidth; |
717 } | 813 } |
718 | 814 |
719 SkSwizzler::ResultAlpha SkSwizzler::swizzle(void* dst, const uint8_t* SK_RESTRIC
T src) { | 815 SkSwizzler::ResultAlpha SkSwizzler::swizzle(void* dst, const uint8_t* SK_RESTRIC
T src) { |
720 SkASSERT(nullptr != dst && nullptr != src); | 816 SkASSERT(nullptr != dst && nullptr != src); |
721 return fRowProc(dst, src, fDstWidth, fBPP, fSampleX * fBPP, fX0 * fBPP, fCol
orTable); | 817 return fRowProc(dst, src, fDstWidth, fBPP, fSampleX * fBPP, fX0 * fBPP, fCol
orTable); |
722 } | 818 } |
OLD | NEW |