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
diff --git a/dm/DM.cpp b/dm/DM.cpp
index ecf231e..58cb773 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 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<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 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<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 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<SkData> encodedBitmap = sk_tools::encode_bitmap_for_png(bitmap);
+    if (encodedBitmap.get() == nullptr) {
+        return false;
     }
+    uint32_t* rgba = static_cast<uint32_t*>(encodedBitmap.get()->writable_data());
 
     // We don't need bitmap anymore.  Might as well drop our ref.
     bitmap.reset();
@@ -1036,7 +978,7 @@
                  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 337bccc..b14c87e 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 190e1fe..8af0dfd 100644
--- a/gyp/tools.gyp
+++ b/gyp/tools.gyp
@@ -351,6 +351,9 @@
         '../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 9661daf..63a48ce 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 @@
         }
     }
 
+    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
diff --git a/tools/picture_utils.h b/tools/picture_utils.h
index 1373020..49a2c82 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 @@
     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<SkData> encode_bitmap_for_png(SkBitmap bitmap);
+
 } // namespace sk_tools
 
 #endif  // picture_utils_DEFINED