| 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 | |
| 566 /** | 483 /** |
| 567 FIXME: This was my idea to cheat in order to continue taking advantage of sk
ipping zeroes. | 484 FIXME: This was my idea to cheat in order to continue taking advantage of sk
ipping zeroes. |
| 568 This would be fine for drawing normally, but not for drawing with transfer m
odes. Being | 485 This would be fine for drawing normally, but not for drawing with transfer m
odes. Being |
| 569 honest means we can draw correctly with transfer modes, with the cost of not
being able | 486 honest means we can draw correctly with transfer modes, with the cost of not
being able |
| 570 to take advantage of Android's free unwritten pages. Something to keep in mi
nd when we | 487 to take advantage of Android's free unwritten pages. Something to keep in mi
nd when we |
| 571 decide whether to switch to unpremul default. | 488 decide whether to switch to unpremul default. |
| 572 static bool swizzle_rgba_to_n32_unpremul_skipZ(void* SK_RESTRICT dstRow, | 489 static bool swizzle_rgba_to_n32_unpremul_skipZ(void* SK_RESTRICT dstRow, |
| 573 const uint8_t* SK_RESTRICT src, | 490 const uint8_t* SK_RESTRICT src, |
| 574 int dstWidth, int bitsPerPixel, i
nt offset, | 491 int dstWidth, int bitsPerPixel, i
nt offset, |
| 575 const SkPMColor[]) { | 492 const SkPMColor[]) { |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 748 } | 665 } |
| 749 break; | 666 break; |
| 750 case kRGB_565: | 667 case kRGB_565: |
| 751 switch (dstInfo.colorType()) { | 668 switch (dstInfo.colorType()) { |
| 752 case kRGB_565_SkColorType: | 669 case kRGB_565_SkColorType: |
| 753 proc = &sample565; | 670 proc = &sample565; |
| 754 break; | 671 break; |
| 755 default: | 672 default: |
| 756 break; | 673 break; |
| 757 } | 674 } |
| 758 case kCMYK: | |
| 759 switch (dstInfo.colorType()) { | |
| 760 case kN32_SkColorType: | |
| 761 proc = &swizzle_cmyk_to_n32; | |
| 762 break; | |
| 763 case kRGB_565_SkColorType: | |
| 764 proc = &swizzle_cmyk_to_565; | |
| 765 break; | |
| 766 default: | |
| 767 break; | |
| 768 } | |
| 769 break; | |
| 770 default: | 675 default: |
| 771 break; | 676 break; |
| 772 } | 677 } |
| 773 if (nullptr == proc) { | 678 if (nullptr == proc) { |
| 774 return nullptr; | 679 return nullptr; |
| 775 } | 680 } |
| 776 | 681 |
| 777 // Store bpp in bytes if it is an even multiple, otherwise use bits | 682 // Store bpp in bytes if it is an even multiple, otherwise use bits |
| 778 int bpp = SkIsAlign8(BitsPerPixel(sc)) ? BytesPerPixel(sc) : BitsPerPixel(sc
); | 683 int bpp = SkIsAlign8(BitsPerPixel(sc)) ? BytesPerPixel(sc) : BitsPerPixel(sc
); |
| 779 | 684 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 808 | 713 |
| 809 // check that fX0 is valid | 714 // check that fX0 is valid |
| 810 SkASSERT(fX0 >= 0); | 715 SkASSERT(fX0 >= 0); |
| 811 return fDstWidth; | 716 return fDstWidth; |
| 812 } | 717 } |
| 813 | 718 |
| 814 SkSwizzler::ResultAlpha SkSwizzler::swizzle(void* dst, const uint8_t* SK_RESTRIC
T src) { | 719 SkSwizzler::ResultAlpha SkSwizzler::swizzle(void* dst, const uint8_t* SK_RESTRIC
T src) { |
| 815 SkASSERT(nullptr != dst && nullptr != src); | 720 SkASSERT(nullptr != dst && nullptr != src); |
| 816 return fRowProc(dst, src, fDstWidth, fBPP, fSampleX * fBPP, fX0 * fBPP, fCol
orTable); | 721 return fRowProc(dst, src, fDstWidth, fBPP, fSampleX * fBPP, fX0 * fBPP, fCol
orTable); |
| 817 } | 722 } |
| OLD | NEW |