SkEncodeImage: no more link-time registration

Also, no more SkImageEncoder class.

SK_SUPPORT_LEGACY_IMAGE_ENCODER_CLASS now only guards some
old API shims.

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

Change-Id: I3797f584f3e8e12ade10d31e8733163453725f40
Reviewed-on: https://skia-review.googlesource.com/5006
Commit-Queue: Hal Canary <halcanary@google.com>
Reviewed-by: Leon Scroggins <scroggo@google.com>
Reviewed-by: Mike Reed <reed@google.com>
diff --git a/BUILD.gn b/BUILD.gn
index dca76eb..078b205 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -576,7 +576,6 @@
     "src/codec/SkSwizzler.cpp",
     "src/codec/SkWbmpCodec.cpp",
     "src/images/SkImageEncoder.cpp",
-    "src/images/SkImageEncoder_Factory.cpp",
     "src/images/SkKTXImageEncoder.cpp",
     "src/ports/SkDiscardableMemory_none.cpp",
     "src/ports/SkGlobalInitialization_default.cpp",
@@ -720,7 +719,6 @@
       }
 
       sources = [
-        "src/images/SkForceLinking.cpp",
         "tools/fiddle/draw.cpp",
         "tools/fiddle/fiddle_main.cpp",
       ]
@@ -848,7 +846,6 @@
       "tools/timer",
     ]
     sources = [
-      "src/images/SkForceLinking.cpp",
       "src/utils/SkMultiPictureDocumentReader.cpp",  # TODO(halcanary): move to tools?
       "tools/AndroidSkDebugToStdOut.cpp",
       "tools/CrashHandler.cpp",
diff --git a/bench/nanobench.cpp b/bench/nanobench.cpp
index 3587242..5abecd6 100644
--- a/bench/nanobench.cpp
+++ b/bench/nanobench.cpp
@@ -32,7 +32,6 @@
 #include "SkCommonFlags.h"
 #include "SkCommonFlagsConfig.h"
 #include "SkData.h"
-#include "SkForceLinking.h"
 #include "SkGraphics.h"
 #include "SkLeanWindows.h"
 #include "SkOSFile.h"
@@ -69,8 +68,6 @@
 
     struct GrContextOptions;
 
-__SK_FORCE_IMAGE_DECODER_LINKING;
-
 static const int kAutoTuneLoops = 0;
 
 static const int kDefaultLoops =
diff --git a/debugger/debuggermain.cpp b/debugger/debuggermain.cpp
index eebcd5f..30c2335 100644
--- a/debugger/debuggermain.cpp
+++ b/debugger/debuggermain.cpp
@@ -7,13 +7,9 @@
  */
 
 #include "SkDebuggerGUI.h"
-#include "SkForceLinking.h"
 #include "SkGraphics.h"
 #include <QApplication>
 
-__SK_FORCE_IMAGE_DECODER_LINKING;
-
-
 static void usage(const char * argv0) {
     SkDebugf("%s <input> \n", argv0);
     SkDebugf("    [--help|-h]: show this help message\n");
diff --git a/gm/encode-platform.cpp b/gm/encode-platform.cpp
index 0357298..e8f420f 100644
--- a/gm/encode-platform.cpp
+++ b/gm/encode-platform.cpp
@@ -37,26 +37,6 @@
     bitmap->setAlphaType(kUnpremul_SkAlphaType);
 }
 
-static SkImageEncoder* make_encoder(SkEncodedImageFormat type) {
-#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
-    return CreateImageEncoder_CG((SkImageEncoder::Type)type);
-#elif defined(SK_BUILD_FOR_WIN)
-    return CreateImageEncoder_WIC((SkImageEncoder::Type)type);
-#else
-    switch (type) {
-        case SkEncodedImageFormat::kPNG:
-            return CreatePNGImageEncoder();
-        case SkEncodedImageFormat::kJPEG:
-            return CreateJPEGImageEncoder();
-        case SkEncodedImageFormat::kWEBP:
-            return CreateWEBPImageEncoder();
-        default:
-            SkASSERT(false);
-            return nullptr;
-    }
-#endif
-}
-
 #if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
 static SkEncodedImageFormat kTypes[] {
         SkEncodedImageFormat::kPNG, SkEncodedImageFormat::kJPEG, SkEncodedImageFormat::kGIF,
@@ -76,9 +56,30 @@
 };
 #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;
+static sk_sp<SkData> encode_data(SkEncodedImageFormat type, const SkBitmap& bitmap) {
+    SkAutoLockPixels autoLockPixels(bitmap);
+    SkPixmap src;
+    if (!bitmap.peekPixels(&src)) {
+        return nullptr;
+    }
+    SkDynamicMemoryWStream buf;
+    #if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
+        return SkEncodeImageWithCG(&buf, src, type) ? buf.detachAsData() : nullptr;
+    #elif defined(SK_BUILD_FOR_WIN)
+        return SkEncodeImageWithWIC(&buf, src, type, 100) ? buf.detachAsData() : nullptr;
+    #else
+        switch (type) {
+            case SkEncodedImageFormat::kPNG:
+                return SkEncodeImageAsPNG(&buf, src) ? buf.detachAsData() : nullptr;
+            case SkEncodedImageFormat::kJPEG:
+                return SkEncodeImageAsJPEG(&buf, src, 100) ? buf.detachAsData() : nullptr;
+            case SkEncodedImageFormat::kWEBP:
+                return SkEncodeImageAsWEBP(&buf, src, 100) ? buf.detachAsData() : nullptr;
+            default:
+                SkASSERT(false);
+                return nullptr;
+        }
+    #endif
 }
 
 class EncodePlatformGM : public GM {
@@ -101,11 +102,9 @@
         make_unpremul_256(&unpremulBm);
 
         for (SkEncodedImageFormat type : kTypes) {
-            std::unique_ptr<SkImageEncoder> encoder(make_encoder(type));
-
-            auto opaqueImage = SkImage::MakeFromEncoded(encode_data(encoder, opaqueBm));
-            auto premulImage = SkImage::MakeFromEncoded(encode_data(encoder, premulBm));
-            auto unpremulImage = SkImage::MakeFromEncoded(encode_data(encoder, unpremulBm));
+            auto opaqueImage = SkImage::MakeFromEncoded(encode_data(type, opaqueBm));
+            auto premulImage = SkImage::MakeFromEncoded(encode_data(type, premulBm));
+            auto unpremulImage = SkImage::MakeFromEncoded(encode_data(type, unpremulBm));
 
             canvas->drawImage(opaqueImage.get(), 0.0f, 0.0f);
             canvas->drawImage(premulImage.get(), 0.0f, 256.0f);
diff --git a/gyp/images.gyp b/gyp/images.gyp
index 1b9920e..efeb3d2 100644
--- a/gyp/images.gyp
+++ b/gyp/images.gyp
@@ -30,21 +30,12 @@
         '../src/image/',
       ],
       'sources': [
-        '../include/images/SkForceLinking.h',
-
-        '../src/images/SkForceLinking.cpp',
-
-        # If encoders are added/removed to/from (all/individual)
-        # platform(s), be sure to update SkForceLinking.cpp
-        # so the right decoders will be forced to link.
-
         '../src/images/SkKTXImageEncoder.cpp',
         '../src/images/SkWEBPImageEncoder.cpp',
         '../src/images/SkJPEGImageEncoder.cpp',
         '../src/images/SkPNGImageEncoder.cpp',
 
         '../src/images/SkImageEncoder.cpp',
-        '../src/images/SkImageEncoder_Factory.cpp',
         '../src/images/SkJPEGWriteUtility.cpp',
 
         '../src/ports/SkImageEncoder_CG.cpp',
diff --git a/include/android/SkBitmapRegionDecoder.h b/include/android/SkBitmapRegionDecoder.h
index b8922d4..660aa0a 100644
--- a/include/android/SkBitmapRegionDecoder.h
+++ b/include/android/SkBitmapRegionDecoder.h
@@ -10,7 +10,7 @@
 
 #include "SkBitmap.h"
 #include "SkBRDAllocator.h"
-#include "SkEncodedFormat.h"
+#include "SkEncodedImageFormat.h"
 #include "SkStream.h"
 
 /*
@@ -66,7 +66,7 @@
      */
     virtual bool conversionSupported(SkColorType colorType) = 0;
 
-    virtual SkEncodedFormat getEncodedFormat() = 0;
+    virtual SkEncodedImageFormat getEncodedFormat() = 0;
 
     int width() const { return fWidth; }
     int height() const { return fHeight; }
diff --git a/include/codec/SkAndroidCodec.h b/include/codec/SkAndroidCodec.h
index ee9d0f3..a4f46f9 100644
--- a/include/codec/SkAndroidCodec.h
+++ b/include/codec/SkAndroidCodec.h
@@ -9,7 +9,7 @@
 #define SkAndroidCodec_DEFINED
 
 #include "SkCodec.h"
-#include "SkEncodedFormat.h"
+#include "SkEncodedImageFormat.h"
 #include "SkStream.h"
 #include "SkTypes.h"
 
@@ -51,7 +51,7 @@
     /**
      *  Format of the encoded data.
      */
-    SkEncodedFormat getEncodedFormat() const { return (SkEncodedFormat)fCodec->getEncodedFormat(); }
+    SkEncodedImageFormat getEncodedFormat() const { return fCodec->getEncodedFormat(); }
 
     /**
      *  @param requestedColorType Color type requested by the client
diff --git a/include/codec/SkEncodedFormat.h b/include/codec/SkEncodedFormat.h
deleted file mode 100644
index 485bff1..0000000
--- a/include/codec/SkEncodedFormat.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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 SkEncodedFormat_DEFINED
-#define SkEncodedFormat_DEFINED
-
-#include "SkEncodedImageFormat.h"
-#include "SkTypes.h"
-
-#ifdef SK_SUPPORT_LEGACY_IMAGE_ENCODER_CLASS
-
-enum SkEncodedFormat {
-    kBMP_SkEncodedFormat  = (int)SkEncodedImageFormat::kBMP,
-    kGIF_SkEncodedFormat  = (int)SkEncodedImageFormat::kGIF,
-    kICO_SkEncodedFormat  = (int)SkEncodedImageFormat::kICO,
-    kJPEG_SkEncodedFormat = (int)SkEncodedImageFormat::kJPEG,
-    kPNG_SkEncodedFormat  = (int)SkEncodedImageFormat::kPNG,
-    kWBMP_SkEncodedFormat = (int)SkEncodedImageFormat::kWBMP,
-    kWEBP_SkEncodedFormat = (int)SkEncodedImageFormat::kWEBP,
-    kPKM_SkEncodedFormat  = (int)SkEncodedImageFormat::kPKM,
-    kKTX_SkEncodedFormat  = (int)SkEncodedImageFormat::kKTX,
-    kASTC_SkEncodedFormat = (int)SkEncodedImageFormat::kASTC,
-    kDNG_SkEncodedFormat  = (int)SkEncodedImageFormat::kDNG,
-};
-
-#else
-
-typedef SkEncodedImageFormat SkEncodedFormat;
-
-#endif  // SK_SUPPORT_LEGACY_IMAGE_ENCODER_CLASS
-
-#endif  // SkEncodedFormat_DEFINED
diff --git a/include/core/SkImageEncoder.h b/include/core/SkImageEncoder.h
index 41cdb38..17d0603 100644
--- a/include/core/SkImageEncoder.h
+++ b/include/core/SkImageEncoder.h
@@ -10,9 +10,7 @@
 
 #include "SkBitmap.h"
 #include "SkEncodedImageFormat.h"
-#include "SkPixelSerializer.h"
 #include "SkStream.h"
-#include "SkTRegistry.h"
 
 /**
  * Encode SkPixmap in the given binary image format.
@@ -41,10 +39,8 @@
     return src.peekPixels(&pixmap) && SkEncodeImage(dst, pixmap, f, q);
 }
 
+//TODO(halcanary):  remove this code once all changes land.
 #ifdef SK_SUPPORT_LEGACY_IMAGE_ENCODER_CLASS
-
-////////////////////////////////////////////////////////////////////////////////
-
 class SkImageEncoder {
 public:
     enum Type {
@@ -60,65 +56,11 @@
         kWEBP_Type    = (int)SkEncodedImageFormat::kWEBP,
         kKTX_Type     = (int)SkEncodedImageFormat::kKTX,
     };
-    static SkImageEncoder* Create(Type);
-
-    virtual ~SkImageEncoder() {}
-
-    /*  Quality ranges from 0..100 */
-    enum {
-        kDefaultQuality = 80
-    };
-
-    /**
-     *  Encode bitmap 'bm', returning the results in an SkData, at quality level
-     *  'quality' (which can be in range 0-100). If the bitmap cannot be
-     *  encoded, return null. On success, the caller is responsible for
-     *  calling unref() on the data when they are finished.
-     */
-    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 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* dst, const SkBitmap& src, int quality) {
-        return this->onEncode(dst, src, SkMin32(100, SkMax32(0, 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 SkBitmap& src, Type t, int quality) {
         SkDynamicMemoryWStream buf;
         return SkEncodeImage(&buf, src, (SkEncodedImageFormat)t, quality)
             ? buf.detachAsData().release() : nullptr;
     }
-
-    static SkData* EncodeData(const SkPixmap& pixmap, Type t, int quality) {
-        SkDynamicMemoryWStream buf;
-        return SkEncodeImage(&buf, pixmap, (SkEncodedImageFormat)t, quality)
-            ? buf.detachAsData().release() : nullptr;
-    }
-
     static bool EncodeFile(const char path[], const SkBitmap& src, Type t, int quality) {
         SkFILEWStream file(path);
         return SkEncodeImage(&file, src, (SkEncodedImageFormat)t, quality);
@@ -126,17 +68,7 @@
     static bool EncodeStream(SkWStream* dst, const SkBitmap& bm, Type t, int quality) {
         return SkEncodeImage(dst, bm, (SkEncodedImageFormat)t, 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).
-     *
-     * This must be overridden by each SkImageEncoder implementation.
-     */
-    virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) = 0;
 };
-
 #endif  // SK_SUPPORT_LEGACY_IMAGE_ENCODER_CLASS
+
 #endif  // SkImageEncoder_DEFINED
diff --git a/include/images/SkForceLinking.h b/include/images/SkForceLinking.h
index 5de8918..ca52eeb 100644
--- a/include/images/SkForceLinking.h
+++ b/include/images/SkForceLinking.h
@@ -4,19 +4,4 @@
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
-
-#include "SkTypes.h"
-
-/**
- *  This function's sole purpose is to trick the linker into not discarding
- *  SkImageDecoder subclasses just because we do not directly call them.
- *  This is necessary in applications that will create image decoders from
- *  a stream.
- *  Call this function with an expression that evaluates to false to ensure
- *  that the linker includes the subclasses.
- *  Passing true will result in leaked objects.
- */
-int SkForceLinking(bool doNotPassTrue);
-
-#define __SK_FORCE_IMAGE_DECODER_LINKING       \
-SK_UNUSED static int linking_forced = SkForceLinking(false)
+// TODO(halcanary): delete this file.
diff --git a/samplecode/SampleApp.cpp b/samplecode/SampleApp.cpp
index a8c2e0b..b9f3cb4 100644
--- a/samplecode/SampleApp.cpp
+++ b/samplecode/SampleApp.cpp
@@ -738,14 +738,11 @@
 #endif
 
 #include "SkTaskGroup.h"
-#include "SkForceLinking.h"
 
 SampleWindow::SampleWindow(void* hwnd, int argc, char** argv, DeviceManager* devManager)
     : INHERITED(hwnd)
     , fDevManager(nullptr) {
 
-    SkForceLinking(false);
-
     SkCommandLineFlags::Parse(argc, argv);
 
     fCurrIndex = -1;
diff --git a/src/android/SkBitmapRegionCodec.h b/src/android/SkBitmapRegionCodec.h
index 2c9536c..c59879b 100644
--- a/src/android/SkBitmapRegionCodec.h
+++ b/src/android/SkBitmapRegionCodec.h
@@ -26,9 +26,7 @@
 
     bool conversionSupported(SkColorType colorType) override;
 
-    SkEncodedFormat getEncodedFormat() override {
-        return (SkEncodedFormat)fCodec->getEncodedFormat();
-    }
+    SkEncodedImageFormat getEncodedFormat() override { return fCodec->getEncodedFormat(); }
 
 private:
 
diff --git a/src/gpu/GrSurface.cpp b/src/gpu/GrSurface.cpp
index 3bb666e..83e5a05 100644
--- a/src/gpu/GrSurface.cpp
+++ b/src/gpu/GrSurface.cpp
@@ -14,6 +14,7 @@
 #include "SkGrPriv.h"
 #include "SkImageEncoder.h"
 #include "SkMathPriv.h"
+#include "SkStream.h"
 #include <stdio.h>
 
 GrSurface::~GrSurface() {
diff --git a/src/image/SkImage.cpp b/src/image/SkImage.cpp
index e043681..d8c3b32 100644
--- a/src/image/SkImage.cpp
+++ b/src/image/SkImage.cpp
@@ -22,6 +22,7 @@
 #include "SkPixelSerializer.h"
 #include "SkReadPixelsRec.h"
 #include "SkSpecialImage.h"
+#include "SkStream.h"
 #include "SkString.h"
 #include "SkSurface.h"
 
diff --git a/src/images/SkForceLinking.cpp b/src/images/SkForceLinking.cpp
deleted file mode 100644
index dfed6b4..0000000
--- a/src/images/SkForceLinking.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2013 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkImageEncoderPriv.h"
-#include "SkForceLinking.h"
-
-// This method is required to fool the linker into not discarding the pre-main
-// initialization and registration of the encoder classes. Passing true will
-// cause memory leaks.
-int SkForceLinking(bool doNotPassTrue) {
-    if (doNotPassTrue) {
-        SkASSERT(false);
-#if defined(SK_HAS_JPEG_LIBRARY) && !defined(SK_USE_CG_ENCODER) && !defined(SK_USE_WIC_ENCODER)
-        CreateJPEGImageEncoder();
-#endif
-#if defined(SK_HAS_WEBP_LIBRARY) && !defined(SK_USE_CG_ENCODER) && !defined(SK_USE_WIC_ENCODER)
-        CreateWEBPImageEncoder();
-#endif
-#if defined(SK_HAS_PNG_LIBRARY) && !defined(SK_USE_CG_ENCODER) && !defined(SK_USE_WIC_ENCODER)
-        CreatePNGImageEncoder();
-#endif
-
-        // Only link hardware texture codecs on platforms that build them. See images.gyp
-#ifndef SK_BUILD_FOR_ANDROID_FRAMEWORK
-        CreateKTXImageEncoder();
-#endif
-
-#if defined (SK_USE_CG_ENCODER)
-        CreateImageEncoder_CG(SkEncodedImageFormat::kPNG);
-#endif
-#if defined (SK_USE_WIC_ENCODER)
-        CreateImageEncoder_WIC(SkEncodedImageFormat::kPNG);
-#endif
-        return -1;
-    }
-    return 0;
-}
diff --git a/src/images/SkImageEncoder.cpp b/src/images/SkImageEncoder.cpp
index c137bc5..c5fff08 100644
--- a/src/images/SkImageEncoder.cpp
+++ b/src/images/SkImageEncoder.cpp
@@ -9,11 +9,18 @@
 
 bool SkEncodeImage(SkWStream* dst, const SkPixmap& src,
                    SkEncodedImageFormat format, int quality) {
-    SkBitmap bm;
-    if (!bm.installPixels(src)) {
-        return false;
-    }
-    bm.setImmutable();
-    std::unique_ptr<SkImageEncoder> enc(SkImageEncoder::Create((SkImageEncoder::Type)format));
-    return enc && enc->encodeStream(dst, bm, quality);
+    #ifdef SK_USE_CG_ENCODER
+        (void)quality;
+        return SkEncodeImageWithCG(dst, src, format);
+    #elif SK_USE_WIC_ENCODER
+        return SkEncodeImageWithWIC(dst, src, format, quality);
+    #else
+        switch(format) {
+            case SkEncodedImageFormat::kJPEG: return SkEncodeImageAsJPEG(dst, src, quality);
+            case SkEncodedImageFormat::kPNG:  return SkEncodeImageAsPNG(dst, src);
+            case SkEncodedImageFormat::kWEBP: return SkEncodeImageAsWEBP(dst, src, quality);
+            case SkEncodedImageFormat::kKTX:  return SkEncodeImageAsKTX(dst, src);
+            default:                          return false;
+        }
+    #endif
 }
diff --git a/src/images/SkImageEncoderPriv.h b/src/images/SkImageEncoderPriv.h
index 9b632f5..982930e 100644
--- a/src/images/SkImageEncoderPriv.h
+++ b/src/images/SkImageEncoderPriv.h
@@ -9,60 +9,37 @@
 #define SkImageEncoderPriv_DEFINED
 
 #include "SkImageEncoder.h"
-#include "SkTRegistry.h"
 
-#ifndef SK_SUPPORT_LEGACY_IMAGE_ENCODER_CLASS
+#ifdef SK_HAS_JPEG_LIBRARY
+    bool SkEncodeImageAsJPEG(SkWStream*, const SkPixmap&, int quality);
+#else
+    #define SkEncodeImageAsJPEG(...) false
+#endif
 
-    // TODO(halcanary): replace this class and registry system with something simpler.
-    class SkImageEncoder {
-    public:
-        typedef SkEncodedImageFormat Type;
-        static SkImageEncoder* Create(SkEncodedImageFormat);
+#ifdef SK_HAS_PNG_LIBRARY
+    bool SkEncodeImageAsPNG(SkWStream*, const SkPixmap&);
+#else
+    #define SkEncodeImageAsPNG(...) false
+#endif
 
-        virtual ~SkImageEncoder() {}
+#ifdef SK_HAS_WEBP_LIBRARY
+    bool SkEncodeImageAsWEBP(SkWStream*, const SkPixmap&, int quality);
+#else
+    #define SkEncodeImageAsWEBP(...) false
+#endif
 
-        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);
+bool SkEncodeImageAsKTX(SkWStream*, const SkPixmap&);
 
 #if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
-SkImageEncoder* CreateImageEncoder_CG(SkImageEncoder::Type type);
+    bool SkEncodeImageWithCG(SkWStream*, const SkPixmap&, SkEncodedImageFormat);
+#else
+    #define SkEncodeImageWithCG(...) false
 #endif
 
-#if defined(SK_BUILD_FOR_WIN)
-SkImageEncoder* CreateImageEncoder_WIC(SkImageEncoder::Type type);
+#ifdef SK_BUILD_FOR_WIN
+    bool SkEncodeImageWithWIC(SkWStream*, const SkPixmap&, SkEncodedImageFormat, int quality);
+#else
+    #define SkEncodeImageWithWIC(...) false
 #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
deleted file mode 100644
index a5ae8d0..0000000
--- a/src/images/SkImageEncoder_Factory.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright 2009 The Android Open Source Project
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkImageEncoderPriv.h"
-
-template SkImageEncoder_EncodeReg* SkImageEncoder_EncodeReg::gHead;
-
-SkImageEncoder* SkImageEncoder::Create(SkImageEncoder::Type t) {
-    SkImageEncoder* codec = nullptr;
-    const SkImageEncoder_EncodeReg* curr = SkImageEncoder_EncodeReg::Head();
-    while (curr) {
-        if ((codec = curr->factory()(t)) != nullptr) {
-            return codec;
-        }
-        curr = curr->next();
-    }
-    return nullptr;
-}
diff --git a/src/images/SkJPEGImageEncoder.cpp b/src/images/SkJPEGImageEncoder.cpp
index 97b8bbc..b1f943b 100644
--- a/src/images/SkJPEGImageEncoder.cpp
+++ b/src/images/SkJPEGImageEncoder.cpp
@@ -7,6 +7,8 @@
 
 #include "SkImageEncoderPriv.h"
 
+#ifdef SK_HAS_JPEG_LIBRARY
+
 #include "SkCanvas.h"
 #include "SkColorPriv.h"
 #include "SkDither.h"
@@ -83,8 +85,8 @@
     }
 }
 
-static WriteScanline ChooseWriter(const SkBitmap& bm) {
-    switch (bm.colorType()) {
+static WriteScanline ChooseWriter(SkColorType ct) {
+    switch (ct) {
         case kN32_SkColorType:
             return Write_32_RGB;
         case kRGB_565_SkColorType:
@@ -98,87 +100,73 @@
     }
 }
 
-class SkJPEGImageEncoder : public SkImageEncoder {
-protected:
-    virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) {
+bool SkEncodeImageAsJPEG(SkWStream* stream, const SkPixmap& pixmap, int quality) {
 #ifdef TIME_ENCODE
-        SkAutoTime atm("JPEG Encode");
+    SkAutoTime atm("JPEG Encode");
 #endif
 
-        SkAutoLockPixels alp(bm);
-        if (nullptr == bm.getPixels()) {
-            return false;
-        }
-
-        jpeg_compress_struct    cinfo;
-        skjpeg_error_mgr        sk_err;
-        skjpeg_destination_mgr  sk_wstream(stream);
-
-        // allocate these before set call setjmp
-        SkAutoTMalloc<uint8_t>  oneRow;
-
-        cinfo.err = jpeg_std_error(&sk_err);
-        sk_err.error_exit = skjpeg_error_exit;
-        if (setjmp(sk_err.fJmpBuf)) {
-            return false;
-        }
-
-        // Keep after setjmp or mark volatile.
-        const WriteScanline writer = ChooseWriter(bm);
-        if (nullptr == writer) {
-            return false;
-        }
-
-        jpeg_create_compress(&cinfo);
-        cinfo.dest = &sk_wstream;
-        cinfo.image_width = bm.width();
-        cinfo.image_height = bm.height();
-        cinfo.input_components = 3;
-        
-        // FIXME: Can we take advantage of other in_color_spaces in libjpeg-turbo?
-        cinfo.in_color_space = JCS_RGB;
-
-        // The gamma value is ignored by libjpeg-turbo.
-        cinfo.input_gamma = 1;
-
-        jpeg_set_defaults(&cinfo);
-        
-        // Tells libjpeg-turbo to compute optimal Huffman coding tables
-        // for the image.  This improves compression at the cost of
-        // slower encode performance.
-        cinfo.optimize_coding = TRUE;
-        jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
-
-        jpeg_start_compress(&cinfo, TRUE);
-
-        const int       width = bm.width();
-        uint8_t*        oneRowP = oneRow.reset(width * 3);
-
-        const SkPMColor* colors = bm.getColorTable() ? bm.getColorTable()->readColors() : nullptr;
-        const void*      srcRow = bm.getPixels();
-
-        while (cinfo.next_scanline < cinfo.image_height) {
-            JSAMPROW row_pointer[1];    /* pointer to JSAMPLE row[s] */
-
-            writer(oneRowP, srcRow, width, colors);
-            row_pointer[0] = oneRowP;
-            (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
-            srcRow = (const void*)((const char*)srcRow + bm.rowBytes());
-        }
-
-        jpeg_finish_compress(&cinfo);
-        jpeg_destroy_compress(&cinfo);
-
-        return true;
+    if (!pixmap.addr()) {
+        return false;
     }
-};
+    jpeg_compress_struct    cinfo;
+    skjpeg_error_mgr        sk_err;
+    skjpeg_destination_mgr  sk_wstream(stream);
 
-///////////////////////////////////////////////////////////////////////////////
-DEFINE_ENCODER_CREATOR(JPEGImageEncoder);
-///////////////////////////////////////////////////////////////////////////////
+    // allocate these before set call setjmp
+    SkAutoTMalloc<uint8_t>  oneRow;
 
-static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) {
-    return (SkEncodedImageFormat::kJPEG == (SkEncodedImageFormat)t) ? new SkJPEGImageEncoder : nullptr;
+    cinfo.err = jpeg_std_error(&sk_err);
+    sk_err.error_exit = skjpeg_error_exit;
+    if (setjmp(sk_err.fJmpBuf)) {
+        return false;
+    }
+
+    // Keep after setjmp or mark volatile.
+    const WriteScanline writer = ChooseWriter(pixmap.colorType());
+    if (!writer) {
+        return false;
+    }
+
+    jpeg_create_compress(&cinfo);
+    cinfo.dest = &sk_wstream;
+    cinfo.image_width = pixmap.width();
+    cinfo.image_height = pixmap.height();
+    cinfo.input_components = 3;
+
+    // FIXME: Can we take advantage of other in_color_spaces in libjpeg-turbo?
+    cinfo.in_color_space = JCS_RGB;
+
+    // The gamma value is ignored by libjpeg-turbo.
+    cinfo.input_gamma = 1;
+
+    jpeg_set_defaults(&cinfo);
+
+    // Tells libjpeg-turbo to compute optimal Huffman coding tables
+    // for the image.  This improves compression at the cost of
+    // slower encode performance.
+    cinfo.optimize_coding = TRUE;
+    jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
+
+    jpeg_start_compress(&cinfo, TRUE);
+
+    const int       width = pixmap.width();
+    uint8_t*        oneRowP = oneRow.reset(width * 3);
+
+    const SkPMColor* colors = pixmap.ctable() ? pixmap.ctable()->readColors() : nullptr;
+    const void*      srcRow = pixmap.addr();
+
+    while (cinfo.next_scanline < cinfo.image_height) {
+        JSAMPROW row_pointer[1];    /* pointer to JSAMPLE row[s] */
+
+        writer(oneRowP, srcRow, width, colors);
+        row_pointer[0] = oneRowP;
+        (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
+        srcRow = (const void*)((const char*)srcRow + pixmap.rowBytes());
+    }
+
+    jpeg_finish_compress(&cinfo);
+    jpeg_destroy_compress(&cinfo);
+
+    return true;
 }
-
-static SkImageEncoder_EncodeReg gEReg(sk_libjpeg_efactory);
+#endif
diff --git a/src/images/SkKTXImageEncoder.cpp b/src/images/SkKTXImageEncoder.cpp
index 6717bea..fb3eb79 100644
--- a/src/images/SkKTXImageEncoder.cpp
+++ b/src/images/SkKTXImageEncoder.cpp
@@ -5,13 +5,13 @@
  * found in the LICENSE file.
  */
 
-#include "SkColorPriv.h"
 #include "SkImageEncoderPriv.h"
+
+#include "SkColorPriv.h"
 #include "SkImageGenerator.h"
 #include "SkPixelRef.h"
 #include "SkStream.h"
 #include "SkStreamPriv.h"
-#include "SkTypes.h"
 
 #include "ktx.h"
 #include "etc1.h"
@@ -30,17 +30,6 @@
 // be represented as a full resolution 8-bit image dump with the appropriate
 // OpenGL defines in the header).
 
-class SkKTXImageEncoder : public SkImageEncoder {
-protected:
-    bool onEncode(SkWStream* stream, const SkBitmap& bitmap, int) override {
-        return SkKTXFile::WriteBitmapToKTX(stream, bitmap);
-    }
-};
-
-DEFINE_ENCODER_CREATOR(KTXImageEncoder);
-
-SkImageEncoder* sk_libktx_efactory(SkImageEncoder::Type t) {
-    return (SkEncodedImageFormat::kKTX == (SkEncodedImageFormat)t) ? new SkKTXImageEncoder : nullptr;
+bool SkEncodeImageAsKTX(SkWStream* stream, const SkPixmap& pixmap) {
+    return SkKTXFile::WritePixmapToKTX(stream, pixmap);
 }
-
-static SkImageEncoder_EncodeReg gEReg(sk_libktx_efactory);
diff --git a/src/images/SkPNGImageEncoder.cpp b/src/images/SkPNGImageEncoder.cpp
index 4fc3a10..16df020 100644
--- a/src/images/SkPNGImageEncoder.cpp
+++ b/src/images/SkPNGImageEncoder.cpp
@@ -6,12 +6,16 @@
  */
 
 #include "SkImageEncoderPriv.h"
+
+#ifdef SK_HAS_PNG_LIBRARY
+
 #include "SkColor.h"
 #include "SkColorPriv.h"
 #include "SkDither.h"
 #include "SkMath.h"
 #include "SkStream.h"
 #include "SkTemplates.h"
+#include "SkUnPreMultiply.h"
 #include "SkUtils.h"
 #include "transform_scanline.h"
 
@@ -41,9 +45,6 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-#include "SkColorPriv.h"
-#include "SkUnPreMultiply.h"
-
 static void sk_error_fn(png_structp png_ptr, png_const_charp msg) {
     if (!c_suppressPNGImageDecoderWarnings) {
         SkDEBUGF(("------ png error %s\n", msg));
@@ -165,22 +166,13 @@
     return numWithAlpha;
 }
 
-class SkPNGImageEncoder : public SkImageEncoder {
-protected:
-    bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) override;
-private:
-    bool doEncode(SkWStream* stream, const SkBitmap& bm,
-                  SkAlphaType alphaType, int colorType,
-                  int bitDepth, SkColorType ct,
-                  png_color_8& sig_bit);
+static bool do_encode(SkWStream*, const SkPixmap&, int, int, png_color_8&);
 
-    typedef SkImageEncoder INHERITED;
-};
-
-bool SkPNGImageEncoder::onEncode(SkWStream* stream,
-                                 const SkBitmap& bitmap,
-                                 int /*quality*/) {
-    const SkColorType ct = bitmap.colorType();
+bool SkEncodeImageAsPNG(SkWStream* stream, const SkPixmap& pixmap) {
+    if (!pixmap.addr() || pixmap.info().isEmpty()) {
+        return false;
+    }
+    const SkColorType ct = pixmap.colorType();
     switch (ct) {
         case kIndex_8_SkColorType:
         case kGray_8_SkColorType:
@@ -193,7 +185,7 @@
             return false;
     }
 
-    const SkAlphaType alphaType = bitmap.alphaType();
+    const SkAlphaType alphaType = pixmap.alphaType();
     switch (alphaType) {
         case kUnpremul_SkAlphaType:
             if (kARGB_4444_SkColorType == ct) {
@@ -252,36 +244,26 @@
         default:
             return false;
     }
-
-    SkAutoLockPixels alp(bitmap);
-    // readyToDraw checks for pixels (and colortable if that is required)
-    if (!bitmap.readyToDraw()) {
-        return false;
-    }
-
-    // we must do this after we have locked the pixels
-    SkColorTable* ctable = bitmap.getColorTable();
-    if (ctable) {
-        if (ctable->count() == 0) {
+    if (kIndex_8_SkColorType == ct) {
+        SkColorTable* ctable = pixmap.ctable();
+        if (!ctable || ctable->count() == 0) {
             return false;
         }
         // check if we can store in fewer than 8 bits
         bitDepth = computeBitDepth(ctable->count());
     }
-
-    return doEncode(stream, bitmap, alphaType, colorType, bitDepth, ct, sig_bit);
+    return do_encode(stream, pixmap, colorType, bitDepth, sig_bit);
 }
 
-bool SkPNGImageEncoder::doEncode(SkWStream* stream, const SkBitmap& bitmap,
-                  SkAlphaType alphaType, int colorType,
-                  int bitDepth, SkColorType ct,
-                  png_color_8& sig_bit) {
+static bool do_encode(SkWStream* stream, const SkPixmap& pixmap,
+                      int colorType, int bitDepth, png_color_8& sig_bit) {
+    SkAlphaType alphaType = pixmap.alphaType();
+    SkColorType ct = pixmap.colorType();
 
     png_structp png_ptr;
     png_infop info_ptr;
 
-    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, sk_error_fn,
-                                      nullptr);
+    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, sk_error_fn, nullptr);
     if (nullptr == png_ptr) {
         return false;
     }
@@ -311,7 +293,7 @@
     * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
     */
 
-    png_set_IHDR(png_ptr, info_ptr, bitmap.width(), bitmap.height(),
+    png_set_IHDR(png_ptr, info_ptr, pixmap.width(), pixmap.height(),
                  bitDepth, colorType,
                  PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
                  PNG_FILTER_TYPE_BASE);
@@ -320,7 +302,7 @@
     png_color paletteColors[256];
     png_byte trans[256];
     if (kIndex_8_SkColorType == ct) {
-        SkColorTable* colorTable = bitmap.getColorTable();
+        SkColorTable* colorTable = pixmap.ctable();
         SkASSERT(colorTable);
         int numTrans = pack_palette(colorTable, paletteColors, trans, alphaType);
         png_set_PLTE(png_ptr, info_ptr, paletteColors, colorTable->count());
@@ -332,16 +314,16 @@
     png_set_sBIT(png_ptr, info_ptr, &sig_bit);
     png_write_info(png_ptr, info_ptr);
 
-    const char* srcImage = (const char*)bitmap.getPixels();
-    SkAutoSTMalloc<1024, char> rowStorage(bitmap.width() << 2);
+    const char* srcImage = (const char*)pixmap.addr();
+    SkAutoSTMalloc<1024, char> rowStorage(pixmap.width() << 2);
     char* storage = rowStorage.get();
     transform_scanline_proc proc = choose_proc(ct, alphaType);
 
-    for (int y = 0; y < bitmap.height(); y++) {
+    for (int y = 0; y < pixmap.height(); y++) {
         png_bytep row_ptr = (png_bytep)storage;
-        proc(storage, srcImage, bitmap.width(), SkColorTypeBytesPerPixel(ct));
+        proc(storage, srcImage, pixmap.width(), SkColorTypeBytesPerPixel(ct));
         png_write_rows(png_ptr, &row_ptr, 1);
-        srcImage += bitmap.rowBytes();
+        srcImage += pixmap.rowBytes();
     }
 
     png_write_end(png_ptr, info_ptr);
@@ -351,12 +333,4 @@
     return true;
 }
 
-///////////////////////////////////////////////////////////////////////////////
-DEFINE_ENCODER_CREATOR(PNGImageEncoder);
-///////////////////////////////////////////////////////////////////////////////
-
-SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) {
-    return (SkEncodedImageFormat::kPNG == (SkEncodedImageFormat)t) ? new SkPNGImageEncoder : nullptr;
-}
-
-static SkImageEncoder_EncodeReg gEReg(sk_libpng_efactory);
+#endif
diff --git a/src/images/SkWEBPImageEncoder.cpp b/src/images/SkWEBPImageEncoder.cpp
index 27c984a..aad06ac 100644
--- a/src/images/SkWEBPImageEncoder.cpp
+++ b/src/images/SkWEBPImageEncoder.cpp
@@ -14,11 +14,15 @@
  * limitations under the License.
  */
 
-#include "SkBitmap.h"
 #include "SkImageEncoderPriv.h"
+
+#ifdef SK_HAS_WEBP_LIBRARY
+
+#include "SkBitmap.h"
 #include "SkColorPriv.h"
 #include "SkStream.h"
 #include "SkTemplates.h"
+#include "SkUnPreMultiply.h"
 #include "SkUtils.h"
 
 // A WebP decoder only, on top of (subset of) libwebp
@@ -34,8 +38,6 @@
 #include "webp/encode.h"
 }
 
-#include "SkUnPreMultiply.h"
-
 typedef void (*ScanlineImporter)(const uint8_t* in, uint8_t* out, int width,
                                  const SkPMColor* SK_RESTRICT ctable);
 
@@ -172,19 +174,10 @@
   return stream->write(data, data_size) ? 1 : 0;
 }
 
-class SkWEBPImageEncoder : public SkImageEncoder {
-protected:
-    bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) override;
-
-private:
-    typedef SkImageEncoder INHERITED;
-};
-
-bool SkWEBPImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bm,
-                                  int quality) {
-    const bool hasAlpha = !bm.isOpaque();
+bool SkEncodeImageAsWEBP(SkWStream* stream, const SkPixmap& pixmap, int quality) {
+    const bool hasAlpha = !pixmap.isOpaque();
     int bpp = -1;
-    const ScanlineImporter scanline_import = ChooseImporter(bm.colorType(), hasAlpha, &bpp);
+    const ScanlineImporter scanline_import = ChooseImporter(pixmap.colorType(), hasAlpha, &bpp);
     if (nullptr == scanline_import) {
         return false;
     }
@@ -192,8 +185,7 @@
         return false;
     }
 
-    SkAutoLockPixels alp(bm);
-    if (nullptr == bm.getPixels()) {
+    if (nullptr == pixmap.addr()) {
         return false;
     }
 
@@ -204,44 +196,33 @@
 
     WebPPicture pic;
     WebPPictureInit(&pic);
-    pic.width = bm.width();
-    pic.height = bm.height();
+    pic.width = pixmap.width();
+    pic.height = pixmap.height();
     pic.writer = stream_writer;
     pic.custom_ptr = (void*)stream;
 
-    const SkPMColor* colors = bm.getColorTable() ? bm.getColorTable()->readColors() : nullptr;
-    const uint8_t* src = (uint8_t*)bm.getPixels();
+    const SkPMColor* colors = pixmap.ctable() ? pixmap.ctable()->readColors() : nullptr;
+    const uint8_t* src = (uint8_t*)pixmap.addr();
     const int rgbStride = pic.width * bpp;
+    const size_t rowBytes = pixmap.rowBytes();
 
     // Import (for each scanline) the bit-map image (in appropriate color-space)
     // to RGB color space.
-    uint8_t* rgb = new uint8_t[rgbStride * pic.height];
+    std::unique_ptr<uint8_t[]> rgb(new uint8_t[rgbStride * pic.height]);
     for (int y = 0; y < pic.height; ++y) {
-        scanline_import(src + y * bm.rowBytes(), rgb + y * rgbStride,
-                        pic.width, colors);
+        scanline_import(src + y * rowBytes, &rgb[y * rgbStride], pic.width, colors);
     }
 
     bool ok;
     if (bpp == 3) {
-        ok = SkToBool(WebPPictureImportRGB(&pic, rgb, rgbStride));
+        ok = SkToBool(WebPPictureImportRGB(&pic, &rgb[0], rgbStride));
     } else {
-        ok = SkToBool(WebPPictureImportRGBA(&pic, rgb, rgbStride));
+        ok = SkToBool(WebPPictureImportRGBA(&pic, &rgb[0], rgbStride));
     }
-    delete[] rgb;
 
     ok = ok && WebPEncode(&webp_config, &pic);
     WebPPictureFree(&pic);
 
     return ok;
 }
-
-
-///////////////////////////////////////////////////////////////////////////////
-DEFINE_ENCODER_CREATOR(WEBPImageEncoder);
-///////////////////////////////////////////////////////////////////////////////
-
-static SkImageEncoder* sk_libwebp_efactory(SkImageEncoder::Type t) {
-    return (SkEncodedImageFormat::kWEBP == (SkEncodedImageFormat)t) ? new SkWEBPImageEncoder : nullptr;
-}
-
-static SkImageEncoder_EncodeReg gEReg(sk_libwebp_efactory);
+#endif
diff --git a/src/ports/SkImageEncoder_CG.cpp b/src/ports/SkImageEncoder_CG.cpp
index 0c3d22d..b3fd243 100644
--- a/src/ports/SkImageEncoder_CG.cpp
+++ b/src/ports/SkImageEncoder_CG.cpp
@@ -5,14 +5,14 @@
  * found in the LICENSE file.
  */
 
-#include "SkTypes.h"
+#include "SkImageEncoderPriv.h"
+
 #if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
 
 #include "SkBitmap.h"
 #include "SkCGUtils.h"
 #include "SkColorPriv.h"
 #include "SkData.h"
-#include "SkImageEncoderPriv.h"
 #include "SkStream.h"
 #include "SkStreamPriv.h"
 #include "SkTemplates.h"
@@ -57,29 +57,19 @@
     return CGImageDestinationCreateWithDataConsumer(consumer, type, 1, nullptr);
 }
 
-class SkImageEncoder_CG : public SkImageEncoder {
-public:
-    SkImageEncoder_CG(SkEncodedImageFormat t) : fType(t) {}
-
-protected:
-    virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality);
-
-private:
-    SkEncodedImageFormat fType;
-};
-
 /*  Encode bitmaps via CGImageDestination. We setup a DataConsumer which writes
     to our SkWStream. Since we don't reference/own the SkWStream, our consumer
     must only live for the duration of the onEncode() method.
  */
-bool SkImageEncoder_CG::onEncode(SkWStream* stream, const SkBitmap& bm,
-                                 int quality) {
-    // Used for converting a bitmap to 8888.
-    const SkBitmap* bmPtr = &bm;
-    SkBitmap bitmap8888;
+bool SkEncodeImageWithCG(SkWStream* stream, const SkPixmap& pixmap, SkEncodedImageFormat format) {
+    SkBitmap bm;
+    if (!bm.installPixels(pixmap)) {
+        return false;
+    }
+    bm.setImmutable();
 
     CFStringRef type;
-    switch (fType) {
+    switch (format) {
         case SkEncodedImageFormat::kICO:
             type = kUTTypeICO;
             break;
@@ -99,8 +89,9 @@
             // <Error>: CGImageDestinationFinalize image destination does not have enough images
             // So instead we copy to 8888.
             if (bm.colorType() == kARGB_4444_SkColorType) {
+                SkBitmap bitmap8888;
                 bm.copyTo(&bitmap8888, kN32_SkColorType);
-                bmPtr = &bitmap8888;
+                bm.swap(bitmap8888);
             }
             type = kUTTypePNG;
             break;
@@ -114,7 +105,7 @@
     }
     SkAutoTCallVProc<const void, CFRelease> ardst(dst);
 
-    CGImageRef image = SkCreateCGImageRef(*bmPtr);
+    CGImageRef image = SkCreateCGImageRef(bm);
     if (nullptr == image) {
         return false;
     }
@@ -124,28 +115,4 @@
     return CGImageDestinationFinalize(dst);
 }
 
-///////////////////////////////////////////////////////////////////////////////
-
-#ifdef SK_USE_CG_ENCODER
-static SkImageEncoder* sk_imageencoder_cg_factory(SkEncodedImageFormat t) {
-    switch (t) {
-        case SkEncodedImageFormat::kICO:
-        case SkEncodedImageFormat::kBMP:
-        case SkEncodedImageFormat::kGIF:
-        case SkEncodedImageFormat::kJPEG:
-        case SkEncodedImageFormat::kPNG:
-            break;
-        default:
-            return nullptr;
-    }
-    return new SkImageEncoder_CG(t);
-}
-
-static SkImageEncoder_EncodeReg gEReg(sk_imageencoder_cg_factory);
-#endif
-
-SkImageEncoder* CreateImageEncoder_CG(SkImageEncoder::Type 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 035359e..52f4599 100644
--- a/src/ports/SkImageEncoder_WIC.cpp
+++ b/src/ports/SkImageEncoder_WIC.cpp
@@ -46,23 +46,10 @@
 #undef CLSID_WICImagingFactory
 #endif
 
-class SkImageEncoder_WIC : public SkImageEncoder {
-public:
-    SkImageEncoder_WIC(SkEncodedImageFormat t) : fType(t) {}
-
-protected:
-    virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality);
-
-private:
-    SkEncodedImageFormat fType;
-};
-
-bool SkImageEncoder_WIC::onEncode(SkWStream* stream
-                                , const SkBitmap& bitmapOrig
-                                , int quality)
-{
+bool SkEncodeImageWithWIC(SkWStream* stream, const SkPixmap& pixmap,
+                          SkEncodedImageFormat format, int quality) {
     GUID type;
-    switch (fType) {
+    switch (format) {
         case SkEncodedImageFormat::kJPEG:
             type = GUID_ContainerFormatJpeg;
             break;
@@ -72,6 +59,11 @@
         default:
             return false;
     }
+    SkBitmap bitmapOrig;
+    if (!bitmapOrig.installPixels(pixmap)) {
+        return false;
+    }
+    bitmapOrig.setImmutable();
 
     // First convert to BGRA if necessary.
     SkBitmap bitmap;
@@ -97,7 +89,7 @@
     size_t rowBytes = bitmap.rowBytes();
     SkAutoMalloc pixelStorage;
     WICPixelFormatGUID formatDesired = GUID_WICPixelFormat32bppBGRA;
-    if (SkEncodedImageFormat::kJPEG == fType) {
+    if (SkEncodedImageFormat::kJPEG == format) {
         formatDesired = GUID_WICPixelFormat24bppBGR;
         rowBytes = SkAlign4(bitmap.width() * 3);
         pixelStorage.reset(rowBytes * bitmap.height());
@@ -216,25 +208,4 @@
     return SUCCEEDED(hr);
 }
 
-///////////////////////////////////////////////////////////////////////////////
-
-#ifdef SK_USE_WIC_ENCODER
-static SkImageEncoder* sk_imageencoder_wic_factory(SkEncodedImageFormat t) {
-    switch (t) {
-        case SkEncodedImageFormat::kPNG:
-        case SkEncodedImageFormat::kJPEG:
-            break;
-        default:
-            return nullptr;
-    }
-    return new SkImageEncoder_WIC(t);
-}
-
-static SkImageEncoder_EncodeReg gEReg(sk_imageencoder_wic_factory);
-#endif
-
-SkImageEncoder* CreateImageEncoder_WIC(SkImageEncoder::Type type) {
-    return new SkImageEncoder_WIC((SkEncodedImageFormat)type);
-}
-
 #endif // defined(SK_BUILD_FOR_WIN32)
diff --git a/tests/PathOpsExtendedTest.cpp b/tests/PathOpsExtendedTest.cpp
index f699b8b..9b08ba9 100644
--- a/tests/PathOpsExtendedTest.cpp
+++ b/tests/PathOpsExtendedTest.cpp
@@ -9,7 +9,6 @@
 #include "PathOpsThreadedCommon.h"
 #include "SkBitmap.h"
 #include "SkCanvas.h"
-#include "SkForceLinking.h"
 #include "SkMatrix.h"
 #include "SkMutex.h"
 #include "SkPaint.h"
@@ -29,9 +28,6 @@
                    SkDEBUGPARAMS(bool skipAssert)
                    SkDEBUGPARAMS(const char* testName));
 
-
-__SK_FORCE_IMAGE_DECODER_LINKING;
-
 static const char marker[] =
     "</div>\n"
     "\n"
diff --git a/tests/PathOpsSkpClipTest.cpp b/tests/PathOpsSkpClipTest.cpp
index 57e9bd1..0c866bd 100644
--- a/tests/PathOpsSkpClipTest.cpp
+++ b/tests/PathOpsSkpClipTest.cpp
@@ -13,7 +13,6 @@
 #include "SkColor.h"
 #include "SkColorPriv.h"
 #include "SkCommandLineFlags.h"
-#include "SkForceLinking.h"
 #include "SkGraphics.h"
 #include "SkImageEncoder.h"
 #include "SkOSFile.h"
diff --git a/third_party/ktx/ktx.cpp b/third_party/ktx/ktx.cpp
index 15a1c69..1a6ce88 100644
--- a/third_party/ktx/ktx.cpp
+++ b/third_party/ktx/ktx.cpp
@@ -6,7 +6,7 @@
  */
 
 #include "ktx.h"
-#include "SkBitmap.h"
+#include "SkPixmap.h"
 #include "SkStream.h"
 #include "SkEndian.h"
 
@@ -395,7 +395,7 @@
 
     // !FIXME! The spec suggests that we put KTXOrientation as a
     // key value pair in the header, but that means that we'd have to
-    // pipe through the bitmap's orientation to properly do that.
+    // pipe through the pixmap's orientation to properly do that.
     hdr.fBytesOfKeyValueData = 0;
 
     // Write the header
@@ -417,16 +417,17 @@
     return true;
 }
 
-bool SkKTXFile::WriteBitmapToKTX(SkWStream* stream, const SkBitmap& bitmap) {
-    const SkColorType ct = bitmap.colorType();
-    SkAutoLockPixels alp(bitmap);
+bool SkKTXFile::WritePixmapToKTX(SkWStream* stream, const SkPixmap& pixmap) {
+    const SkColorType ct = pixmap.colorType();
 
-    const int width = bitmap.width();
-    const int height = bitmap.height();
-    const uint8_t* src = reinterpret_cast<uint8_t*>(bitmap.getPixels());
-    if (NULL == bitmap.getPixels()) {
+    const int width = pixmap.width();
+    const int height = pixmap.height();
+    const uint8_t* src = reinterpret_cast<const uint8_t*>(pixmap.addr());
+    if (!src) {
         return false;
     }
+    const size_t rowBytes = pixmap.rowBytes();
+    const int bytesPerPixel = pixmap.info().bytesPerPixel();
 
     // First thing's first, write out the magic identifier and endianness...
     if (!stream->write(KTX_FILE_IDENTIFIER, KTX_FILE_IDENTIFIER_SIZE) ||
@@ -437,16 +438,16 @@
     // Collect our key/value pairs...
     SkTArray<KeyValue> kvPairs;
 
-    // Next, write the header based on the bitmap's config.
+    // Next, write the header based on the pixmap's config.
     Header hdr;
     switch (ct) {
         case kIndex_8_SkColorType:
             // There is a compressed format for this, but we don't support it yet.
-            SkDebugf("Writing indexed bitmap to KTX unsupported.\n");
+            SkDebugf("Writing indexed pixmap to KTX unsupported.\n");
             // VVV fall through VVV
         default:
         case kUnknown_SkColorType:
-            // Bitmap hasn't been configured.
+            // Pixmap hasn't been configured.
             return false;
 
         case kAlpha_8_SkColorType:
@@ -516,10 +517,9 @@
     }
 
     // Calculate the size of the data
-    int bpp = bitmap.bytesPerPixel();
-    uint32_t dataSz = bpp * width * height;
+    uint32_t dataSz = bytesPerPixel * width * height;
 
-    if (0 >= bpp) {
+    if (0 >= bytesPerPixel) {
         return false;
     }
 
@@ -544,14 +544,14 @@
                     return false;
                 }
             }
-            rowPtr += bitmap.rowBytes();
+            rowPtr += rowBytes;
         }
     } else {
         for (int i = 0; i < height; ++i) {
-            if (!stream->write(rowPtr, bpp*width)) {
+            if (!stream->write(rowPtr, bytesPerPixel * width)) {
                 return false;
             }
-            rowPtr += bitmap.rowBytes();
+            rowPtr += rowBytes;
         }
     }
 
diff --git a/third_party/ktx/ktx.h b/third_party/ktx/ktx.h
index f06613d..6772f86 100644
--- a/third_party/ktx/ktx.h
+++ b/third_party/ktx/ktx.h
@@ -16,7 +16,7 @@
 #include "SkString.h"
 #include "SkRefCnt.h"
 
-class SkBitmap;
+class SkPixmap;
 class SkStreamRewindable;
 class SkWStream;
 
@@ -65,7 +65,7 @@
 
     static bool WriteETC1ToKTX(SkWStream* stream, const uint8_t *etc1Data,
                                uint32_t width, uint32_t height);
-    static bool WriteBitmapToKTX(SkWStream* stream, const SkBitmap& bitmap);
+    static bool WritePixmapToKTX(SkWStream* stream, const SkPixmap& bitmap);
 private:
 
     // The blob holding the file data.
diff --git a/tools/colorspaceinfo.cpp b/tools/colorspaceinfo.cpp
index 945c4a5..f413038 100644
--- a/tools/colorspaceinfo.cpp
+++ b/tools/colorspaceinfo.cpp
@@ -12,15 +12,12 @@
 #include "SkCodec.h"
 #include "SkColorSpace_XYZ.h"
 #include "SkCommandLineFlags.h"
-#include "SkForceLinking.h"
 #include "SkImageEncoder.h"
 #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.");
 DEFINE_string(output, "output.png", "A path to the output image.");
 DEFINE_bool(sRGB, false, "Draws the sRGB gamut.");
diff --git a/tools/fiddle/fiddle_main.cpp b/tools/fiddle/fiddle_main.cpp
index f83026f..9e39292 100644
--- a/tools/fiddle/fiddle_main.cpp
+++ b/tools/fiddle/fiddle_main.cpp
@@ -7,9 +7,6 @@
 
 #include <stdio.h>
 #include <stdlib.h>
-#include "SkForceLinking.h"
-
-__SK_FORCE_IMAGE_DECODER_LINKING;
 
 #include "fiddle_main.h"
 
diff --git a/tools/imgblur.cpp b/tools/imgblur.cpp
index 28d8447..23ba815 100644
--- a/tools/imgblur.cpp
+++ b/tools/imgblur.cpp
@@ -9,15 +9,12 @@
 #include "SkCommandLineFlags.h"
 #include "SkCommonFlags.h"
 #include "SkData.h"
-#include "SkForceLinking.h"
 #include "SkImage.h"
 #include "SkStream.h"
 #include "SkTypes.h"
 
 #include "sk_tool_utils.h"
 
-__SK_FORCE_IMAGE_DECODER_LINKING;
-
 DEFINE_string(in, "input.png", "Input image");
 DEFINE_string(out, "blurred.png", "Output image");
 DEFINE_double(sigma, 1, "Sigma to be used for blur (> 0.0f)");
diff --git a/tools/sk_tool_utils.h b/tools/sk_tool_utils.h
index 526f0ef..b097757 100644
--- a/tools/sk_tool_utils.h
+++ b/tools/sk_tool_utils.h
@@ -13,6 +13,7 @@
 #include "SkImageInfo.h"
 #include "SkPixelSerializer.h"
 #include "SkRandom.h"
+#include "SkStream.h"
 #include "SkTDArray.h"
 #include "SkTypeface.h"
 
diff --git a/tools/skdiff/skdiff_main.cpp b/tools/skdiff/skdiff_main.cpp
index b4e5607..b496cad 100644
--- a/tools/skdiff/skdiff_main.cpp
+++ b/tools/skdiff/skdiff_main.cpp
@@ -9,7 +9,6 @@
 #include "skdiff_utils.h"
 #include "SkBitmap.h"
 #include "SkData.h"
-#include "SkForceLinking.h"
 #include "SkImageEncoder.h"
 #include "SkOSFile.h"
 #include "SkOSPath.h"
@@ -19,8 +18,6 @@
 
 #include <stdlib.h>
 
-__SK_FORCE_IMAGE_DECODER_LINKING;
-
 /**
  * skdiff
  *
diff --git a/tools/skhello.cpp b/tools/skhello.cpp
index d1fb96e..d1f8cb8 100644
--- a/tools/skhello.cpp
+++ b/tools/skhello.cpp
@@ -9,15 +9,12 @@
 #include "SkCommandLineFlags.h"
 #include "SkData.h"
 #include "SkDocument.h"
-#include "SkForceLinking.h"
 #include "SkGraphics.h"
 #include "SkSurface.h"
 #include "SkImage.h"
 #include "SkStream.h"
 #include "SkString.h"
 
-__SK_FORCE_IMAGE_DECODER_LINKING;
-
 DEFINE_string2(outFile, o, "skhello", "The filename to write the image.");
 DEFINE_string2(text, t, "Hello", "The string to write.");
 
diff --git a/tools/whitelist_typefaces.cpp b/tools/whitelist_typefaces.cpp
index 205f54a..b446a3a 100644
--- a/tools/whitelist_typefaces.cpp
+++ b/tools/whitelist_typefaces.cpp
@@ -5,11 +5,8 @@
  * found in the LICENSE file.
  */
 
-#include "SkForceLinking.h"
 #include "SkGraphics.h"
 
-__SK_FORCE_IMAGE_DECODER_LINKING;
-
 extern bool CheckChecksums();
 extern bool GenerateChecksums();