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 |