From fc3341632fc04264e968bd1996ccb73b95088084 Mon Sep 17 00:00:00 2001 From: Mike Klein Date: Mon, 12 Jun 2017 08:59:16 -0400 Subject: port encode_bitmap_for_png() to SkRasterPipeline This logically shouldn't change anything, but it does a bit: - no diffs in 565 - sRGB and 8888 show minor diffs, only when unpremul is non-trivial - f16 shows minor diffs all over, and major ones in shallow gradients I think the shallow gradient diffs make sense. F16's high-precision is being quantized down to a much narrower range (something like 10-40 values), so where the lines are drawn between sRGB bits will come down to all sorts of things, especially rounding. Change-Id: I156b7c613b73d6d6089221e61d0c529798ac1f9f Reviewed-on: https://skia-review.googlesource.com/19449 Reviewed-by: Brian Osman Commit-Queue: Mike Klein --- tools/picture_utils.cpp | 89 ++++++++++++++++++------------------------------- 1 file changed, 32 insertions(+), 57 deletions(-) (limited to 'tools/picture_utils.cpp') diff --git a/tools/picture_utils.cpp b/tools/picture_utils.cpp index db245538d4..5e87639ffc 100644 --- a/tools/picture_utils.cpp +++ b/tools/picture_utils.cpp @@ -16,6 +16,7 @@ #include "SkPicture.h" #include "SkStream.h" #include "SkString.h" +#include "SkRasterPipeline.h" #include "sk_tool_utils.h" @@ -74,71 +75,45 @@ namespace sk_tools { sk_sp encode_bitmap_for_png(SkBitmap bitmap) { const int w = bitmap.width(), - h = bitmap.height(); + 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); - auto srgbColorSpace = SkColorSpace::MakeSRGB(); - 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. - 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. - } + const void* src = bitmap.getPixels(); + uint32_t* dst = rgba.get(); - } 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. - 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)))); - if (fs[3]) { // Unpremultiply. - fs *= Sk4f(1/fs[3], 1/fs[3], 1/fs[3], 1); - } - fs = Sk4f::Max(0.0f, Sk4f::Min(fs, 1.0f)); // Clamp to [0,1]. - 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 (!sk_tool_utils::copy_to(&n32, kN32_SkColorType, bitmap)) { - return nullptr; - } - bitmap = n32; - } + SkRasterPipeline_<256> p; + switch (bitmap.colorType()) { + case kRGBA_F16_SkColorType: p.append(SkRasterPipeline::load_f16, &src); break; + case kRGBA_8888_SkColorType: + case kBGRA_8888_SkColorType: p.append(SkRasterPipeline::load_8888, &src); break; + case kRGB_565_SkColorType: p.append(SkRasterPipeline::load_565, &src); break; + default: SkASSERT(false); // DM doesn't support any other formats, does it? + } + if (bitmap.info().gammaCloseToSRGB()) { + p.append(SkRasterPipeline::from_srgb); + } + if (bitmap.colorType() == kBGRA_8888_SkColorType) { + p.append(SkRasterPipeline::swap_rb); + } + p.append(SkRasterPipeline::unpremul); + p.append(SkRasterPipeline::clamp_0); + p.append(SkRasterPipeline::clamp_1); + if (bitmap.info().colorSpace()) { + // We leave legacy modes as-is. They're already sRGB encoded (kind of). + p.append(SkRasterPipeline::to_srgb); + } + p.append(SkRasterPipeline::store_8888, &dst); - // 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; - } + auto run = p.compile(); + for (int y = 0; y < h; y++) { + run(0,y, w); + src = SkTAddOffset(src, bitmap.rowBytes()); + dst += w; } return SkData::MakeFromMalloc(rgba.release(), w*h*sizeof(uint32_t)); -- cgit v1.2.3