diff --git a/src/core/SkPixmap.cpp b/src/core/SkPixmap.cpp index 78d6f4f5f6..f842afd8ce 100644 --- a/src/core/SkPixmap.cpp +++ b/src/core/SkPixmap.cpp @@ -350,12 +350,98 @@ SkColor SkPixmap::getColor(int x, int y) const { SkASSERT((unsigned)x < (unsigned)this->width()); SkASSERT((unsigned)y < (unsigned)this->height()); - SkColor result; - auto info = SkImageInfo::Make(1,1, - kBGRA_8888_SkColorType,kUnpremul_SkAlphaType, - sk_ref_sp(this->colorSpace())); - SkAssertResult(this->readPixels(info, &result, sizeof(result), x,y)); - return result; + const bool needsUnpremul = (kPremul_SkAlphaType == fInfo.alphaType()); + auto toColor = [needsUnpremul](uint32_t maybePremulColor) { + return needsUnpremul ? SkUnPreMultiply::PMColorToColor(maybePremulColor) + : SkSwizzle_BGRA_to_PMColor(maybePremulColor); + }; + + 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 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 toColor(c); + } + case kRGB_888x_SkColorType: { + uint32_t value = *this->addr32(x, y); + return SkSwizzle_RB(value | 0xff000000); + } + case kBGRA_8888_SkColorType: { + uint32_t value = *this->addr32(x, y); + SkPMColor c = SkSwizzle_BGRA_to_PMColor(value); + return toColor(c); + } + case kRGBA_8888_SkColorType: { + uint32_t value = *this->addr32(x, y); + SkPMColor c = SkSwizzle_RGBA_to_PMColor(value); + return toColor(c); + } + case kRGB_101010x_SkColorType: { + uint32_t value = *this->addr32(x, y); + // Convert 10-bit rgb to 8-bit bgr, and mask in 0xff alpha at the top. + return (uint32_t)( ((value >> 0) & 0x3ff) * (255/1023.0f) ) << 16 + | (uint32_t)( ((value >> 10) & 0x3ff) * (255/1023.0f) ) << 8 + | (uint32_t)( ((value >> 20) & 0x3ff) * (255/1023.0f) ) << 0 + | 0xff000000; + } + case kRGBA_1010102_SkColorType: { + uint32_t value = *this->addr32(x, y); + + float r = ((value >> 0) & 0x3ff) * (1/1023.0f), + g = ((value >> 10) & 0x3ff) * (1/1023.0f), + b = ((value >> 20) & 0x3ff) * (1/1023.0f), + a = ((value >> 30) & 0x3 ) * (1/ 3.0f); + if (a != 0 && needsUnpremul) { + r *= (1.0f/a); + g *= (1.0f/a); + b *= (1.0f/a); + } + return (uint32_t)( r * 255.0f ) << 16 + | (uint32_t)( g * 255.0f ) << 8 + | (uint32_t)( b * 255.0f ) << 0 + | (uint32_t)( a * 255.0f ) << 24; + } + 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] && needsUnpremul) { + 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); + } + case kRGBA_F32_SkColorType: { + const float* rgba = + (const float*)fPixels + 4*y*(fRowBytes >> 4) + 4*x; + Sk4f p4 = Sk4f::Load(rgba); + // From here on, just like F16: + if (p4[3] && needsUnpremul) { + 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); + } } bool SkPixmap::computeIsOpaque() const {