Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(10)

Side by Side Diff: src/core/SkBitmap.cpp

Issue 16410009: Add an option to create unpremultiplied bitmaps. (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 1
2 /* 2 /*
3 * Copyright 2008 The Android Open Source Project 3 * Copyright 2008 The Android Open Source Project
4 * 4 *
5 * Use of this source code is governed by a BSD-style license that can be 5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file. 6 * found in the LICENSE file.
7 */ 7 */
8 8
9 9
10 #include "SkBitmap.h" 10 #include "SkBitmap.h"
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 SkIntToScalar(fWidth), SkIntToScalar(fHeight)); 261 SkIntToScalar(fWidth), SkIntToScalar(fHeight));
262 } 262 }
263 263
264 void SkBitmap::getBounds(SkIRect* bounds) const { 264 void SkBitmap::getBounds(SkIRect* bounds) const {
265 SkASSERT(bounds); 265 SkASSERT(bounds);
266 bounds->set(0, 0, fWidth, fHeight); 266 bounds->set(0, 0, fWidth, fHeight);
267 } 267 }
268 268
269 /////////////////////////////////////////////////////////////////////////////// 269 ///////////////////////////////////////////////////////////////////////////////
270 270
271 void SkBitmap::setConfig(Config c, int width, int height, size_t rowBytes) { 271 void SkBitmap::setConfig(Config c, int width, int height, size_t rowBytes,
272 bool premul) {
272 this->freePixels(); 273 this->freePixels();
273 274
274 if ((width | height) < 0) { 275 if ((width | height) < 0) {
275 goto err; 276 goto err;
276 } 277 }
277 278
278 if (rowBytes == 0) { 279 if (rowBytes == 0) {
279 rowBytes = SkBitmap::ComputeRowBytes(c, width); 280 rowBytes = SkBitmap::ComputeRowBytes(c, width);
280 if (0 == rowBytes && kNo_Config != c) { 281 if (0 == rowBytes && kNo_Config != c) {
281 goto err; 282 goto err;
282 } 283 }
283 } 284 }
284 285
285 fConfig = SkToU8(c); 286 fConfig = SkToU8(c);
286 fWidth = width; 287 fWidth = width;
287 fHeight = height; 288 fHeight = height;
288 fRowBytes = SkToU32(rowBytes); 289 fRowBytes = SkToU32(rowBytes);
290 if (premul) {
291 fFlags &= ~kColorsAreNotPremultiplied_Flag;
292 } else {
293 if (c != kARGB_8888_Config) {
294 goto err;
295 }
296 fFlags |= kColorsAreNotPremultiplied_Flag;
297 }
289 298
290 fBytesPerPixel = (uint8_t)ComputeBytesPerPixel(c); 299 fBytesPerPixel = (uint8_t)ComputeBytesPerPixel(c);
291 300
292 SkDEBUGCODE(this->validate();) 301 SkDEBUGCODE(this->validate();)
293 return; 302 return;
294 303
295 // if we got here, we had an error, so we reset the bitmap to empty 304 // if we got here, we had an error, so we reset the bitmap to empty
296 err: 305 err:
297 this->reset(); 306 this->reset();
298 } 307 }
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after
644 case SkBitmap::kRGB_565_Config: { 653 case SkBitmap::kRGB_565_Config: {
645 uint16_t* addr = this->getAddr16(x, y); 654 uint16_t* addr = this->getAddr16(x, y);
646 return SkPixel16ToColor(addr[0]); 655 return SkPixel16ToColor(addr[0]);
647 } 656 }
648 case SkBitmap::kARGB_4444_Config: { 657 case SkBitmap::kARGB_4444_Config: {
649 uint16_t* addr = this->getAddr16(x, y); 658 uint16_t* addr = this->getAddr16(x, y);
650 SkPMColor c = SkPixel4444ToPixel32(addr[0]); 659 SkPMColor c = SkPixel4444ToPixel32(addr[0]);
651 return SkUnPreMultiply::PMColorToColor(c); 660 return SkUnPreMultiply::PMColorToColor(c);
652 } 661 }
653 case SkBitmap::kARGB_8888_Config: { 662 case SkBitmap::kARGB_8888_Config: {
654 uint32_t* addr = this->getAddr32(x, y); 663 if (this->premultiplied()) {
655 return SkUnPreMultiply::PMColorToColor(addr[0]); 664 uint32_t* addr = this->getAddr32(x, y);
665 return SkUnPreMultiply::PMColorToColor(addr[0]);
666 } else {
667 SkUnPMColor* addr = this->getAddr32(x, y);
668 SkUnPMColor c = *addr;
669 U8CPU a = SkGetPackedA32(c);
670 U8CPU r = SkGetPackedR32(c);
671 U8CPU g = SkGetPackedG32(c);
672 U8CPU b = SkGetPackedB32(c);
673 return SkColorSetARGB(a, r, g, b);
674 }
656 } 675 }
657 case kRLE_Index8_Config: { 676 case kRLE_Index8_Config: {
658 uint8_t dst; 677 uint8_t dst;
659 const SkBitmap::RLEPixels* rle = 678 const SkBitmap::RLEPixels* rle =
660 (const SkBitmap::RLEPixels*)this->getPixels(); 679 (const SkBitmap::RLEPixels*)this->getPixels();
661 SkPackBits::Unpack8(&dst, x, 1, rle->packedAtY(y)); 680 SkPackBits::Unpack8(&dst, x, 1, rle->packedAtY(y));
662 return SkUnPreMultiply::PMColorToColor((*fColorTable)[dst]); 681 return SkUnPreMultiply::PMColorToColor((*fColorTable)[dst]);
663 } 682 }
664 case kNo_Config: 683 case kNo_Config:
665 case kConfigCount: 684 case kConfigCount:
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
761 if (!this->readyToDraw()) { 780 if (!this->readyToDraw()) {
762 return; 781 return;
763 } 782 }
764 783
765 int height = fHeight; 784 int height = fHeight;
766 const int width = fWidth; 785 const int width = fWidth;
767 const int rowBytes = fRowBytes; 786 const int rowBytes = fRowBytes;
768 787
769 // make rgb premultiplied 788 // make rgb premultiplied
770 if (255 != a) { 789 if (255 != a) {
790 // Unpremultiplied exits above at readyToDraw.
791 SkASSERT(this->premultiplied());
771 r = SkAlphaMul(r, a); 792 r = SkAlphaMul(r, a);
772 g = SkAlphaMul(g, a); 793 g = SkAlphaMul(g, a);
773 b = SkAlphaMul(b, a); 794 b = SkAlphaMul(b, a);
774 } 795 }
775 796
776 switch (fConfig) { 797 switch (fConfig) {
777 case kA1_Config: { 798 case kA1_Config: {
778 uint8_t* p = (uint8_t*)fPixels; 799 uint8_t* p = (uint8_t*)fPixels;
779 const int count = (width + 7) >> 3; 800 const int count = (width + 7) >> 3;
780 a = (a >> 7) ? 0xFF : 0; 801 a = (a >> 7) ? 0xFF : 0;
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
921 srcRect.set(0, 0, this->width(), this->height()); 942 srcRect.set(0, 0, this->width(), this->height());
922 if (!r.intersect(srcRect, subset)) { 943 if (!r.intersect(srcRect, subset)) {
923 return false; // r is empty (i.e. no intersection) 944 return false; // r is empty (i.e. no intersection)
924 } 945 }
925 946
926 if (fPixelRef->getTexture() != NULL) { 947 if (fPixelRef->getTexture() != NULL) {
927 // Do a deep copy 948 // Do a deep copy
928 SkPixelRef* pixelRef = fPixelRef->deepCopy(this->config(), &subset); 949 SkPixelRef* pixelRef = fPixelRef->deepCopy(this->config(), &subset);
929 if (pixelRef != NULL) { 950 if (pixelRef != NULL) {
930 SkBitmap dst; 951 SkBitmap dst;
931 dst.setConfig(this->config(), subset.width(), subset.height()); 952 dst.setConfig(this->config(), subset.width(), subset.height(), 0,
953 this->premultiplied());
932 dst.setIsVolatile(this->isVolatile()); 954 dst.setIsVolatile(this->isVolatile());
933 dst.setIsOpaque(this->isOpaque()); 955 dst.setIsOpaque(this->isOpaque());
934 dst.setPixelRef(pixelRef)->unref(); 956 dst.setPixelRef(pixelRef)->unref();
935 SkDEBUGCODE(dst.validate()); 957 SkDEBUGCODE(dst.validate());
936 result->swap(dst); 958 result->swap(dst);
937 return true; 959 return true;
938 } 960 }
939 } 961 }
940 962
941 if (kRLE_Index8_Config == fConfig) { 963 if (kRLE_Index8_Config == fConfig) {
942 SkAutoLockPixels alp(*this); 964 SkAutoLockPixels alp(*this);
943 // don't call readyToDraw(), since we can operate w/o a colortable 965 // don't call readyToDraw(), since we can operate w/o a colortable
944 // at this stage 966 // at this stage
945 if (this->getPixels() == NULL) { 967 if (this->getPixels() == NULL) {
946 return false; 968 return false;
947 } 969 }
948 SkBitmap bm; 970 SkBitmap bm;
949 971
972 // kRLE_Index8_Config is not compatible with unpremultiplied.
973 SkASSERT(this->premultiplied());
950 bm.setConfig(kIndex8_Config, r.width(), r.height()); 974 bm.setConfig(kIndex8_Config, r.width(), r.height());
951 bm.allocPixels(this->getColorTable()); 975 bm.allocPixels(this->getColorTable());
952 if (NULL == bm.getPixels()) { 976 if (NULL == bm.getPixels()) {
953 return false; 977 return false;
954 } 978 }
955 979
956 const RLEPixels* rle = (const RLEPixels*)this->getPixels(); 980 const RLEPixels* rle = (const RLEPixels*)this->getPixels();
957 uint8_t* dst = bm.getAddr8(0, 0); 981 uint8_t* dst = bm.getAddr8(0, 0);
958 const int width = bm.width(); 982 const int width = bm.width();
959 const size_t rowBytes = bm.rowBytes(); 983 const size_t rowBytes = bm.rowBytes();
(...skipping 10 matching lines...) Expand all
970 // exited above. 994 // exited above.
971 SkASSERT(static_cast<unsigned>(r.fLeft) < static_cast<unsigned>(this->width( ))); 995 SkASSERT(static_cast<unsigned>(r.fLeft) < static_cast<unsigned>(this->width( )));
972 SkASSERT(static_cast<unsigned>(r.fTop) < static_cast<unsigned>(this->height( ))); 996 SkASSERT(static_cast<unsigned>(r.fTop) < static_cast<unsigned>(this->height( )));
973 997
974 size_t offset = get_sub_offset(*this, r.fLeft, r.fTop); 998 size_t offset = get_sub_offset(*this, r.fLeft, r.fTop);
975 if (SUB_OFFSET_FAILURE == offset) { 999 if (SUB_OFFSET_FAILURE == offset) {
976 return false; // config not supported 1000 return false; // config not supported
977 } 1001 }
978 1002
979 SkBitmap dst; 1003 SkBitmap dst;
980 dst.setConfig(this->config(), r.width(), r.height(), this->rowBytes()); 1004 dst.setConfig(this->config(), r.width(), r.height(), this->rowBytes(), this- >premultiplied());
981 dst.setIsVolatile(this->isVolatile()); 1005 dst.setIsVolatile(this->isVolatile());
982 dst.setIsOpaque(this->isOpaque()); 1006 dst.setIsOpaque(this->isOpaque());
983 1007
984 if (fPixelRef) { 1008 if (fPixelRef) {
985 // share the pixelref with a custom offset 1009 // share the pixelref with a custom offset
986 dst.setPixelRef(fPixelRef, fPixelRefOffset + offset); 1010 dst.setPixelRef(fPixelRef, fPixelRefOffset + offset);
987 } 1011 }
988 SkDEBUGCODE(dst.validate();) 1012 SkDEBUGCODE(dst.validate();)
989 1013
990 // we know we're good, so commit to result 1014 // we know we're good, so commit to result
(...skipping 26 matching lines...) Expand all
1017 break; 1041 break;
1018 default: 1042 default:
1019 return false; 1043 return false;
1020 } 1044 }
1021 1045
1022 // do not copy src if srcConfig == kA1_Config while dstConfig != kA1_Config 1046 // do not copy src if srcConfig == kA1_Config while dstConfig != kA1_Config
1023 if (this->getConfig() == kA1_Config && !sameConfigs) { 1047 if (this->getConfig() == kA1_Config && !sameConfigs) {
1024 return false; 1048 return false;
1025 } 1049 }
1026 1050
1051 if (!this->premultiplied()) {
1052 // Cannot copy unpremultiplied, which returns false for readyToDraw.
1053 SkASSERT(kARGB_8888_Config == this->config());
1054 return false;
1055 }
1056
1027 return true; 1057 return true;
1028 } 1058 }
1029 1059
1030 bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const { 1060 bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const {
1031 if (!this->canCopyTo(dstConfig)) { 1061 if (!this->canCopyTo(dstConfig)) {
1032 return false; 1062 return false;
1033 } 1063 }
1064 // Cannot copy an unpremultiplied bitmap.
1065 // canCopyTo should have returned false.
1066 SkASSERT(this->premultiplied());
1034 1067
1035 // if we have a texture, first get those pixels 1068 // if we have a texture, first get those pixels
1036 SkBitmap tmpSrc; 1069 SkBitmap tmpSrc;
1037 const SkBitmap* src = this; 1070 const SkBitmap* src = this;
1038 1071
1039 if (fPixelRef) { 1072 if (fPixelRef) {
1040 SkIRect subset; 1073 SkIRect subset;
1041 if (get_upper_left_from_offset(*this, &subset.fLeft, &subset.fTop)) { 1074 if (get_upper_left_from_offset(*this, &subset.fLeft, &subset.fTop)) {
1042 subset.fRight = subset.fLeft + fWidth; 1075 subset.fRight = subset.fLeft + fWidth;
1043 subset.fBottom = subset.fTop + fHeight; 1076 subset.fBottom = subset.fTop + fHeight;
(...skipping 513 matching lines...) Expand 10 before | Expand all | Expand 10 after
1557 enum { 1590 enum {
1558 SERIALIZE_PIXELTYPE_NONE, 1591 SERIALIZE_PIXELTYPE_NONE,
1559 SERIALIZE_PIXELTYPE_REF_DATA 1592 SERIALIZE_PIXELTYPE_REF_DATA
1560 }; 1593 };
1561 1594
1562 void SkBitmap::flatten(SkFlattenableWriteBuffer& buffer) const { 1595 void SkBitmap::flatten(SkFlattenableWriteBuffer& buffer) const {
1563 buffer.writeInt(fWidth); 1596 buffer.writeInt(fWidth);
1564 buffer.writeInt(fHeight); 1597 buffer.writeInt(fHeight);
1565 buffer.writeInt(fRowBytes); 1598 buffer.writeInt(fRowBytes);
1566 buffer.writeInt(fConfig); 1599 buffer.writeInt(fConfig);
1600 #ifdef BUMP_PICTURE_VERSION
1601 // FIXME: Storing whether the colors are premultiplied
1602 // should be written to the stream, but breaks picture
1603 // serialization without changing PICTURE_VERSION
1604 buffer.writeBool(this->premultiplied());
1605 #endif
1567 buffer.writeBool(this->isOpaque()); 1606 buffer.writeBool(this->isOpaque());
1568 1607
1569 if (fPixelRef) { 1608 if (fPixelRef) {
1570 if (fPixelRef->getFactory()) { 1609 if (fPixelRef->getFactory()) {
1571 buffer.writeInt(SERIALIZE_PIXELTYPE_REF_DATA); 1610 buffer.writeInt(SERIALIZE_PIXELTYPE_REF_DATA);
1572 buffer.writeUInt(SkToU32(fPixelRefOffset)); 1611 buffer.writeUInt(SkToU32(fPixelRefOffset));
1573 buffer.writeFlattenable(fPixelRef); 1612 buffer.writeFlattenable(fPixelRef);
1574 return; 1613 return;
1575 } 1614 }
1576 // if we get here, we can't record the pixels 1615 // if we get here, we can't record the pixels
1577 buffer.writeInt(SERIALIZE_PIXELTYPE_NONE); 1616 buffer.writeInt(SERIALIZE_PIXELTYPE_NONE);
1578 } else { 1617 } else {
1579 buffer.writeInt(SERIALIZE_PIXELTYPE_NONE); 1618 buffer.writeInt(SERIALIZE_PIXELTYPE_NONE);
1580 } 1619 }
1581 } 1620 }
1582 1621
1583 void SkBitmap::unflatten(SkFlattenableReadBuffer& buffer) { 1622 void SkBitmap::unflatten(SkFlattenableReadBuffer& buffer) {
1584 this->reset(); 1623 this->reset();
1585 1624
1586 int width = buffer.readInt(); 1625 int width = buffer.readInt();
1587 int height = buffer.readInt(); 1626 int height = buffer.readInt();
1588 int rowBytes = buffer.readInt(); 1627 int rowBytes = buffer.readInt();
1589 int config = buffer.readInt(); 1628 int config = buffer.readInt();
1629 #ifdef BUMP_PICTURE_VERSION
1630 bool premul = buffer.readBool();
1631 #else
1632 bool premul = true;
1633 #endif
1590 1634
1591 this->setConfig((Config)config, width, height, rowBytes); 1635 this->setConfig((Config)config, width, height, rowBytes, premul);
1592 this->setIsOpaque(buffer.readBool()); 1636 this->setIsOpaque(buffer.readBool());
1593 1637
1594 int reftype = buffer.readInt(); 1638 int reftype = buffer.readInt();
1595 switch (reftype) { 1639 switch (reftype) {
1596 case SERIALIZE_PIXELTYPE_REF_DATA: { 1640 case SERIALIZE_PIXELTYPE_REF_DATA: {
1597 size_t offset = buffer.readUInt(); 1641 size_t offset = buffer.readUInt();
1598 SkPixelRef* pr = buffer.readFlattenableT<SkPixelRef>(); 1642 SkPixelRef* pr = buffer.readFlattenableT<SkPixelRef>();
1599 SkSafeUnref(this->setPixelRef(pr, offset)); 1643 SkSafeUnref(this->setPixelRef(pr, offset));
1600 break; 1644 break;
1601 } 1645 }
(...skipping 16 matching lines...) Expand all
1618 SkBitmap::RLEPixels::~RLEPixels() { 1662 SkBitmap::RLEPixels::~RLEPixels() {
1619 sk_free(fYPtrs); 1663 sk_free(fYPtrs);
1620 } 1664 }
1621 1665
1622 /////////////////////////////////////////////////////////////////////////////// 1666 ///////////////////////////////////////////////////////////////////////////////
1623 1667
1624 #ifdef SK_DEBUG 1668 #ifdef SK_DEBUG
1625 void SkBitmap::validate() const { 1669 void SkBitmap::validate() const {
1626 SkASSERT(fConfig < kConfigCount); 1670 SkASSERT(fConfig < kConfigCount);
1627 SkASSERT(fRowBytes >= (unsigned)ComputeRowBytes((Config)fConfig, fWidth)); 1671 SkASSERT(fRowBytes >= (unsigned)ComputeRowBytes((Config)fConfig, fWidth));
1628 SkASSERT(fFlags <= (kImageIsOpaque_Flag | kImageIsVolatile_Flag | kImageIsIm mutable_Flag)); 1672 int8_t allFlags = kImageIsOpaque_Flag | kImageIsVolatile_Flag | kImageIsImmu table_Flag
1673 | kColorsAreNotPremultiplied_Flag;
1674 #ifdef SK_BUILD_FOR_ANDROID
1675 allFlags |= kHasHardwareMipMap_Flag;
1676 #endif
1677 SkASSERT(fFlags <= allFlags);
1629 SkASSERT(fPixelLockCount >= 0); 1678 SkASSERT(fPixelLockCount >= 0);
1630 SkASSERT(NULL == fColorTable || (unsigned)fColorTable->getRefCnt() < 10000); 1679 SkASSERT(NULL == fColorTable || (unsigned)fColorTable->getRefCnt() < 10000);
1631 SkASSERT((uint8_t)ComputeBytesPerPixel((Config)fConfig) == fBytesPerPixel); 1680 SkASSERT((uint8_t)ComputeBytesPerPixel((Config)fConfig) == fBytesPerPixel);
1632 1681
1633 #if 0 // these asserts are not thread-correct, so disable for now 1682 #if 0 // these asserts are not thread-correct, so disable for now
1634 if (fPixelRef) { 1683 if (fPixelRef) {
1635 if (fPixelLockCount > 0) { 1684 if (fPixelLockCount > 0) {
1636 SkASSERT(fPixelRef->isLocked()); 1685 SkASSERT(fPixelRef->isLocked());
1637 } else { 1686 } else {
1638 SkASSERT(NULL == fPixels); 1687 SkASSERT(NULL == fPixels);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1675 if (NULL != uri) { 1724 if (NULL != uri) {
1676 str->appendf(" uri:\"%s\"", uri); 1725 str->appendf(" uri:\"%s\"", uri);
1677 } else { 1726 } else {
1678 str->appendf(" pixelref:%p", pr); 1727 str->appendf(" pixelref:%p", pr);
1679 } 1728 }
1680 } 1729 }
1681 1730
1682 str->append(")"); 1731 str->append(")");
1683 } 1732 }
1684 #endif 1733 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698