Index: tools/picture_utils.cpp |
diff --git a/tools/picture_utils.cpp b/tools/picture_utils.cpp |
index 9661daf2d0af0768b5b9c9d55eaec714c9b3a5bc..63a48ce3e17b61749ecde00178d609fa98795fa3 100644 |
--- a/tools/picture_utils.cpp |
+++ b/tools/picture_utils.cpp |
@@ -8,8 +8,10 @@ |
#include "picture_utils.h" |
#include "SkBitmap.h" |
#include "SkColorPriv.h" |
+#include "SkHalf.h" |
#include "SkImageEncoder.h" |
#include "SkOSFile.h" |
+#include "SkPM4fPriv.h" |
#include "SkPicture.h" |
#include "SkStream.h" |
#include "SkString.h" |
@@ -69,4 +71,76 @@ namespace sk_tools { |
} |
} |
+ 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); |
+ |
+ if (bitmap. colorType() == kN32_SkColorType && |
+ bitmap.profileType() == kSRGB_SkColorProfileType) { |
+ // 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 { |
+ // We "should" gamma correct in here but we don't. |
+ // We want Gold to show exactly what our clients are seeing, broken gamma. |
+ |
+ // Convert smaller formats up to premul linear 8-bit (in SkPMColor order). |
+ if (bitmap.colorType() != kN32_SkColorType) { |
+ SkBitmap n32; |
+ if (!bitmap.copyTo(&n32, kN32_SkColorType)) { |
+ return nullptr; |
+ } |
+ bitmap = n32; |
+ } |
+ |
+ // Convert premul linear 8-bit to unpremul linear 8-bit RGBA. |
+ if (!bitmap.readPixels(SkImageInfo::Make(w,h, kRGBA_8888_SkColorType, |
+ kUnpremul_SkAlphaType), |
+ rgba, 4*w, 0,0)) { |
+ return nullptr; |
+ } |
+ } |
+ |
+ return SkData::MakeFromMalloc(rgba.release(), w*h*sizeof(uint32_t)); |
+ } |
+ |
} // namespace sk_tools |