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 uint8_t* pixel = (uint8_t*) &dst[x]; | |
536 #if defined(SK_PMCOLOR_IS_RGBA) | |
msarett
2015/10/23 14:25:42
Can we use SkPackARGB32NoCheck here instead of #if
scroggo_chromium
2015/10/23 14:35:36
Yes! I was just copying code, but this is much cle
| |
537 pixel[0] = SkMulDiv255Round(src[0], src[3]); | |
538 pixel[1] = SkMulDiv255Round(src[1], src[3]); | |
539 pixel[2] = SkMulDiv255Round(src[2], src[3]); | |
540 #else | |
541 pixel[0] = SkMulDiv255Round(src[2], src[3]); | |
542 pixel[1] = SkMulDiv255Round(src[1], src[3]); | |
543 pixel[2] = SkMulDiv255Round(src[0], src[3]); | |
544 #endif | |
545 pixel[3] = 0xFF; | |
546 src += deltaSrc; | |
547 } | |
548 | |
549 // CMYK is always opaque | |
550 return SkSwizzler::kOpaque_ResultAlpha; | |
551 } | |
552 | |
553 static SkSwizzler::ResultAlpha swizzle_cmyk_to_565( | |
554 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, | |
555 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) { | |
556 | |
557 src += offset; | |
558 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; | |
559 for (int x = 0; x < dstWidth; x++) { | |
560 const uint8_t r = SkMulDiv255Round(src[0], src[3]); | |
561 const uint8_t g = SkMulDiv255Round(src[1], src[3]); | |
562 const uint8_t b = SkMulDiv255Round(src[2], src[3]); | |
563 | |
564 dst[x] = SkPack888ToRGB16(r, g, b); | |
565 src += deltaSrc; | |
566 } | |
567 | |
568 // CMYK is always opaque | |
569 return SkSwizzler::kOpaque_ResultAlpha; | |
570 } | |
571 | |
483 /** | 572 /** |
484 FIXME: This was my idea to cheat in order to continue taking advantage of sk ipping zeroes. | 573 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 | 574 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 | 575 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 | 576 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. | 577 decide whether to switch to unpremul default. |
489 static bool swizzle_rgba_to_n32_unpremul_skipZ(void* SK_RESTRICT dstRow, | 578 static bool swizzle_rgba_to_n32_unpremul_skipZ(void* SK_RESTRICT dstRow, |
490 const uint8_t* SK_RESTRICT src, | 579 const uint8_t* SK_RESTRICT src, |
491 int dstWidth, int bitsPerPixel, i nt offset, | 580 int dstWidth, int bitsPerPixel, i nt offset, |
492 const SkPMColor[]) { | 581 const SkPMColor[]) { |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
665 } | 754 } |
666 break; | 755 break; |
667 case kRGB_565: | 756 case kRGB_565: |
668 switch (dstInfo.colorType()) { | 757 switch (dstInfo.colorType()) { |
669 case kRGB_565_SkColorType: | 758 case kRGB_565_SkColorType: |
670 proc = &sample565; | 759 proc = &sample565; |
671 break; | 760 break; |
672 default: | 761 default: |
673 break; | 762 break; |
674 } | 763 } |
764 case kCMYK: | |
765 switch (dstInfo.colorType()) { | |
766 case kN32_SkColorType: | |
767 proc = &swizzle_cmyk_to_n32; | |
768 break; | |
769 case kRGB_565_SkColorType: | |
770 proc = &swizzle_cmyk_to_565; | |
771 break; | |
772 default: | |
773 break; | |
774 } | |
775 break; | |
675 default: | 776 default: |
676 break; | 777 break; |
677 } | 778 } |
678 if (nullptr == proc) { | 779 if (nullptr == proc) { |
679 return nullptr; | 780 return nullptr; |
680 } | 781 } |
681 | 782 |
682 // Store bpp in bytes if it is an even multiple, otherwise use bits | 783 // Store bpp in bytes if it is an even multiple, otherwise use bits |
683 int bpp = SkIsAlign8(BitsPerPixel(sc)) ? BytesPerPixel(sc) : BitsPerPixel(sc ); | 784 int bpp = SkIsAlign8(BitsPerPixel(sc)) ? BytesPerPixel(sc) : BitsPerPixel(sc ); |
684 | 785 |
(...skipping 28 matching lines...) Expand all Loading... | |
713 | 814 |
714 // check that fX0 is valid | 815 // check that fX0 is valid |
715 SkASSERT(fX0 >= 0); | 816 SkASSERT(fX0 >= 0); |
716 return fDstWidth; | 817 return fDstWidth; |
717 } | 818 } |
718 | 819 |
719 SkSwizzler::ResultAlpha SkSwizzler::swizzle(void* dst, const uint8_t* SK_RESTRIC T src) { | 820 SkSwizzler::ResultAlpha SkSwizzler::swizzle(void* dst, const uint8_t* SK_RESTRIC T src) { |
720 SkASSERT(nullptr != dst && nullptr != src); | 821 SkASSERT(nullptr != dst && nullptr != src); |
721 return fRowProc(dst, src, fDstWidth, fBPP, fSampleX * fBPP, fX0 * fBPP, fCol orTable); | 822 return fRowProc(dst, src, fDstWidth, fBPP, fSampleX * fBPP, fX0 * fBPP, fCol orTable); |
722 } | 823 } |
OLD | NEW |