From 3c579dcff81dab48a5fb3801d7a34f9c00256ec4 Mon Sep 17 00:00:00 2001 From: brianosman Date: Tue, 19 Apr 2016 09:18:11 -0700 Subject: Move DM png code to picture_utils, for use by other tools. Planning to re-use this code in skiaserve in an upcoming change. TBR=mtklein@google.com BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1901113002 Review URL: https://codereview.chromium.org/1901113002 --- dm/DM.cpp | 72 +++++------------------------------------------ gyp/dm.gypi | 1 + gyp/tools.gyp | 3 ++ tools/picture_utils.cpp | 74 +++++++++++++++++++++++++++++++++++++++++++++++++ tools/picture_utils.h | 10 ++++++- 5 files changed, 94 insertions(+), 66 deletions(-) diff --git a/dm/DM.cpp b/dm/DM.cpp index ecf231ed63..58cb773e03 100644 --- a/dm/DM.cpp +++ b/dm/DM.cpp @@ -17,6 +17,7 @@ #include "SkColorPriv.h" #include "SkCommonFlags.h" #include "SkCommonFlagsConfig.h" +#include "SkData.h" #include "SkFontMgr.h" #include "SkGraphics.h" #include "SkHalf.h" @@ -30,6 +31,7 @@ #include "SkThreadUtils.h" #include "Test.h" #include "Timer.h" +#include "picture_utils.h" #include "sk_tool_utils.h" #ifdef SK_PDF_IMAGE_STATS @@ -924,72 +926,12 @@ static void gather_sinks() { static bool dump_png(SkBitmap bitmap, const char* path, const char* md5) { 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 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 false; - } - 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 false; - } - for (int i = 0; i < w*h; i++) { - // Convert up to linear floats. - Sk4f fs(SkHalfToFloat(static_cast(px[i] >> (0 * 16))), - SkHalfToFloat(static_cast(px[i] >> (1 * 16))), - SkHalfToFloat(static_cast(px[i] >> (2 * 16))), - SkHalfToFloat(static_cast(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 false; - } - 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 false; - } + sk_sp encodedBitmap = sk_tools::encode_bitmap_for_png(bitmap); + if (encodedBitmap.get() == nullptr) { + return false; } + uint32_t* rgba = static_cast(encodedBitmap.get()->writable_data()); // We don't need bitmap anymore. Might as well drop our ref. bitmap.reset(); @@ -1036,7 +978,7 @@ static bool dump_png(SkBitmap bitmap, const char* path, const char* md5) { PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_write_info(png, info); for (int j = 0; j < h; j++) { - png_bytep row = (png_bytep)(rgba.get() + w*j); + png_bytep row = (png_bytep)(rgba + w*j); png_write_rows(png, &row, 1); } png_write_end(png, info); diff --git a/gyp/dm.gypi b/gyp/dm.gypi index 337bcccd7c..b14c87e5c6 100644 --- a/gyp/dm.gypi +++ b/gyp/dm.gypi @@ -24,6 +24,7 @@ 'skia_lib.gyp:skia_lib', 'svg.gyp:svg', 'tools.gyp:crash_handler', + 'tools.gyp:picture_utils', 'tools.gyp:proc_stats', 'tools.gyp:sk_tool_utils', 'tools.gyp:url_data_manager', diff --git a/gyp/tools.gyp b/gyp/tools.gyp index 190e1fe5a8..8af0dfd1ac 100644 --- a/gyp/tools.gyp +++ b/gyp/tools.gyp @@ -350,6 +350,9 @@ 'sources': [ '../tools/picture_utils.cpp', '../tools/picture_utils.h', + ], + 'include_dirs': [ + '../src/core/', ], 'dependencies': [ 'skia_lib.gyp:skia_lib', diff --git a/tools/picture_utils.cpp b/tools/picture_utils.cpp index 9661daf2d0..63a48ce3e1 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 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 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(px[i] >> (0 * 16))), + SkHalfToFloat(static_cast(px[i] >> (1 * 16))), + SkHalfToFloat(static_cast(px[i] >> (2 * 16))), + SkHalfToFloat(static_cast(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 diff --git a/tools/picture_utils.h b/tools/picture_utils.h index 1373020a5b..49a2c821a4 100644 --- a/tools/picture_utils.h +++ b/tools/picture_utils.h @@ -8,7 +8,9 @@ #ifndef picture_utils_DEFINED #define picture_utils_DEFINED -class SkBitmap; +#include "SkBitmap.h" + +class SkData; class SkString; namespace sk_tools { @@ -47,6 +49,12 @@ namespace sk_tools { bool write_bitmap_to_disk(const SkBitmap& bm, const SkString& dirPath, const char *subdirOrNull, const SkString& baseName); + // Return raw unpremultiplied RGBA bytes, suitable for storing in a PNG. The output + // colors are assumed to be sRGB values. This is only guaranteed to work for the + // cases that are currently emitted by tools: + // Linear premul 8888, sRGB premul 8888, Linear premul F16 + sk_sp encode_bitmap_for_png(SkBitmap bitmap); + } // namespace sk_tools #endif // picture_utils_DEFINED -- cgit v1.2.3