sk_sp<SkData> encode_bitmap_for_png(SkBitmap bitmap) { const int w = bitmap.width(), h = bitmap.height(); // PNG wants unpremultiplied 8-bit RGBA pixels (16-bit could work fine too). // We leave the gamma of these bytes unspecified, to continue the status quo, // which we think generally is to interpret them as sRGB. SkAutoTMalloc<uint32_t> rgba(w*h); auto srgbColorSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named); if (bitmap. colorType() == kN32_SkColorType && bitmap.colorSpace() == srgbColorSpace.get()) { // These are premul sRGB 8-bit pixels in SkPMColor order. // We want unpremul sRGB 8-bit pixels in RGBA order. We'll get there via floats. bitmap.lockPixels(); auto px = (const uint32_t*)bitmap.getPixels(); if (!px) { return nullptr; } for (int i = 0; i < w*h; i++) { Sk4f fs = Sk4f_fromS32(px[i]); // Convert up to linear floats. #if defined(SK_PMCOLOR_IS_BGRA) fs = SkNx_shuffle<2,1,0,3>(fs); // Shuffle to RGBA, if not there already. #endif float invA = 1.0f / fs[3]; fs = fs * Sk4f(invA, invA, invA, 1); // Unpremultiply. rgba[i] = Sk4f_toS32(fs); // Pack down to sRGB bytes. } } else if (bitmap.colorType() == kRGBA_F16_SkColorType) { // These are premul linear half-float pixels in RGBA order. // We want unpremul sRGB 8-bit pixels in RGBA order. We'll get there via floats. bitmap.lockPixels(); auto px = (const uint64_t*)bitmap.getPixels(); if (!px) { return nullptr; } for (int i = 0; i < w*h; i++) { // Convert up to linear floats. Sk4f fs(SkHalfToFloat(static_cast<SkHalf>(px[i] >> (0 * 16))), SkHalfToFloat(static_cast<SkHalf>(px[i] >> (1 * 16))), SkHalfToFloat(static_cast<SkHalf>(px[i] >> (2 * 16))), SkHalfToFloat(static_cast<SkHalf>(px[i] >> (3 * 16)))); fs = Sk4f::Max(0.0f, Sk4f::Min(fs, 1.0f)); // Clamp float invA = 1.0f / fs[3]; fs = fs * Sk4f(invA, invA, invA, 1); // Unpremultiply. rgba[i] = Sk4f_toS32(fs); // Pack down to sRGB bytes. } } else {
static void clear_srgb(const SkXfermode*, uint32_t dst[], const SkPM4f[], int count, const SkAlpha aa[]) { if (aa) { for (int i = 0; i < count; ++i) { if (aa[i]) { Sk4f d = Sk4f_fromS32(dst[i]) * Sk4f((255 - aa[i]) * (1/255.0f)); dst[i] = Sk4f_toS32(d); } } } else { sk_memset32(dst, 0, count); } }
static void clear_srgb_n(const SkXfermode::PM4fState& state, uint32_t dst[], const SkPM4f[], int count, const SkAlpha aa[]) { if (aa) { for (int i = 0; i < count; ++i) { unsigned a = aa[i]; if (a) { Sk4f d = Sk4f_fromS32(dst[i]) * Sk4f((255 - a) * (1/255.0f)); dst[i] = Sk4f_toS32(d); } } } else { sk_bzero(dst, count * sizeof(SkPMColor)); } }
SkColor SkColor4f::toSkColor() const { return Sk4f_toS32(swizzle_rb(Sk4f::Load(this->vec()))); }
static inline void brute_srcover_srgb_srgb_1(uint32_t* dst, uint32_t src) { auto d = Sk4f_fromS32(*dst), s = Sk4f_fromS32( src); *dst = Sk4f_toS32(s + d * (1.0f - s[3])); }
template <DstType D> uint32_t store_dst(const Sk4f& x4) { return (D == kSRGB_Dst) ? Sk4f_toS32(x4) : Sk4f_toL32(x4); }