Have DM manually encode its .png outputs.

This eliminates some variability on various axes: different PNG encoders, different libpng versions, different formats (RGB, indexed), different unpremultiplication, different sRGB tags.

BUG=skia:

Committed: https://skia.googlesource.com/skia/+/3cc0dfffb70c0bd08ed8899efcd2e98da86a6ec7

CQ_EXTRA_TRYBOTS=client.skia:Test-Win8-MSVC-ShuttleB-CPU-AVX2-x86_64-Debug-Trybot

Review URL: https://codereview.chromium.org/1304443002
diff --git a/dm/DM.cpp b/dm/DM.cpp
index c637edd..8537313 100644
--- a/dm/DM.cpp
+++ b/dm/DM.cpp
@@ -28,6 +28,12 @@
 #include "Timer.h"
 #include "sk_tool_utils.h"
 
+#ifdef SKIA_PNG_PREFIXED
+    // this must proceed png.h
+    #include "pngprefix.h"
+#endif
+#include "png.h"
+
 DEFINE_string(src, "tests gm skp image", "Source types to test.");
 DEFINE_bool(nameByHash, false,
             "If true, write to FLAGS_writePath[0]/<hash>.png instead of "
@@ -466,6 +472,70 @@
     }
 }
 
+static bool dump_png(SkBitmap bitmap, const char* path, const char* md5) {
+    const int w = bitmap.width(),
+              h = bitmap.height();
+
+    // First get the bitmap into N32 color format.  The next step will work only there.
+    if (bitmap.colorType() != kN32_SkColorType) {
+        SkBitmap n32;
+        if (!bitmap.copyTo(&n32, kN32_SkColorType)) {
+            return false;
+        }
+        bitmap = n32;
+    }
+
+    // Convert our N32 bitmap into unpremul RGBA for libpng.
+    SkAutoTMalloc<uint32_t> rgba(w*h);
+    if (!bitmap.readPixels(SkImageInfo::Make(w,h, kRGBA_8888_SkColorType, kUnpremul_SkAlphaType),
+                           rgba, 4*w, 0,0)) {
+        return false;
+    }
+
+    // We don't need bitmap anymore.  Might as well drop our ref.
+    bitmap = SkBitmap();
+
+    FILE* f = fopen(path, "w");
+    if (!f) { return false; }
+
+    png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
+    if (!png) {
+        fclose(f);
+        return false;
+    }
+
+    png_infop info = png_create_info_struct(png);
+    if (!info) {
+        png_destroy_write_struct(&png, &info);
+        fclose(f);
+        return false;
+    }
+
+    png_text text[2];
+    text[0].key = (png_charp)"Author";
+    text[0].text = (png_charp)"DM dump_png()";
+    text[0].compression = PNG_TEXT_COMPRESSION_NONE;
+    text[1].key = (png_charp)"Description";
+    text[1].text = (png_charp)md5;
+    text[1].compression = PNG_TEXT_COMPRESSION_NONE;
+    png_set_text(png, info, text, 2);
+
+    png_init_io(png, f);
+    png_set_IHDR(png, info, (png_uint_32)w, (png_uint_32)h, 8,
+                 PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
+                 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_write_rows(png, &row, 1);
+    }
+    png_write_end(png, info);
+
+    png_destroy_write_struct(&png, &info);
+    fclose(f);
+    return true;
+}
+
 static bool match(const char* needle, const char* haystack) {
     return 0 == strcmp("_", needle) || NULL != strstr(haystack, needle);
 }
@@ -635,27 +705,17 @@
             path.append(ext);
         }
 
-        SkFILEWStream file(path.c_str());
-        if (!file.isValid()) {
-            fail(SkStringPrintf("Can't open %s for writing.\n", path.c_str()));
-            return;
-        }
-
         if (bitmap) {
-            // We can't encode A8 bitmaps as PNGs.  Convert them to 8888 first.
-            SkBitmap converted;
-            if (bitmap->info().colorType() == kAlpha_8_SkColorType) {
-                if (!bitmap->copyTo(&converted, kN32_SkColorType)) {
-                    fail("Can't convert A8 to 8888.\n");
-                    return;
-                }
-                bitmap = &converted;
-            }
-            if (!SkImageEncoder::EncodeStream(&file, *bitmap, SkImageEncoder::kPNG_Type, 100)) {
+            if (!dump_png(*bitmap, path.c_str(), result.md5.c_str())) {
                 fail(SkStringPrintf("Can't encode PNG to %s.\n", path.c_str()));
                 return;
             }
         } else {
+            SkFILEWStream file(path.c_str());
+            if (!file.isValid()) {
+                fail(SkStringPrintf("Can't open %s for writing.\n", path.c_str()));
+                return;
+            }
             if (!file.writeStream(data, len)) {
                 fail(SkStringPrintf("Can't write to %s.\n", path.c_str()));
                 return;