SkImageEncoder: simplify API

  - Hide SkImageEncoder class in private header.
  - SkImageEncoder::Type becomes SkEncodedImageFormat
  - SkEncodedFormat becomes SkEncodedImageFormat
  - SkImageEncoder static functions replaced with
    single function EncodeImage()
  - utility wrappers for EncodeImage() are in
    sk_tool_utils.h

TODO: remove link-time registration mechanism.
TODO: clean up clients use of API and flip the flag.
TODO: implement EncodeImage() in chromeium/skia/ext

GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=4909

Change-Id: Ib48b31fdc05cf23cda7f56ebfd67c841c149ce70
Reviewed-on: https://skia-review.googlesource.com/4909
Reviewed-by: Mike Reed <reed@google.com>
Reviewed-by: Leon Scroggins <scroggo@google.com>
Commit-Queue: Hal Canary <halcanary@google.com>
diff --git a/BUILD.gn b/BUILD.gn
index c25458a..501c568 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -1242,6 +1242,7 @@
     deps = [
       ":flags",
       ":skia",
+      ":tool_utils",
     ]
     testonly = true
   }
diff --git a/bench/EncoderBench.cpp b/bench/EncoderBench.cpp
index d7ddfbc..f0adaa1 100644
--- a/bench/EncoderBench.cpp
+++ b/bench/EncoderBench.cpp
@@ -11,9 +11,11 @@
 #include "SkData.h"
 #include "SkImageEncoder.h"
 
+#include "sk_tool_utils.h"
+
 class EncodeBench : public Benchmark {
 public:
-    EncodeBench(const char* filename, SkImageEncoder::Type type, int quality)
+    EncodeBench(const char* filename, SkEncodedImageFormat type, int quality)
         : fFilename(filename)
         , fType(type)
         , fQuality(quality)
@@ -23,13 +25,13 @@
         name.append(filename);
         name.append("_");
         switch (type) {
-            case SkImageEncoder::kJPEG_Type:
+            case SkEncodedImageFormat::kJPEG:
                 name.append("JPEG");
                 break;
-            case SkImageEncoder::kPNG_Type:
+            case SkEncodedImageFormat::kPNG:
                 name.append("PNG");
                 break;
-            case SkImageEncoder::kWEBP_Type:
+            case SkEncodedImageFormat::kWEBP:
                 name.append("WEBP");
                 break;
             default:
@@ -54,14 +56,14 @@
 
     void onDraw(int loops, SkCanvas*) override {
         for (int i = 0; i < loops; i++) {
-            sk_sp<SkData> data(SkImageEncoder::EncodeData(fBitmap, fType, fQuality));
+            sk_sp<SkData> data(sk_tool_utils::EncodeImageToData(fBitmap, fType, fQuality));
             SkASSERT(data);
         }
     }
 
 private:
     const char*                fFilename;
-    const SkImageEncoder::Type fType;
+    const SkEncodedImageFormat fType;
     const int                  fQuality;
     SkString                   fName;
     SkBitmap                   fBitmap;
@@ -69,13 +71,13 @@
 
 
 // The Android Photos app uses a quality of 90 on JPEG encodes
-DEF_BENCH(return new EncodeBench("mandrill_512.png", SkImageEncoder::kJPEG_Type, 90));
-DEF_BENCH(return new EncodeBench("color_wheel.jpg", SkImageEncoder::kJPEG_Type, 90));
+DEF_BENCH(return new EncodeBench("mandrill_512.png", SkEncodedImageFormat::kJPEG, 90));
+DEF_BENCH(return new EncodeBench("color_wheel.jpg", SkEncodedImageFormat::kJPEG, 90));
 
 // PNG encodes are lossless so quality should be ignored
-DEF_BENCH(return new EncodeBench("mandrill_512.png", SkImageEncoder::kPNG_Type, 90));
-DEF_BENCH(return new EncodeBench("color_wheel.jpg", SkImageEncoder::kPNG_Type, 90));
+DEF_BENCH(return new EncodeBench("mandrill_512.png", SkEncodedImageFormat::kPNG, 90));
+DEF_BENCH(return new EncodeBench("color_wheel.jpg", SkEncodedImageFormat::kPNG, 90));
 
 // TODO: What is the appropriate quality to use to benchmark WEBP encodes?
-DEF_BENCH(return new EncodeBench("mandrill_512.png", SkImageEncoder::kWEBP_Type, 90));
-DEF_BENCH(return new EncodeBench("color_wheel.jpg", SkImageEncoder::kWEBP_Type, 90));
+DEF_BENCH(return new EncodeBench("mandrill_512.png", SkEncodedImageFormat::kWEBP, 90));
+DEF_BENCH(return new EncodeBench("color_wheel.jpg", SkEncodedImageFormat::kWEBP, 90));
diff --git a/bench/GLBench.cpp b/bench/GLBench.cpp
index a39edee..cb824da 100644
--- a/bench/GLBench.cpp
+++ b/bench/GLBench.cpp
@@ -15,6 +15,8 @@
 #include "SkSLCompiler.h"
 #include <stdio.h>
 
+#include "sk_tool_utils.h"
+
 const GrGLContext* GLBench::getGLContext(SkCanvas* canvas) {
     // This bench exclusively tests GL calls directly
     if (nullptr == canvas->getGrContext()) {
@@ -181,7 +183,7 @@
 
     bm.setPixels(readback.get());
 
-    if (!SkImageEncoder::EncodeFile(filename, bm, SkImageEncoder::kPNG_Type, 100)) {
+    if (!sk_tool_utils::EncodeImageToFile(filename, bm, SkEncodedImageFormat::kPNG, 100)) {
         SkDebugf("------ failed to encode %s\n", filename);
         remove(filename);   // remove any partial file
         return;
diff --git a/bench/nanobench.cpp b/bench/nanobench.cpp
index 9b4db96..3587242 100644
--- a/bench/nanobench.cpp
+++ b/bench/nanobench.cpp
@@ -300,7 +300,7 @@
         SkDebugf("Can't write %s.\n", filename.c_str());
         return false;
     }
-    if (!SkImageEncoder::EncodeStream(&stream, bmp, SkImageEncoder::kPNG_Type, 100)) {
+    if (!SkEncodeImage(&stream, bmp, SkEncodedImageFormat::kPNG, 100)) {
         SkDebugf("Can't encode a PNG.\n");
         return false;
     }
diff --git a/cmake/example.cpp b/cmake/example.cpp
index 38ce901..ca6e55e 100644
--- a/cmake/example.cpp
+++ b/cmake/example.cpp
@@ -82,7 +82,7 @@
     // Grab a snapshot of the surface as an immutable SkImage.
     sk_sp<SkImage> image = surface->makeImageSnapshot();
     // Encode that image as a .png into a blob in memory.
-    std::shared_ptr<SkData> png = adopt(image->encode(SkImageEncoder::kPNG_Type, 100));
+    std::shared_ptr<SkData> png = adopt(image->encode(SkEncodedImageFormat::kPNG, 100));
 
     // This code is no longer Skia-specific.  We just dump the .png to disk.  Any way works.
     static const char* path = "example.png";
diff --git a/debugger/QT/SkDebuggerGUI.cpp b/debugger/QT/SkDebuggerGUI.cpp
index 1437faf..6013183 100644
--- a/debugger/QT/SkDebuggerGUI.cpp
+++ b/debugger/QT/SkDebuggerGUI.cpp
@@ -281,8 +281,7 @@
     SkFILEWStream file(filename.c_str());
     sk_sp<SkPicture> copy(fDebugger.copyPicture());
 
-    sk_sp<SkPixelSerializer> serializer(
-            SkImageEncoder::CreatePixelSerializer());
+    sk_sp<SkPixelSerializer> serializer(sk_tool_utils::MakePixelSerializer());
     copy->serialize(&file, serializer.get());
 }
 
diff --git a/dm/DM.cpp b/dm/DM.cpp
index d42a5f0..c3e3af4 100644
--- a/dm/DM.cpp
+++ b/dm/DM.cpp
@@ -524,17 +524,17 @@
     nativeModes.push_back(CodecSrc::kCodec_Mode);
     nativeModes.push_back(CodecSrc::kCodecZeroInit_Mode);
     switch (codec->getEncodedFormat()) {
-        case SkEncodedFormat::kJPEG_SkEncodedFormat:
+        case SkEncodedImageFormat::kJPEG:
             nativeModes.push_back(CodecSrc::kScanline_Mode);
             nativeModes.push_back(CodecSrc::kStripe_Mode);
             nativeModes.push_back(CodecSrc::kCroppedScanline_Mode);
             supportsNativeScaling = true;
             break;
-        case SkEncodedFormat::kWEBP_SkEncodedFormat:
+        case SkEncodedImageFormat::kWEBP:
             nativeModes.push_back(CodecSrc::kSubset_Mode);
             supportsNativeScaling = true;
             break;
-        case SkEncodedFormat::kDNG_SkEncodedFormat:
+        case SkEncodedImageFormat::kDNG:
             break;
         default:
             nativeModes.push_back(CodecSrc::kScanline_Mode);
@@ -547,7 +547,7 @@
     switch (codec->getInfo().colorType()) {
         case kGray_8_SkColorType:
             colorTypes.push_back(CodecSrc::kGrayscale_Always_DstColorType);
-            if (kWBMP_SkEncodedFormat == codec->getEncodedFormat()) {
+            if (SkEncodedImageFormat::kWBMP == codec->getEncodedFormat()) {
                 colorTypes.push_back(CodecSrc::kIndex8_Always_DstColorType);
             }
             break;
@@ -640,15 +640,15 @@
         push_image_gen_src(path, ImageGenSrc::kCodec_Mode, alphaType, false);
 
 #if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
-        if (kWEBP_SkEncodedFormat != codec->getEncodedFormat() &&
-            kWBMP_SkEncodedFormat != codec->getEncodedFormat() &&
+        if (SkEncodedImageFormat::kWEBP != codec->getEncodedFormat() &&
+            SkEncodedImageFormat::kWBMP != codec->getEncodedFormat() &&
             kUnpremul_SkAlphaType != alphaType)
         {
             push_image_gen_src(path, ImageGenSrc::kPlatform_Mode, alphaType, false);
         }
 #elif defined(SK_BUILD_FOR_WIN)
-        if (kWEBP_SkEncodedFormat != codec->getEncodedFormat() &&
-            kWBMP_SkEncodedFormat != codec->getEncodedFormat())
+        if (SkEncodedImageFormat::kWEBP != codec->getEncodedFormat() &&
+            SkEncodedImageFormat::kWBMP != codec->getEncodedFormat())
         {
             push_image_gen_src(path, ImageGenSrc::kPlatform_Mode, alphaType, false);
         }
diff --git a/fuzz/fuzz.cpp b/fuzz/fuzz.cpp
index 377e53f..b27eec9 100644
--- a/fuzz/fuzz.cpp
+++ b/fuzz/fuzz.cpp
@@ -23,6 +23,8 @@
 
 #include <signal.h>
 
+#include "sk_tool_utils.h"
+
 DEFINE_string2(bytes, b, "", "A path to a file.  This can be the fuzz bytes or a binary to parse.");
 DEFINE_string2(name, n, "", "If --type is 'api', fuzz the API with this name.");
 
@@ -122,7 +124,7 @@
 
 static void dump_png(SkBitmap bitmap) {
     if (!FLAGS_dump.isEmpty()) {
-        SkImageEncoder::EncodeFile(FLAGS_dump[0], bitmap, SkImageEncoder::kPNG_Type, 100);
+        sk_tool_utils::EncodeImageToFile(FLAGS_dump[0], bitmap, SkEncodedImageFormat::kPNG, 100);
         SkDebugf("Dumped to %s\n", FLAGS_dump[0]);
     }
 }
diff --git a/gm/encode-platform.cpp b/gm/encode-platform.cpp
index 09b64cc..0357298 100644
--- a/gm/encode-platform.cpp
+++ b/gm/encode-platform.cpp
@@ -6,10 +6,11 @@
  */
 
 #include "gm.h"
+
 #include "Resources.h"
 #include "SkCanvas.h"
 #include "SkData.h"
-#include "SkImageEncoder.h"
+#include "SkImageEncoderPriv.h"
 #include "SkUnPreMultiply.h"
 
 namespace skiagm {
@@ -36,18 +37,18 @@
     bitmap->setAlphaType(kUnpremul_SkAlphaType);
 }
 
-static SkImageEncoder* make_encoder(SkImageEncoder::Type type) {
+static SkImageEncoder* make_encoder(SkEncodedImageFormat type) {
 #if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
-    return CreateImageEncoder_CG(type);
+    return CreateImageEncoder_CG((SkImageEncoder::Type)type);
 #elif defined(SK_BUILD_FOR_WIN)
-    return CreateImageEncoder_WIC(type);
+    return CreateImageEncoder_WIC((SkImageEncoder::Type)type);
 #else
     switch (type) {
-        case SkImageEncoder::kPNG_Type:
+        case SkEncodedImageFormat::kPNG:
             return CreatePNGImageEncoder();
-        case SkImageEncoder::kJPEG_Type:
+        case SkEncodedImageFormat::kJPEG:
             return CreateJPEGImageEncoder();
-        case SkImageEncoder::kWEBP_Type:
+        case SkEncodedImageFormat::kWEBP:
             return CreateWEBPImageEncoder();
         default:
             SkASSERT(false);
@@ -57,24 +58,28 @@
 }
 
 #if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
-static SkImageEncoder::Type kTypes[] {
-        SkImageEncoder::kPNG_Type, SkImageEncoder::kJPEG_Type, SkImageEncoder::kGIF_Type,
-        SkImageEncoder::kBMP_Type, SkImageEncoder::kICO_Type,
+static SkEncodedImageFormat kTypes[] {
+        SkEncodedImageFormat::kPNG, SkEncodedImageFormat::kJPEG, SkEncodedImageFormat::kGIF,
+        SkEncodedImageFormat::kBMP, SkEncodedImageFormat::kICO,
 };
 #elif defined(SK_BUILD_FOR_WIN)
 // Use PNG multiple times because our WIC encoder does not support GIF, BMP, or ICO.
-static SkImageEncoder::Type kTypes[] {
-        SkImageEncoder::kPNG_Type, SkImageEncoder::kJPEG_Type, SkImageEncoder::kPNG_Type,
-        SkImageEncoder::kPNG_Type, SkImageEncoder::kPNG_Type,
+static SkEncodedImageFormat kTypes[] {
+        SkEncodedImageFormat::kPNG, SkEncodedImageFormat::kJPEG, SkEncodedImageFormat::kPNG,
+        SkEncodedImageFormat::kPNG, SkEncodedImageFormat::kPNG,
 };
 #else
 // Use WEBP in place of GIF.  Use PNG two extra times.  We don't support GIF, BMP, or ICO.
-static SkImageEncoder::Type kTypes[] {
-        SkImageEncoder::kPNG_Type, SkImageEncoder::kJPEG_Type, SkImageEncoder::kWEBP_Type,
-        SkImageEncoder::kPNG_Type, SkImageEncoder::kPNG_Type,
+static SkEncodedImageFormat kTypes[] {
+        SkEncodedImageFormat::kPNG, SkEncodedImageFormat::kJPEG, SkEncodedImageFormat::kWEBP,
+        SkEncodedImageFormat::kPNG, SkEncodedImageFormat::kPNG,
 };
 #endif
 
+static sk_sp<SkData> encode_data(std::unique_ptr<SkImageEncoder>& encoder, const SkBitmap& src) {
+    SkDynamicMemoryWStream buffer;
+    return encoder->encodeStream(&buffer, src, 100) ? buffer.detachAsData() : nullptr;
+}
 
 class EncodePlatformGM : public GM {
 public:
@@ -95,15 +100,12 @@
         make_premul_256(&premulBm);
         make_unpremul_256(&unpremulBm);
 
-        for (SkImageEncoder::Type type : kTypes) {
+        for (SkEncodedImageFormat type : kTypes) {
             std::unique_ptr<SkImageEncoder> encoder(make_encoder(type));
-            sk_sp<SkData> opaqueData(encoder->encodeData(opaqueBm, 100));
-            sk_sp<SkData> premulData(encoder->encodeData(premulBm, 100));
-            sk_sp<SkData> unpremulData(encoder->encodeData(unpremulBm, 100));
 
-            sk_sp<SkImage> opaqueImage = SkImage::MakeFromEncoded(opaqueData);
-            sk_sp<SkImage> premulImage = SkImage::MakeFromEncoded(premulData);
-            sk_sp<SkImage> unpremulImage = SkImage::MakeFromEncoded(unpremulData);
+            auto opaqueImage = SkImage::MakeFromEncoded(encode_data(encoder, opaqueBm));
+            auto premulImage = SkImage::MakeFromEncoded(encode_data(encoder, premulBm));
+            auto unpremulImage = SkImage::MakeFromEncoded(encode_data(encoder, unpremulBm));
 
             canvas->drawImage(opaqueImage.get(), 0.0f, 0.0f);
             canvas->drawImage(premulImage.get(), 0.0f, 256.0f);
diff --git a/gm/encode.cpp b/gm/encode.cpp
index 0cd562a..d4598d0 100644
--- a/gm/encode.cpp
+++ b/gm/encode.cpp
@@ -28,8 +28,8 @@
     void onDraw(SkCanvas* canvas) override {
         SkBitmap orig;
         GetResourceAsBitmap("mandrill_512_q075.jpg", &orig);
-        sk_sp<SkData> pngData(SkImageEncoder::EncodeData(orig, SkImageEncoder::kPNG_Type, 100));
-        sk_sp<SkData> jpegData(SkImageEncoder::EncodeData(orig, SkImageEncoder::kJPEG_Type, 100));
+        sk_sp<SkData> pngData(sk_tool_utils::EncodeImageToData(orig, SkEncodedImageFormat::kPNG, 100));
+        sk_sp<SkData> jpegData(sk_tool_utils::EncodeImageToData(orig, SkEncodedImageFormat::kJPEG, 100));
 
         sk_sp<SkImage> pngImage = SkImage::MakeFromEncoded(pngData);
         sk_sp<SkImage> jpegImage = SkImage::MakeFromEncoded(jpegData);
diff --git a/gm/image.cpp b/gm/image.cpp
index 5454ac3..6545c0a 100644
--- a/gm/image.cpp
+++ b/gm/image.cpp
@@ -348,13 +348,13 @@
 
 static SkImageGenerator* gen_png(const SkImageInfo& info) {
     sk_sp<SkImage> image(make_raster(info, nullptr, draw_opaque_contents));
-    sk_sp<SkData> data(image->encode(SkImageEncoder::kPNG_Type, 100));
+    sk_sp<SkData> data(image->encode(SkEncodedImageFormat::kPNG, 100));
     return SkImageGenerator::NewFromEncoded(data.get());
 }
 
 static SkImageGenerator* gen_jpg(const SkImageInfo& info) {
     sk_sp<SkImage> image(make_raster(info, nullptr, draw_opaque_contents));
-    sk_sp<SkData> data(image->encode(SkImageEncoder::kJPEG_Type, 100));
+    sk_sp<SkData> data(image->encode(SkEncodedImageFormat::kJPEG, 100));
     return SkImageGenerator::NewFromEncoded(data.get());
 }
 
@@ -467,7 +467,7 @@
         // Create encoded image.
         [bmp] {
             sk_sp<SkData> src(
-                SkImageEncoder::EncodeData(bmp, SkImageEncoder::kPNG_Type, 100));
+                sk_tool_utils::EncodeImageToData(bmp, SkEncodedImageFormat::kPNG, 100));
             return SkImage::MakeFromEncoded(std::move(src));
         },
         // Create a picture image.
diff --git a/gm/image_shader.cpp b/gm/image_shader.cpp
index 924199e..49b1ed5 100644
--- a/gm/image_shader.cpp
+++ b/gm/image_shader.cpp
@@ -55,7 +55,7 @@
     if (!src) {
         return nullptr;
     }
-    sk_sp<SkData> encoded(src->encode(SkImageEncoder::kPNG_Type, 100));
+    sk_sp<SkData> encoded(src->encode(SkEncodedImageFormat::kPNG, 100));
     if (!encoded) {
         return nullptr;
     }
diff --git a/gn/android_framework_defines.gni b/gn/android_framework_defines.gni
index 90fea2f..a80e38d 100644
--- a/gn/android_framework_defines.gni
+++ b/gn/android_framework_defines.gni
@@ -14,5 +14,6 @@
   "SK_IGNORE_GPU_DITHER",
   "SK_SUPPORT_LEGACY_CANVAS_IS_REFCNT",
   "SK_SUPPORT_LEGACY_CLIP_REGIONOPS",
+  "SK_SUPPORT_LEGACY_IMAGE_ENCODER_CLASS",
   "SK_SUPPORT_LEGACY_SHADER_ISABITMAP",
 ]
diff --git a/include/codec/SkAndroidCodec.h b/include/codec/SkAndroidCodec.h
index 07d1b13..ee9d0f3 100644
--- a/include/codec/SkAndroidCodec.h
+++ b/include/codec/SkAndroidCodec.h
@@ -51,7 +51,7 @@
     /**
      *  Format of the encoded data.
      */
-    SkEncodedFormat getEncodedFormat() const { return fCodec->getEncodedFormat(); }
+    SkEncodedFormat getEncodedFormat() const { return (SkEncodedFormat)fCodec->getEncodedFormat(); }
 
     /**
      *  @param requestedColorType Color type requested by the client
@@ -154,7 +154,7 @@
          *
          *  Must be within the bounds returned by getInfo().
          *
-         *  If the EncodedFormat is kWEBP_SkEncodedFormat, the top and left
+         *  If the EncodedFormat is SkEncodedImageFormat::kWEBP, the top and left
          *  values must be even.
          *
          *  The default is NULL, meaning a decode of the entire image.
diff --git a/include/codec/SkCodec.h b/include/codec/SkCodec.h
index d5280b4..ebc2b9a 100644
--- a/include/codec/SkCodec.h
+++ b/include/codec/SkCodec.h
@@ -10,7 +10,7 @@
 
 #include "../private/SkTemplates.h"
 #include "SkColor.h"
-#include "SkEncodedFormat.h"
+#include "SkEncodedImageFormat.h"
 #include "SkEncodedInfo.h"
 #include "SkImageInfo.h"
 #include "SkSize.h"
@@ -176,7 +176,7 @@
     /**
      *  Format of the encoded data.
      */
-    SkEncodedFormat getEncodedFormat() const { return this->onGetEncodedFormat(); }
+    SkEncodedImageFormat getEncodedFormat() const { return this->onGetEncodedFormat(); }
 
     /**
      *  Used to describe the result of a call to getPixels().
@@ -255,7 +255,7 @@
         /**
          *  If not NULL, represents a subset of the original image to decode.
          *  Must be within the bounds returned by getInfo().
-         *  If the EncodedFormat is kWEBP_SkEncodedFormat (the only one which
+         *  If the EncodedFormat is SkEncodedImageFormat::kWEBP (the only one which
          *  currently supports subsets), the top and left values must be even.
          *
          *  In getPixels and incremental decode, we will attempt to decode the
@@ -667,7 +667,7 @@
         return false;
     }
 
-    virtual SkEncodedFormat onGetEncodedFormat() const = 0;
+    virtual SkEncodedImageFormat onGetEncodedFormat() const = 0;
 
     /**
      * @param rowsDecoded When the encoded image stream is incomplete, this function
diff --git a/include/codec/SkEncodedFormat.h b/include/codec/SkEncodedFormat.h
index c097e08..114e976 100644
--- a/include/codec/SkEncodedFormat.h
+++ b/include/codec/SkEncodedFormat.h
@@ -8,21 +8,29 @@
 #ifndef SkEncodedFormat_DEFINED
 #define SkEncodedFormat_DEFINED
 
-/**
- *  Enum describing format of encoded data.
- */
+#include "SkEncodedImageFormat.h"
+#include "SkTypes.h"
+
+#ifdef SK_SUPPORT_LEGACY_IMAGE_ENCODER_CLASS
+
 enum SkEncodedFormat {
-    kUnknown_SkEncodedFormat,
-    kBMP_SkEncodedFormat,
-    kGIF_SkEncodedFormat,
-    kICO_SkEncodedFormat,
-    kJPEG_SkEncodedFormat,
-    kPNG_SkEncodedFormat,
-    kWBMP_SkEncodedFormat,
-    kWEBP_SkEncodedFormat,
-    kPKM_SkEncodedFormat,
-    kKTX_SkEncodedFormat,
-    kASTC_SkEncodedFormat,
-    kDNG_SkEncodedFormat,
+    kBMP_SkEncodedFormat  = (uint8_t)SkEncodedImageFormat::kBMP,
+    kGIF_SkEncodedFormat  = (uint8_t)SkEncodedImageFormat::kGIF,
+    kICO_SkEncodedFormat  = (uint8_t)SkEncodedImageFormat::kICO,
+    kJPEG_SkEncodedFormat = (uint8_t)SkEncodedImageFormat::kJPEG,
+    kPNG_SkEncodedFormat  = (uint8_t)SkEncodedImageFormat::kPNG,
+    kWBMP_SkEncodedFormat = (uint8_t)SkEncodedImageFormat::kWBMP,
+    kWEBP_SkEncodedFormat = (uint8_t)SkEncodedImageFormat::kWEBP,
+    kPKM_SkEncodedFormat  = (uint8_t)SkEncodedImageFormat::kPKM,
+    kKTX_SkEncodedFormat  = (uint8_t)SkEncodedImageFormat::kKTX,
+    kASTC_SkEncodedFormat = (uint8_t)SkEncodedImageFormat::kASTC,
+    kDNG_SkEncodedFormat  = (uint8_t)SkEncodedImageFormat::kDNG,
 };
+
+#else
+
+typedef SkEncodedImageFormat SkEncodedFormat;
+
+#endif  // SK_SUPPORT_LEGACY_IMAGE_ENCODER_CLASS
+
 #endif  // SkEncodedFormat_DEFINED
diff --git a/include/core/SkEncodedImageFormat.h b/include/core/SkEncodedImageFormat.h
new file mode 100644
index 0000000..eb714f3
--- /dev/null
+++ b/include/core/SkEncodedImageFormat.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkEncodedImageFormat_DEFINED
+#define SkEncodedImageFormat_DEFINED
+
+#include <stdint.h>
+
+/**
+ *  Enum describing format of encoded data.
+ */
+enum class SkEncodedImageFormat {
+    kBMP,
+    kGIF,
+    kICO,
+    kJPEG,
+    kPNG,
+    kWBMP,
+    kWEBP,
+    kPKM,
+    kKTX,
+    kASTC,
+    kDNG,
+};
+
+#endif  // SkEncodedImageFormat_DEFINED
diff --git a/include/core/SkImage.h b/include/core/SkImage.h
index 02b632b..625d0a0 100644
--- a/include/core/SkImage.h
+++ b/include/core/SkImage.h
@@ -275,7 +275,12 @@
      *  Note: this will attempt to encode the image's pixels in the specified format,
      *  even if the image returns a data from refEncoded(). That data will be ignored.
      */
-    SkData* encode(SkImageEncoder::Type, int quality) const;
+    SkData* encode(SkEncodedImageFormat, int quality) const;
+#ifdef SK_SUPPORT_LEGACY_IMAGE_ENCODER_CLASS
+    SkData* encode(SkImageEncoder::Type t, int quality) const {
+        return this->encode((SkEncodedImageFormat)t, quality);
+    }
+#endif
 
     /**
      *  Encode the image and return the result as a caller-managed SkData.  This will
diff --git a/include/core/SkImageEncoder.h b/include/core/SkImageEncoder.h
index 7d15250..eb6ce65 100644
--- a/include/core/SkImageEncoder.h
+++ b/include/core/SkImageEncoder.h
@@ -8,32 +8,57 @@
 #ifndef SkImageEncoder_DEFINED
 #define SkImageEncoder_DEFINED
 
-#include "SkImageInfo.h"
-#include "SkTRegistry.h"
+#include "SkBitmap.h"
+#include "SkEncodedImageFormat.h"
+#include "SkPixelSerializer.h"
+#include "SkStream.h"
 
-class SkBitmap;
-class SkPixelSerializer;
-class SkPixmap;
-class SkData;
-class SkWStream;
+/**
+ * Encode SkPixmap in the given binary image format.
+ *
+ * @param  dst     results are written to this stream.
+ * @param  src     source pixels.
+ * @param  format  image format, not all formats are supported.
+ * @param  quality range from 0-100, not all formats respect quality.
+ *
+ * @return false iff input is bad or format is unsupported.
+ *
+ * Will always return false if Skia is compiled without image
+ * encoders.
+ *
+ * For examples of encoding an image to a file or to a block of memory,
+ * see tools/sk_tool_utils.h.
+ */
+SK_API bool SkEncodeImage(SkWStream* dst, const SkPixmap& src,
+                          SkEncodedImageFormat format, int quality);
+/**
+ * The following helper function wraps SkEncodeImage().
+ */
+inline bool SkEncodeImage(SkWStream* dst, const SkBitmap& src, SkEncodedImageFormat f, int q) {
+    SkAutoLockPixels autoLockPixels(src);
+    SkPixmap pixmap;
+    return src.peekPixels(&pixmap) && SkEncodeImage(dst, pixmap, f, q);
+}
+
+#ifdef SK_SUPPORT_LEGACY_IMAGE_ENCODER_CLASS
+
+////////////////////////////////////////////////////////////////////////////////
 
 class SkImageEncoder {
 public:
-    // TODO (scroggo): Merge with SkEncodedFormat.
     enum Type {
-        kUnknown_Type,
-        kBMP_Type,
-        kGIF_Type,
-        kICO_Type,
-        kJPEG_Type,
-        kPNG_Type,
-        kWBMP_Type,
-        kWEBP_Type,
-        kKTX_Type,
+        kBMP_Type     = (uint8_t)SkEncodedImageFormat::kBMP,
+        kGIF_Type     = (uint8_t)SkEncodedImageFormat::kGIF,
+        kICO_Type     = (uint8_t)SkEncodedImageFormat::kICO,
+        kJPEG_Type    = (uint8_t)SkEncodedImageFormat::kJPEG,
+        kPNG_Type     = (uint8_t)SkEncodedImageFormat::kPNG,
+        kWBMP_Type    = (uint8_t)SkEncodedImageFormat::kWBMP,
+        kWEBP_Type    = (uint8_t)SkEncodedImageFormat::kWEBP,
+        kKTX_Type     = (uint8_t)SkEncodedImageFormat::kKTX,
     };
     static SkImageEncoder* Create(Type);
 
-    virtual ~SkImageEncoder();
+    virtual ~SkImageEncoder() {}
 
     /*  Quality ranges from 0..100 */
     enum {
@@ -46,36 +71,57 @@
      *  encoded, return null. On success, the caller is responsible for
      *  calling unref() on the data when they are finished.
      */
-    SkData* encodeData(const SkBitmap&, int quality);
+    SkData* encodeData(const SkBitmap& bm, int quality) {
+        SkDynamicMemoryWStream buffer;
+        return this->encodeStream(&buffer, bm, quality)
+               ? buffer.detachAsData().release()
+               : nullptr;
+    }
 
     /**
      * Encode bitmap 'bm' in the desired format, writing results to
      * file 'file', at quality level 'quality' (which can be in range
      * 0-100). Returns false on failure.
      */
-    bool encodeFile(const char file[], const SkBitmap& bm, int quality);
+    bool encodeFile(const char path[], const SkBitmap& bm, int quality) {
+        SkFILEWStream file(path);
+        return this->encodeStream(&file, bm, quality);
+    }
 
     /**
      * Encode bitmap 'bm' in the desired format, writing results to
      * stream 'stream', at quality level 'quality' (which can be in
      * range 0-100). Returns false on failure.
      */
-    bool encodeStream(SkWStream* stream, const SkBitmap& bm, int quality);
+    bool encodeStream(SkWStream* dst, const SkBitmap& src, int quality) {
+        return this->onEncode(dst, src, SkMin32(100, SkMax32(0, quality)));
+    }
 
-    static SkData* EncodeData(const SkImageInfo&, const void* pixels, size_t rowBytes,
-                              Type, int quality);
-    static SkData* EncodeData(const SkBitmap&, Type, int quality);
+    static SkData* EncodeData(const SkImageInfo& info, const void* pixels, size_t rowBytes,
+                              Type t, int quality) {
+        SkPixmap pixmap(info, pixels, rowBytes, nullptr);
+        return SkImageEncoder::EncodeData(pixmap, t, quality);
+    }
 
-    static SkData* EncodeData(const SkPixmap&, Type, int quality);
+    static SkData* EncodeData(const SkBitmap& src, Type t, int quality) {
+        SkDynamicMemoryWStream buf;
+        return SkEncodeImage(&buf, src, (SkEncodedImageFormat)t, quality)
+            ? buf.detachAsData().release() : nullptr;
+    }
 
-    static bool EncodeFile(const char file[], const SkBitmap&, Type,
-                           int quality);
-    static bool EncodeStream(SkWStream*, const SkBitmap&, Type,
-                           int quality);
+    static SkData* EncodeData(const SkPixmap& pixmap, Type t, int quality) {
+        SkDynamicMemoryWStream buf;
+        return SkEncodeImage(&buf, pixmap, (SkEncodedImageFormat)t, quality)
+            ? buf.detachAsData().release() : nullptr;
+    }
 
-    /** Uses SkImageEncoder to serialize images that are not already
-        encoded as SkImageEncoder::kPNG_Type images. */
-    static SkPixelSerializer* CreatePixelSerializer();
+    static bool EncodeFile(const char path[], const SkBitmap& src, Type t, int quality) {
+        SkFILEWStream file(path);
+        return SkEncodeImage(&file, src, (SkEncodedImageFormat)t, quality);
+    }
+    static bool EncodeStream(SkWStream* dst, const SkBitmap& bm, Type t, int quality) {
+        return SkEncodeImage(dst, bm, (SkEncodedImageFormat)t, quality);
+    }
 
 protected:
     /**
@@ -88,32 +134,5 @@
     virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) = 0;
 };
 
-// This macro declares a global (i.e., non-class owned) creation entry point
-// for each encoder (e.g., CreateJPEGImageEncoder)
-#define DECLARE_ENCODER_CREATOR(codec)          \
-    SK_API SkImageEncoder *Create ## codec ();
-
-// This macro defines the global creation entry point for each encoder. Each
-// encoder implementation that registers with the encoder factory must call it.
-#define DEFINE_ENCODER_CREATOR(codec) \
-    SkImageEncoder* Create##codec() { return new Sk##codec; }
-
-// All the encoders known by Skia. Note that, depending on the compiler settings,
-// not all of these will be available
-DECLARE_ENCODER_CREATOR(JPEGImageEncoder);
-DECLARE_ENCODER_CREATOR(PNGImageEncoder);
-DECLARE_ENCODER_CREATOR(KTXImageEncoder);
-DECLARE_ENCODER_CREATOR(WEBPImageEncoder);
-
-#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
-SkImageEncoder* CreateImageEncoder_CG(SkImageEncoder::Type type);
-#endif
-
-#if defined(SK_BUILD_FOR_WIN)
-SkImageEncoder* CreateImageEncoder_WIC(SkImageEncoder::Type type);
-#endif
-
-// Typedef to make registering encoder callback easier
-// This has to be defined outside SkImageEncoder. :(
-typedef SkTRegistry<SkImageEncoder*(*)(SkImageEncoder::Type)> SkImageEncoder_EncodeReg;
-#endif
+#endif  // SK_SUPPORT_LEGACY_IMAGE_ENCODER_CLASS
+#endif  // SkImageEncoder_DEFINED
diff --git a/public.bzl b/public.bzl
index 55f40f8..d385279 100644
--- a/public.bzl
+++ b/public.bzl
@@ -599,6 +599,7 @@
     # Staging flags for API changes
     "SK_SUPPORT_LEGACY_ACCESSBITMAP",
     "SK_SUPPORT_LEGACY_CLIP_REGIONOPS",
+    "SK_SUPPORT_LEGACY_IMAGE_ENCODER_CLASS",
     "SK_SUPPORT_LEGACY_XFERMODE_IS_PUBLIC",
     # Temporarily Disable analytic AA for Google3
     "SK_NO_ANALYTIC_AA",
diff --git a/samplecode/SampleApp.cpp b/samplecode/SampleApp.cpp
index 8a5927f..a8c2e0b 100644
--- a/samplecode/SampleApp.cpp
+++ b/samplecode/SampleApp.cpp
@@ -1407,8 +1407,8 @@
             static int gSampleGrabCounter;
             SkString name;
             name.printf("sample_grab_%d.png", gSampleGrabCounter++);
-            SkImageEncoder::EncodeFile(name.c_str(), bmp,
-                                       SkImageEncoder::kPNG_Type, 100);
+            sk_tool_utils::EncodeImageToFile(name.c_str(), bmp,
+                                       SkEncodedImageFormat::kPNG, 100);
         }
         this->inval(nullptr);
         return;
diff --git a/samplecode/SampleSlides.cpp b/samplecode/SampleSlides.cpp
index 43221d4..c1c49b4 100644
--- a/samplecode/SampleSlides.cpp
+++ b/samplecode/SampleSlides.cpp
@@ -15,6 +15,8 @@
 #include "SkPaint.h"
 #include "SkView.h"
 
+#include "sk_tool_utils.h"
+
 #define BG_COLOR    0xFFDDDDDD
 
 typedef void (*SlideProc)(SkCanvas*);
@@ -681,7 +683,7 @@
             canvas.restore();
             SkString str;
             str.printf("/skimages/slide_" SK_SIZE_T_SPECIFIER ".png", i);
-            SkImageEncoder::EncodeFile(str.c_str(), bm, SkImageEncoder::kPNG_Type, 100);
+            sk_tool_utils::EncodeImageToFile(str.c_str(), bm, SkEncodedImageFormat::kPNG, 100);
         }
         this->setBGColor(BG_COLOR);
     }
diff --git a/src/android/SkBitmapRegionCodec.h b/src/android/SkBitmapRegionCodec.h
index 5c59d52..2c9536c 100644
--- a/src/android/SkBitmapRegionCodec.h
+++ b/src/android/SkBitmapRegionCodec.h
@@ -26,7 +26,9 @@
 
     bool conversionSupported(SkColorType colorType) override;
 
-    SkEncodedFormat getEncodedFormat() override { return fCodec->getEncodedFormat(); }
+    SkEncodedFormat getEncodedFormat() override {
+        return (SkEncodedFormat)fCodec->getEncodedFormat();
+    }
 
 private:
 
diff --git a/src/android/SkBitmapRegionDecoder.cpp b/src/android/SkBitmapRegionDecoder.cpp
index 15a530e..8298fb5 100644
--- a/src/android/SkBitmapRegionDecoder.cpp
+++ b/src/android/SkBitmapRegionDecoder.cpp
@@ -29,11 +29,10 @@
                 return NULL;
             }
 
-            SkEncodedFormat format = codec->getEncodedFormat();
-            switch (format) {
-                case SkEncodedFormat::kJPEG_SkEncodedFormat:
-                case SkEncodedFormat::kPNG_SkEncodedFormat:
-                case SkEncodedFormat::kWEBP_SkEncodedFormat:
+            switch ((SkEncodedImageFormat)codec->getEncodedFormat()) {
+                case SkEncodedImageFormat::kJPEG:
+                case SkEncodedImageFormat::kPNG:
+                case SkEncodedImageFormat::kWEBP:
                     break;
                 default:
                     return nullptr;
diff --git a/src/animator/SkSnapshot.cpp b/src/animator/SkSnapshot.cpp
index fbaedff..6be1a53 100644
--- a/src/animator/SkSnapshot.cpp
+++ b/src/animator/SkSnapshot.cpp
@@ -30,7 +30,7 @@
 SkSnapshot::SkSnapshot()
 {
     quality     = 100 * SK_Scalar1;
-    type        = (SkImageEncoder::Type) -1;
+    type        = (SkEncodedImageFormat) -1;
     sequence    = false;
     fSeqVal     = 0;
 }
@@ -38,7 +38,7 @@
 bool SkSnapshot::draw(SkAnimateMaker& maker) {
     SkASSERT(type >= 0);
     SkASSERT(filename.size() > 0);
-    SkImageEncoder* encoder = SkImageEncoder::Create((SkImageEncoder::Type) type);
+    SkImageEncoder* encoder = SkImageEncoder::Create((SkEncodedImageFormat) type);
     if (!encoder) {
         return false;
     }
@@ -54,9 +54,9 @@
         if (++fSeqVal > 999)
             sequence = false;
     }
-    if (type == SkImageEncoder::kJPEG_Type)
+    if (type == SkEncodedImageFormat::kJPEG)
         name.append(".jpg");
-    else if (type == SkImageEncoder::kPNG_Type)
+    else if (type == SkEncodedImageFormat::kPNG)
         name.append(".png");
 
     SkBitmap pixels;
diff --git a/src/animator/SkSnapshot.h b/src/animator/SkSnapshot.h
index 003a9dc..a802d99 100644
--- a/src/animator/SkSnapshot.h
+++ b/src/animator/SkSnapshot.h
@@ -22,7 +22,7 @@
     SkString filename;
     SkScalar quality;
     SkBool sequence;
-    int /*SkImageEncoder::Type*/    type;
+    int /*SkEncodedImageFormat*/    type;
     int fSeqVal;
 };
 
diff --git a/src/codec/SkAndroidCodec.cpp b/src/codec/SkAndroidCodec.cpp
index 01605b2..c315b03 100644
--- a/src/codec/SkAndroidCodec.cpp
+++ b/src/codec/SkAndroidCodec.cpp
@@ -28,24 +28,24 @@
         return nullptr;
     }
 
-    switch (codec->getEncodedFormat()) {
+    switch ((SkEncodedImageFormat)codec->getEncodedFormat()) {
 #ifdef SK_HAS_PNG_LIBRARY
-        case kPNG_SkEncodedFormat:
-        case kICO_SkEncodedFormat:
+        case SkEncodedImageFormat::kPNG:
+        case SkEncodedImageFormat::kICO:
 #endif
 #ifdef SK_HAS_JPEG_LIBRARY
-        case kJPEG_SkEncodedFormat:
+        case SkEncodedImageFormat::kJPEG:
 #endif
-        case kGIF_SkEncodedFormat:
-        case kBMP_SkEncodedFormat:
-        case kWBMP_SkEncodedFormat:
+        case SkEncodedImageFormat::kGIF:
+        case SkEncodedImageFormat::kBMP:
+        case SkEncodedImageFormat::kWBMP:
             return new SkSampledCodec(codec.release());
 #ifdef SK_HAS_WEBP_LIBRARY
-        case kWEBP_SkEncodedFormat:
+        case SkEncodedImageFormat::kWEBP:
             return new SkWebpAdapterCodec((SkWebpCodec*) codec.release());
 #endif
 #ifdef SK_CODEC_DECODES_RAW
-        case kDNG_SkEncodedFormat:
+        case SkEncodedImageFormat::kDNG:
             return new SkRawAdapterCodec((SkRawCodec*)codec.release());
 #endif
         default:
@@ -64,8 +64,8 @@
 SkColorType SkAndroidCodec::computeOutputColorType(SkColorType requestedColorType) {
     // The legacy GIF and WBMP decoders always decode to kIndex_8_SkColorType.
     // We will maintain this behavior.
-    SkEncodedFormat format = this->getEncodedFormat();
-    if (kGIF_SkEncodedFormat == format || kWBMP_SkEncodedFormat == format) {
+    SkEncodedImageFormat format = (SkEncodedImageFormat)this->getEncodedFormat();
+    if (SkEncodedImageFormat::kGIF == format || SkEncodedImageFormat::kWBMP == format) {
         return kIndex_8_SkColorType;
     }
 
diff --git a/src/codec/SkBmpCodec.h b/src/codec/SkBmpCodec.h
index 0e38c84..75740f7 100644
--- a/src/codec/SkBmpCodec.h
+++ b/src/codec/SkBmpCodec.h
@@ -41,7 +41,7 @@
     SkBmpCodec(int width, int height, const SkEncodedInfo& info, SkStream* stream,
             uint16_t bitsPerPixel, SkCodec::SkScanlineOrder rowOrder);
 
-    SkEncodedFormat onGetEncodedFormat() const override { return kBMP_SkEncodedFormat; }
+    SkEncodedImageFormat onGetEncodedFormat() const override { return SkEncodedImageFormat::kBMP; }
 
     /*
      * Read enough of the stream to initialize the SkBmpCodec. Returns a bool
diff --git a/src/codec/SkGifCodec.h b/src/codec/SkGifCodec.h
index 8e93730..9e980ab 100644
--- a/src/codec/SkGifCodec.h
+++ b/src/codec/SkGifCodec.h
@@ -40,8 +40,8 @@
     Result onGetPixels(const SkImageInfo&, void*, size_t, const Options&,
             SkPMColor*, int*, int*) override;
 
-    SkEncodedFormat onGetEncodedFormat() const override {
-        return kGIF_SkEncodedFormat;
+    SkEncodedImageFormat onGetEncodedFormat() const override {
+        return SkEncodedImageFormat::kGIF;
     }
 
     bool onRewind() override;
diff --git a/src/codec/SkIcoCodec.h b/src/codec/SkIcoCodec.h
index 0c4e504..e8dcc83 100644
--- a/src/codec/SkIcoCodec.h
+++ b/src/codec/SkIcoCodec.h
@@ -39,8 +39,8 @@
     Result onGetPixels(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes, const Options&,
             SkPMColor*, int*, int*) override;
 
-    SkEncodedFormat onGetEncodedFormat() const override {
-        return kICO_SkEncodedFormat;
+    SkEncodedImageFormat onGetEncodedFormat() const override {
+        return SkEncodedImageFormat::kICO;
     }
 
     SkScanlineOrder onGetScanlineOrder() const override;
diff --git a/src/codec/SkJpegCodec.h b/src/codec/SkJpegCodec.h
index 9e08c86..9a34aa6 100644
--- a/src/codec/SkJpegCodec.h
+++ b/src/codec/SkJpegCodec.h
@@ -51,8 +51,8 @@
 
     Result onGetYUV8Planes(const SkYUVSizeInfo& sizeInfo, void* planes[3]) override;
 
-    SkEncodedFormat onGetEncodedFormat() const override {
-        return kJPEG_SkEncodedFormat;
+    SkEncodedImageFormat onGetEncodedFormat() const override {
+        return SkEncodedImageFormat::kJPEG;
     }
 
     bool onRewind() override;
diff --git a/src/codec/SkPngCodec.h b/src/codec/SkPngCodec.h
index 590a631..c246887 100644
--- a/src/codec/SkPngCodec.h
+++ b/src/codec/SkPngCodec.h
@@ -9,7 +9,7 @@
 #include "SkColorSpaceXform.h"
 #include "SkColorTable.h"
 #include "SkPngChunkReader.h"
-#include "SkEncodedFormat.h"
+#include "SkEncodedImageFormat.h"
 #include "SkImageInfo.h"
 #include "SkRefCnt.h"
 #include "SkSwizzler.h"
@@ -51,7 +51,7 @@
 
     Result onGetPixels(const SkImageInfo&, void*, size_t, const Options&, SkPMColor*, int*, int*)
             override;
-    SkEncodedFormat onGetEncodedFormat() const override { return kPNG_SkEncodedFormat; }
+    SkEncodedImageFormat onGetEncodedFormat() const override { return SkEncodedImageFormat::kPNG; }
     bool onRewind() override;
     uint64_t onGetFillValue(const SkImageInfo&) const override;
 
diff --git a/src/codec/SkRawAdapterCodec.h b/src/codec/SkRawAdapterCodec.h
index b552f2a..8777180 100644
--- a/src/codec/SkRawAdapterCodec.h
+++ b/src/codec/SkRawAdapterCodec.h
@@ -10,7 +10,7 @@
 
 #include "SkAndroidCodec.h"
 #include "SkCodec.h"
-#include "SkEncodedFormat.h"
+#include "SkEncodedImageFormat.h"
 #include "SkRawCodec.h"
 #include "SkStream.h"
 #include "SkTypes.h"
diff --git a/src/codec/SkRawCodec.h b/src/codec/SkRawCodec.h
index 75654c7..51bb234 100644
--- a/src/codec/SkRawCodec.h
+++ b/src/codec/SkRawCodec.h
@@ -37,8 +37,8 @@
     Result onGetPixels(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes, const Options&,
             SkPMColor*, int*, int*) override;
 
-    SkEncodedFormat onGetEncodedFormat() const override {
-        return kDNG_SkEncodedFormat;
+    SkEncodedImageFormat onGetEncodedFormat() const override {
+        return SkEncodedImageFormat::kDNG;
     }
 
     SkISize onGetScaledDimensions(float desiredScale) const override;
diff --git a/src/codec/SkSampledCodec.cpp b/src/codec/SkSampledCodec.cpp
index e70aade..1d9953b 100644
--- a/src/codec/SkSampledCodec.cpp
+++ b/src/codec/SkSampledCodec.cpp
@@ -26,7 +26,7 @@
     }
 
     // Only JPEG supports native downsampling.
-    if (this->codec()->getEncodedFormat() == kJPEG_SkEncodedFormat) {
+    if (this->codec()->getEncodedFormat() == SkEncodedImageFormat::kJPEG) {
         // See if libjpeg supports this scale directly
         switch (sampleSize) {
             case 2:
diff --git a/src/codec/SkWbmpCodec.cpp b/src/codec/SkWbmpCodec.cpp
index 19c8c7d..6356e30 100644
--- a/src/codec/SkWbmpCodec.cpp
+++ b/src/codec/SkWbmpCodec.cpp
@@ -113,8 +113,8 @@
     , fColorTable(nullptr)
 {}
 
-SkEncodedFormat SkWbmpCodec::onGetEncodedFormat() const {
-    return kWBMP_SkEncodedFormat;
+SkEncodedImageFormat SkWbmpCodec::onGetEncodedFormat() const {
+    return SkEncodedImageFormat::kWBMP;
 }
 
 SkCodec::Result SkWbmpCodec::onGetPixels(const SkImageInfo& info,
diff --git a/src/codec/SkWbmpCodec.h b/src/codec/SkWbmpCodec.h
index 6946ea0..40f507e 100644
--- a/src/codec/SkWbmpCodec.h
+++ b/src/codec/SkWbmpCodec.h
@@ -24,7 +24,7 @@
     static SkCodec* NewFromStream(SkStream*);
 
 protected:
-    SkEncodedFormat onGetEncodedFormat() const override;
+    SkEncodedImageFormat onGetEncodedFormat() const override;
     Result onGetPixels(const SkImageInfo&, void*, size_t,
                        const Options&, SkPMColor[], int*, int*) override;
     bool onRewind() override;
diff --git a/src/codec/SkWebpCodec.h b/src/codec/SkWebpCodec.h
index b9c493f..93b60f6 100644
--- a/src/codec/SkWebpCodec.h
+++ b/src/codec/SkWebpCodec.h
@@ -10,7 +10,7 @@
 
 #include "SkCodec.h"
 #include "SkColorSpace.h"
-#include "SkEncodedFormat.h"
+#include "SkEncodedImageFormat.h"
 #include "SkImageInfo.h"
 #include "SkTypes.h"
 
@@ -30,7 +30,7 @@
 protected:
     Result onGetPixels(const SkImageInfo&, void*, size_t, const Options&, SkPMColor*, int*, int*)
             override;
-    SkEncodedFormat onGetEncodedFormat() const override { return kWEBP_SkEncodedFormat; }
+    SkEncodedImageFormat onGetEncodedFormat() const override { return SkEncodedImageFormat::kWEBP; }
 
     SkISize onGetScaledDimensions(float desiredScale) const override;
 
diff --git a/src/gpu/GrSurface.cpp b/src/gpu/GrSurface.cpp
index f67bfd4..3bb666e 100644
--- a/src/gpu/GrSurface.cpp
+++ b/src/gpu/GrSurface.cpp
@@ -165,6 +165,11 @@
                                       rowBytes, pixelOpsFlags);
 }
 
+static bool encode_image_to_file(const char* path, const SkBitmap& src) {
+    SkFILEWStream file(path);
+    return file.isValid() && SkEncodeImage(&file, src, SkEncodedImageFormat::kPNG, 100);
+}
+
 // TODO: This should probably be a non-member helper function. It might only be needed in
 // debug or developer builds.
 bool GrSurface::savePixels(const char* filename) {
@@ -183,7 +188,7 @@
     // remove any previous version of this file
     remove(filename);
 
-    if (!SkImageEncoder::EncodeFile(filename, bm, SkImageEncoder::kPNG_Type, 100)) {
+    if (!encode_image_to_file(filename, bm)) {
         SkDebugf("------ failed to encode %s\n", filename);
         remove(filename);   // remove any partial file
         return false;
diff --git a/src/image/SkImage.cpp b/src/image/SkImage.cpp
index f976242..485bd24 100644
--- a/src/image/SkImage.cpp
+++ b/src/image/SkImage.cpp
@@ -103,27 +103,22 @@
     return SkImageShader::Make(sk_ref_sp(const_cast<SkImage*>(this)), tileX, tileY, localMatrix);
 }
 
-SkData* SkImage::encode(SkImageEncoder::Type type, int quality) const {
+SkData* SkImage::encode(SkEncodedImageFormat type, int quality) const {
     SkBitmap bm;
     // TODO: Right now, the encoders don't handle F16 or linearly premultiplied data. Once they do,
     // we should decode in "color space aware" mode, then re-encode that. For now, work around this
     // by asking for a legacy decode (which gives us the raw data in N32).
     if (as_IB(this)->getROPixels(&bm, SkDestinationSurfaceColorMode::kLegacy)) {
-        return SkImageEncoder::EncodeData(bm, type, quality);
+        SkDynamicMemoryWStream buf;
+        return SkEncodeImage(&buf, bm, type, quality) ? buf.detachAsData().release() : nullptr;
     }
     return nullptr;
 }
 
 SkData* SkImage::encode(SkPixelSerializer* serializer) const {
-    sk_sp<SkPixelSerializer> defaultSerializer;
-    SkPixelSerializer* effectiveSerializer = serializer;
-    if (!effectiveSerializer) {
-        defaultSerializer.reset(SkImageEncoder::CreatePixelSerializer());
-        SkASSERT(defaultSerializer.get());
-        effectiveSerializer = defaultSerializer.get();
-    }
     sk_sp<SkData> encoded(this->refEncoded());
-    if (encoded && effectiveSerializer->useEncodedData(encoded->data(), encoded->size())) {
+    if (encoded &&
+        (!serializer || serializer->useEncodedData(encoded->data(), encoded->size()))) {
         return encoded.release();
     }
 
@@ -134,7 +129,13 @@
     // by asking for a legacy decode (which gives us the raw data in N32).
     if (as_IB(this)->getROPixels(&bm, SkDestinationSurfaceColorMode::kLegacy) &&
         bm.requestLock(&apu)) {
-        return effectiveSerializer->encode(apu.pixmap());
+        if (serializer) {
+            return serializer->encode(apu.pixmap());
+        } else {
+            SkDynamicMemoryWStream buf;
+            return SkEncodeImage(&buf, apu.pixmap(), SkEncodedImageFormat::kPNG, 100)
+                   ? buf.detachAsData().release() : nullptr;
+        }
     }
 
     return nullptr;
@@ -188,7 +189,7 @@
     GrTexture* texture = as_IB(this)->peekTexture();
     if (texture) {
         GrContext* context = texture->getContext();
-        if (context) {            
+        if (context) {
             if (flushPendingGrContextIO) {
                 context->prepareSurfaceForExternalIO(texture);
             }
diff --git a/src/images/SkForceLinking.cpp b/src/images/SkForceLinking.cpp
index 81d485c..dfed6b4 100644
--- a/src/images/SkForceLinking.cpp
+++ b/src/images/SkForceLinking.cpp
@@ -5,7 +5,7 @@
  * found in the LICENSE file.
  */
 
-#include "SkImageEncoder.h"
+#include "SkImageEncoderPriv.h"
 #include "SkForceLinking.h"
 
 // This method is required to fool the linker into not discarding the pre-main
@@ -30,10 +30,10 @@
 #endif
 
 #if defined (SK_USE_CG_ENCODER)
-        CreateImageEncoder_CG(SkImageEncoder::kPNG_Type);
+        CreateImageEncoder_CG(SkEncodedImageFormat::kPNG);
 #endif
 #if defined (SK_USE_WIC_ENCODER)
-        CreateImageEncoder_WIC(SkImageEncoder::kPNG_Type);
+        CreateImageEncoder_WIC(SkEncodedImageFormat::kPNG);
 #endif
         return -1;
     }
diff --git a/src/images/SkImageEncoder.cpp b/src/images/SkImageEncoder.cpp
index 787ff8e..fc5f126 100644
--- a/src/images/SkImageEncoder.cpp
+++ b/src/images/SkImageEncoder.cpp
@@ -5,84 +5,15 @@
  * found in the LICENSE file.
  */
 
-#include "SkImageEncoder.h"
-#include "SkBitmap.h"
-#include "SkPixelSerializer.h"
-#include "SkPixmap.h"
-#include "SkStream.h"
-#include "SkTemplates.h"
+#include "SkImageEncoderPriv.h"
 
-SkImageEncoder::~SkImageEncoder() {}
-
-bool SkImageEncoder::encodeStream(SkWStream* stream, const SkBitmap& bm,
-                                  int quality) {
-    quality = SkMin32(100, SkMax32(0, quality));
-    return this->onEncode(stream, bm, quality);
-}
-
-bool SkImageEncoder::encodeFile(const char file[], const SkBitmap& bm,
-                                int quality) {
-    quality = SkMin32(100, SkMax32(0, quality));
-    SkFILEWStream   stream(file);
-    return this->onEncode(&stream, bm, quality);
-}
-
-SkData* SkImageEncoder::encodeData(const SkBitmap& bm, int quality) {
-    SkDynamicMemoryWStream stream;
-    quality = SkMin32(100, SkMax32(0, quality));
-    if (this->onEncode(&stream, bm, quality)) {
-        return stream.detachAsData().release();
-    }
-    return nullptr;
-}
-
-bool SkImageEncoder::EncodeFile(const char file[], const SkBitmap& bm, Type t,
-                                int quality) {
-    std::unique_ptr<SkImageEncoder> enc(SkImageEncoder::Create(t));
-    return enc.get() && enc.get()->encodeFile(file, bm, quality);
-}
-
-bool SkImageEncoder::EncodeStream(SkWStream* stream, const SkBitmap& bm, Type t,
-                                  int quality) {
-    std::unique_ptr<SkImageEncoder> enc(SkImageEncoder::Create(t));
-    return enc.get() && enc.get()->encodeStream(stream, bm, quality);
-}
-
-SkData* SkImageEncoder::EncodeData(const SkBitmap& bm, Type t, int quality) {
-    std::unique_ptr<SkImageEncoder> enc(SkImageEncoder::Create(t));
-    return enc.get() ? enc.get()->encodeData(bm, quality) : nullptr;
-}
-
-SkData* SkImageEncoder::EncodeData(const SkImageInfo& info, const void* pixels, size_t rowBytes,
-                                   Type t, int quality) {
+bool SkEncodeImage(SkWStream* dst, const SkPixmap& src,
+                   SkEncodedImageFormat format, int quality) {
     SkBitmap bm;
-    if (!bm.installPixels(info, const_cast<void*>(pixels), rowBytes)) {
+    if (!bm.installPixels(src)) {
         return nullptr;
     }
     bm.setImmutable();
-    return SkImageEncoder::EncodeData(bm, t, quality);
-}
-
-SkData* SkImageEncoder::EncodeData(const SkPixmap& pixmap,
-                                   Type t, int quality) {
-    SkBitmap bm;
-    if (!bm.installPixels(pixmap)) {
-        return nullptr;
-    }
-    bm.setImmutable();
-    return SkImageEncoder::EncodeData(bm, t, quality);
-}
-
-namespace {
-class ImageEncoderPixelSerializer final : public SkPixelSerializer {
-protected:
-    bool onUseEncodedData(const void*, size_t) override { return true; }
-    SkData* onEncode(const SkPixmap& pmap) override {
-        return SkImageEncoder::EncodeData(pmap, SkImageEncoder::kPNG_Type, 100);
-    }
-};
-} // namespace
-
-SkPixelSerializer* SkImageEncoder::CreatePixelSerializer() {
-    return new ImageEncoderPixelSerializer;
+    std::unique_ptr<SkImageEncoder> enc(SkImageEncoder::Create((SkImageEncoder::Type)format));
+    return enc && enc->encodeStream(dst, bm, quality);
 }
diff --git a/src/images/SkImageEncoderPriv.h b/src/images/SkImageEncoderPriv.h
new file mode 100644
index 0000000..9b632f5
--- /dev/null
+++ b/src/images/SkImageEncoderPriv.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkImageEncoderPriv_DEFINED
+#define SkImageEncoderPriv_DEFINED
+
+#include "SkImageEncoder.h"
+#include "SkTRegistry.h"
+
+#ifndef SK_SUPPORT_LEGACY_IMAGE_ENCODER_CLASS
+
+    // TODO(halcanary): replace this class and registry system with something simpler.
+    class SkImageEncoder {
+    public:
+        typedef SkEncodedImageFormat Type;
+        static SkImageEncoder* Create(SkEncodedImageFormat);
+
+        virtual ~SkImageEncoder() {}
+
+        bool encodeStream(SkWStream* dst, const SkBitmap& src, int quality) {
+            return this->onEncode(dst, src, SkMin32(100, SkMax32(0, quality)));
+        }
+
+    protected:
+        /**
+         * Encode bitmap 'bm' in the desired format, writing results to
+         * stream 'stream', at quality level 'quality' (which can be in
+         * range 0-100).
+         */
+        virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) = 0;
+    };
+
+#endif  // SK_SUPPORT_LEGACY_IMAGE_ENCODER_CLASS
+
+// This macro declares a global (i.e., non-class owned) creation entry point
+// for each encoder (e.g., CreateJPEGImageEncoder)
+#define DECLARE_ENCODER_CREATOR(codec)          \
+    SK_API SkImageEncoder *Create ## codec ();
+
+// This macro defines the global creation entry point for each encoder. Each
+// encoder implementation that registers with the encoder factory must call it.
+#define DEFINE_ENCODER_CREATOR(codec) \
+    SkImageEncoder* Create##codec() { return new Sk##codec; }
+
+// All the encoders known by Skia. Note that, depending on the compiler settings,
+// not all of these will be available
+DECLARE_ENCODER_CREATOR(JPEGImageEncoder);
+DECLARE_ENCODER_CREATOR(PNGImageEncoder);
+DECLARE_ENCODER_CREATOR(KTXImageEncoder);
+DECLARE_ENCODER_CREATOR(WEBPImageEncoder);
+
+#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
+SkImageEncoder* CreateImageEncoder_CG(SkImageEncoder::Type type);
+#endif
+
+#if defined(SK_BUILD_FOR_WIN)
+SkImageEncoder* CreateImageEncoder_WIC(SkImageEncoder::Type type);
+#endif
+
+// Typedef to make registering encoder callback easier
+// This has to be defined outside SkImageEncoder. :(
+typedef SkTRegistry<SkImageEncoder*(*)(SkImageEncoder::Type)> SkImageEncoder_EncodeReg;
+
+#endif // SkImageEncoderPriv_DEFINED
diff --git a/src/images/SkImageEncoder_Factory.cpp b/src/images/SkImageEncoder_Factory.cpp
index 887ce55..a5ae8d0 100644
--- a/src/images/SkImageEncoder_Factory.cpp
+++ b/src/images/SkImageEncoder_Factory.cpp
@@ -5,11 +5,11 @@
  * found in the LICENSE file.
  */
 
-#include "SkImageEncoder.h"
+#include "SkImageEncoderPriv.h"
 
 template SkImageEncoder_EncodeReg* SkImageEncoder_EncodeReg::gHead;
 
-SkImageEncoder* SkImageEncoder::Create(Type t) {
+SkImageEncoder* SkImageEncoder::Create(SkImageEncoder::Type t) {
     SkImageEncoder* codec = nullptr;
     const SkImageEncoder_EncodeReg* curr = SkImageEncoder_EncodeReg::Head();
     while (curr) {
diff --git a/src/images/SkJPEGImageEncoder.cpp b/src/images/SkJPEGImageEncoder.cpp
index 66b2440..97b8bbc 100644
--- a/src/images/SkJPEGImageEncoder.cpp
+++ b/src/images/SkJPEGImageEncoder.cpp
@@ -5,20 +5,20 @@
  * found in the LICENSE file.
  */
 
+#include "SkImageEncoderPriv.h"
 
-#include "SkImageEncoder.h"
+#include "SkCanvas.h"
 #include "SkColorPriv.h"
 #include "SkDither.h"
+#include "SkJPEGWriteUtility.h"
+#include "SkRect.h"
 #include "SkStream.h"
 #include "SkTemplates.h"
 #include "SkTime.h"
 #include "SkUtils.h"
-#include "SkRect.h"
-#include "SkCanvas.h"
-
 
 #include <stdio.h>
-#include "SkJPEGWriteUtility.h"
+
 extern "C" {
     #include "jpeglib.h"
     #include "jerror.h"
@@ -178,7 +178,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) {
-    return (SkImageEncoder::kJPEG_Type == t) ? new SkJPEGImageEncoder : nullptr;
+    return (SkEncodedImageFormat::kJPEG == (SkEncodedImageFormat)t) ? new SkJPEGImageEncoder : nullptr;
 }
 
 static SkImageEncoder_EncodeReg gEReg(sk_libjpeg_efactory);
diff --git a/src/images/SkKTXImageEncoder.cpp b/src/images/SkKTXImageEncoder.cpp
index 078cec6..7a0ccb3 100644
--- a/src/images/SkKTXImageEncoder.cpp
+++ b/src/images/SkKTXImageEncoder.cpp
@@ -6,7 +6,7 @@
  */
 
 #include "SkColorPriv.h"
-#include "SkImageEncoder.h"
+#include "SkImageEncoderPriv.h"
 #include "SkImageGenerator.h"
 #include "SkPixelRef.h"
 #include "SkStream.h"
@@ -91,7 +91,7 @@
 /////////////////////////////////////////////////////////////////////////////////////////
 
 SkImageEncoder* sk_libktx_efactory(SkImageEncoder::Type t) {
-    return (SkImageEncoder::kKTX_Type == t) ? new SkKTXImageEncoder : nullptr;
+    return (SkEncodedImageFormat::kKTX == (SkEncodedImageFormat)t) ? new SkKTXImageEncoder : nullptr;
 }
 
 static SkImageEncoder_EncodeReg gEReg(sk_libktx_efactory);
diff --git a/src/images/SkPNGImageEncoder.cpp b/src/images/SkPNGImageEncoder.cpp
index 69a53fb..4fc3a10 100644
--- a/src/images/SkPNGImageEncoder.cpp
+++ b/src/images/SkPNGImageEncoder.cpp
@@ -5,7 +5,7 @@
  * found in the LICENSE file.
  */
 
-#include "SkImageEncoder.h"
+#include "SkImageEncoderPriv.h"
 #include "SkColor.h"
 #include "SkColorPriv.h"
 #include "SkDither.h"
@@ -356,7 +356,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) {
-    return (SkImageEncoder::kPNG_Type == t) ? new SkPNGImageEncoder : nullptr;
+    return (SkEncodedImageFormat::kPNG == (SkEncodedImageFormat)t) ? new SkPNGImageEncoder : nullptr;
 }
 
 static SkImageEncoder_EncodeReg gEReg(sk_libpng_efactory);
diff --git a/src/images/SkWEBPImageEncoder.cpp b/src/images/SkWEBPImageEncoder.cpp
index 116608a..27c984a 100644
--- a/src/images/SkWEBPImageEncoder.cpp
+++ b/src/images/SkWEBPImageEncoder.cpp
@@ -15,7 +15,7 @@
  */
 
 #include "SkBitmap.h"
-#include "SkImageEncoder.h"
+#include "SkImageEncoderPriv.h"
 #include "SkColorPriv.h"
 #include "SkStream.h"
 #include "SkTemplates.h"
@@ -241,7 +241,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 static SkImageEncoder* sk_libwebp_efactory(SkImageEncoder::Type t) {
-    return (SkImageEncoder::kWEBP_Type == t) ? new SkWEBPImageEncoder : nullptr;
+    return (SkEncodedImageFormat::kWEBP == (SkEncodedImageFormat)t) ? new SkWEBPImageEncoder : nullptr;
 }
 
 static SkImageEncoder_EncodeReg gEReg(sk_libwebp_efactory);
diff --git a/src/ports/SkImageEncoder_CG.cpp b/src/ports/SkImageEncoder_CG.cpp
index 7892856..0c3d22d 100644
--- a/src/ports/SkImageEncoder_CG.cpp
+++ b/src/ports/SkImageEncoder_CG.cpp
@@ -12,7 +12,7 @@
 #include "SkCGUtils.h"
 #include "SkColorPriv.h"
 #include "SkData.h"
-#include "SkImageEncoder.h"
+#include "SkImageEncoderPriv.h"
 #include "SkStream.h"
 #include "SkStreamPriv.h"
 #include "SkTemplates.h"
@@ -59,13 +59,13 @@
 
 class SkImageEncoder_CG : public SkImageEncoder {
 public:
-    SkImageEncoder_CG(Type t) : fType(t) {}
+    SkImageEncoder_CG(SkEncodedImageFormat t) : fType(t) {}
 
 protected:
     virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality);
 
 private:
-    Type fType;
+    SkEncodedImageFormat fType;
 };
 
 /*  Encode bitmaps via CGImageDestination. We setup a DataConsumer which writes
@@ -80,19 +80,19 @@
 
     CFStringRef type;
     switch (fType) {
-        case kICO_Type:
+        case SkEncodedImageFormat::kICO:
             type = kUTTypeICO;
             break;
-        case kBMP_Type:
+        case SkEncodedImageFormat::kBMP:
             type = kUTTypeBMP;
             break;
-        case kGIF_Type:
+        case SkEncodedImageFormat::kGIF:
             type = kUTTypeGIF;
             break;
-        case kJPEG_Type:
+        case SkEncodedImageFormat::kJPEG:
             type = kUTTypeJPEG;
             break;
-        case kPNG_Type:
+        case SkEncodedImageFormat::kPNG:
             // PNG encoding an ARGB_4444 bitmap gives the following errors in GM:
             // <Error>: CGImageDestinationAddImage image could not be converted to destination
             // format.
@@ -127,13 +127,13 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 #ifdef SK_USE_CG_ENCODER
-static SkImageEncoder* sk_imageencoder_cg_factory(SkImageEncoder::Type t) {
+static SkImageEncoder* sk_imageencoder_cg_factory(SkEncodedImageFormat t) {
     switch (t) {
-        case SkImageEncoder::kICO_Type:
-        case SkImageEncoder::kBMP_Type:
-        case SkImageEncoder::kGIF_Type:
-        case SkImageEncoder::kJPEG_Type:
-        case SkImageEncoder::kPNG_Type:
+        case SkEncodedImageFormat::kICO:
+        case SkEncodedImageFormat::kBMP:
+        case SkEncodedImageFormat::kGIF:
+        case SkEncodedImageFormat::kJPEG:
+        case SkEncodedImageFormat::kPNG:
             break;
         default:
             return nullptr;
@@ -145,7 +145,7 @@
 #endif
 
 SkImageEncoder* CreateImageEncoder_CG(SkImageEncoder::Type type) {
-    return new SkImageEncoder_CG(type);
+    return new SkImageEncoder_CG((SkEncodedImageFormat)type);
 }
 
 #endif//defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
diff --git a/src/ports/SkImageEncoder_WIC.cpp b/src/ports/SkImageEncoder_WIC.cpp
index 6524526..035359e 100644
--- a/src/ports/SkImageEncoder_WIC.cpp
+++ b/src/ports/SkImageEncoder_WIC.cpp
@@ -31,7 +31,7 @@
 #include <wincodec.h>
 #include "SkAutoCoInitialize.h"
 #include "SkBitmap.h"
-#include "SkImageEncoder.h"
+#include "SkImageEncoderPriv.h"
 #include "SkIStream.h"
 #include "SkStream.h"
 #include "SkTScopedComPtr.h"
@@ -48,13 +48,13 @@
 
 class SkImageEncoder_WIC : public SkImageEncoder {
 public:
-    SkImageEncoder_WIC(Type t) : fType(t) {}
+    SkImageEncoder_WIC(SkEncodedImageFormat t) : fType(t) {}
 
 protected:
     virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality);
 
 private:
-    Type fType;
+    SkEncodedImageFormat fType;
 };
 
 bool SkImageEncoder_WIC::onEncode(SkWStream* stream
@@ -63,10 +63,10 @@
 {
     GUID type;
     switch (fType) {
-        case kJPEG_Type:
+        case SkEncodedImageFormat::kJPEG:
             type = GUID_ContainerFormatJpeg;
             break;
-        case kPNG_Type:
+        case SkEncodedImageFormat::kPNG:
             type = GUID_ContainerFormatPng;
             break;
         default:
@@ -97,7 +97,7 @@
     size_t rowBytes = bitmap.rowBytes();
     SkAutoMalloc pixelStorage;
     WICPixelFormatGUID formatDesired = GUID_WICPixelFormat32bppBGRA;
-    if (kJPEG_Type == fType) {
+    if (SkEncodedImageFormat::kJPEG == fType) {
         formatDesired = GUID_WICPixelFormat24bppBGR;
         rowBytes = SkAlign4(bitmap.width() * 3);
         pixelStorage.reset(rowBytes * bitmap.height());
@@ -219,10 +219,10 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 #ifdef SK_USE_WIC_ENCODER
-static SkImageEncoder* sk_imageencoder_wic_factory(SkImageEncoder::Type t) {
+static SkImageEncoder* sk_imageencoder_wic_factory(SkEncodedImageFormat t) {
     switch (t) {
-        case SkImageEncoder::kPNG_Type:
-        case SkImageEncoder::kJPEG_Type:
+        case SkEncodedImageFormat::kPNG:
+        case SkEncodedImageFormat::kJPEG:
             break;
         default:
             return nullptr;
@@ -234,7 +234,7 @@
 #endif
 
 SkImageEncoder* CreateImageEncoder_WIC(SkImageEncoder::Type type) {
-    return new SkImageEncoder_WIC(type);
+    return new SkImageEncoder_WIC((SkEncodedImageFormat)type);
 }
 
 #endif // defined(SK_BUILD_FOR_WIN32)
diff --git a/src/ports/SkImageEncoder_none.cpp b/src/ports/SkImageEncoder_none.cpp
index 327a220..a26698b 100644
--- a/src/ports/SkImageEncoder_none.cpp
+++ b/src/ports/SkImageEncoder_none.cpp
@@ -5,63 +5,9 @@
  * found in the LICENSE file.
  */
 
-#include "SkBitmap.h"
-#include "SkImage.h"
 #include "SkImageEncoder.h"
-#include "SkPixelSerializer.h"
-#include "SkStream.h"
 
-/////////////////////////////////////////////////////////////////////////
-
-// Empty implementations for SkImageEncoder.
-
-SkImageEncoder* SkImageEncoder::Create(Type t) {
-    return nullptr;
-}
-
-bool SkImageEncoder::EncodeFile(const char file[], const SkBitmap&, Type, int quality) {
+bool SkEncodeImage(SkWStream*, const SkPixmap&, SkEncodedImageFormat, int) {
     return false;
 }
 
-bool SkImageEncoder::EncodeStream(SkWStream*, const SkBitmap&, SkImageEncoder::Type, int) {
-    return false;
-}
-
-SkData* SkImageEncoder::EncodeData(const SkBitmap&, Type, int quality) {
-    return nullptr;
-}
-
-SkData* SkImageEncoder::EncodeData(const SkImageInfo&, const void* pixels, size_t rowBytes,
-                                   Type, int quality) {
-    return nullptr;
-}
-
-SkData* SkImageEncoder::EncodeData(const SkPixmap&, Type, int) {
-    return nullptr;
-}
-
-bool SkImageEncoder::encodeStream(SkWStream*, const SkBitmap&, int) {
-    return false;
-}
-
-SkData* SkImageEncoder::encodeData(const SkBitmap&, int) {
-    return nullptr;
-}
-
-bool SkImageEncoder::encodeFile(const char file[], const SkBitmap& bm, int quality) {
-    return false;
-}
-
-namespace {
-class ImageEncoderPixelSerializer final : public SkPixelSerializer {
-protected:
-    bool onUseEncodedData(const void*, size_t) override { return true; }
-    SkData* onEncode(const SkPixmap&) override { return nullptr; }
-};
-}  // namespace
-
-SkPixelSerializer* SkImageEncoder::CreatePixelSerializer() {
-    return new ImageEncoderPixelSerializer;
-}
-
-/////////////////////////////////////////////////////////////////////////
diff --git a/src/svg/SkSVGDevice.cpp b/src/svg/SkSVGDevice.cpp
index ffdf034..b9f1424 100644
--- a/src/svg/SkSVGDevice.cpp
+++ b/src/svg/SkSVGDevice.cpp
@@ -659,10 +659,14 @@
     }
 }
 
+static sk_sp<SkData> encode(const SkBitmap& src) {
+    SkDynamicMemoryWStream buf;
+    return SkEncodeImage(&buf, src, SkEncodedImageFormat::kPNG, 80) ? buf.detachAsData() : nullptr;
+}
+
 void SkSVGDevice::drawBitmapCommon(const SkDraw& draw, const SkBitmap& bm,
                                    const SkPaint& paint) {
-    sk_sp<const SkData> pngData(
-        SkImageEncoder::EncodeData(bm, SkImageEncoder::kPNG_Type, SkImageEncoder::kDefaultQuality));
+    sk_sp<SkData> pngData = encode(bm);
     if (!pngData) {
         return;
     }
diff --git a/src/xps/SkXPSDevice.cpp b/src/xps/SkXPSDevice.cpp
index 22c7b24..3787433 100644
--- a/src/xps/SkXPSDevice.cpp
+++ b/src/xps/SkXPSDevice.cpp
@@ -658,8 +658,7 @@
         const SkAlpha alpha,
         IXpsOMTileBrush** xpsBrush) {
     SkDynamicMemoryWStream write;
-    if (!SkImageEncoder::EncodeStream(&write, bitmap,
-                                      SkImageEncoder::kPNG_Type, 100)) {
+    if (!SkEncodeImage(&write, bitmap, SkEncodedImageFormat::kPNG, 100)) {
         HRM(E_FAIL, "Unable to encode bitmap as png.");
     }
     SkMemoryStream* read = new SkMemoryStream;
diff --git a/tests/BlitRowTest.cpp b/tests/BlitRowTest.cpp
index b4a4a64..3439a5e 100644
--- a/tests/BlitRowTest.cpp
+++ b/tests/BlitRowTest.cpp
@@ -12,6 +12,8 @@
 #include "SkRect.h"
 #include "Test.h"
 
+#include "sk_tool_utils.h"
+
 // these are in the same order as the SkColorType enum
 static const char* gColorTypeName[] = {
     "None", "A8", "565", "4444", "RGBA", "BGRA", "Index8"
@@ -178,7 +180,7 @@
 
 #include "SkImageEncoder.h"
 static void save_bm(const SkBitmap& bm, const char name[]) {
-    SkImageEncoder::EncodeFile(name, bm, SkImageEncoder::kPNG_Type, 100);
+    sk_tool_utils::EncodeImageToFile(name, bm, SkEncodedImageFormat::kPNG, 100);
 }
 
 static bool gOnce;
diff --git a/tests/CodecTest.cpp b/tests/CodecTest.cpp
index dacabca..d15c710 100644
--- a/tests/CodecTest.cpp
+++ b/tests/CodecTest.cpp
@@ -23,6 +23,8 @@
 
 #include "png.h"
 
+#include "sk_tool_utils.h"
+
 #if PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR < 5
     // FIXME (scroggo): Google3 needs to be updated to use a newer version of libpng. In
     // the meantime, we had to break some pieces of SkPngCodec in order to support Google3.
@@ -1102,7 +1104,7 @@
 
     // Encode the image to png.
     sk_sp<SkData> data =
-            sk_sp<SkData>(SkImageEncoder::EncodeData(bm1, SkImageEncoder::kPNG_Type, 100));
+            sk_sp<SkData>(sk_tool_utils::EncodeImageToData(bm1, SkEncodedImageFormat::kPNG, 100));
 
     std::unique_ptr<SkCodec> codec(SkCodec::NewFromData(data));
     REPORTER_ASSERT(r, color_type_match(info.colorType(), codec->getInfo().colorType()));
diff --git a/tests/ImageTest.cpp b/tests/ImageTest.cpp
index 18883fe..020e322 100644
--- a/tests/ImageTest.cpp
+++ b/tests/ImageTest.cpp
@@ -26,6 +26,8 @@
 #include "SkUtils.h"
 #include "Test.h"
 
+#include "sk_tool_utils.h"
+
 #if SK_SUPPORT_GPU
 #include "GrGpu.h"
 #endif
@@ -153,7 +155,7 @@
     sk_sp<SkData> data(create_image_data(&info));
     SkBitmap bitmap;
     bitmap.installPixels(info, data->writable_data(), info.minRowBytes());
-    sk_sp<SkData> src(SkImageEncoder::EncodeData(bitmap, SkImageEncoder::kPNG_Type, 100));
+    sk_sp<SkData> src(sk_tool_utils::EncodeImageToData(bitmap, SkEncodedImageFormat::kPNG, 100));
     return SkImage::MakeFromEncoded(std::move(src));
 }
 #if SK_SUPPORT_GPU
@@ -1026,7 +1028,7 @@
     make_all_premul(&bm0);
 
     auto img0 = SkImage::MakeFromBitmap(bm0);
-    sk_sp<SkData> data(img0->encode(SkImageEncoder::kPNG_Type, 100));
+    sk_sp<SkData> data(img0->encode(SkEncodedImageFormat::kPNG, 100));
     auto img1 = SkImage::MakeFromEncoded(data);
 
     SkBitmap bm1;
diff --git a/tests/PDFDocumentTest.cpp b/tests/PDFDocumentTest.cpp
index fca8496..b320015 100644
--- a/tests/PDFDocumentTest.cpp
+++ b/tests/PDFDocumentTest.cpp
@@ -14,6 +14,8 @@
 #include "SkStream.h"
 #include "SkPixelSerializer.h"
 
+#include "sk_tool_utils.h"
+
 static void test_empty(skiatest::Reporter* reporter) {
     SkDynamicMemoryWStream stream;
 
@@ -119,14 +121,7 @@
 class JPEGSerializer final : public SkPixelSerializer {
     bool onUseEncodedData(const void*, size_t) override { return true; }
     SkData* onEncode(const SkPixmap& pixmap) override {
-        SkBitmap bm;
-        return bm.installPixels(pixmap.info(),
-                                pixmap.writable_addr(),
-                                pixmap.rowBytes(),
-                                pixmap.ctable(),
-                                nullptr, nullptr)
-            ? SkImageEncoder::EncodeData(bm, SkImageEncoder::kJPEG_Type, 85)
-            : nullptr;
+        return sk_tool_utils::EncodeImageToData(pixmap, SkEncodedImageFormat::kJPEG, 85).release();
     }
 };
 }  // namespace
diff --git a/tests/PathOpsConicIntersectionTest.cpp b/tests/PathOpsConicIntersectionTest.cpp
index 41c0acb..1de1583 100644
--- a/tests/PathOpsConicIntersectionTest.cpp
+++ b/tests/PathOpsConicIntersectionTest.cpp
@@ -110,8 +110,8 @@
     canvas.drawPath(path, paint);
     SkString filename("c:\\Users\\caryclark\\Documents\\");
     filename.appendf("%s.png", name);
-    SkImageEncoder::EncodeFile(filename.c_str(), bitmap,
-            SkImageEncoder::kPNG_Type, 100);
+    sk_tool_utils::EncodeImageToFile(filename.c_str(), bitmap,
+            SkEncodedImageFormat::kPNG, 100);
 }
 
 static void writeDPng(const SkDConic& dC, const char* name) {
@@ -152,8 +152,8 @@
     canvas.drawPath(path, paint);
     SkString filename("c:\\Users\\caryclark\\Documents\\");
     filename.appendf("%s.png", name);
-    SkImageEncoder::EncodeFile(filename.c_str(), bitmap,
-            SkImageEncoder::kPNG_Type, 100);
+    sk_tool_utils::EncodeImageToFile(filename.c_str(), bitmap,
+            SkEncodedImageFormat::kPNG, 100);
 }
 #endif
 
@@ -290,7 +290,7 @@
         }
         SkString filename("c:\\Users\\caryclark\\Documents\\");
         filename.appendf("f%d.png", index);
-        SkImageEncoder::EncodeFile(filename.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100);
+        sk_tool_utils::EncodeImageToFile(filename.c_str(), bitmap, SkEncodedImageFormat::kPNG, 100);
     }
 }
 #endif
diff --git a/tests/PathOpsSkpClipTest.cpp b/tests/PathOpsSkpClipTest.cpp
index 3cbe7ef..57e9bd1 100644
--- a/tests/PathOpsSkpClipTest.cpp
+++ b/tests/PathOpsSkpClipTest.cpp
@@ -429,7 +429,7 @@
 static void writePict(const SkBitmap& bitmap, const char* outDir, const char* pngName) {
     SkString outFile = get_sum_path(outDir);
     outFile.appendf("%s%s", PATH_SLASH, pngName);
-    if (!SkImageEncoder::EncodeFile(outFile.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100)) {
+    if (!sk_tool_utils::EncodeImageToFile(outFile.c_str(), bitmap, SkEncodedImageFormat::kPNG, 100)) {
         SkDebugf("unable to encode gr %s (width=%d height=%d)\n", pngName,
                     bitmap.width(), bitmap.height());
     }
diff --git a/tests/SkpSkGrTest.cpp b/tests/SkpSkGrTest.cpp
index c87926e..0e425a0 100644
--- a/tests/SkpSkGrTest.cpp
+++ b/tests/SkpSkGrTest.cpp
@@ -368,8 +368,8 @@
 
 static void writePict(const SkBitmap& bitmap, const char* outDir, const char* pngName) {
     SkString outFile = make_filepath(0, outDir, pngName);
-    if (!SkImageEncoder::EncodeFile(outFile.c_str(), bitmap,
-            SkImageEncoder::kPNG_Type, 100)) {
+    if (!sk_tool_utils::EncodeImageToFile(outFile.c_str(), bitmap,
+            SkEncodedImageFormat::kPNG, 100)) {
         SkDebugf("unable to encode gr %s (width=%d height=%d)br \n", pngName,
                     bitmap.width(), bitmap.height());
     }
diff --git a/tools/colorspaceinfo.cpp b/tools/colorspaceinfo.cpp
index 301f47d..945c4a5 100644
--- a/tools/colorspaceinfo.cpp
+++ b/tools/colorspaceinfo.cpp
@@ -17,6 +17,8 @@
 #include "SkMatrix44.h"
 #include "SkOSFile.h"
 
+#include "sk_tool_utils.h"
+
 __SK_FORCE_IMAGE_DECODER_LINKING;
 
 DEFINE_string(input, "input.png", "A path to the input image or icc profile.");
@@ -219,7 +221,7 @@
     }
 
     // Finally, encode the result to the output file.
-    sk_sp<SkData> out(SkImageEncoder::EncodeData(gamut, SkImageEncoder::kPNG_Type, 100));
+    sk_sp<SkData> out = sk_tool_utils::EncodeImageToData(gamut, SkEncodedImageFormat::kPNG, 100);
     if (!out) {
         SkDebugf("Failed to encode gamut output.\n");
         return -1;
@@ -243,7 +245,7 @@
             SkDebugf("Could not decode input image.\n");
             return -1;
         }
-        out.reset(SkImageEncoder::EncodeData(bitmap, SkImageEncoder::kPNG_Type, 100));
+        out = sk_tool_utils::EncodeImageToData(bitmap, SkEncodedImageFormat::kPNG, 100);
         if (!out) {
             SkDebugf("Failed to encode uncorrected image.\n");
             return -1;
diff --git a/tools/get_images_from_skps.cpp b/tools/get_images_from_skps.cpp
index 6cd3512..d3a2343 100644
--- a/tools/get_images_from_skps.cpp
+++ b/tools/get_images_from_skps.cpp
@@ -65,14 +65,14 @@
         }
         SkString ext;
         switch (codec->getEncodedFormat()) {
-            case SkEncodedFormat::kBMP_SkEncodedFormat:  ext =  "bmp"; break;
-            case SkEncodedFormat::kGIF_SkEncodedFormat:  ext =  "gif"; break;
-            case SkEncodedFormat::kICO_SkEncodedFormat:  ext =  "ico"; break;
-            case SkEncodedFormat::kJPEG_SkEncodedFormat: ext =  "jpg"; break;
-            case SkEncodedFormat::kPNG_SkEncodedFormat:  ext =  "png"; break;
-            case SkEncodedFormat::kDNG_SkEncodedFormat:  ext =  "dng"; break;
-            case SkEncodedFormat::kWBMP_SkEncodedFormat: ext = "wbmp"; break;
-            case SkEncodedFormat::kWEBP_SkEncodedFormat: ext = "webp"; break;
+            case SkEncodedImageFormat::kBMP:  ext =  "bmp"; break;
+            case SkEncodedImageFormat::kGIF:  ext =  "gif"; break;
+            case SkEncodedImageFormat::kICO:  ext =  "ico"; break;
+            case SkEncodedImageFormat::kJPEG: ext =  "jpg"; break;
+            case SkEncodedImageFormat::kPNG:  ext =  "png"; break;
+            case SkEncodedImageFormat::kDNG:  ext =  "dng"; break;
+            case SkEncodedImageFormat::kWBMP: ext = "wbmp"; break;
+            case SkEncodedImageFormat::kWEBP: ext = "webp"; break;
             default:
                 // This should be unreachable because we cannot create a codec if we do not know
                 // the image type.
diff --git a/tools/imgblur.cpp b/tools/imgblur.cpp
index 3a0ae00..28d8447 100644
--- a/tools/imgblur.cpp
+++ b/tools/imgblur.cpp
@@ -66,7 +66,7 @@
 
     SkBitmap dst = sk_tool_utils::slow_blur(src, (float) FLAGS_sigma);
 
-    if (!SkImageEncoder::EncodeFile(FLAGS_out[0], dst, SkImageEncoder::kPNG_Type, 100)) {
+    if (!sk_tool_utils::EncodeImageToFile(FLAGS_out[0], dst, SkEncodedImageFormat::kPNG, 100)) {
         if (!FLAGS_quiet) {
             SkDebugf("Couldn't write to file: %s\n", FLAGS_out[0]);
         }
diff --git a/tools/picture_utils.cpp b/tools/picture_utils.cpp
index 43ca2f0..84925b4 100644
--- a/tools/picture_utils.cpp
+++ b/tools/picture_utils.cpp
@@ -17,6 +17,8 @@
 #include "SkStream.h"
 #include "SkString.h"
 
+#include "sk_tool_utils.h"
+
 namespace sk_tools {
     void force_all_opaque(const SkBitmap& bitmap) {
         SkASSERT(kN32_SkColorType == bitmap.colorType());
@@ -63,7 +65,7 @@
             partialPath.set(dirPath);
         }
         SkString fullPath = SkOSPath::Join(partialPath.c_str(), baseName.c_str());
-        if (SkImageEncoder::EncodeFile(fullPath.c_str(), bm, SkImageEncoder::kPNG_Type, 100)) {
+        if (sk_tool_utils::EncodeImageToFile(fullPath.c_str(), bm, SkEncodedImageFormat::kPNG, 100)) {
             return true;
         } else {
             SkDebugf("Failed to write the bitmap to %s.\n", fullPath.c_str());
diff --git a/tools/sk_tool_utils.h b/tools/sk_tool_utils.h
index c6abbcf..526f0ef 100644
--- a/tools/sk_tool_utils.h
+++ b/tools/sk_tool_utils.h
@@ -225,6 +225,31 @@
         SkTDArray<TopoTestNode*> fDependencies;
     };
 
+    template <typename T>
+    inline bool EncodeImageToFile(const char* path, const T& src, SkEncodedImageFormat f, int q) {
+        SkFILEWStream file(path);
+        return file.isValid() && SkEncodeImage(&file, src, f, q);
+    }
+
+    template <typename T>
+    inline sk_sp<SkData> EncodeImageToData(const T& src, SkEncodedImageFormat f, int q) {
+        SkDynamicMemoryWStream buf;
+        return SkEncodeImage(&buf, src , f, q) ? buf.detachAsData() : nullptr;
+    }
+
+    /**
+     * Uses SkEncodeImage to serialize images that are not already
+     * encoded as SkEncodedImageFormat::kPNG images.
+     */
+    inline sk_sp<SkPixelSerializer> MakePixelSerializer() {
+        struct EncodeImagePixelSerializer final : SkPixelSerializer {
+            bool onUseEncodedData(const void*, size_t) override { return true; }
+            SkData* onEncode(const SkPixmap& pmap) override {
+                return EncodeImageToData(pmap, SkEncodedImageFormat::kPNG, 100).release();
+            }
+        };
+        return sk_make_sp<EncodeImagePixelSerializer>();
+    }
 }  // namespace sk_tool_utils
 
 #endif  // sk_tool_utils_DEFINED
diff --git a/tools/skdiff/skdiff_utils.cpp b/tools/skdiff/skdiff_utils.cpp
index f788ec8..f8eed90 100644
--- a/tools/skdiff/skdiff_utils.cpp
+++ b/tools/skdiff/skdiff_utils.cpp
@@ -6,6 +6,7 @@
  */
 #include "skdiff.h"
 #include "skdiff_utils.h"
+#include "sk_tool_utils.h"
 #include "SkBitmap.h"
 #include "SkCodec.h"
 #include "SkData.h"
@@ -82,8 +83,8 @@
     SkBitmap copy;
     bitmap.copyTo(&copy, kN32_SkColorType);
     force_all_opaque(copy);
-    return SkImageEncoder::EncodeFile(path.c_str(), copy,
-                                      SkImageEncoder::kPNG_Type, 100);
+    return sk_tool_utils::EncodeImageToFile(path.c_str(), copy,
+                                      SkEncodedImageFormat::kPNG, 100);
 }
 
 /// Return a copy of the "input" string, within which we have replaced all instances
diff --git a/tools/skiaserve/Request.cpp b/tools/skiaserve/Request.cpp
index c1b3b25..2064a46 100644
--- a/tools/skiaserve/Request.cpp
+++ b/tools/skiaserve/Request.cpp
@@ -11,6 +11,7 @@
 #include "SkPixelSerializer.h"
 #include "SkPM4fPriv.h"
 #include "picture_utils.h"
+#include "sk_tool_utils.h"
 
 using namespace sk_gpu_test;
 
@@ -117,7 +118,7 @@
 
     SkDynamicMemoryWStream outStream;
 
-    sk_sp<SkPixelSerializer> serializer(SkImageEncoder::CreatePixelSerializer());
+    sk_sp<SkPixelSerializer> serializer = sk_tool_utils::MakePixelSerializer();
     picture->serialize(&outStream, serializer.get());
 
     return outStream.detachAsData();