Delete SkImageDecoder

This image decoding implementation has been replaced
by SkCodec in Android.

Additionally, we have replaced uses of SkImageDecoder
in Skia and Google3 with uses of SkCodec.

Now we can delete SkImageDecoder :).

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1820503002
CQ_EXTRA_TRYBOTS=client.skia.compile:Build-Ubuntu-GCC-x86_64-Release-CMake-Trybot,Build-Mac-Clang-x86_64-Release-CMake-Trybot

Committed: https://skia.googlesource.com/skia/+/f799706656f2581c5bf5510d94df3fa17cce1607

Committed: https://skia.googlesource.com/skia/+/5b6e73e0c8282c4d85accbfbcecc6dee84f8a1eb

Committed: https://skia.googlesource.com/skia/+/f037fdebda2a2626e6512d7532063f2cd41a264d

Review URL: https://codereview.chromium.org/1820503002
diff --git a/src/images/SkImageDecoder_libjpeg.cpp b/src/images/SkImageDecoder_libjpeg.cpp
index 89bfefc..fd10bdb 100644
--- a/src/images/SkImageDecoder_libjpeg.cpp
+++ b/src/images/SkImageDecoder_libjpeg.cpp
@@ -6,13 +6,10 @@
  */
 
 
-#include "SkImageDecoder.h"
 #include "SkImageEncoder.h"
 #include "SkJpegUtility.h"
 #include "SkColorPriv.h"
 #include "SkDither.h"
-#include "SkMSAN.h"
-#include "SkScaledBitmapSampler.h"
 #include "SkStream.h"
 #include "SkTemplates.h"
 #include "SkTime.h"
@@ -28,730 +25,12 @@
     #include "jerror.h"
 }
 
-// These enable timing code that report milliseconds for an encoding/decoding
+// These enable timing code that report milliseconds for an encoding
 //#define TIME_ENCODE
-//#define TIME_DECODE
 
 // this enables our rgb->yuv code, which is faster than libjpeg on ARM
 #define WE_CONVERT_TO_YUV
 
-// If ANDROID_RGB is defined by in the jpeg headers it indicates that jpeg offers
-// support for two additional formats (1) JCS_RGBA_8888 and (2) JCS_RGB_565.
-
-#define DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_WARNINGS true
-#define DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_ERRORS true
-SK_CONF_DECLARE(bool, c_suppressJPEGImageDecoderWarnings,
-                "images.jpeg.suppressDecoderWarnings",
-                DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_WARNINGS,
-                "Suppress most JPG warnings when calling decode functions.");
-SK_CONF_DECLARE(bool, c_suppressJPEGImageDecoderErrors,
-                "images.jpeg.suppressDecoderErrors",
-                DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_ERRORS,
-                "Suppress most JPG error messages when decode "
-                "function fails.");
-
-//////////////////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////
-
-static void do_nothing_emit_message(jpeg_common_struct*, int) {
-    /* do nothing */
-}
-static void do_nothing_output_message(j_common_ptr) {
-    /* do nothing */
-}
-
-static void initialize_info(jpeg_decompress_struct* cinfo, skjpeg_source_mgr* src_mgr) {
-    SkASSERT(cinfo != nullptr);
-    SkASSERT(src_mgr != nullptr);
-    jpeg_create_decompress(cinfo);
-    cinfo->src = src_mgr;
-    /* To suppress warnings with a SK_DEBUG binary, set the
-     * environment variable "skia_images_jpeg_suppressDecoderWarnings"
-     * to "true".  Inside a program that links to skia:
-     * SK_CONF_SET("images.jpeg.suppressDecoderWarnings", true); */
-    if (c_suppressJPEGImageDecoderWarnings) {
-        cinfo->err->emit_message = &do_nothing_emit_message;
-    }
-    /* To suppress error messages with a SK_DEBUG binary, set the
-     * environment variable "skia_images_jpeg_suppressDecoderErrors"
-     * to "true".  Inside a program that links to skia:
-     * SK_CONF_SET("images.jpeg.suppressDecoderErrors", true); */
-    if (c_suppressJPEGImageDecoderErrors) {
-        cinfo->err->output_message = &do_nothing_output_message;
-    }
-}
-
-class SkJPEGImageDecoder : public SkImageDecoder {
-public:
-
-    Format getFormat() const override {
-        return kJPEG_Format;
-    }
-
-protected:
-    Result onDecode(SkStream* stream, SkBitmap* bm, Mode) override;
-    bool onDecodeYUV8Planes(SkStream* stream, SkISize componentSizes[3],
-                            void* planes[3], size_t rowBytes[3],
-                            SkYUVColorSpace* colorSpace) override;
-
-private:
-
-    /**
-     *  Determine the appropriate bitmap colortype and out_color_space based on
-     *  both the preference of the caller and the jpeg_color_space on the
-     *  jpeg_decompress_struct passed in.
-     *  Must be called after jpeg_read_header.
-     */
-    SkColorType getBitmapColorType(jpeg_decompress_struct*);
-
-    typedef SkImageDecoder INHERITED;
-};
-
-//////////////////////////////////////////////////////////////////////////
-
-/* Automatically clean up after throwing an exception */
-class JPEGAutoClean {
-public:
-    JPEGAutoClean(): cinfo_ptr(nullptr) {}
-    ~JPEGAutoClean() {
-        if (cinfo_ptr) {
-            jpeg_destroy_decompress(cinfo_ptr);
-        }
-    }
-    void set(jpeg_decompress_struct* info) {
-        cinfo_ptr = info;
-    }
-private:
-    jpeg_decompress_struct* cinfo_ptr;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
-/*  If we need to better match the request, we might examine the image and
-     output dimensions, and determine if the downsampling jpeg provided is
-     not sufficient. If so, we can recompute a modified sampleSize value to
-     make up the difference.
-
-     To skip this additional scaling, just set sampleSize = 1; below.
- */
-static int recompute_sampleSize(int sampleSize,
-                                const jpeg_decompress_struct& cinfo) {
-    return sampleSize * cinfo.output_width / cinfo.image_width;
-}
-
-static bool valid_output_dimensions(const jpeg_decompress_struct& cinfo) {
-    /* These are initialized to 0, so if they have non-zero values, we assume
-       they are "valid" (i.e. have been computed by libjpeg)
-     */
-    return 0 != cinfo.output_width && 0 != cinfo.output_height;
-}
-
-static bool skip_src_rows(jpeg_decompress_struct* cinfo, void* buffer, int count) {
-    for (int i = 0; i < count; i++) {
-        JSAMPLE* rowptr = (JSAMPLE*)buffer;
-        int row_count = jpeg_read_scanlines(cinfo, &rowptr, 1);
-        if (1 != row_count) {
-            return false;
-        }
-    }
-    return true;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-// This guy exists just to aid in debugging, as it allows debuggers to just
-// set a break-point in one place to see all error exists.
-static void print_jpeg_decoder_errors(const jpeg_decompress_struct& cinfo,
-                         int width, int height, const char caller[]) {
-    if (!(c_suppressJPEGImageDecoderErrors)) {
-        char buffer[JMSG_LENGTH_MAX];
-        cinfo.err->format_message((const j_common_ptr)&cinfo, buffer);
-        SkDebugf("libjpeg error %d <%s> from %s [%d %d]\n",
-                 cinfo.err->msg_code, buffer, caller, width, height);
-    }
-}
-
-static bool return_false(const jpeg_decompress_struct& cinfo,
-                         const char caller[]) {
-    print_jpeg_decoder_errors(cinfo, 0, 0, caller);
-    return false;
-}
-
-static SkImageDecoder::Result return_failure(const jpeg_decompress_struct& cinfo,
-                                             const SkBitmap& bm, const char caller[]) {
-    print_jpeg_decoder_errors(cinfo, bm.width(), bm.height(), caller);
-    return SkImageDecoder::kFailure;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-// Convert a scanline of CMYK samples to RGBX in place. Note that this
-// method moves the "scanline" pointer in its processing
-static void convert_CMYK_to_RGB(uint8_t* scanline, unsigned int width) {
-    // At this point we've received CMYK pixels from libjpeg. We
-    // perform a crude conversion to RGB (based on the formulae
-    // from easyrgb.com):
-    //  CMYK -> CMY
-    //    C = ( C * (1 - K) + K )      // for each CMY component
-    //  CMY -> RGB
-    //    R = ( 1 - C ) * 255          // for each RGB component
-    // Unfortunately we are seeing inverted CMYK so all the original terms
-    // are 1-. This yields:
-    //  CMYK -> CMY
-    //    C = ( (1-C) * (1 - (1-K) + (1-K) ) -> C = 1 - C*K
-    // The conversion from CMY->RGB remains the same
-    for (unsigned int x = 0; x < width; ++x, scanline += 4) {
-        scanline[0] = SkMulDiv255Round(scanline[0], scanline[3]);
-        scanline[1] = SkMulDiv255Round(scanline[1], scanline[3]);
-        scanline[2] = SkMulDiv255Round(scanline[2], scanline[3]);
-        scanline[3] = 255;
-    }
-}
-
-/**
- *  Common code for setting the error manager.
- */
-static void set_error_mgr(jpeg_decompress_struct* cinfo, skjpeg_error_mgr* errorManager) {
-    SkASSERT(cinfo != nullptr);
-    SkASSERT(errorManager != nullptr);
-    cinfo->err = jpeg_std_error(errorManager);
-    errorManager->error_exit = skjpeg_error_exit;
-}
-
-/**
- * Common code for setting the dct method.
- */
-static void set_dct_method(const SkImageDecoder& decoder, jpeg_decompress_struct* cinfo) {
-    SkASSERT(cinfo != nullptr);
-    cinfo->dct_method = JDCT_ISLOW;
-}
-
-SkColorType SkJPEGImageDecoder::getBitmapColorType(jpeg_decompress_struct* cinfo) {
-    SkASSERT(cinfo != nullptr);
-
-    SrcDepth srcDepth = k32Bit_SrcDepth;
-    if (JCS_GRAYSCALE == cinfo->jpeg_color_space) {
-        srcDepth = k8BitGray_SrcDepth;
-    }
-
-    SkColorType colorType = this->getPrefColorType(srcDepth, /*hasAlpha*/ false);
-    switch (colorType) {
-        case kAlpha_8_SkColorType:
-            // Only respect A8 colortype if the original is grayscale,
-            // in which case we will treat the grayscale as alpha
-            // values.
-            if (cinfo->jpeg_color_space != JCS_GRAYSCALE) {
-                colorType = kN32_SkColorType;
-            }
-            break;
-        case kN32_SkColorType:
-            // Fall through.
-        case kARGB_4444_SkColorType:
-            // Fall through.
-        case kRGB_565_SkColorType:
-            // These are acceptable destination colortypes.
-            break;
-        default:
-            // Force all other colortypes to 8888.
-            colorType = kN32_SkColorType;
-            break;
-    }
-
-    switch (cinfo->jpeg_color_space) {
-        case JCS_CMYK:
-            // Fall through.
-        case JCS_YCCK:
-            // libjpeg cannot convert from CMYK or YCCK to RGB - here we set up
-            // so libjpeg will give us CMYK samples back and we will later
-            // manually convert them to RGB
-            cinfo->out_color_space = JCS_CMYK;
-            break;
-        case JCS_GRAYSCALE:
-            if (kAlpha_8_SkColorType == colorType) {
-                cinfo->out_color_space = JCS_GRAYSCALE;
-                break;
-            }
-            // The data is JCS_GRAYSCALE, but the caller wants some sort of RGB
-            // colortype. Fall through to set to the default.
-        default:
-            cinfo->out_color_space = JCS_RGB;
-            break;
-    }
-    return colorType;
-}
-
-/**
- *  Based on the colortype and dither mode, adjust out_color_space and
- *  dither_mode of cinfo. Only does work in ANDROID_RGB
- */
-static void adjust_out_color_space_and_dither(jpeg_decompress_struct* cinfo,
-                                              SkColorType colorType,
-                                              const SkImageDecoder& decoder) {
-    SkASSERT(cinfo != nullptr);
-#ifdef ANDROID_RGB
-    cinfo->dither_mode = JDITHER_NONE;
-    if (JCS_CMYK == cinfo->out_color_space) {
-        return;
-    }
-    switch (colorType) {
-        case kN32_SkColorType:
-            cinfo->out_color_space = JCS_RGBA_8888;
-            break;
-        case kRGB_565_SkColorType:
-            cinfo->out_color_space = JCS_RGB_565;
-            if (decoder.getDitherImage()) {
-                cinfo->dither_mode = JDITHER_ORDERED;
-            }
-            break;
-        default:
-            break;
-    }
-#endif
-}
-
-/**
-   Sets all pixels in given bitmap to SK_ColorWHITE for all rows >= y.
-   Used when decoding fails partway through reading scanlines to fill
-   remaining lines. */
-static void fill_below_level(int y, SkBitmap* bitmap) {
-    SkIRect rect = SkIRect::MakeLTRB(0, y, bitmap->width(), bitmap->height());
-    SkCanvas canvas(*bitmap);
-    canvas.clipRect(SkRect::Make(rect));
-    canvas.drawColor(SK_ColorWHITE);
-}
-
-/**
- *  Get the config and bytes per pixel of the source data. Return
- *  whether the data is supported.
- */
-static bool get_src_config(const jpeg_decompress_struct& cinfo,
-                           SkScaledBitmapSampler::SrcConfig* sc,
-                           int* srcBytesPerPixel) {
-    SkASSERT(sc != nullptr && srcBytesPerPixel != nullptr);
-    if (JCS_CMYK == cinfo.out_color_space) {
-        // In this case we will manually convert the CMYK values to RGB
-        *sc = SkScaledBitmapSampler::kRGBX;
-        // The CMYK work-around relies on 4 components per pixel here
-        *srcBytesPerPixel = 4;
-    } else if (3 == cinfo.out_color_components && JCS_RGB == cinfo.out_color_space) {
-        *sc = SkScaledBitmapSampler::kRGB;
-        *srcBytesPerPixel = 3;
-#ifdef ANDROID_RGB
-    } else if (JCS_RGBA_8888 == cinfo.out_color_space) {
-        *sc = SkScaledBitmapSampler::kRGBX;
-        *srcBytesPerPixel = 4;
-    } else if (JCS_RGB_565 == cinfo.out_color_space) {
-        *sc = SkScaledBitmapSampler::kRGB_565;
-        *srcBytesPerPixel = 2;
-#endif
-    } else if (1 == cinfo.out_color_components &&
-               JCS_GRAYSCALE == cinfo.out_color_space) {
-        *sc = SkScaledBitmapSampler::kGray;
-        *srcBytesPerPixel = 1;
-    } else {
-        return false;
-    }
-    return true;
-}
-
-SkImageDecoder::Result SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
-#ifdef TIME_DECODE
-    SkAutoTime atm("JPEG Decode");
-#endif
-
-    JPEGAutoClean autoClean;
-
-    jpeg_decompress_struct  cinfo;
-    skjpeg_source_mgr       srcManager(stream, this);
-
-    skjpeg_error_mgr errorManager;
-    set_error_mgr(&cinfo, &errorManager);
-
-    // All objects need to be instantiated before this setjmp call so that
-    // they will be cleaned up properly if an error occurs.
-    if (setjmp(errorManager.fJmpBuf)) {
-        return return_failure(cinfo, *bm, "setjmp");
-    }
-
-    initialize_info(&cinfo, &srcManager);
-    autoClean.set(&cinfo);
-
-    int status = jpeg_read_header(&cinfo, true);
-    if (status != JPEG_HEADER_OK) {
-        return return_failure(cinfo, *bm, "read_header");
-    }
-
-    /*  Try to fulfill the requested sampleSize. Since jpeg can do it (when it
-        can) much faster that we, just use their num/denom api to approximate
-        the size.
-    */
-    int sampleSize = this->getSampleSize();
-
-    set_dct_method(*this, &cinfo);
-
-    SkASSERT(1 == cinfo.scale_num);
-    cinfo.scale_denom = sampleSize;
-
-    const SkColorType colorType = this->getBitmapColorType(&cinfo);
-    const SkAlphaType alphaType = kAlpha_8_SkColorType == colorType ?
-                                      kPremul_SkAlphaType : kOpaque_SkAlphaType;
-
-    adjust_out_color_space_and_dither(&cinfo, colorType, *this);
-
-    if (1 == sampleSize && SkImageDecoder::kDecodeBounds_Mode == mode) {
-        // Assume an A8 bitmap is not opaque to avoid the check of each
-        // individual pixel. It is very unlikely to be opaque, since
-        // an opaque A8 bitmap would not be very interesting.
-        // Otherwise, a jpeg image is opaque.
-        bool success = bm->setInfo(SkImageInfo::Make(cinfo.image_width, cinfo.image_height,
-                                                     colorType, alphaType));
-        return success ? kSuccess : kFailure;
-    }
-
-    /*  image_width and image_height are the original dimensions, available
-        after jpeg_read_header(). To see the scaled dimensions, we have to call
-        jpeg_start_decompress(), and then read output_width and output_height.
-    */
-    if (!jpeg_start_decompress(&cinfo)) {
-        /*  If we failed here, we may still have enough information to return
-            to the caller if they just wanted (subsampled bounds). If sampleSize
-            was 1, then we would have already returned. Thus we just check if
-            we're in kDecodeBounds_Mode, and that we have valid output sizes.
-
-            One reason to fail here is that we have insufficient stream data
-            to complete the setup. However, output dimensions seem to get
-            computed very early, which is why this special check can pay off.
-         */
-        if (SkImageDecoder::kDecodeBounds_Mode == mode && valid_output_dimensions(cinfo)) {
-            SkScaledBitmapSampler smpl(cinfo.output_width, cinfo.output_height,
-                                       recompute_sampleSize(sampleSize, cinfo));
-            // Assume an A8 bitmap is not opaque to avoid the check of each
-            // individual pixel. It is very unlikely to be opaque, since
-            // an opaque A8 bitmap would not be very interesting.
-            // Otherwise, a jpeg image is opaque.
-            bool success = bm->setInfo(SkImageInfo::Make(smpl.scaledWidth(), smpl.scaledHeight(),
-                                                         colorType, alphaType));
-            return success ? kSuccess : kFailure;
-        } else {
-            return return_failure(cinfo, *bm, "start_decompress");
-        }
-    }
-    sampleSize = recompute_sampleSize(sampleSize, cinfo);
-
-    SkScaledBitmapSampler sampler(cinfo.output_width, cinfo.output_height, sampleSize);
-    // Assume an A8 bitmap is not opaque to avoid the check of each
-    // individual pixel. It is very unlikely to be opaque, since
-    // an opaque A8 bitmap would not be very interesting.
-    // Otherwise, a jpeg image is opaque.
-    bm->setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(),
-                                  colorType, alphaType));
-    if (SkImageDecoder::kDecodeBounds_Mode == mode) {
-        return kSuccess;
-    }
-    if (!this->allocPixelRef(bm, nullptr)) {
-        return return_failure(cinfo, *bm, "allocPixelRef");
-    }
-
-    SkAutoLockPixels alp(*bm);
-
-#ifdef ANDROID_RGB
-    /* short-circuit the SkScaledBitmapSampler when possible, as this gives
-       a significant performance boost.
-    */
-    if (sampleSize == 1 &&
-        ((kN32_SkColorType == colorType && cinfo.out_color_space == JCS_RGBA_8888) ||
-         (kRGB_565_SkColorType == colorType && cinfo.out_color_space == JCS_RGB_565)))
-    {
-        JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels();
-        INT32 const bpr =  bm->rowBytes();
-
-        while (cinfo.output_scanline < cinfo.output_height) {
-            int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1);
-            if (0 == row_count) {
-                // if row_count == 0, then we didn't get a scanline,
-                // so return early.  We will return a partial image.
-                fill_below_level(cinfo.output_scanline, bm);
-                cinfo.output_scanline = cinfo.output_height;
-                jpeg_finish_decompress(&cinfo);
-                return kPartialSuccess;
-            }
-            if (this->shouldCancelDecode()) {
-                return return_failure(cinfo, *bm, "shouldCancelDecode");
-            }
-            rowptr += bpr;
-        }
-        jpeg_finish_decompress(&cinfo);
-        return kSuccess;
-    }
-#endif
-
-    // check for supported formats
-    SkScaledBitmapSampler::SrcConfig sc;
-    int srcBytesPerPixel;
-
-    if (!get_src_config(cinfo, &sc, &srcBytesPerPixel)) {
-        return return_failure(cinfo, *bm, "jpeg colorspace");
-    }
-
-    if (!sampler.begin(bm, sc, *this)) {
-        return return_failure(cinfo, *bm, "sampler.begin");
-    }
-
-    SkAutoTMalloc<uint8_t> srcStorage(cinfo.output_width * srcBytesPerPixel);
-    uint8_t* srcRow = srcStorage.get();
-
-    //  Possibly skip initial rows [sampler.srcY0]
-    if (!skip_src_rows(&cinfo, srcRow, sampler.srcY0())) {
-        return return_failure(cinfo, *bm, "skip rows");
-    }
-
-    // now loop through scanlines until y == bm->height() - 1
-    for (int y = 0;; y++) {
-        JSAMPLE* rowptr = (JSAMPLE*)srcRow;
-        int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1);
-        sk_msan_mark_initialized(srcRow, srcRow + cinfo.output_width * srcBytesPerPixel,
-                                 "skbug.com/4550");
-        if (0 == row_count) {
-            // if row_count == 0, then we didn't get a scanline,
-            // so return early.  We will return a partial image.
-            fill_below_level(y, bm);
-            cinfo.output_scanline = cinfo.output_height;
-            jpeg_finish_decompress(&cinfo);
-            return kPartialSuccess;
-        }
-        if (this->shouldCancelDecode()) {
-            return return_failure(cinfo, *bm, "shouldCancelDecode");
-        }
-
-        if (JCS_CMYK == cinfo.out_color_space) {
-            convert_CMYK_to_RGB(srcRow, cinfo.output_width);
-        }
-
-
-        sampler.next(srcRow);
-        if (bm->height() - 1 == y) {
-            // we're done
-            break;
-        }
-
-        if (!skip_src_rows(&cinfo, srcRow, sampler.srcDY() - 1)) {
-            return return_failure(cinfo, *bm, "skip rows");
-        }
-    }
-
-    // we formally skip the rest, so we don't get a complaint from libjpeg
-    if (!skip_src_rows(&cinfo, srcRow,
-                       cinfo.output_height - cinfo.output_scanline)) {
-        return return_failure(cinfo, *bm, "skip rows");
-    }
-    jpeg_finish_decompress(&cinfo);
-
-    return kSuccess;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-enum SizeType {
-    kSizeForMemoryAllocation_SizeType,
-    kActualSize_SizeType
-};
-
-static SkISize compute_yuv_size(const jpeg_decompress_struct& info, int component,
-                                SizeType sizeType) {
-    if (sizeType == kSizeForMemoryAllocation_SizeType) {
-        return SkISize::Make(info.cur_comp_info[component]->width_in_blocks * DCTSIZE,
-                             info.cur_comp_info[component]->height_in_blocks * DCTSIZE);
-    }
-    return SkISize::Make(info.cur_comp_info[component]->downsampled_width,
-                         info.cur_comp_info[component]->downsampled_height);
-}
-
-static bool appears_to_be_yuv(const jpeg_decompress_struct& info) {
-    return (info.jpeg_color_space == JCS_YCbCr)
-        && (DCTSIZE == 8)
-        && (info.num_components == 3)
-        && (info.comps_in_scan >= info.num_components)
-        && (info.scale_denom <= 8)
-        && (info.cur_comp_info[0])
-        && (info.cur_comp_info[1])
-        && (info.cur_comp_info[2])
-        && (info.cur_comp_info[1]->h_samp_factor == 1)
-        && (info.cur_comp_info[1]->v_samp_factor == 1)
-        && (info.cur_comp_info[2]->h_samp_factor == 1)
-        && (info.cur_comp_info[2]->v_samp_factor == 1);
-}
-
-static void update_components_sizes(const jpeg_decompress_struct& cinfo, SkISize componentSizes[3],
-                                    SizeType sizeType) {
-    SkASSERT(appears_to_be_yuv(cinfo));
-    for (int i = 0; i < 3; ++i) {
-        componentSizes[i] = compute_yuv_size(cinfo, i, sizeType);
-    }
-}
-
-static bool output_raw_data(jpeg_decompress_struct& cinfo, void* planes[3], size_t rowBytes[3]) {
-    SkASSERT(appears_to_be_yuv(cinfo));
-    // U size and V size have to be the same if we're calling output_raw_data()
-    SkISize uvSize = compute_yuv_size(cinfo, 1, kSizeForMemoryAllocation_SizeType);
-    SkASSERT(uvSize == compute_yuv_size(cinfo, 2, kSizeForMemoryAllocation_SizeType));
-
-    JSAMPARRAY bufferraw[3];
-    JSAMPROW bufferraw2[32];
-    bufferraw[0] = &bufferraw2[0]; // Y channel rows (8 or 16)
-    bufferraw[1] = &bufferraw2[16]; // U channel rows (8)
-    bufferraw[2] = &bufferraw2[24]; // V channel rows (8)
-    int yWidth = cinfo.output_width;
-    int yHeight = cinfo.output_height;
-    int yMaxH = yHeight - 1;
-    int v = cinfo.cur_comp_info[0]->v_samp_factor;
-    int uvMaxH = uvSize.height() - 1;
-    JSAMPROW outputY = static_cast<JSAMPROW>(planes[0]);
-    JSAMPROW outputU = static_cast<JSAMPROW>(planes[1]);
-    JSAMPROW outputV = static_cast<JSAMPROW>(planes[2]);
-    size_t rowBytesY = rowBytes[0];
-    size_t rowBytesU = rowBytes[1];
-    size_t rowBytesV = rowBytes[2];
-
-    int yScanlinesToRead = DCTSIZE * v;
-    SkAutoMalloc lastRowStorage(rowBytesY * 4);
-    JSAMPROW yLastRow = (JSAMPROW)lastRowStorage.get();
-    JSAMPROW uLastRow = yLastRow + rowBytesY;
-    JSAMPROW vLastRow = uLastRow + rowBytesY;
-    JSAMPROW dummyRow = vLastRow + rowBytesY;
-
-    while (cinfo.output_scanline < cinfo.output_height) {
-        // Request 8 or 16 scanlines: returns 0 or more scanlines.
-        bool hasYLastRow(false), hasUVLastRow(false);
-        // Assign 8 or 16 rows of memory to read the Y channel.
-        for (int i = 0; i < yScanlinesToRead; ++i) {
-            int scanline = (cinfo.output_scanline + i);
-            if (scanline < yMaxH) {
-                bufferraw2[i] = &outputY[scanline * rowBytesY];
-            } else if (scanline == yMaxH) {
-                bufferraw2[i] = yLastRow;
-                hasYLastRow = true;
-            } else {
-                bufferraw2[i] = dummyRow;
-            }
-        }
-        int scaledScanline = cinfo.output_scanline / v;
-        // Assign 8 rows of memory to read the U and V channels.
-        for (int i = 0; i < 8; ++i) {
-            int scanline = (scaledScanline + i);
-            if (scanline < uvMaxH) {
-                bufferraw2[16 + i] = &outputU[scanline * rowBytesU];
-                bufferraw2[24 + i] = &outputV[scanline * rowBytesV];
-            } else if (scanline == uvMaxH) {
-                bufferraw2[16 + i] = uLastRow;
-                bufferraw2[24 + i] = vLastRow;
-                hasUVLastRow = true;
-            } else {
-                bufferraw2[16 + i] = dummyRow;
-                bufferraw2[24 + i] = dummyRow;
-            }
-        }
-        JDIMENSION scanlinesRead = jpeg_read_raw_data(&cinfo, bufferraw, yScanlinesToRead);
-
-        if (scanlinesRead == 0) {
-            return false;
-        }
-
-        if (hasYLastRow) {
-            memcpy(&outputY[yMaxH * rowBytesY], yLastRow, yWidth);
-        }
-        if (hasUVLastRow) {
-            memcpy(&outputU[uvMaxH * rowBytesU], uLastRow, uvSize.width());
-            memcpy(&outputV[uvMaxH * rowBytesV], vLastRow, uvSize.width());
-        }
-    }
-
-    cinfo.output_scanline = SkMin32(cinfo.output_scanline, cinfo.output_height);
-
-    return true;
-}
-
-bool SkJPEGImageDecoder::onDecodeYUV8Planes(SkStream* stream, SkISize componentSizes[3],
-                                            void* planes[3], size_t rowBytes[3],
-                                            SkYUVColorSpace* colorSpace) {
-#ifdef TIME_DECODE
-    SkAutoTime atm("JPEG YUV8 Decode");
-#endif
-    if (this->getSampleSize() != 1) {
-        return false; // Resizing not supported
-    }
-
-    JPEGAutoClean autoClean;
-
-    jpeg_decompress_struct  cinfo;
-    skjpeg_source_mgr       srcManager(stream, this);
-
-    skjpeg_error_mgr errorManager;
-    set_error_mgr(&cinfo, &errorManager);
-
-    // All objects need to be instantiated before this setjmp call so that
-    // they will be cleaned up properly if an error occurs.
-    if (setjmp(errorManager.fJmpBuf)) {
-        return return_false(cinfo, "setjmp YUV8");
-    }
-
-    initialize_info(&cinfo, &srcManager);
-    autoClean.set(&cinfo);
-
-    int status = jpeg_read_header(&cinfo, true);
-    if (status != JPEG_HEADER_OK) {
-        return return_false(cinfo, "read_header YUV8");
-    }
-
-    if (!appears_to_be_yuv(cinfo)) {
-        // It's not an error to not be encoded in YUV, so no need to use return_false()
-        return false;
-    }
-
-    cinfo.out_color_space = JCS_YCbCr;
-    cinfo.raw_data_out = TRUE;
-
-    if (!planes || !planes[0] || !rowBytes || !rowBytes[0]) { // Compute size only
-        update_components_sizes(cinfo, componentSizes, kSizeForMemoryAllocation_SizeType);
-        return true;
-    }
-
-    set_dct_method(*this, &cinfo);
-
-    SkASSERT(1 == cinfo.scale_num);
-    cinfo.scale_denom = 1;
-
-#ifdef ANDROID_RGB
-    cinfo.dither_mode = JDITHER_NONE;
-#endif
-
-    /*  image_width and image_height are the original dimensions, available
-        after jpeg_read_header(). To see the scaled dimensions, we have to call
-        jpeg_start_decompress(), and then read output_width and output_height.
-    */
-    if (!jpeg_start_decompress(&cinfo)) {
-        return return_false(cinfo, "start_decompress YUV8");
-    }
-
-    // Seems like jpeg_start_decompress is updating our opinion of whether cinfo represents YUV.
-    // Again, not really an error.
-    if (!appears_to_be_yuv(cinfo)) {
-        return false;
-    }
-
-    if (!output_raw_data(cinfo, planes, rowBytes)) {
-        return return_false(cinfo, "output_raw_data");
-    }
-
-    update_components_sizes(cinfo, componentSizes, kActualSize_SizeType);
-    jpeg_finish_decompress(&cinfo);
-
-    if (nullptr != colorSpace) {
-        *colorSpace = kJPEG_SkYUVColorSpace;
-    }
-
-    return true;
-}
-
 ///////////////////////////////////////////////////////////////////////////////
 
 #include "SkColorPriv.h"
@@ -993,45 +272,11 @@
 };
 
 ///////////////////////////////////////////////////////////////////////////////
-DEFINE_DECODER_CREATOR(JPEGImageDecoder);
 DEFINE_ENCODER_CREATOR(JPEGImageEncoder);
 ///////////////////////////////////////////////////////////////////////////////
 
-static bool is_jpeg(SkStreamRewindable* stream) {
-    static const unsigned char gHeader[] = { 0xFF, 0xD8, 0xFF };
-    static const size_t HEADER_SIZE = sizeof(gHeader);
-
-    char buffer[HEADER_SIZE];
-    size_t len = stream->read(buffer, HEADER_SIZE);
-
-    if (len != HEADER_SIZE) {
-        return false;   // can't read enough
-    }
-    if (memcmp(buffer, gHeader, HEADER_SIZE)) {
-        return false;
-    }
-    return true;
-}
-
-
-static SkImageDecoder* sk_libjpeg_dfactory(SkStreamRewindable* stream) {
-    if (is_jpeg(stream)) {
-        return new SkJPEGImageDecoder;
-    }
-    return nullptr;
-}
-
-static SkImageDecoder::Format get_format_jpeg(SkStreamRewindable* stream) {
-    if (is_jpeg(stream)) {
-        return SkImageDecoder::kJPEG_Format;
-    }
-    return SkImageDecoder::kUnknown_Format;
-}
-
 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) {
     return (SkImageEncoder::kJPEG_Type == t) ? new SkJPEGImageEncoder : nullptr;
 }
 
-static SkImageDecoder_DecodeReg gDReg(sk_libjpeg_dfactory);
-static SkImageDecoder_FormatReg gFormatReg(get_format_jpeg);
 static SkImageEncoder_EncodeReg gEReg(sk_libjpeg_efactory);