RESTRICT AUTOMERGE: Fix bug decoding JCS_RGB jpeg files

Bug: 118372692
Test: I90586f1518fdc501608f28f33c6d90d145922560

Cherry-picked from
https://skia-review.googlesource.com/c/164619

Remove conflicting changes in infra. Resolved conflicts in:
- src/codec/SkHeifCodec.cpp
- src/codec/SkJpegCodec.cpp
- src/codec/SkSwizzler.cpp

Use old version of SkEncodedInfo::Make
Remove references to SkEncodedInfo::kXAlpha_Color and ::k565_Color
which are unused by Android.

Also include SafetyNet logging from
https://skia-review.googlesource.com/c/skia/+/171222.

Original message follows:

Bug: chromium:897031
Bug: chromium:896776

Prior to this fix, we would treat the output from such a JPEG
as if it were a 16 bit per component RGB PNG. We hit an assert
in debug, but in release mode we do the wrong thing.

Split up SkSwizzler::CreateSwizzler into two public factories
(and a private one) based on whether format conversion is desired.
Without format conversion, we may have already converted (as is
the case with this JPEG), so the SkEncodedInfo::Color is not relevant.
That flavor of the factory just needs to know the bytes per pixel,
so provide that info instead.

Add a test file to Google Storage: apron.jpg, from Chromium's
benchmark files.

Conflicts:
- src/codec/SkHeifCodec.cpp
  - Does not exist here
  - TODO: Cherry-pick separately to oc-mr1-dev
- src/codec/SkSwizzler.cpp
- src/codec/SkWbmpCodec.cpp
- src/codec/SkWbmpCodec.h
  - conflicts due to removing kIndex8 in P

Change-Id: If1a35947d48c0139d6e93e420309725b79c4163a
Merged-In: Idc55ecb1be7ba53455ca60bbca30477eb321a702
(cherry picked from commit a65763e69aed2d97ca80f8e2fc30c168f055c0c2)
diff --git a/src/codec/SkBmpStandardCodec.cpp b/src/codec/SkBmpStandardCodec.cpp
index a0ad787..9f2d359 100644
--- a/src/codec/SkBmpStandardCodec.cpp
+++ b/src/codec/SkBmpStandardCodec.cpp
@@ -191,9 +191,7 @@
         swizzlerOptions.fZeroInitialized = kNo_ZeroInitialized;
     }
 
-
-    fSwizzler.reset(SkSwizzler::CreateSwizzler(encodedInfo, colorPtr, swizzlerInfo,
-                                               swizzlerOptions));
+    fSwizzler = SkSwizzler::Make(encodedInfo, colorPtr, swizzlerInfo, swizzlerOptions);
     SkASSERT(fSwizzler);
 }
 
diff --git a/src/codec/SkGifCodec.cpp b/src/codec/SkGifCodec.cpp
index 40339b5..081c52f 100644
--- a/src/codec/SkGifCodec.cpp
+++ b/src/codec/SkGifCodec.cpp
@@ -292,8 +292,8 @@
     // - the swizzler does not need to know about the frame.
     // We may not be able to use the real Options anyway, since getPixels does not store it (due to
     // a bug).
-    fSwizzler.reset(SkSwizzler::CreateSwizzler(this->getEncodedInfo(),
-                    fCurrColorTable->readColors(), swizzlerInfo, Options(), &swizzleRect));
+    fSwizzler = SkSwizzler::Make(this->getEncodedInfo(), fCurrColorTable->readColors(),
+                                 swizzlerInfo, Options(), &swizzleRect);
     SkASSERT(fSwizzler.get());
 }
 
diff --git a/src/codec/SkJpegCodec.cpp b/src/codec/SkJpegCodec.cpp
index 75fe113..fd8d258 100644
--- a/src/codec/SkJpegCodec.cpp
+++ b/src/codec/SkJpegCodec.cpp
@@ -641,13 +641,6 @@
 
 void SkJpegCodec::initializeSwizzler(const SkImageInfo& dstInfo, const Options& options,
         bool needsCMYKToRGB) {
-    SkEncodedInfo swizzlerInfo = this->getEncodedInfo();
-    if (needsCMYKToRGB) {
-        swizzlerInfo = SkEncodedInfo::Make(SkEncodedInfo::kInvertedCMYK_Color,
-                                           swizzlerInfo.alpha(),
-                                           swizzlerInfo.bitsPerComponent());
-    }
-
     Options swizzlerOptions = options;
     if (options.fSubset) {
         // Use fSwizzlerSubset if this is a subset decode.  This is necessary in the case
@@ -664,8 +657,31 @@
         swizzlerDstInfo = swizzlerDstInfo.makeColorType(kRGBA_8888_SkColorType);
     }
 
-    fSwizzler.reset(SkSwizzler::CreateSwizzler(swizzlerInfo, nullptr, swizzlerDstInfo,
-                                               swizzlerOptions, nullptr, !needsCMYKToRGB));
+    if (needsCMYKToRGB) {
+        // The swizzler is used to convert to from CMYK.
+        auto swizzlerInfo = SkEncodedInfo::Make(SkEncodedInfo::kInvertedCMYK_Color,
+                                                SkEncodedInfo::kOpaque_Alpha, 8);
+        fSwizzler = SkSwizzler::Make(swizzlerInfo, nullptr, swizzlerDstInfo, swizzlerOptions);
+    } else {
+        int srcBPP = 0;
+        switch (fDecoderMgr->dinfo()->out_color_space) {
+            case JCS_EXT_RGBA:
+            case JCS_EXT_BGRA:
+            case JCS_CMYK:
+                srcBPP = 4;
+                break;
+            case JCS_RGB565:
+                srcBPP = 2;
+                break;
+            case JCS_GRAYSCALE:
+                srcBPP = 1;
+                break;
+            default:
+                SkASSERT(false);
+                break;
+        }
+        fSwizzler = SkSwizzler::MakeSimple(srcBPP, swizzlerDstInfo, swizzlerOptions);
+    }
     SkASSERT(fSwizzler);
 }
 
diff --git a/src/codec/SkJpegDecoderMgr.cpp b/src/codec/SkJpegDecoderMgr.cpp
index c2837aa..20810b3 100644
--- a/src/codec/SkJpegDecoderMgr.cpp
+++ b/src/codec/SkJpegDecoderMgr.cpp
@@ -9,6 +9,10 @@
 
 #include "SkJpegUtility.h"
 
+#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
+    #include "SkAndroidFrameworkUtils.h"
+#endif
+
 /*
  * Print information, warning, and error messages
  */
@@ -55,6 +59,9 @@
             *outColor = SkEncodedInfo::kYUV_Color;
             return true;
         case JCS_RGB:
+#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
+            SkAndroidFrameworkUtils::SafetyNetLog("118372692");
+#endif
             *outColor = SkEncodedInfo::kRGB_Color;
             return true;
         case JCS_YCCK:
diff --git a/src/codec/SkPngCodec.cpp b/src/codec/SkPngCodec.cpp
index b6f418f..b4bc499 100644
--- a/src/codec/SkPngCodec.cpp
+++ b/src/codec/SkPngCodec.cpp
@@ -1076,9 +1076,31 @@
         swizzlerOptions.fZeroInitialized = kNo_ZeroInitialized;
     }
 
-    const SkPMColor* colors = get_color_ptr(fColorTable.get());
-    fSwizzler.reset(SkSwizzler::CreateSwizzler(this->getEncodedInfo(), colors, swizzlerInfo,
-                                               swizzlerOptions, nullptr, skipFormatConversion));
+    if (skipFormatConversion) {
+        // We cannot skip format conversion when there is a color table.
+        SkASSERT(!fColorTable);
+        int srcBPP = 0;
+        switch (this->getEncodedInfo().color()) {
+            case SkEncodedInfo::kRGB_Color:
+                SkASSERT(this->getEncodedInfo().bitsPerComponent() == 16);
+                srcBPP = 6;
+                break;
+            case SkEncodedInfo::kRGBA_Color:
+                srcBPP = this->getEncodedInfo().bitsPerComponent() / 2;
+                break;
+            case SkEncodedInfo::kGray_Color:
+                srcBPP = 1;
+                break;
+            default:
+                SkASSERT(false);
+                break;
+        }
+        fSwizzler = SkSwizzler::MakeSimple(srcBPP, swizzlerInfo, swizzlerOptions);
+    } else {
+        const SkPMColor* colors = get_color_ptr(fColorTable.get());
+        fSwizzler = SkSwizzler::Make(this->getEncodedInfo(), colors, swizzlerInfo,
+                                     swizzlerOptions);
+    }
     SkASSERT(fSwizzler);
 }
 
diff --git a/src/codec/SkRawCodec.cpp b/src/codec/SkRawCodec.cpp
index 272f737..24051d1 100644
--- a/src/codec/SkRawCodec.cpp
+++ b/src/codec/SkRawCodec.cpp
@@ -705,8 +705,8 @@
         xformBuffer.reset(new uint32_t[dstInfo.width()]);
     }
 
-    std::unique_ptr<SkSwizzler> swizzler(SkSwizzler::CreateSwizzler(
-            this->getEncodedInfo(), nullptr, swizzlerInfo, options));
+    std::unique_ptr<SkSwizzler> swizzler = SkSwizzler::Make(
+            this->getEncodedInfo(), nullptr, swizzlerInfo, options);
     SkASSERT(swizzler);
 
     const int width = dstInfo.width();
diff --git a/src/codec/SkSwizzler.cpp b/src/codec/SkSwizzler.cpp
index bf9c549..546a6ba 100644
--- a/src/codec/SkSwizzler.cpp
+++ b/src/codec/SkSwizzler.cpp
@@ -809,403 +809,378 @@
     proc(dst32, (const uint8_t*)src32, dstWidth, bpp, deltaSrc, 0, ctable);
 }
 
-SkSwizzler* SkSwizzler::CreateSwizzler(const SkEncodedInfo& encodedInfo,
-                                       const SkPMColor* ctable,
-                                       const SkImageInfo& dstInfo,
-                                       const SkCodec::Options& options,
-                                       const SkIRect* frame,
-                                       bool skipFormatConversion) {
+std::unique_ptr<SkSwizzler> SkSwizzler::MakeSimple(int srcBPP, const SkImageInfo& dstInfo,
+                                                   const SkCodec::Options& options) {
+    RowProc proc = nullptr;
+    switch (srcBPP) {
+        case 1:     // kGray_8_SkColorType
+            proc = &sample1;
+            break;
+        case 2:     // kRGB_565_SkColorType
+            proc = &sample2;
+            break;
+        case 4:     // kRGBA_8888_SkColorType
+                    // kBGRA_8888_SkColorType
+            proc = &sample4;
+            break;
+        case 6:     // 16 bit PNG no alpha
+            proc = &sample6;
+            break;
+        case 8:     // 16 bit PNG with alpha
+            proc = &sample8;
+            break;
+        default:
+            return nullptr;
+    }
+
+    return Make(dstInfo, &copy, proc, nullptr /*ctable*/, srcBPP,
+                dstInfo.bytesPerPixel(), options, nullptr /*frame*/);
+}
+
+std::unique_ptr<SkSwizzler> SkSwizzler::Make(const SkEncodedInfo& encodedInfo,
+                                             const SkPMColor* ctable,
+                                             const SkImageInfo& dstInfo,
+                                             const SkCodec::Options& options,
+                                             const SkIRect* frame) {
     if (SkEncodedInfo::kPalette_Color == encodedInfo.color() && nullptr == ctable) {
         return nullptr;
     }
 
     RowProc fastProc = nullptr;
     RowProc proc = nullptr;
-    int srcBPP;
-    const int dstBPP = SkColorTypeBytesPerPixel(dstInfo.colorType());
-    if (skipFormatConversion) {
-        switch (encodedInfo.color()) {
-            case SkEncodedInfo::kGray_Color:
-            case SkEncodedInfo::kYUV_Color:
-                // We have a jpeg that has already been converted to the dstColorType.
-                srcBPP = dstBPP;
-                switch (dstInfo.colorType()) {
-                    case kGray_8_SkColorType:
-                        proc = &sample1;
-                        fastProc = &copy;
-                        break;
-                    case kRGB_565_SkColorType:
-                        proc = &sample2;
-                        fastProc = &copy;
-                        break;
-                    case kRGBA_8888_SkColorType:
-                    case kBGRA_8888_SkColorType:
-                        proc = &sample4;
-                        fastProc = &copy;
-                        break;
-                    default:
-                        return nullptr;
-                }
-                break;
-            case SkEncodedInfo::kInvertedCMYK_Color:
-            case SkEncodedInfo::kYCCK_Color:
-                // We have a jpeg that remains in its original format.
-                srcBPP = 4;
-                proc = &sample4;
-                fastProc = &copy;
-                break;
-            case SkEncodedInfo::kRGBA_Color:
-                // We have a png that should remain in its original format.
-                SkASSERT(16 == encodedInfo.bitsPerComponent() ||
-                          8 == encodedInfo.bitsPerComponent());
-                if (8 == encodedInfo.bitsPerComponent()) {
-                    srcBPP = 4;
-                    proc = &sample4;
-                } else {
-                    srcBPP = 8;
-                    proc = &sample8;
-                }
-                fastProc = &copy;
-                break;
-            case SkEncodedInfo::kRGB_Color:
-                // We have a png that remains in its original format.
-                SkASSERT(16 == encodedInfo.bitsPerComponent());
-                srcBPP = 6;
-                proc = &sample6;
-                fastProc = &copy;
-                break;
-            default:
-                return nullptr;
-        }
-    } else {
-        SkCodec::ZeroInitialized zeroInit = options.fZeroInitialized;
-        const bool premultiply = (SkEncodedInfo::kOpaque_Alpha != encodedInfo.alpha()) &&
-                (kPremul_SkAlphaType == dstInfo.alphaType());
+    SkCodec::ZeroInitialized zeroInit = options.fZeroInitialized;
+    const bool premultiply = (SkEncodedInfo::kOpaque_Alpha != encodedInfo.alpha()) &&
+            (kPremul_SkAlphaType == dstInfo.alphaType());
 
-        switch (encodedInfo.color()) {
-            case SkEncodedInfo::kGray_Color:
-                switch (encodedInfo.bitsPerComponent()) {
-                    case 1:
-                        switch (dstInfo.colorType()) {
-                            case kRGBA_8888_SkColorType:
-                            case kBGRA_8888_SkColorType:
-                                proc = &swizzle_bit_to_n32;
-                                break;
-                            case kIndex_8_SkColorType:
-                                proc = &swizzle_bit_to_index;
-                                break;
-                            case kRGB_565_SkColorType:
-                                proc = &swizzle_bit_to_565;
-                                break;
-                            case kGray_8_SkColorType:
-                                proc = &swizzle_bit_to_grayscale;
-                                break;
-                            case kRGBA_F16_SkColorType:
-                                proc = &swizzle_bit_to_f16;
-                                break;
-                            default:
-                                return nullptr;
-                        }
-                        break;
-                    case 8:
-                        switch (dstInfo.colorType()) {
-                            case kRGBA_8888_SkColorType:
-                            case kBGRA_8888_SkColorType:
-                                proc = &swizzle_gray_to_n32;
-                                fastProc = &fast_swizzle_gray_to_n32;
-                                break;
-                            case kGray_8_SkColorType:
-                                proc = &sample1;
-                                fastProc = &copy;
-                                break;
-                            case kRGB_565_SkColorType:
-                                proc = &swizzle_gray_to_565;
-                                break;
-                            default:
-                                return nullptr;
-                        }
-                        break;
-                    default:
-                        return nullptr;
-                }
-                break;
-            case SkEncodedInfo::kGrayAlpha_Color:
-                switch (dstInfo.colorType()) {
-                    case kRGBA_8888_SkColorType:
-                    case kBGRA_8888_SkColorType:
-                        if (premultiply) {
-                            if (SkCodec::kYes_ZeroInitialized == zeroInit) {
-                                proc = &SkipLeadingGrayAlphaZerosThen
-                                        <swizzle_grayalpha_to_n32_premul>;
-                                fastProc = &SkipLeadingGrayAlphaZerosThen
-                                        <fast_swizzle_grayalpha_to_n32_premul>;
-                            } else {
-                                proc = &swizzle_grayalpha_to_n32_premul;
-                                fastProc = &fast_swizzle_grayalpha_to_n32_premul;
-                            }
-                        } else {
-                            if (SkCodec::kYes_ZeroInitialized == zeroInit) {
-                                proc = &SkipLeadingGrayAlphaZerosThen
-                                        <swizzle_grayalpha_to_n32_unpremul>;
-                                fastProc = &SkipLeadingGrayAlphaZerosThen
-                                        <fast_swizzle_grayalpha_to_n32_unpremul>;
-                            } else {
-                                proc = &swizzle_grayalpha_to_n32_unpremul;
-                                fastProc = &fast_swizzle_grayalpha_to_n32_unpremul;
-                            }
-                        }
-                        break;
-                    default:
-                        return nullptr;
-                }
-                break;
-            case SkEncodedInfo::kPalette_Color:
-                // We assume that the color table is premultiplied and swizzled
-                // as desired.
-                switch (encodedInfo.bitsPerComponent()) {
-                    case 1:
-                    case 2:
-                    case 4:
-                        switch (dstInfo.colorType()) {
-                            case kRGBA_8888_SkColorType:
-                            case kBGRA_8888_SkColorType:
-                                proc = &swizzle_small_index_to_n32;
-                                break;
-                            case kRGB_565_SkColorType:
-                                proc = &swizzle_small_index_to_565;
-                                break;
-                            case kIndex_8_SkColorType:
-                                proc = &swizzle_small_index_to_index;
-                                break;
-                            default:
-                                return nullptr;
-                        }
-                        break;
-                    case 8:
-                        switch (dstInfo.colorType()) {
-                            case kRGBA_8888_SkColorType:
-                            case kBGRA_8888_SkColorType:
-                                if (SkCodec::kYes_ZeroInitialized == zeroInit) {
-                                    proc = &swizzle_index_to_n32_skipZ;
-                                } else {
-                                    proc = &swizzle_index_to_n32;
-                                }
-                                break;
-                            case kRGB_565_SkColorType:
-                                proc = &swizzle_index_to_565;
-                                break;
-                            case kIndex_8_SkColorType:
-                                proc = &sample1;
-                                fastProc = &copy;
-                                break;
-                            default:
-                                return nullptr;
-                        }
-                        break;
-                    default:
-                        return nullptr;
-                }
-                break;
-            case SkEncodedInfo::kRGB_Color:
-                switch (dstInfo.colorType()) {
-                    case kRGBA_8888_SkColorType:
-                        if (16 == encodedInfo.bitsPerComponent()) {
-                            proc = &swizzle_rgb16_to_rgba;
+    switch (encodedInfo.color()) {
+        case SkEncodedInfo::kGray_Color:
+            switch (encodedInfo.bitsPerComponent()) {
+                case 1:
+                    switch (dstInfo.colorType()) {
+                        case kRGBA_8888_SkColorType:
+                        case kBGRA_8888_SkColorType:
+                            proc = &swizzle_bit_to_n32;
                             break;
-                        }
-
-                        SkASSERT(8 == encodedInfo.bitsPerComponent());
-                        proc = &swizzle_rgb_to_rgba;
-                        fastProc = &fast_swizzle_rgb_to_rgba;
-                        break;
-                    case kBGRA_8888_SkColorType:
-                        if (16 == encodedInfo.bitsPerComponent()) {
-                            proc = &swizzle_rgb16_to_bgra;
+                        case kIndex_8_SkColorType:
+                            proc = &swizzle_bit_to_index;
                             break;
-                        }
-
-                        SkASSERT(8 == encodedInfo.bitsPerComponent());
-                        proc = &swizzle_rgb_to_bgra;
-                        fastProc = &fast_swizzle_rgb_to_bgra;
-                        break;
-                    case kRGB_565_SkColorType:
-                        if (16 == encodedInfo.bitsPerComponent()) {
-                            proc = &swizzle_rgb16_to_565;
+                        case kRGB_565_SkColorType:
+                            proc = &swizzle_bit_to_565;
                             break;
-                        }
-
-                        proc = &swizzle_rgb_to_565;
-                        break;
-                    default:
-                        return nullptr;
-                }
-                break;
-            case SkEncodedInfo::kRGBA_Color:
-                switch (dstInfo.colorType()) {
-                    case kRGBA_8888_SkColorType:
-                        if (16 == encodedInfo.bitsPerComponent()) {
-                            proc = premultiply ? &swizzle_rgba16_to_rgba_premul :
-                                                 &swizzle_rgba16_to_rgba_unpremul;
+                        case kGray_8_SkColorType:
+                            proc = &swizzle_bit_to_grayscale;
                             break;
-                        }
-
-                        SkASSERT(8 == encodedInfo.bitsPerComponent());
-                        if (premultiply) {
-                            if (SkCodec::kYes_ZeroInitialized == zeroInit) {
-                                proc = &SkipLeading8888ZerosThen<swizzle_rgba_to_rgba_premul>;
-                                fastProc = &SkipLeading8888ZerosThen
-                                        <fast_swizzle_rgba_to_rgba_premul>;
-                            } else {
-                                proc = &swizzle_rgba_to_rgba_premul;
-                                fastProc = &fast_swizzle_rgba_to_rgba_premul;
-                            }
-                        } else {
-                            if (SkCodec::kYes_ZeroInitialized == zeroInit) {
-                                proc = &SkipLeading8888ZerosThen<sample4>;
-                                fastProc = &SkipLeading8888ZerosThen<copy>;
-                            } else {
-                                proc = &sample4;
-                                fastProc = &copy;
-                            }
-                        }
-                        break;
-                    case kBGRA_8888_SkColorType:
-                        if (16 == encodedInfo.bitsPerComponent()) {
-                            proc = premultiply ? &swizzle_rgba16_to_bgra_premul :
-                                                 &swizzle_rgba16_to_bgra_unpremul;
+                        case kRGBA_F16_SkColorType:
+                            proc = &swizzle_bit_to_f16;
                             break;
+                        default:
+                            return nullptr;
+                    }
+                    break;
+                case 8:
+                    switch (dstInfo.colorType()) {
+                        case kRGBA_8888_SkColorType:
+                        case kBGRA_8888_SkColorType:
+                            proc = &swizzle_gray_to_n32;
+                            fastProc = &fast_swizzle_gray_to_n32;
+                            break;
+                        case kGray_8_SkColorType:
+                            proc = &sample1;
+                            fastProc = &copy;
+                            break;
+                        case kRGB_565_SkColorType:
+                            proc = &swizzle_gray_to_565;
+                            break;
+                        default:
+                            return nullptr;
+                    }
+                    break;
+                default:
+                    return nullptr;
+            }
+            break;
+        case SkEncodedInfo::kGrayAlpha_Color:
+            switch (dstInfo.colorType()) {
+                case kRGBA_8888_SkColorType:
+                case kBGRA_8888_SkColorType:
+                    if (premultiply) {
+                        if (SkCodec::kYes_ZeroInitialized == zeroInit) {
+                            proc = &SkipLeadingGrayAlphaZerosThen
+                                    <swizzle_grayalpha_to_n32_premul>;
+                            fastProc = &SkipLeadingGrayAlphaZerosThen
+                                    <fast_swizzle_grayalpha_to_n32_premul>;
+                        } else {
+                            proc = &swizzle_grayalpha_to_n32_premul;
+                            fastProc = &fast_swizzle_grayalpha_to_n32_premul;
                         }
+                    } else {
+                        if (SkCodec::kYes_ZeroInitialized == zeroInit) {
+                            proc = &SkipLeadingGrayAlphaZerosThen
+                                    <swizzle_grayalpha_to_n32_unpremul>;
+                            fastProc = &SkipLeadingGrayAlphaZerosThen
+                                    <fast_swizzle_grayalpha_to_n32_unpremul>;
+                        } else {
+                            proc = &swizzle_grayalpha_to_n32_unpremul;
+                            fastProc = &fast_swizzle_grayalpha_to_n32_unpremul;
+                        }
+                    }
+                    break;
+                default:
+                    return nullptr;
+            }
+            break;
+        case SkEncodedInfo::kPalette_Color:
+            // We assume that the color table is premultiplied and swizzled
+            // as desired.
+            switch (encodedInfo.bitsPerComponent()) {
+                case 1:
+                case 2:
+                case 4:
+                    switch (dstInfo.colorType()) {
+                        case kRGBA_8888_SkColorType:
+                        case kBGRA_8888_SkColorType:
+                            proc = &swizzle_small_index_to_n32;
+                            break;
+                        case kRGB_565_SkColorType:
+                            proc = &swizzle_small_index_to_565;
+                            break;
+                        case kIndex_8_SkColorType:
+                            proc = &swizzle_small_index_to_index;
+                            break;
+                        default:
+                            return nullptr;
+                    }
+                    break;
+                case 8:
+                    switch (dstInfo.colorType()) {
+                        case kRGBA_8888_SkColorType:
+                        case kBGRA_8888_SkColorType:
+                            if (SkCodec::kYes_ZeroInitialized == zeroInit) {
+                                proc = &swizzle_index_to_n32_skipZ;
+                            } else {
+                                proc = &swizzle_index_to_n32;
+                            }
+                            break;
+                        case kRGB_565_SkColorType:
+                            proc = &swizzle_index_to_565;
+                            break;
+                        case kIndex_8_SkColorType:
+                            proc = &sample1;
+                            fastProc = &copy;
+                            break;
+                        default:
+                            return nullptr;
+                    }
+                    break;
+                default:
+                    return nullptr;
+            }
+            break;
+        case SkEncodedInfo::kRGB_Color:
+            switch (dstInfo.colorType()) {
+                case kRGBA_8888_SkColorType:
+                    if (16 == encodedInfo.bitsPerComponent()) {
+                        proc = &swizzle_rgb16_to_rgba;
+                        break;
+                    }
 
-                        SkASSERT(8 == encodedInfo.bitsPerComponent());
-                        if (premultiply) {
-                            if (SkCodec::kYes_ZeroInitialized == zeroInit) {
-                                proc = &SkipLeading8888ZerosThen<swizzle_rgba_to_bgra_premul>;
-                                fastProc = &SkipLeading8888ZerosThen
-                                        <fast_swizzle_rgba_to_bgra_premul>;
-                            } else {
-                                proc = &swizzle_rgba_to_bgra_premul;
-                                fastProc = &fast_swizzle_rgba_to_bgra_premul;
-                            }
-                        } else {
-                            if (SkCodec::kYes_ZeroInitialized == zeroInit) {
-                                proc = &SkipLeading8888ZerosThen<swizzle_rgba_to_bgra_unpremul>;
-                                fastProc = &SkipLeading8888ZerosThen
-                                        <fast_swizzle_rgba_to_bgra_unpremul>;
-                            } else {
-                                proc = &swizzle_rgba_to_bgra_unpremul;
-                                fastProc = &fast_swizzle_rgba_to_bgra_unpremul;
-                            }
-                        }
+                    SkASSERT(8 == encodedInfo.bitsPerComponent());
+                    proc = &swizzle_rgb_to_rgba;
+                    fastProc = &fast_swizzle_rgb_to_rgba;
+                    break;
+                case kBGRA_8888_SkColorType:
+                    if (16 == encodedInfo.bitsPerComponent()) {
+                        proc = &swizzle_rgb16_to_bgra;
                         break;
-                    default:
-                        return nullptr;
-                }
-                break;
-            case SkEncodedInfo::kBGR_Color:
-                switch (dstInfo.colorType()) {
-                    case kBGRA_8888_SkColorType:
-                        proc = &swizzle_rgb_to_rgba;
-                        fastProc = &fast_swizzle_rgb_to_rgba;
-                        break;
-                    case kRGBA_8888_SkColorType:
-                        proc = &swizzle_rgb_to_bgra;
-                        fastProc = &fast_swizzle_rgb_to_bgra;
-                        break;
-                    case kRGB_565_SkColorType:
-                        proc = &swizzle_bgr_to_565;
-                        break;
-                    default:
-                        return nullptr;
-                }
-                break;
-            case SkEncodedInfo::kBGRX_Color:
-                switch (dstInfo.colorType()) {
-                    case kBGRA_8888_SkColorType:
-                        proc = &swizzle_rgb_to_rgba;
-                        break;
-                    case kRGBA_8888_SkColorType:
-                        proc = &swizzle_rgb_to_bgra;
-                        break;
-                    case kRGB_565_SkColorType:
-                        proc = &swizzle_bgr_to_565;
-                        break;
-                    default:
-                        return nullptr;
-                }
-                break;
-            case SkEncodedInfo::kBGRA_Color:
-                switch (dstInfo.colorType()) {
-                    case kBGRA_8888_SkColorType:
-                        if (premultiply) {
-                            if (SkCodec::kYes_ZeroInitialized == zeroInit) {
-                                proc = &SkipLeading8888ZerosThen<swizzle_rgba_to_rgba_premul>;
-                                fastProc = &SkipLeading8888ZerosThen
-                                        <fast_swizzle_rgba_to_rgba_premul>;
-                            } else {
-                                proc = &swizzle_rgba_to_rgba_premul;
-                                fastProc = &fast_swizzle_rgba_to_rgba_premul;
-                            }
-                        } else {
-                            if (SkCodec::kYes_ZeroInitialized == zeroInit) {
-                                proc = &SkipLeading8888ZerosThen<sample4>;
-                                fastProc = &SkipLeading8888ZerosThen<copy>;
-                            } else {
-                                proc = &sample4;
-                                fastProc = &copy;
-                            }
-                        }
-                        break;
-                    case kRGBA_8888_SkColorType:
-                        if (premultiply) {
-                            if (SkCodec::kYes_ZeroInitialized == zeroInit) {
-                                proc = &SkipLeading8888ZerosThen<swizzle_rgba_to_bgra_premul>;
-                                fastProc = &SkipLeading8888ZerosThen
-                                        <fast_swizzle_rgba_to_bgra_premul>;
-                            } else {
-                                proc = &swizzle_rgba_to_bgra_premul;
-                                fastProc = &fast_swizzle_rgba_to_bgra_premul;
-                            }
-                        } else {
-                            if (SkCodec::kYes_ZeroInitialized == zeroInit) {
-                                proc = &SkipLeading8888ZerosThen<swizzle_rgba_to_bgra_unpremul>;
-                                fastProc = &SkipLeading8888ZerosThen
-                                        <fast_swizzle_rgba_to_bgra_unpremul>;
-                            } else {
-                                proc = &swizzle_rgba_to_bgra_unpremul;
-                                fastProc = &fast_swizzle_rgba_to_bgra_unpremul;
-                            }
-                        }
-                        break;
-                    default:
-                        return nullptr;
-                }
-                break;
-            case SkEncodedInfo::kInvertedCMYK_Color:
-                switch (dstInfo.colorType()) {
-                    case kRGBA_8888_SkColorType:
-                        proc = &swizzle_cmyk_to_rgba;
-                        fastProc = &fast_swizzle_cmyk_to_rgba;
-                        break;
-                    case kBGRA_8888_SkColorType:
-                        proc = &swizzle_cmyk_to_bgra;
-                        fastProc = &fast_swizzle_cmyk_to_bgra;
-                        break;
-                    case kRGB_565_SkColorType:
-                        proc = &swizzle_cmyk_to_565;
-                        break;
-                    default:
-                        return nullptr;
-                }
-                break;
-            default:
-                return nullptr;
-        }
+                    }
 
-        // Store bpp in bytes if it is an even multiple, otherwise use bits
-        uint8_t bitsPerPixel = encodedInfo.bitsPerPixel();
-        srcBPP = SkIsAlign8(bitsPerPixel) ? bitsPerPixel / 8 : bitsPerPixel;
+                    SkASSERT(8 == encodedInfo.bitsPerComponent());
+                    proc = &swizzle_rgb_to_bgra;
+                    fastProc = &fast_swizzle_rgb_to_bgra;
+                    break;
+                case kRGB_565_SkColorType:
+                    if (16 == encodedInfo.bitsPerComponent()) {
+                        proc = &swizzle_rgb16_to_565;
+                        break;
+                    }
+
+                    proc = &swizzle_rgb_to_565;
+                    break;
+                default:
+                    return nullptr;
+            }
+            break;
+        case SkEncodedInfo::kRGBA_Color:
+            switch (dstInfo.colorType()) {
+                case kRGBA_8888_SkColorType:
+                    if (16 == encodedInfo.bitsPerComponent()) {
+                        proc = premultiply ? &swizzle_rgba16_to_rgba_premul :
+                                             &swizzle_rgba16_to_rgba_unpremul;
+                        break;
+                    }
+
+                    SkASSERT(8 == encodedInfo.bitsPerComponent());
+                    if (premultiply) {
+                        if (SkCodec::kYes_ZeroInitialized == zeroInit) {
+                            proc = &SkipLeading8888ZerosThen<swizzle_rgba_to_rgba_premul>;
+                            fastProc = &SkipLeading8888ZerosThen
+                                    <fast_swizzle_rgba_to_rgba_premul>;
+                        } else {
+                            proc = &swizzle_rgba_to_rgba_premul;
+                            fastProc = &fast_swizzle_rgba_to_rgba_premul;
+                        }
+                    } else {
+                        if (SkCodec::kYes_ZeroInitialized == zeroInit) {
+                            proc = &SkipLeading8888ZerosThen<sample4>;
+                            fastProc = &SkipLeading8888ZerosThen<copy>;
+                        } else {
+                            proc = &sample4;
+                            fastProc = &copy;
+                        }
+                    }
+                    break;
+                case kBGRA_8888_SkColorType:
+                    if (16 == encodedInfo.bitsPerComponent()) {
+                        proc = premultiply ? &swizzle_rgba16_to_bgra_premul :
+                                             &swizzle_rgba16_to_bgra_unpremul;
+                        break;
+                    }
+
+                    SkASSERT(8 == encodedInfo.bitsPerComponent());
+                    if (premultiply) {
+                        if (SkCodec::kYes_ZeroInitialized == zeroInit) {
+                            proc = &SkipLeading8888ZerosThen<swizzle_rgba_to_bgra_premul>;
+                            fastProc = &SkipLeading8888ZerosThen
+                                    <fast_swizzle_rgba_to_bgra_premul>;
+                        } else {
+                            proc = &swizzle_rgba_to_bgra_premul;
+                            fastProc = &fast_swizzle_rgba_to_bgra_premul;
+                        }
+                    } else {
+                        if (SkCodec::kYes_ZeroInitialized == zeroInit) {
+                            proc = &SkipLeading8888ZerosThen<swizzle_rgba_to_bgra_unpremul>;
+                            fastProc = &SkipLeading8888ZerosThen
+                                    <fast_swizzle_rgba_to_bgra_unpremul>;
+                        } else {
+                            proc = &swizzle_rgba_to_bgra_unpremul;
+                            fastProc = &fast_swizzle_rgba_to_bgra_unpremul;
+                        }
+                    }
+                    break;
+                default:
+                    return nullptr;
+            }
+            break;
+        case SkEncodedInfo::kBGR_Color:
+            switch (dstInfo.colorType()) {
+                case kBGRA_8888_SkColorType:
+                    proc = &swizzle_rgb_to_rgba;
+                    fastProc = &fast_swizzle_rgb_to_rgba;
+                    break;
+                case kRGBA_8888_SkColorType:
+                    proc = &swizzle_rgb_to_bgra;
+                    fastProc = &fast_swizzle_rgb_to_bgra;
+                    break;
+                case kRGB_565_SkColorType:
+                    proc = &swizzle_bgr_to_565;
+                    break;
+                default:
+                    return nullptr;
+            }
+            break;
+        case SkEncodedInfo::kBGRX_Color:
+            switch (dstInfo.colorType()) {
+                case kBGRA_8888_SkColorType:
+                    proc = &swizzle_rgb_to_rgba;
+                    break;
+                case kRGBA_8888_SkColorType:
+                    proc = &swizzle_rgb_to_bgra;
+                    break;
+                case kRGB_565_SkColorType:
+                    proc = &swizzle_bgr_to_565;
+                    break;
+                default:
+                    return nullptr;
+            }
+            break;
+        case SkEncodedInfo::kBGRA_Color:
+            switch (dstInfo.colorType()) {
+                case kBGRA_8888_SkColorType:
+                    if (premultiply) {
+                        if (SkCodec::kYes_ZeroInitialized == zeroInit) {
+                            proc = &SkipLeading8888ZerosThen<swizzle_rgba_to_rgba_premul>;
+                            fastProc = &SkipLeading8888ZerosThen
+                                    <fast_swizzle_rgba_to_rgba_premul>;
+                        } else {
+                            proc = &swizzle_rgba_to_rgba_premul;
+                            fastProc = &fast_swizzle_rgba_to_rgba_premul;
+                        }
+                    } else {
+                        if (SkCodec::kYes_ZeroInitialized == zeroInit) {
+                            proc = &SkipLeading8888ZerosThen<sample4>;
+                            fastProc = &SkipLeading8888ZerosThen<copy>;
+                        } else {
+                            proc = &sample4;
+                            fastProc = &copy;
+                        }
+                    }
+                    break;
+                case kRGBA_8888_SkColorType:
+                    if (premultiply) {
+                        if (SkCodec::kYes_ZeroInitialized == zeroInit) {
+                            proc = &SkipLeading8888ZerosThen<swizzle_rgba_to_bgra_premul>;
+                            fastProc = &SkipLeading8888ZerosThen
+                                    <fast_swizzle_rgba_to_bgra_premul>;
+                        } else {
+                            proc = &swizzle_rgba_to_bgra_premul;
+                            fastProc = &fast_swizzle_rgba_to_bgra_premul;
+                        }
+                    } else {
+                        if (SkCodec::kYes_ZeroInitialized == zeroInit) {
+                            proc = &SkipLeading8888ZerosThen<swizzle_rgba_to_bgra_unpremul>;
+                            fastProc = &SkipLeading8888ZerosThen
+                                    <fast_swizzle_rgba_to_bgra_unpremul>;
+                        } else {
+                            proc = &swizzle_rgba_to_bgra_unpremul;
+                            fastProc = &fast_swizzle_rgba_to_bgra_unpremul;
+                        }
+                    }
+                    break;
+                default:
+                    return nullptr;
+            }
+            break;
+        case SkEncodedInfo::kInvertedCMYK_Color:
+            switch (dstInfo.colorType()) {
+                case kRGBA_8888_SkColorType:
+                    proc = &swizzle_cmyk_to_rgba;
+                    fastProc = &fast_swizzle_cmyk_to_rgba;
+                    break;
+                case kBGRA_8888_SkColorType:
+                    proc = &swizzle_cmyk_to_bgra;
+                    fastProc = &fast_swizzle_cmyk_to_bgra;
+                    break;
+                case kRGB_565_SkColorType:
+                    proc = &swizzle_cmyk_to_565;
+                    break;
+                default:
+                    return nullptr;
+            }
+            break;
+        default:
+            return nullptr;
     }
 
+    // Store bpp in bytes if it is an even multiple, otherwise use bits
+    uint8_t bitsPerPixel = encodedInfo.bitsPerPixel();
+    int srcBPP = SkIsAlign8(bitsPerPixel) ? bitsPerPixel / 8 : bitsPerPixel;
+    int dstBPP = dstInfo.bytesPerPixel();
+    return Make(dstInfo, fastProc, proc, ctable, srcBPP, dstBPP, options, frame);
+}
+
+std::unique_ptr<SkSwizzler> SkSwizzler::Make(const SkImageInfo& dstInfo,
+        RowProc fastProc, RowProc proc, const SkPMColor* ctable, int srcBPP,
+        int dstBPP, const SkCodec::Options& options, const SkIRect* frame) {
     int srcOffset = 0;
     int srcWidth = dstInfo.width();
     int dstOffset = 0;
@@ -1222,8 +1197,8 @@
         srcWidth = frame->width();
     }
 
-    return new SkSwizzler(fastProc, proc, ctable, srcOffset, srcWidth, dstOffset, dstWidth,
-            srcBPP, dstBPP);
+    return std::unique_ptr<SkSwizzler>(new SkSwizzler(fastProc, proc, ctable, srcOffset, srcWidth,
+                                                      dstOffset, dstWidth, srcBPP, dstBPP));
 }
 
 SkSwizzler::SkSwizzler(RowProc fastProc, RowProc proc, const SkPMColor* ctable, int srcOffset,
diff --git a/src/codec/SkSwizzler.h b/src/codec/SkSwizzler.h
index ebaed7e..6ecedda 100644
--- a/src/codec/SkSwizzler.h
+++ b/src/codec/SkSwizzler.h
@@ -21,14 +21,10 @@
      *  @param ctable Unowned pointer to an array of up to 256 colors for an
      *                index source.
      *  @param dstInfo Describes the destination.
-     *  @param options Indicates if dst is zero-initialized. The
-     *                         implementation may choose to skip writing zeroes
-     *                         if set to kYes_ZeroInitialized.
-     *                 Contains partial scanline information.
+     *  @param options Contains partial scanline information and whether the dst is zero-
+     *                 initialized.
      *  @param frame   Is non-NULL if the source pixels are part of an image
      *                 frame that is a subset of the full image.
-     *  @param skipFormatConversion Indicates that we should skip format conversion.
-     *                              The swizzler only needs to sample and/or subset.
      *
      *  Note that a deeper discussion of partial scanline subsets and image frame
      *  subsets is below.  Currently, we do not support both simultaneously.  If
@@ -36,10 +32,22 @@
      *
      *  @return A new SkSwizzler or nullptr on failure.
      */
-    static SkSwizzler* CreateSwizzler(const SkEncodedInfo& encodedInfo, const SkPMColor* ctable,
-                                      const SkImageInfo& dstInfo, const SkCodec::Options&,
-                                      const SkIRect* frame = nullptr,
-                                      bool skipFormatConversion = false);
+    static std::unique_ptr<SkSwizzler> Make(const SkEncodedInfo& encodedInfo,
+            const SkPMColor* ctable, const SkImageInfo& dstInfo, const SkCodec::Options&,
+            const SkIRect* frame = nullptr);
+
+    /**
+     *  Create a simplified swizzler that does not need to do format conversion. The swizzler
+     *  only needs to sample and/or subset.
+     *
+     *  @param srcBPP Bytes per pixel of the source.
+     *  @param dstInfo Describes the destination.
+     *  @param options Contains partial scanline information and whether the dst is zero-
+     *                 initialized.
+     *  @return A new SkSwizzler or nullptr on failure.
+     */
+    static std::unique_ptr<SkSwizzler> MakeSimple(int srcBPP, const SkImageInfo& dstInfo,
+                                                  const SkCodec::Options&);
 
     /**
      *  Swizzle a line. Generally this will be called height times, once
@@ -209,6 +217,9 @@
 
     SkSwizzler(RowProc fastProc, RowProc proc, const SkPMColor* ctable, int srcOffset,
             int srcWidth, int dstOffset, int dstWidth, int srcBPP, int dstBPP);
+    static std::unique_ptr<SkSwizzler> Make(const SkImageInfo& dstInfo, RowProc fastProc,
+            RowProc proc, const SkPMColor* ctable, int srcBPP, int dstBPP,
+            const SkCodec::Options& options, const SkIRect* frame);
 
     int onSetSampleX(int) override;
 
diff --git a/src/codec/SkWbmpCodec.cpp b/src/codec/SkWbmpCodec.cpp
index d59789b..96f7529 100644
--- a/src/codec/SkWbmpCodec.cpp
+++ b/src/codec/SkWbmpCodec.cpp
@@ -97,11 +97,6 @@
     return read_header(this->stream(), nullptr);
 }
 
-SkSwizzler* SkWbmpCodec::initializeSwizzler(const SkImageInfo& info, const SkPMColor* ctable,
-        const Options& opts) {
-    return SkSwizzler::CreateSwizzler(this->getEncodedInfo(), ctable, info, opts);
-}
-
 bool SkWbmpCodec::readRow(uint8_t* row) {
     return this->stream()->read(row, fSrcRowBytes) == fSrcRowBytes;
 }
@@ -137,7 +132,8 @@
     setup_color_table(info.colorType(), ctable, ctableCount);
 
     // Initialize the swizzler
-    std::unique_ptr<SkSwizzler> swizzler(this->initializeSwizzler(info, ctable, options));
+    std::unique_ptr<SkSwizzler> swizzler = SkSwizzler::Make(this->getEncodedInfo(), nullptr, info,
+                                                            options);
     SkASSERT(swizzler);
 
     // Perform the decode
@@ -210,7 +206,8 @@
     }
 
     // Initialize the swizzler
-    fSwizzler.reset(this->initializeSwizzler(dstInfo, get_color_ptr(fColorTable.get()), options));
+    fSwizzler = SkSwizzler::Make(this->getEncodedInfo(), get_color_ptr(fColorTable.get()),
+                                 dstInfo, options);
     SkASSERT(fSwizzler);
 
     fSrcBuffer.reset(fSrcRowBytes);
diff --git a/src/codec/SkWbmpCodec.h b/src/codec/SkWbmpCodec.h
index 40f507e..c37b493 100644
--- a/src/codec/SkWbmpCodec.h
+++ b/src/codec/SkWbmpCodec.h
@@ -29,11 +29,6 @@
                        const Options&, SkPMColor[], int*, int*) override;
     bool onRewind() override;
 private:
-    /*
-     * Returns a swizzler on success, nullptr on failure
-     */
-    SkSwizzler* initializeSwizzler(const SkImageInfo& info, const SkPMColor* ctable,
-                                   const Options& opts);
     SkSampler* getSampler(bool createIfNecessary) override {
         SkASSERT(fSwizzler || !createIfNecessary);
         return fSwizzler.get();