1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2015 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "include/core/SkPixmap.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "include/core/SkBitmap.h" 11cb93a386Sopenharmony_ci#include "include/core/SkData.h" 12cb93a386Sopenharmony_ci#include "include/core/SkSurface.h" 13cb93a386Sopenharmony_ci#include "include/core/SkUnPreMultiply.h" 14cb93a386Sopenharmony_ci#include "include/private/SkColorData.h" 15cb93a386Sopenharmony_ci#include "include/private/SkHalf.h" 16cb93a386Sopenharmony_ci#include "include/private/SkImageInfoPriv.h" 17cb93a386Sopenharmony_ci#include "include/private/SkNx.h" 18cb93a386Sopenharmony_ci#include "include/private/SkTPin.h" 19cb93a386Sopenharmony_ci#include "include/private/SkTemplates.h" 20cb93a386Sopenharmony_ci#include "include/private/SkTo.h" 21cb93a386Sopenharmony_ci#include "src/core/SkConvertPixels.h" 22cb93a386Sopenharmony_ci#include "src/core/SkDraw.h" 23cb93a386Sopenharmony_ci#include "src/core/SkMask.h" 24cb93a386Sopenharmony_ci#include "src/core/SkMatrixProvider.h" 25cb93a386Sopenharmony_ci#include "src/core/SkPixmapPriv.h" 26cb93a386Sopenharmony_ci#include "src/core/SkRasterClip.h" 27cb93a386Sopenharmony_ci#include "src/core/SkUtils.h" 28cb93a386Sopenharmony_ci#include "src/image/SkReadPixelsRec.h" 29cb93a386Sopenharmony_ci#include "src/shaders/SkImageShader.h" 30cb93a386Sopenharmony_ci 31cb93a386Sopenharmony_ci#include <utility> 32cb93a386Sopenharmony_ci 33cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////////////////////// 34cb93a386Sopenharmony_ci 35cb93a386Sopenharmony_civoid SkPixmap::reset() { 36cb93a386Sopenharmony_ci fPixels = nullptr; 37cb93a386Sopenharmony_ci fRowBytes = 0; 38cb93a386Sopenharmony_ci fInfo = SkImageInfo::MakeUnknown(); 39cb93a386Sopenharmony_ci} 40cb93a386Sopenharmony_ci 41cb93a386Sopenharmony_civoid SkPixmap::reset(const SkImageInfo& info, const void* addr, size_t rowBytes) { 42cb93a386Sopenharmony_ci if (addr) { 43cb93a386Sopenharmony_ci SkASSERT(info.validRowBytes(rowBytes)); 44cb93a386Sopenharmony_ci } 45cb93a386Sopenharmony_ci fPixels = addr; 46cb93a386Sopenharmony_ci fRowBytes = rowBytes; 47cb93a386Sopenharmony_ci fInfo = info; 48cb93a386Sopenharmony_ci} 49cb93a386Sopenharmony_ci 50cb93a386Sopenharmony_cibool SkPixmap::reset(const SkMask& src) { 51cb93a386Sopenharmony_ci if (SkMask::kA8_Format == src.fFormat) { 52cb93a386Sopenharmony_ci this->reset(SkImageInfo::MakeA8(src.fBounds.width(), src.fBounds.height()), 53cb93a386Sopenharmony_ci src.fImage, src.fRowBytes); 54cb93a386Sopenharmony_ci return true; 55cb93a386Sopenharmony_ci } 56cb93a386Sopenharmony_ci this->reset(); 57cb93a386Sopenharmony_ci return false; 58cb93a386Sopenharmony_ci} 59cb93a386Sopenharmony_ci 60cb93a386Sopenharmony_civoid SkPixmap::setColorSpace(sk_sp<SkColorSpace> cs) { 61cb93a386Sopenharmony_ci fInfo = fInfo.makeColorSpace(std::move(cs)); 62cb93a386Sopenharmony_ci} 63cb93a386Sopenharmony_ci 64cb93a386Sopenharmony_cibool SkPixmap::extractSubset(SkPixmap* result, const SkIRect& subset) const { 65cb93a386Sopenharmony_ci SkIRect srcRect, r; 66cb93a386Sopenharmony_ci srcRect.setWH(this->width(), this->height()); 67cb93a386Sopenharmony_ci if (!r.intersect(srcRect, subset)) { 68cb93a386Sopenharmony_ci return false; // r is empty (i.e. no intersection) 69cb93a386Sopenharmony_ci } 70cb93a386Sopenharmony_ci 71cb93a386Sopenharmony_ci // If the upper left of the rectangle was outside the bounds of this SkBitmap, we should have 72cb93a386Sopenharmony_ci // exited above. 73cb93a386Sopenharmony_ci SkASSERT(static_cast<unsigned>(r.fLeft) < static_cast<unsigned>(this->width())); 74cb93a386Sopenharmony_ci SkASSERT(static_cast<unsigned>(r.fTop) < static_cast<unsigned>(this->height())); 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_ci const void* pixels = nullptr; 77cb93a386Sopenharmony_ci if (fPixels) { 78cb93a386Sopenharmony_ci const size_t bpp = fInfo.bytesPerPixel(); 79cb93a386Sopenharmony_ci pixels = (const uint8_t*)fPixels + r.fTop * fRowBytes + r.fLeft * bpp; 80cb93a386Sopenharmony_ci } 81cb93a386Sopenharmony_ci result->reset(fInfo.makeDimensions(r.size()), pixels, fRowBytes); 82cb93a386Sopenharmony_ci return true; 83cb93a386Sopenharmony_ci} 84cb93a386Sopenharmony_ci 85cb93a386Sopenharmony_ci// This is the same as SkPixmap::addr(x,y), but this version gets inlined, while the public 86cb93a386Sopenharmony_ci// method does not. Perhaps we could bloat it so it can be inlined, but that would grow code-size 87cb93a386Sopenharmony_ci// everywhere, instead of just here (on behalf of getAlphaf()). 88cb93a386Sopenharmony_cistatic const void* fast_getaddr(const SkPixmap& pm, int x, int y) { 89cb93a386Sopenharmony_ci x <<= SkColorTypeShiftPerPixel(pm.colorType()); 90cb93a386Sopenharmony_ci return static_cast<const char*>(pm.addr()) + y * pm.rowBytes() + x; 91cb93a386Sopenharmony_ci} 92cb93a386Sopenharmony_ci 93cb93a386Sopenharmony_cifloat SkPixmap::getAlphaf(int x, int y) const { 94cb93a386Sopenharmony_ci SkASSERT(this->addr()); 95cb93a386Sopenharmony_ci SkASSERT((unsigned)x < (unsigned)this->width()); 96cb93a386Sopenharmony_ci SkASSERT((unsigned)y < (unsigned)this->height()); 97cb93a386Sopenharmony_ci 98cb93a386Sopenharmony_ci float value = 0; 99cb93a386Sopenharmony_ci const void* srcPtr = fast_getaddr(*this, x, y); 100cb93a386Sopenharmony_ci 101cb93a386Sopenharmony_ci switch (this->colorType()) { 102cb93a386Sopenharmony_ci case kUnknown_SkColorType: 103cb93a386Sopenharmony_ci return 0; 104cb93a386Sopenharmony_ci case kGray_8_SkColorType: 105cb93a386Sopenharmony_ci case kR8G8_unorm_SkColorType: 106cb93a386Sopenharmony_ci case kR16G16_unorm_SkColorType: 107cb93a386Sopenharmony_ci case kR16G16_float_SkColorType: 108cb93a386Sopenharmony_ci case kRGB_565_SkColorType: 109cb93a386Sopenharmony_ci case kRGB_888x_SkColorType: 110cb93a386Sopenharmony_ci case kRGB_101010x_SkColorType: 111cb93a386Sopenharmony_ci case kBGR_101010x_SkColorType: 112cb93a386Sopenharmony_ci return 1; 113cb93a386Sopenharmony_ci case kAlpha_8_SkColorType: 114cb93a386Sopenharmony_ci value = static_cast<const uint8_t*>(srcPtr)[0] * (1.0f/255); 115cb93a386Sopenharmony_ci break; 116cb93a386Sopenharmony_ci case kA16_unorm_SkColorType: 117cb93a386Sopenharmony_ci value = static_cast<const uint16_t*>(srcPtr)[0] * (1.0f/65535); 118cb93a386Sopenharmony_ci break; 119cb93a386Sopenharmony_ci case kA16_float_SkColorType: { 120cb93a386Sopenharmony_ci SkHalf half = static_cast<const SkHalf*>(srcPtr)[0]; 121cb93a386Sopenharmony_ci value = SkHalfToFloat(half); 122cb93a386Sopenharmony_ci break; 123cb93a386Sopenharmony_ci } 124cb93a386Sopenharmony_ci case kARGB_4444_SkColorType: { 125cb93a386Sopenharmony_ci uint16_t u16 = static_cast<const uint16_t*>(srcPtr)[0]; 126cb93a386Sopenharmony_ci value = SkGetPackedA4444(u16) * (1.0f/15); 127cb93a386Sopenharmony_ci break; 128cb93a386Sopenharmony_ci } 129cb93a386Sopenharmony_ci case kRGBA_8888_SkColorType: 130cb93a386Sopenharmony_ci case kBGRA_8888_SkColorType: 131cb93a386Sopenharmony_ci case kSRGBA_8888_SkColorType: 132cb93a386Sopenharmony_ci value = static_cast<const uint8_t*>(srcPtr)[3] * (1.0f/255); 133cb93a386Sopenharmony_ci break; 134cb93a386Sopenharmony_ci case kRGBA_1010102_SkColorType: 135cb93a386Sopenharmony_ci case kBGRA_1010102_SkColorType: { 136cb93a386Sopenharmony_ci uint32_t u32 = static_cast<const uint32_t*>(srcPtr)[0]; 137cb93a386Sopenharmony_ci value = (u32 >> 30) * (1.0f/3); 138cb93a386Sopenharmony_ci break; 139cb93a386Sopenharmony_ci } 140cb93a386Sopenharmony_ci case kR16G16B16A16_unorm_SkColorType: { 141cb93a386Sopenharmony_ci uint64_t u64 = static_cast<const uint64_t*>(srcPtr)[0]; 142cb93a386Sopenharmony_ci value = (u64 >> 48) * (1.0f/65535); 143cb93a386Sopenharmony_ci break; 144cb93a386Sopenharmony_ci } 145cb93a386Sopenharmony_ci case kRGBA_F16Norm_SkColorType: 146cb93a386Sopenharmony_ci case kRGBA_F16_SkColorType: { 147cb93a386Sopenharmony_ci uint64_t px; 148cb93a386Sopenharmony_ci memcpy(&px, srcPtr, sizeof(px)); 149cb93a386Sopenharmony_ci value = SkHalfToFloat_finite_ftz(px)[3]; 150cb93a386Sopenharmony_ci break; 151cb93a386Sopenharmony_ci } 152cb93a386Sopenharmony_ci case kRGBA_F32_SkColorType: 153cb93a386Sopenharmony_ci value = static_cast<const float*>(srcPtr)[3]; 154cb93a386Sopenharmony_ci break; 155cb93a386Sopenharmony_ci } 156cb93a386Sopenharmony_ci return value; 157cb93a386Sopenharmony_ci} 158cb93a386Sopenharmony_ci 159cb93a386Sopenharmony_cibool SkPixmap::readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB, 160cb93a386Sopenharmony_ci int x, int y) const { 161cb93a386Sopenharmony_ci if (!SkImageInfoValidConversion(dstInfo, fInfo)) { 162cb93a386Sopenharmony_ci return false; 163cb93a386Sopenharmony_ci } 164cb93a386Sopenharmony_ci 165cb93a386Sopenharmony_ci SkReadPixelsRec rec(dstInfo, dstPixels, dstRB, x, y); 166cb93a386Sopenharmony_ci if (!rec.trim(fInfo.width(), fInfo.height())) { 167cb93a386Sopenharmony_ci return false; 168cb93a386Sopenharmony_ci } 169cb93a386Sopenharmony_ci 170cb93a386Sopenharmony_ci const void* srcPixels = this->addr(rec.fX, rec.fY); 171cb93a386Sopenharmony_ci const SkImageInfo srcInfo = fInfo.makeDimensions(rec.fInfo.dimensions()); 172cb93a386Sopenharmony_ci return SkConvertPixels(rec.fInfo, rec.fPixels, rec.fRowBytes, srcInfo, srcPixels, 173cb93a386Sopenharmony_ci this->rowBytes()); 174cb93a386Sopenharmony_ci} 175cb93a386Sopenharmony_ci 176cb93a386Sopenharmony_cibool SkPixmap::erase(SkColor color, const SkIRect& subset) const { 177cb93a386Sopenharmony_ci return this->erase(SkColor4f::FromColor(color), &subset); 178cb93a386Sopenharmony_ci} 179cb93a386Sopenharmony_ci 180cb93a386Sopenharmony_cibool SkPixmap::erase(const SkColor4f& color, SkColorSpace* cs, const SkIRect* subset) const { 181cb93a386Sopenharmony_ci SkPaint paint; 182cb93a386Sopenharmony_ci paint.setBlendMode(SkBlendMode::kSrc); 183cb93a386Sopenharmony_ci paint.setColor4f(color, cs); 184cb93a386Sopenharmony_ci 185cb93a386Sopenharmony_ci SkIRect clip = this->bounds(); 186cb93a386Sopenharmony_ci if (subset && !clip.intersect(*subset)) { 187cb93a386Sopenharmony_ci return false; 188cb93a386Sopenharmony_ci } 189cb93a386Sopenharmony_ci SkRasterClip rc{clip}; 190cb93a386Sopenharmony_ci 191cb93a386Sopenharmony_ci SkDraw draw; 192cb93a386Sopenharmony_ci SkSimpleMatrixProvider matrixProvider(SkMatrix::I()); 193cb93a386Sopenharmony_ci draw.fDst = *this; 194cb93a386Sopenharmony_ci draw.fMatrixProvider = &matrixProvider; 195cb93a386Sopenharmony_ci draw.fRC = &rc; 196cb93a386Sopenharmony_ci 197cb93a386Sopenharmony_ci draw.drawPaint(paint); 198cb93a386Sopenharmony_ci return true; 199cb93a386Sopenharmony_ci} 200cb93a386Sopenharmony_ci 201cb93a386Sopenharmony_cibool SkPixmap::scalePixels(const SkPixmap& actualDst, const SkSamplingOptions& sampling) const { 202cb93a386Sopenharmony_ci // We may need to tweak how we interpret these just a little below, so we make copies. 203cb93a386Sopenharmony_ci SkPixmap src = *this, 204cb93a386Sopenharmony_ci dst = actualDst; 205cb93a386Sopenharmony_ci 206cb93a386Sopenharmony_ci // Can't do anthing with empty src or dst 207cb93a386Sopenharmony_ci if (src.width() <= 0 || src.height() <= 0 || 208cb93a386Sopenharmony_ci dst.width() <= 0 || dst.height() <= 0) { 209cb93a386Sopenharmony_ci return false; 210cb93a386Sopenharmony_ci } 211cb93a386Sopenharmony_ci 212cb93a386Sopenharmony_ci // no scaling involved? 213cb93a386Sopenharmony_ci if (src.width() == dst.width() && src.height() == dst.height()) { 214cb93a386Sopenharmony_ci return src.readPixels(dst); 215cb93a386Sopenharmony_ci } 216cb93a386Sopenharmony_ci 217cb93a386Sopenharmony_ci // If src and dst are both unpremul, we'll fake the source out to appear as if premul, 218cb93a386Sopenharmony_ci // and mark the destination as opaque. This odd combination allows us to scale unpremul 219cb93a386Sopenharmony_ci // pixels without ever premultiplying them (perhaps losing information in the color channels). 220cb93a386Sopenharmony_ci // This is an idiosyncratic feature of scalePixels(), and is tested by scalepixels_unpremul GM. 221cb93a386Sopenharmony_ci bool clampAsIfUnpremul = false; 222cb93a386Sopenharmony_ci if (src.alphaType() == kUnpremul_SkAlphaType && 223cb93a386Sopenharmony_ci dst.alphaType() == kUnpremul_SkAlphaType) { 224cb93a386Sopenharmony_ci src.reset(src.info().makeAlphaType(kPremul_SkAlphaType), src.addr(), src.rowBytes()); 225cb93a386Sopenharmony_ci dst.reset(dst.info().makeAlphaType(kOpaque_SkAlphaType), dst.addr(), dst.rowBytes()); 226cb93a386Sopenharmony_ci 227cb93a386Sopenharmony_ci // We'll need to tell the image shader to clamp to [0,1] instead of the 228cb93a386Sopenharmony_ci // usual [0,a] when using a bicubic scaling (kHigh_SkFilterQuality). 229cb93a386Sopenharmony_ci clampAsIfUnpremul = true; 230cb93a386Sopenharmony_ci } 231cb93a386Sopenharmony_ci 232cb93a386Sopenharmony_ci SkBitmap bitmap; 233cb93a386Sopenharmony_ci if (!bitmap.installPixels(src)) { 234cb93a386Sopenharmony_ci return false; 235cb93a386Sopenharmony_ci } 236cb93a386Sopenharmony_ci bitmap.setImmutable(); // Don't copy when we create an image. 237cb93a386Sopenharmony_ci 238cb93a386Sopenharmony_ci SkMatrix scale = SkMatrix::RectToRect(SkRect::Make(src.bounds()), SkRect::Make(dst.bounds())); 239cb93a386Sopenharmony_ci 240cb93a386Sopenharmony_ci sk_sp<SkShader> shader = SkImageShader::Make(bitmap.asImage(), 241cb93a386Sopenharmony_ci SkTileMode::kClamp, 242cb93a386Sopenharmony_ci SkTileMode::kClamp, 243cb93a386Sopenharmony_ci sampling, 244cb93a386Sopenharmony_ci &scale, 245cb93a386Sopenharmony_ci clampAsIfUnpremul); 246cb93a386Sopenharmony_ci 247cb93a386Sopenharmony_ci sk_sp<SkSurface> surface = SkSurface::MakeRasterDirect(dst.info(), 248cb93a386Sopenharmony_ci dst.writable_addr(), 249cb93a386Sopenharmony_ci dst.rowBytes()); 250cb93a386Sopenharmony_ci if (!shader || !surface) { 251cb93a386Sopenharmony_ci return false; 252cb93a386Sopenharmony_ci } 253cb93a386Sopenharmony_ci 254cb93a386Sopenharmony_ci SkPaint paint; 255cb93a386Sopenharmony_ci paint.setBlendMode(SkBlendMode::kSrc); 256cb93a386Sopenharmony_ci paint.setShader(std::move(shader)); 257cb93a386Sopenharmony_ci surface->getCanvas()->drawPaint(paint); 258cb93a386Sopenharmony_ci return true; 259cb93a386Sopenharmony_ci} 260cb93a386Sopenharmony_ci 261cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////////////////////////// 262cb93a386Sopenharmony_ci 263cb93a386Sopenharmony_ciSkColor SkPixmap::getColor(int x, int y) const { 264cb93a386Sopenharmony_ci SkASSERT(this->addr()); 265cb93a386Sopenharmony_ci SkASSERT((unsigned)x < (unsigned)this->width()); 266cb93a386Sopenharmony_ci SkASSERT((unsigned)y < (unsigned)this->height()); 267cb93a386Sopenharmony_ci 268cb93a386Sopenharmony_ci const bool needsUnpremul = (kPremul_SkAlphaType == fInfo.alphaType()); 269cb93a386Sopenharmony_ci auto toColor = [needsUnpremul](uint32_t maybePremulColor) { 270cb93a386Sopenharmony_ci return needsUnpremul ? SkUnPreMultiply::PMColorToColor(maybePremulColor) 271cb93a386Sopenharmony_ci : SkSwizzle_BGRA_to_PMColor(maybePremulColor); 272cb93a386Sopenharmony_ci }; 273cb93a386Sopenharmony_ci 274cb93a386Sopenharmony_ci switch (this->colorType()) { 275cb93a386Sopenharmony_ci case kGray_8_SkColorType: { 276cb93a386Sopenharmony_ci uint8_t value = *this->addr8(x, y); 277cb93a386Sopenharmony_ci return SkColorSetRGB(value, value, value); 278cb93a386Sopenharmony_ci } 279cb93a386Sopenharmony_ci case kAlpha_8_SkColorType: { 280cb93a386Sopenharmony_ci return SkColorSetA(0, *this->addr8(x, y)); 281cb93a386Sopenharmony_ci } 282cb93a386Sopenharmony_ci case kA16_unorm_SkColorType: { 283cb93a386Sopenharmony_ci uint16_t value = *this->addr16(x, y); 284cb93a386Sopenharmony_ci return SkColorSetA(0, value * (255 / 65535.0f)); 285cb93a386Sopenharmony_ci } 286cb93a386Sopenharmony_ci case kA16_float_SkColorType: { 287cb93a386Sopenharmony_ci SkHalf value = *this->addr16(x, y); 288cb93a386Sopenharmony_ci return SkColorSetA(0, 255 * SkHalfToFloat(value)); 289cb93a386Sopenharmony_ci } 290cb93a386Sopenharmony_ci case kRGB_565_SkColorType: { 291cb93a386Sopenharmony_ci return SkPixel16ToColor(*this->addr16(x, y)); 292cb93a386Sopenharmony_ci } 293cb93a386Sopenharmony_ci case kARGB_4444_SkColorType: { 294cb93a386Sopenharmony_ci uint16_t value = *this->addr16(x, y); 295cb93a386Sopenharmony_ci SkPMColor c = SkPixel4444ToPixel32(value); 296cb93a386Sopenharmony_ci return toColor(c); 297cb93a386Sopenharmony_ci } 298cb93a386Sopenharmony_ci case kR8G8_unorm_SkColorType: { 299cb93a386Sopenharmony_ci uint16_t value = *this->addr16(x, y); 300cb93a386Sopenharmony_ci return (uint32_t)( ((value >> 0) & 0xff) ) << 16 301cb93a386Sopenharmony_ci | (uint32_t)( ((value >> 8) & 0xff) ) << 8 302cb93a386Sopenharmony_ci | 0xff000000; 303cb93a386Sopenharmony_ci } 304cb93a386Sopenharmony_ci case kR16G16_unorm_SkColorType: { 305cb93a386Sopenharmony_ci uint32_t value = *this->addr32(x, y); 306cb93a386Sopenharmony_ci return (uint32_t)( ((value >> 0) & 0xffff) * (255/65535.0f) ) << 16 307cb93a386Sopenharmony_ci | (uint32_t)( ((value >> 16) & 0xffff) * (255/65535.0f) ) << 8 308cb93a386Sopenharmony_ci | 0xff000000; 309cb93a386Sopenharmony_ci } 310cb93a386Sopenharmony_ci case kR16G16_float_SkColorType: { 311cb93a386Sopenharmony_ci uint32_t value = *this->addr32(x, y); 312cb93a386Sopenharmony_ci uint32_t r = 255 * SkHalfToFloat((value >> 0) & 0xffff); 313cb93a386Sopenharmony_ci uint32_t g = 255 * SkHalfToFloat((value >> 16) & 0xffff); 314cb93a386Sopenharmony_ci return (r << 16) | (g << 8) | 0xff000000; 315cb93a386Sopenharmony_ci } 316cb93a386Sopenharmony_ci case kRGB_888x_SkColorType: { 317cb93a386Sopenharmony_ci uint32_t value = *this->addr32(x, y); 318cb93a386Sopenharmony_ci return SkSwizzle_RB(value | 0xff000000); 319cb93a386Sopenharmony_ci } 320cb93a386Sopenharmony_ci case kBGRA_8888_SkColorType: { 321cb93a386Sopenharmony_ci uint32_t value = *this->addr32(x, y); 322cb93a386Sopenharmony_ci SkPMColor c = SkSwizzle_BGRA_to_PMColor(value); 323cb93a386Sopenharmony_ci return toColor(c); 324cb93a386Sopenharmony_ci } 325cb93a386Sopenharmony_ci case kRGBA_8888_SkColorType: { 326cb93a386Sopenharmony_ci uint32_t value = *this->addr32(x, y); 327cb93a386Sopenharmony_ci SkPMColor c = SkSwizzle_RGBA_to_PMColor(value); 328cb93a386Sopenharmony_ci return toColor(c); 329cb93a386Sopenharmony_ci } 330cb93a386Sopenharmony_ci case kSRGBA_8888_SkColorType: { 331cb93a386Sopenharmony_ci auto srgb_to_linear = [](float x) { 332cb93a386Sopenharmony_ci return (x <= 0.04045f) ? x * (1 / 12.92f) 333cb93a386Sopenharmony_ci : sk_float_pow(x * (1 / 1.055f) + (0.055f / 1.055f), 2.4f); 334cb93a386Sopenharmony_ci }; 335cb93a386Sopenharmony_ci 336cb93a386Sopenharmony_ci uint32_t value = *this->addr32(x, y); 337cb93a386Sopenharmony_ci float r = ((value >> 0) & 0xff) * (1/255.0f), 338cb93a386Sopenharmony_ci g = ((value >> 8) & 0xff) * (1/255.0f), 339cb93a386Sopenharmony_ci b = ((value >> 16) & 0xff) * (1/255.0f), 340cb93a386Sopenharmony_ci a = ((value >> 24) & 0xff) * (1/255.0f); 341cb93a386Sopenharmony_ci r = srgb_to_linear(r); 342cb93a386Sopenharmony_ci g = srgb_to_linear(g); 343cb93a386Sopenharmony_ci b = srgb_to_linear(b); 344cb93a386Sopenharmony_ci if (a != 0 && needsUnpremul) { 345cb93a386Sopenharmony_ci r = SkTPin(r/a, 0.0f, 1.0f); 346cb93a386Sopenharmony_ci g = SkTPin(g/a, 0.0f, 1.0f); 347cb93a386Sopenharmony_ci b = SkTPin(b/a, 0.0f, 1.0f); 348cb93a386Sopenharmony_ci } 349cb93a386Sopenharmony_ci return (uint32_t)( r * 255.0f ) << 16 350cb93a386Sopenharmony_ci | (uint32_t)( g * 255.0f ) << 8 351cb93a386Sopenharmony_ci | (uint32_t)( b * 255.0f ) << 0 352cb93a386Sopenharmony_ci | (uint32_t)( a * 255.0f ) << 24; 353cb93a386Sopenharmony_ci } 354cb93a386Sopenharmony_ci case kRGB_101010x_SkColorType: { 355cb93a386Sopenharmony_ci uint32_t value = *this->addr32(x, y); 356cb93a386Sopenharmony_ci // Convert 10-bit rgb to 8-bit bgr, and mask in 0xff alpha at the top. 357cb93a386Sopenharmony_ci return (uint32_t)( ((value >> 0) & 0x3ff) * (255/1023.0f) ) << 16 358cb93a386Sopenharmony_ci | (uint32_t)( ((value >> 10) & 0x3ff) * (255/1023.0f) ) << 8 359cb93a386Sopenharmony_ci | (uint32_t)( ((value >> 20) & 0x3ff) * (255/1023.0f) ) << 0 360cb93a386Sopenharmony_ci | 0xff000000; 361cb93a386Sopenharmony_ci } 362cb93a386Sopenharmony_ci case kBGR_101010x_SkColorType: { 363cb93a386Sopenharmony_ci uint32_t value = *this->addr32(x, y); 364cb93a386Sopenharmony_ci // Convert 10-bit bgr to 8-bit bgr, and mask in 0xff alpha at the top. 365cb93a386Sopenharmony_ci return (uint32_t)( ((value >> 0) & 0x3ff) * (255/1023.0f) ) << 0 366cb93a386Sopenharmony_ci | (uint32_t)( ((value >> 10) & 0x3ff) * (255/1023.0f) ) << 8 367cb93a386Sopenharmony_ci | (uint32_t)( ((value >> 20) & 0x3ff) * (255/1023.0f) ) << 16 368cb93a386Sopenharmony_ci | 0xff000000; 369cb93a386Sopenharmony_ci } 370cb93a386Sopenharmony_ci case kRGBA_1010102_SkColorType: 371cb93a386Sopenharmony_ci case kBGRA_1010102_SkColorType: { 372cb93a386Sopenharmony_ci uint32_t value = *this->addr32(x, y); 373cb93a386Sopenharmony_ci 374cb93a386Sopenharmony_ci float r = ((value >> 0) & 0x3ff) * (1/1023.0f), 375cb93a386Sopenharmony_ci g = ((value >> 10) & 0x3ff) * (1/1023.0f), 376cb93a386Sopenharmony_ci b = ((value >> 20) & 0x3ff) * (1/1023.0f), 377cb93a386Sopenharmony_ci a = ((value >> 30) & 0x3 ) * (1/ 3.0f); 378cb93a386Sopenharmony_ci if (this->colorType() == kBGRA_1010102_SkColorType) { 379cb93a386Sopenharmony_ci std::swap(r,b); 380cb93a386Sopenharmony_ci } 381cb93a386Sopenharmony_ci if (a != 0 && needsUnpremul) { 382cb93a386Sopenharmony_ci r = SkTPin(r/a, 0.0f, 1.0f); 383cb93a386Sopenharmony_ci g = SkTPin(g/a, 0.0f, 1.0f); 384cb93a386Sopenharmony_ci b = SkTPin(b/a, 0.0f, 1.0f); 385cb93a386Sopenharmony_ci } 386cb93a386Sopenharmony_ci return (uint32_t)( r * 255.0f ) << 16 387cb93a386Sopenharmony_ci | (uint32_t)( g * 255.0f ) << 8 388cb93a386Sopenharmony_ci | (uint32_t)( b * 255.0f ) << 0 389cb93a386Sopenharmony_ci | (uint32_t)( a * 255.0f ) << 24; 390cb93a386Sopenharmony_ci } 391cb93a386Sopenharmony_ci case kR16G16B16A16_unorm_SkColorType: { 392cb93a386Sopenharmony_ci uint64_t value = *this->addr64(x, y); 393cb93a386Sopenharmony_ci 394cb93a386Sopenharmony_ci float r = ((value ) & 0xffff) * (1/65535.0f), 395cb93a386Sopenharmony_ci g = ((value >> 16) & 0xffff) * (1/65535.0f), 396cb93a386Sopenharmony_ci b = ((value >> 32) & 0xffff) * (1/65535.0f), 397cb93a386Sopenharmony_ci a = ((value >> 48) & 0xffff) * (1/65535.0f); 398cb93a386Sopenharmony_ci if (a != 0 && needsUnpremul) { 399cb93a386Sopenharmony_ci r *= (1.0f/a); 400cb93a386Sopenharmony_ci g *= (1.0f/a); 401cb93a386Sopenharmony_ci b *= (1.0f/a); 402cb93a386Sopenharmony_ci } 403cb93a386Sopenharmony_ci return (uint32_t)( r * 255.0f ) << 16 404cb93a386Sopenharmony_ci | (uint32_t)( g * 255.0f ) << 8 405cb93a386Sopenharmony_ci | (uint32_t)( b * 255.0f ) << 0 406cb93a386Sopenharmony_ci | (uint32_t)( a * 255.0f ) << 24; 407cb93a386Sopenharmony_ci } 408cb93a386Sopenharmony_ci case kRGBA_F16Norm_SkColorType: 409cb93a386Sopenharmony_ci case kRGBA_F16_SkColorType: { 410cb93a386Sopenharmony_ci const uint64_t* addr = 411cb93a386Sopenharmony_ci (const uint64_t*)fPixels + y * (fRowBytes >> 3) + x; 412cb93a386Sopenharmony_ci Sk4f p4 = SkHalfToFloat_finite_ftz(*addr); 413cb93a386Sopenharmony_ci if (p4[3] && needsUnpremul) { 414cb93a386Sopenharmony_ci float inva = 1 / p4[3]; 415cb93a386Sopenharmony_ci p4 = p4 * Sk4f(inva, inva, inva, 1); 416cb93a386Sopenharmony_ci } 417cb93a386Sopenharmony_ci SkColor c; 418cb93a386Sopenharmony_ci SkNx_cast<uint8_t>(p4 * Sk4f(255) + Sk4f(0.5f)).store(&c); 419cb93a386Sopenharmony_ci // p4 is RGBA, but we want BGRA, so we need to swap next 420cb93a386Sopenharmony_ci return SkSwizzle_RB(c); 421cb93a386Sopenharmony_ci } 422cb93a386Sopenharmony_ci case kRGBA_F32_SkColorType: { 423cb93a386Sopenharmony_ci const float* rgba = 424cb93a386Sopenharmony_ci (const float*)fPixels + 4*y*(fRowBytes >> 4) + 4*x; 425cb93a386Sopenharmony_ci Sk4f p4 = Sk4f::Load(rgba); 426cb93a386Sopenharmony_ci // From here on, just like F16: 427cb93a386Sopenharmony_ci if (p4[3] && needsUnpremul) { 428cb93a386Sopenharmony_ci float inva = 1 / p4[3]; 429cb93a386Sopenharmony_ci p4 = p4 * Sk4f(inva, inva, inva, 1); 430cb93a386Sopenharmony_ci } 431cb93a386Sopenharmony_ci SkColor c; 432cb93a386Sopenharmony_ci SkNx_cast<uint8_t>(p4 * Sk4f(255) + Sk4f(0.5f)).store(&c); 433cb93a386Sopenharmony_ci // p4 is RGBA, but we want BGRA, so we need to swap next 434cb93a386Sopenharmony_ci return SkSwizzle_RB(c); 435cb93a386Sopenharmony_ci } 436cb93a386Sopenharmony_ci case kUnknown_SkColorType: 437cb93a386Sopenharmony_ci break; 438cb93a386Sopenharmony_ci } 439cb93a386Sopenharmony_ci SkDEBUGFAIL(""); 440cb93a386Sopenharmony_ci return SkColorSetARGB(0, 0, 0, 0); 441cb93a386Sopenharmony_ci} 442cb93a386Sopenharmony_ci 443cb93a386Sopenharmony_cibool SkPixmap::computeIsOpaque() const { 444cb93a386Sopenharmony_ci const int height = this->height(); 445cb93a386Sopenharmony_ci const int width = this->width(); 446cb93a386Sopenharmony_ci 447cb93a386Sopenharmony_ci switch (this->colorType()) { 448cb93a386Sopenharmony_ci case kAlpha_8_SkColorType: { 449cb93a386Sopenharmony_ci unsigned a = 0xFF; 450cb93a386Sopenharmony_ci for (int y = 0; y < height; ++y) { 451cb93a386Sopenharmony_ci const uint8_t* row = this->addr8(0, y); 452cb93a386Sopenharmony_ci for (int x = 0; x < width; ++x) { 453cb93a386Sopenharmony_ci a &= row[x]; 454cb93a386Sopenharmony_ci } 455cb93a386Sopenharmony_ci if (0xFF != a) { 456cb93a386Sopenharmony_ci return false; 457cb93a386Sopenharmony_ci } 458cb93a386Sopenharmony_ci } 459cb93a386Sopenharmony_ci return true; 460cb93a386Sopenharmony_ci } 461cb93a386Sopenharmony_ci case kA16_unorm_SkColorType: { 462cb93a386Sopenharmony_ci unsigned a = 0xFFFF; 463cb93a386Sopenharmony_ci for (int y = 0; y < height; ++y) { 464cb93a386Sopenharmony_ci const uint16_t* row = this->addr16(0, y); 465cb93a386Sopenharmony_ci for (int x = 0; x < width; ++x) { 466cb93a386Sopenharmony_ci a &= row[x]; 467cb93a386Sopenharmony_ci } 468cb93a386Sopenharmony_ci if (0xFFFF != a) { 469cb93a386Sopenharmony_ci return false; 470cb93a386Sopenharmony_ci } 471cb93a386Sopenharmony_ci } 472cb93a386Sopenharmony_ci return true; 473cb93a386Sopenharmony_ci } 474cb93a386Sopenharmony_ci case kA16_float_SkColorType: { 475cb93a386Sopenharmony_ci for (int y = 0; y < height; ++y) { 476cb93a386Sopenharmony_ci const SkHalf* row = this->addr16(0, y); 477cb93a386Sopenharmony_ci for (int x = 0; x < width; ++x) { 478cb93a386Sopenharmony_ci if (row[x] < SK_Half1) { 479cb93a386Sopenharmony_ci return false; 480cb93a386Sopenharmony_ci } 481cb93a386Sopenharmony_ci } 482cb93a386Sopenharmony_ci } 483cb93a386Sopenharmony_ci return true; 484cb93a386Sopenharmony_ci } 485cb93a386Sopenharmony_ci case kRGB_565_SkColorType: 486cb93a386Sopenharmony_ci case kGray_8_SkColorType: 487cb93a386Sopenharmony_ci case kR8G8_unorm_SkColorType: 488cb93a386Sopenharmony_ci case kR16G16_unorm_SkColorType: 489cb93a386Sopenharmony_ci case kR16G16_float_SkColorType: 490cb93a386Sopenharmony_ci case kRGB_888x_SkColorType: 491cb93a386Sopenharmony_ci case kRGB_101010x_SkColorType: 492cb93a386Sopenharmony_ci case kBGR_101010x_SkColorType: 493cb93a386Sopenharmony_ci return true; 494cb93a386Sopenharmony_ci break; 495cb93a386Sopenharmony_ci case kARGB_4444_SkColorType: { 496cb93a386Sopenharmony_ci unsigned c = 0xFFFF; 497cb93a386Sopenharmony_ci for (int y = 0; y < height; ++y) { 498cb93a386Sopenharmony_ci const SkPMColor16* row = this->addr16(0, y); 499cb93a386Sopenharmony_ci for (int x = 0; x < width; ++x) { 500cb93a386Sopenharmony_ci c &= row[x]; 501cb93a386Sopenharmony_ci } 502cb93a386Sopenharmony_ci if (0xF != SkGetPackedA4444(c)) { 503cb93a386Sopenharmony_ci return false; 504cb93a386Sopenharmony_ci } 505cb93a386Sopenharmony_ci } 506cb93a386Sopenharmony_ci return true; 507cb93a386Sopenharmony_ci } 508cb93a386Sopenharmony_ci case kBGRA_8888_SkColorType: 509cb93a386Sopenharmony_ci case kRGBA_8888_SkColorType: 510cb93a386Sopenharmony_ci case kSRGBA_8888_SkColorType: { 511cb93a386Sopenharmony_ci SkPMColor c = (SkPMColor)~0; 512cb93a386Sopenharmony_ci for (int y = 0; y < height; ++y) { 513cb93a386Sopenharmony_ci const SkPMColor* row = this->addr32(0, y); 514cb93a386Sopenharmony_ci for (int x = 0; x < width; ++x) { 515cb93a386Sopenharmony_ci c &= row[x]; 516cb93a386Sopenharmony_ci } 517cb93a386Sopenharmony_ci if (0xFF != SkGetPackedA32(c)) { 518cb93a386Sopenharmony_ci return false; 519cb93a386Sopenharmony_ci } 520cb93a386Sopenharmony_ci } 521cb93a386Sopenharmony_ci return true; 522cb93a386Sopenharmony_ci } 523cb93a386Sopenharmony_ci case kRGBA_F16Norm_SkColorType: 524cb93a386Sopenharmony_ci case kRGBA_F16_SkColorType: { 525cb93a386Sopenharmony_ci const SkHalf* row = (const SkHalf*)this->addr(); 526cb93a386Sopenharmony_ci for (int y = 0; y < height; ++y) { 527cb93a386Sopenharmony_ci for (int x = 0; x < width; ++x) { 528cb93a386Sopenharmony_ci if (row[4 * x + 3] < SK_Half1) { 529cb93a386Sopenharmony_ci return false; 530cb93a386Sopenharmony_ci } 531cb93a386Sopenharmony_ci } 532cb93a386Sopenharmony_ci row += this->rowBytes() >> 1; 533cb93a386Sopenharmony_ci } 534cb93a386Sopenharmony_ci return true; 535cb93a386Sopenharmony_ci } 536cb93a386Sopenharmony_ci case kRGBA_F32_SkColorType: { 537cb93a386Sopenharmony_ci const float* row = (const float*)this->addr(); 538cb93a386Sopenharmony_ci for (int y = 0; y < height; ++y) { 539cb93a386Sopenharmony_ci for (int x = 0; x < width; ++x) { 540cb93a386Sopenharmony_ci if (row[4 * x + 3] < 1.0f) { 541cb93a386Sopenharmony_ci return false; 542cb93a386Sopenharmony_ci } 543cb93a386Sopenharmony_ci } 544cb93a386Sopenharmony_ci row += this->rowBytes() >> 2; 545cb93a386Sopenharmony_ci } 546cb93a386Sopenharmony_ci return true; 547cb93a386Sopenharmony_ci } 548cb93a386Sopenharmony_ci case kRGBA_1010102_SkColorType: 549cb93a386Sopenharmony_ci case kBGRA_1010102_SkColorType: { 550cb93a386Sopenharmony_ci uint32_t c = ~0; 551cb93a386Sopenharmony_ci for (int y = 0; y < height; ++y) { 552cb93a386Sopenharmony_ci const uint32_t* row = this->addr32(0, y); 553cb93a386Sopenharmony_ci for (int x = 0; x < width; ++x) { 554cb93a386Sopenharmony_ci c &= row[x]; 555cb93a386Sopenharmony_ci } 556cb93a386Sopenharmony_ci if (0b11 != c >> 30) { 557cb93a386Sopenharmony_ci return false; 558cb93a386Sopenharmony_ci } 559cb93a386Sopenharmony_ci } 560cb93a386Sopenharmony_ci return true; 561cb93a386Sopenharmony_ci } 562cb93a386Sopenharmony_ci case kR16G16B16A16_unorm_SkColorType: { 563cb93a386Sopenharmony_ci uint16_t acc = 0xFFFF; 564cb93a386Sopenharmony_ci for (int y = 0; y < height; ++y) { 565cb93a386Sopenharmony_ci const uint64_t* row = this->addr64(0, y); 566cb93a386Sopenharmony_ci for (int x = 0; x < width; ++x) { 567cb93a386Sopenharmony_ci acc &= (row[x] >> 48); 568cb93a386Sopenharmony_ci } 569cb93a386Sopenharmony_ci if (0xFFFF != acc) { 570cb93a386Sopenharmony_ci return false; 571cb93a386Sopenharmony_ci } 572cb93a386Sopenharmony_ci } 573cb93a386Sopenharmony_ci return true; 574cb93a386Sopenharmony_ci } 575cb93a386Sopenharmony_ci case kUnknown_SkColorType: 576cb93a386Sopenharmony_ci SkDEBUGFAIL(""); 577cb93a386Sopenharmony_ci break; 578cb93a386Sopenharmony_ci } 579cb93a386Sopenharmony_ci return false; 580cb93a386Sopenharmony_ci} 581cb93a386Sopenharmony_ci 582cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////////////////////////// 583cb93a386Sopenharmony_ci 584cb93a386Sopenharmony_cistatic bool draw_orientation(const SkPixmap& dst, const SkPixmap& src, SkEncodedOrigin origin) { 585cb93a386Sopenharmony_ci auto surf = SkSurface::MakeRasterDirect(dst.info(), dst.writable_addr(), dst.rowBytes()); 586cb93a386Sopenharmony_ci if (!surf) { 587cb93a386Sopenharmony_ci return false; 588cb93a386Sopenharmony_ci } 589cb93a386Sopenharmony_ci 590cb93a386Sopenharmony_ci SkBitmap bm; 591cb93a386Sopenharmony_ci bm.installPixels(src); 592cb93a386Sopenharmony_ci 593cb93a386Sopenharmony_ci SkMatrix m = SkEncodedOriginToMatrix(origin, dst.width(), dst.height()); 594cb93a386Sopenharmony_ci 595cb93a386Sopenharmony_ci SkPaint p; 596cb93a386Sopenharmony_ci p.setBlendMode(SkBlendMode::kSrc); 597cb93a386Sopenharmony_ci surf->getCanvas()->concat(m); 598cb93a386Sopenharmony_ci surf->getCanvas()->drawImage(SkImage::MakeFromBitmap(bm), 0, 0, SkSamplingOptions(), &p); 599cb93a386Sopenharmony_ci return true; 600cb93a386Sopenharmony_ci} 601cb93a386Sopenharmony_ci 602cb93a386Sopenharmony_cibool SkPixmapPriv::Orient(const SkPixmap& dst, const SkPixmap& src, SkEncodedOrigin origin) { 603cb93a386Sopenharmony_ci if (src.colorType() != dst.colorType()) { 604cb93a386Sopenharmony_ci return false; 605cb93a386Sopenharmony_ci } 606cb93a386Sopenharmony_ci // note: we just ignore alphaType and colorSpace for this transformation 607cb93a386Sopenharmony_ci 608cb93a386Sopenharmony_ci int w = src.width(); 609cb93a386Sopenharmony_ci int h = src.height(); 610cb93a386Sopenharmony_ci if (SkEncodedOriginSwapsWidthHeight(origin)) { 611cb93a386Sopenharmony_ci using std::swap; 612cb93a386Sopenharmony_ci swap(w, h); 613cb93a386Sopenharmony_ci } 614cb93a386Sopenharmony_ci if (dst.width() != w || dst.height() != h) { 615cb93a386Sopenharmony_ci return false; 616cb93a386Sopenharmony_ci } 617cb93a386Sopenharmony_ci if (w == 0 || h == 0) { 618cb93a386Sopenharmony_ci return true; 619cb93a386Sopenharmony_ci } 620cb93a386Sopenharmony_ci 621cb93a386Sopenharmony_ci // check for aliasing to self 622cb93a386Sopenharmony_ci if (src.addr() == dst.addr()) { 623cb93a386Sopenharmony_ci return kTopLeft_SkEncodedOrigin == origin; 624cb93a386Sopenharmony_ci } 625cb93a386Sopenharmony_ci return draw_orientation(dst, src, origin); 626cb93a386Sopenharmony_ci} 627cb93a386Sopenharmony_ci 628cb93a386Sopenharmony_ciSkImageInfo SkPixmapPriv::SwapWidthHeight(const SkImageInfo& info) { 629cb93a386Sopenharmony_ci return info.makeWH(info.height(), info.width()); 630cb93a386Sopenharmony_ci} 631cb93a386Sopenharmony_ci 632