Add support for row-by-row png encodes

Also adds a SkEncoder base class.

Bug: 713862
Change-Id: Ia3f009cd9f376514f6c19396245fab3a43ae6536
Reviewed-on: https://skia-review.googlesource.com/15152
Reviewed-by: Leon Scroggins <scroggo@google.com>
Commit-Queue: Matt Sarett <msarett@google.com>
diff --git a/tests/CodecTest.cpp b/tests/CodecTest.cpp
index 45362db..4303521 100644
--- a/tests/CodecTest.cpp
+++ b/tests/CodecTest.cpp
@@ -22,6 +22,7 @@
 #include "SkOSPath.h"
 #include "SkJpegEncoder.h"
 #include "SkPngChunkReader.h"
+#include "SkPngEncoder.h"
 #include "SkRandom.h"
 #include "SkStream.h"
 #include "SkStreamPriv.h"
@@ -1525,16 +1526,21 @@
 }
 
 static void encode_format(SkDynamicMemoryWStream* stream, const SkPixmap& pixmap,
-                          const SkEncodeOptions& opts, SkEncodedImageFormat format) {
+                          SkTransferFunctionBehavior unpremulBehavior,
+                          SkEncodedImageFormat format) {
+    SkPngEncoder::Options pngOptions;
+    SkEncodeOptions options;
+    pngOptions.fUnpremulBehavior = unpremulBehavior;
+    options.fUnpremulBehavior = unpremulBehavior;
     switch (format) {
         case SkEncodedImageFormat::kPNG:
-            SkEncodeImageAsPNG(stream, pixmap, opts);
+            SkPngEncoder::Encode(stream, pixmap, pngOptions);
             break;
         case SkEncodedImageFormat::kJPEG:
             SkJpegEncoder::Encode(stream, pixmap, SkJpegEncoder::Options());
             break;
         case SkEncodedImageFormat::kWEBP:
-            SkEncodeImageAsWEBP(stream, pixmap, opts);
+            SkEncodeImageAsWEBP(stream, pixmap, options);
             break;
         default:
             SkASSERT(false);
@@ -1552,9 +1558,7 @@
     SkPixmap pixmap;
     srgbBitmap.peekPixels(&pixmap);
     SkDynamicMemoryWStream srgbBuf;
-    SkEncodeOptions opts;
-    opts.fUnpremulBehavior = unpremulBehavior;
-    encode_format(&srgbBuf, pixmap, opts, format);
+    encode_format(&srgbBuf, pixmap, unpremulBehavior, format);
     sk_sp<SkData> srgbData = srgbBuf.detachAsData();
     std::unique_ptr<SkCodec> srgbCodec(SkCodec::NewFromData(srgbData));
     REPORTER_ASSERT(r, srgbCodec->getInfo().colorSpace() == SkColorSpace::MakeSRGB().get());
@@ -1564,7 +1568,7 @@
     sk_sp<SkColorSpace> p3 = SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
                                                    SkColorSpace::kDCIP3_D65_Gamut);
     pixmap.setColorSpace(p3);
-    encode_format(&p3Buf, pixmap, opts, format);
+    encode_format(&p3Buf, pixmap, unpremulBehavior, format);
     sk_sp<SkData> p3Data = p3Buf.detachAsData();
     std::unique_ptr<SkCodec> p3Codec(SkCodec::NewFromData(p3Data));
     REPORTER_ASSERT(r, p3Codec->getInfo().colorSpace()->gammaCloseToSRGB());
diff --git a/tests/EncodeTest.cpp b/tests/EncodeTest.cpp
index 9db5039..a3b39f2 100644
--- a/tests/EncodeTest.cpp
+++ b/tests/EncodeTest.cpp
@@ -9,10 +9,35 @@
 #include "Test.h"
 
 #include "SkBitmap.h"
+#include "SkEncodedImageFormat.h"
 #include "SkJpegEncoder.h"
+#include "SkPngEncoder.h"
 #include "SkStream.h"
 
-DEF_TEST(Encode_Jpeg, r) {
+static bool encode(SkEncodedImageFormat format, SkWStream* dst, const SkPixmap& src) {
+    switch (format) {
+        case SkEncodedImageFormat::kJPEG:
+            return SkJpegEncoder::Encode(dst, src, SkJpegEncoder::Options());
+        case SkEncodedImageFormat::kPNG:
+            return SkPngEncoder::Encode(dst, src, SkPngEncoder::Options());
+        default:
+            return nullptr;
+    }
+}
+
+static std::unique_ptr<SkEncoder> make(SkEncodedImageFormat format, SkWStream* dst,
+                                       const SkPixmap& src) {
+    switch (format) {
+        case SkEncodedImageFormat::kJPEG:
+            return SkJpegEncoder::Make(dst, src, SkJpegEncoder::Options());
+        case SkEncodedImageFormat::kPNG:
+            return SkPngEncoder::Make(dst, src, SkPngEncoder::Options());
+        default:
+            return nullptr;
+    }
+}
+
+static void test_encode(skiatest::Reporter* r, SkEncodedImageFormat format) {
     SkBitmap bitmap;
     bool success = GetResourceAsBitmap("mandrill_128.png", &bitmap);
     if (!success) {
@@ -27,22 +52,22 @@
     }
 
     SkDynamicMemoryWStream dst0, dst1, dst2, dst3;
-    success = SkJpegEncoder::Encode(&dst0, src, SkJpegEncoder::Options());
+    success = encode(format, &dst0, src);
     REPORTER_ASSERT(r, success);
 
-    auto encoder1 = SkJpegEncoder::Make(&dst1, src, SkJpegEncoder::Options());
+    auto encoder1 = make(format, &dst1, src);
     for (int i = 0; i < src.height(); i++) {
         success = encoder1->encodeRows(1);
         REPORTER_ASSERT(r, success);
     }
 
-    auto encoder2 = SkJpegEncoder::Make(&dst2, src, SkJpegEncoder::Options());
+    auto encoder2 = make(format, &dst2, src);
     for (int i = 0; i < src.height(); i+=3) {
         success = encoder2->encodeRows(3);
         REPORTER_ASSERT(r, success);
     }
 
-    auto encoder3 = SkJpegEncoder::Make(&dst3, src, SkJpegEncoder::Options());
+    auto encoder3 = make(format, &dst3, src);
     success = encoder3->encodeRows(200);
     REPORTER_ASSERT(r, success);
 
@@ -54,3 +79,8 @@
     REPORTER_ASSERT(r, data0->equals(data2.get()));
     REPORTER_ASSERT(r, data0->equals(data3.get()));
 }
+
+DEF_TEST(Encoder, r) {
+    test_encode(r, SkEncodedImageFormat::kJPEG);
+    test_encode(r, SkEncodedImageFormat::kPNG);
+}