SkImageEncoder: simplify API

(re-land 248ff02 & 2cb6cb7, with changes)

  - 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

Change-Id: I47d451e50be4d5c6c130869c7fa7c2857243d9f0
Reviewed-on: https://skia-review.googlesource.com/4909
Reviewed-by: Mike Reed <reed@google.com>
Reviewed-by: Leon Scroggins <scroggo@google.com>
Reviewed-on: https://skia-review.googlesource.com/5186
Commit-Queue: Hal Canary <halcanary@google.com>
Reviewed-by: Hal Canary <halcanary@google.com>
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 3487b7d..e043681 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..c137bc5 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)) {
-        return nullptr;
+    if (!bm.installPixels(src)) {
+        return false;
     }
     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 62c0346..6717bea 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"
@@ -40,7 +40,7 @@
 DEFINE_ENCODER_CREATOR(KTXImageEncoder);
 
 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;