diff --git a/include/core/SkBitmap.h b/include/core/SkBitmap.h index ce1b56e7bf..061f0e5c95 100644 --- a/include/core/SkBitmap.h +++ b/include/core/SkBitmap.h @@ -525,13 +525,19 @@ public: } /** - * Return the SkColor of the specified pixel. In most cases this will - * require un-premultiplying the color. Alpha only colortypes (e.g. kAlpha_8_SkColorType) - * return black with the appropriate alpha set. The value is undefined - * for kUnknown_SkColorType or if x or y are out of bounds, or if the bitmap - * does not have any pixels (or has not be locked with lockPixels()). + * Converts the pixel at the specified coordinate to an unpremultiplied + * SkColor. Note: this ignores any SkColorSpace information, and may return + * lower precision data than is actually in the pixel. Alpha only + * colortypes (e.g. kAlpha_8_SkColorType) return black with the appropriate + * alpha set. The value is undefined for kUnknown_SkColorType or if x or y + * are out of bounds, or if the bitmap does not have any pixels (or has not + * be locked with lockPixels()).. */ - SkColor getColor(int x, int y) const; + SkColor getColor(int x, int y) const { + SkPixmap pixmap; + SkAssertResult(this->peekPixels(&pixmap)); + return pixmap.getColor(x, y); + } /** Returns the address of the specified pixel. This performs a runtime check to know the size of the pixels, and will return the same answer diff --git a/include/core/SkPixmap.h b/include/core/SkPixmap.h index 699ddb4d44..fe2a0b92a4 100644 --- a/include/core/SkPixmap.h +++ b/include/core/SkPixmap.h @@ -89,6 +89,16 @@ public: uint64_t getSafeSize64() const { return fInfo.getSafeSize64(fRowBytes); } size_t getSafeSize() const { return fInfo.getSafeSize(fRowBytes); } + /** + * Converts the pixel at the specified coordinate to an unpremultiplied + * SkColor. Note: this ignores any SkColorSpace information, and may return + * lower precision data than is actually in the pixel. Alpha only + * colortypes (e.g. kAlpha_8_SkColorType) return black with the appropriate + * alpha set. The value is undefined for kUnknown_SkColorType or if x or y + * are out of bounds, or if the pixtap does not have any pixels. + */ + SkColor getColor(int x, int y) const; + const void* addr(int x, int y) const { return (const char*)fPixels + fInfo.computeOffset(x, y, fRowBytes); } diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp index c62f5f391b..beeda4fb42 100644 --- a/src/core/SkBitmap.cpp +++ b/src/core/SkBitmap.cpp @@ -561,64 +561,6 @@ void* SkBitmap::getAddr(int x, int y) const { return base; } -#include "SkHalf.h" - -SkColor SkBitmap::getColor(int x, int y) const { - SkASSERT((unsigned)x < (unsigned)this->width()); - SkASSERT((unsigned)y < (unsigned)this->height()); - - switch (this->colorType()) { - case kGray_8_SkColorType: { - uint8_t* addr = this->getAddr8(x, y); - return SkColorSetRGB(*addr, *addr, *addr); - } - case kAlpha_8_SkColorType: { - uint8_t* addr = this->getAddr8(x, y); - return SkColorSetA(0, addr[0]); - } - case kIndex_8_SkColorType: { - SkPMColor c = this->getIndex8Color(x, y); - return SkUnPreMultiply::PMColorToColor(c); - } - case kRGB_565_SkColorType: { - uint16_t* addr = this->getAddr16(x, y); - return SkPixel16ToColor(addr[0]); - } - case kARGB_4444_SkColorType: { - uint16_t* addr = this->getAddr16(x, y); - SkPMColor c = SkPixel4444ToPixel32(addr[0]); - return SkUnPreMultiply::PMColorToColor(c); - } - case kBGRA_8888_SkColorType: { - uint32_t* addr = this->getAddr32(x, y); - SkPMColor c = SkSwizzle_BGRA_to_PMColor(addr[0]); - return SkUnPreMultiply::PMColorToColor(c); - } - case kRGBA_8888_SkColorType: { - uint32_t* addr = this->getAddr32(x, y); - SkPMColor c = SkSwizzle_RGBA_to_PMColor(addr[0]); - return SkUnPreMultiply::PMColorToColor(c); - } - case kRGBA_F16_SkColorType: { - const uint64_t* addr = (const uint64_t*)fPixels + y * (fRowBytes >> 3) + x; - Sk4f p4 = SkHalfToFloat_finite_ftz(addr[0]); - if (p4[3]) { - float inva = 1 / p4[3]; - p4 = p4 * Sk4f(inva, inva, inva, 1); - } - SkColor c; - SkNx_cast(p4 * Sk4f(255) + Sk4f(0.5f)).store(&c); - // p4 is RGBA, but we want BGRA, so we need to swap next - return SkSwizzle_RB(c); - } - default: - SkASSERT(false); - return 0; - } - SkASSERT(false); // Not reached. - return 0; -} - static bool compute_is_opaque(const SkPixmap& pmap) { const int height = pmap.height(); const int width = pmap.width(); diff --git a/src/core/SkPixmap.cpp b/src/core/SkPixmap.cpp index 108c87757b..7f933a75d2 100644 --- a/src/core/SkPixmap.cpp +++ b/src/core/SkPixmap.cpp @@ -274,3 +274,57 @@ bool SkPixmap::scalePixels(const SkPixmap& dst, SkFilterQuality quality) const { } ////////////////////////////////////////////////////////////////////////////////////////////////// + +SkColor SkPixmap::getColor(int x, int y) const { + SkASSERT(this->addr()); + SkASSERT((unsigned)x < (unsigned)this->width()); + SkASSERT((unsigned)y < (unsigned)this->height()); + switch (this->colorType()) { + case kGray_8_SkColorType: { + uint8_t value = *this->addr8(x, y); + return SkColorSetRGB(value, value, value); + } + case kAlpha_8_SkColorType: { + return SkColorSetA(0, *this->addr8(x, y)); + } + case kIndex_8_SkColorType: { + SkASSERT(this->ctable()); + SkPMColor pmColor = (*this->ctable())[*this->addr8(x, y)]; + return SkUnPreMultiply::PMColorToColor(pmColor); + } + case kRGB_565_SkColorType: { + return SkPixel16ToColor(*this->addr16(x, y)); + } + case kARGB_4444_SkColorType: { + uint16_t value = *this->addr16(x, y); + SkPMColor c = SkPixel4444ToPixel32(value); + return SkUnPreMultiply::PMColorToColor(c); + } + case kBGRA_8888_SkColorType: { + uint32_t value = *this->addr32(x, y); + SkPMColor c = SkSwizzle_BGRA_to_PMColor(value); + return SkUnPreMultiply::PMColorToColor(c); + } + case kRGBA_8888_SkColorType: { + uint32_t value = *this->addr32(x, y); + SkPMColor c = SkSwizzle_RGBA_to_PMColor(value); + return SkUnPreMultiply::PMColorToColor(c); + } + case kRGBA_F16_SkColorType: { + const uint64_t* addr = + (const uint64_t*)fPixels + y * (fRowBytes >> 3) + x; + Sk4f p4 = SkHalfToFloat_finite_ftz(*addr); + if (p4[3]) { + float inva = 1 / p4[3]; + p4 = p4 * Sk4f(inva, inva, inva, 1); + } + SkColor c; + SkNx_cast(p4 * Sk4f(255) + Sk4f(0.5f)).store(&c); + // p4 is RGBA, but we want BGRA, so we need to swap next + return SkSwizzle_RB(c); + } + default: + SkDEBUGFAIL(""); + return SkColorSetARGB(0, 0, 0, 0); + } +}