Home | History | Annotate | Download | only in images
      1 /*
      2  * Copyright 2007 The Android Open Source Project
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 
      9 #include "SkImageDecoder.h"
     10 #include "SkImageEncoder.h"
     11 #include "SkJpegUtility.h"
     12 #include "SkColorPriv.h"
     13 #include "SkDither.h"
     14 #include "SkScaledBitmapSampler.h"
     15 #include "SkStream.h"
     16 #include "SkTemplates.h"
     17 #include "SkTime.h"
     18 #include "SkUtils.h"
     19 #include "SkRTConf.h"
     20 #include "SkRect.h"
     21 #include "SkCanvas.h"
     22 
     23 
     24 #include <stdio.h>
     25 extern "C" {
     26     #include "jpeglib.h"
     27     #include "jerror.h"
     28 }
     29 
     30 // These enable timing code that report milliseconds for an encoding/decoding
     31 //#define TIME_ENCODE
     32 //#define TIME_DECODE
     33 
     34 // this enables our rgb->yuv code, which is faster than libjpeg on ARM
     35 #define WE_CONVERT_TO_YUV
     36 
     37 // If ANDROID_RGB is defined by in the jpeg headers it indicates that jpeg offers
     38 // support for two additional formats (1) JCS_RGBA_8888 and (2) JCS_RGB_565.
     39 
     40 #if defined(SK_DEBUG)
     41 #define DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_WARNINGS false
     42 #define DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_ERRORS false
     43 #else  // !defined(SK_DEBUG)
     44 #define DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_WARNINGS true
     45 #define DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_ERRORS true
     46 #endif  // defined(SK_DEBUG)
     47 SK_CONF_DECLARE(bool, c_suppressJPEGImageDecoderWarnings,
     48                 "images.jpeg.suppressDecoderWarnings",
     49                 DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_WARNINGS,
     50                 "Suppress most JPG warnings when calling decode functions.");
     51 SK_CONF_DECLARE(bool, c_suppressJPEGImageDecoderErrors,
     52                 "images.jpeg.suppressDecoderErrors",
     53                 DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_ERRORS,
     54                 "Suppress most JPG error messages when decode "
     55                 "function fails.");
     56 
     57 //////////////////////////////////////////////////////////////////////////
     58 //////////////////////////////////////////////////////////////////////////
     59 
     60 static void overwrite_mem_buffer_size(jpeg_decompress_struct* cinfo) {
     61 #ifdef SK_BUILD_FOR_ANDROID
     62     /* Check if the device indicates that it has a large amount of system memory
     63      * if so, increase the memory allocation to 30MB instead of the default 5MB.
     64      */
     65 #ifdef ANDROID_LARGE_MEMORY_DEVICE
     66     cinfo->mem->max_memory_to_use = 30 * 1024 * 1024;
     67 #else
     68     cinfo->mem->max_memory_to_use = 5 * 1024 * 1024;
     69 #endif
     70 #endif // SK_BUILD_FOR_ANDROID
     71 }
     72 
     73 //////////////////////////////////////////////////////////////////////////
     74 //////////////////////////////////////////////////////////////////////////
     75 
     76 static void do_nothing_emit_message(jpeg_common_struct*, int) {
     77     /* do nothing */
     78 }
     79 static void do_nothing_output_message(j_common_ptr) {
     80     /* do nothing */
     81 }
     82 
     83 static void initialize_info(jpeg_decompress_struct* cinfo, skjpeg_source_mgr* src_mgr) {
     84     SkASSERT(cinfo != NULL);
     85     SkASSERT(src_mgr != NULL);
     86     jpeg_create_decompress(cinfo);
     87     overwrite_mem_buffer_size(cinfo);
     88     cinfo->src = src_mgr;
     89     /* To suppress warnings with a SK_DEBUG binary, set the
     90      * environment variable "skia_images_jpeg_suppressDecoderWarnings"
     91      * to "true".  Inside a program that links to skia:
     92      * SK_CONF_SET("images.jpeg.suppressDecoderWarnings", true); */
     93     if (c_suppressJPEGImageDecoderWarnings) {
     94         cinfo->err->emit_message = &do_nothing_emit_message;
     95     }
     96     /* To suppress error messages with a SK_DEBUG binary, set the
     97      * environment variable "skia_images_jpeg_suppressDecoderErrors"
     98      * to "true".  Inside a program that links to skia:
     99      * SK_CONF_SET("images.jpeg.suppressDecoderErrors", true); */
    100     if (c_suppressJPEGImageDecoderErrors) {
    101         cinfo->err->output_message = &do_nothing_output_message;
    102     }
    103 }
    104 
    105 #ifdef SK_BUILD_FOR_ANDROID
    106 class SkJPEGImageIndex {
    107 public:
    108     SkJPEGImageIndex(SkStreamRewindable* stream, SkImageDecoder* decoder)
    109         : fSrcMgr(stream, decoder)
    110         , fInfoInitialized(false)
    111         , fHuffmanCreated(false)
    112         , fDecompressStarted(false)
    113         {
    114             SkDEBUGCODE(fReadHeaderSucceeded = false;)
    115         }
    116 
    117     ~SkJPEGImageIndex() {
    118         if (fHuffmanCreated) {
    119             // Set to false before calling the libjpeg function, in case
    120             // the libjpeg function calls longjmp. Our setjmp handler may
    121             // attempt to delete this SkJPEGImageIndex, thus entering this
    122             // destructor again. Setting fHuffmanCreated to false first
    123             // prevents an infinite loop.
    124             fHuffmanCreated = false;
    125             jpeg_destroy_huffman_index(&fHuffmanIndex);
    126         }
    127         if (fDecompressStarted) {
    128             // Like fHuffmanCreated, set to false before calling libjpeg
    129             // function to prevent potential infinite loop.
    130             fDecompressStarted = false;
    131             jpeg_finish_decompress(&fCInfo);
    132         }
    133         if (fInfoInitialized) {
    134             this->destroyInfo();
    135         }
    136     }
    137 
    138     /**
    139      *  Destroy the cinfo struct.
    140      *  After this call, if a huffman index was already built, it
    141      *  can be used after calling initializeInfoAndReadHeader
    142      *  again. Must not be called after startTileDecompress except
    143      *  in the destructor.
    144      */
    145     void destroyInfo() {
    146         SkASSERT(fInfoInitialized);
    147         SkASSERT(!fDecompressStarted);
    148         // Like fHuffmanCreated, set to false before calling libjpeg
    149         // function to prevent potential infinite loop.
    150         fInfoInitialized = false;
    151         jpeg_destroy_decompress(&fCInfo);
    152         SkDEBUGCODE(fReadHeaderSucceeded = false;)
    153     }
    154 
    155     /**
    156      *  Initialize the cinfo struct.
    157      *  Calls jpeg_create_decompress, makes customizations, and
    158      *  finally calls jpeg_read_header. Returns true if jpeg_read_header
    159      *  returns JPEG_HEADER_OK.
    160      *  If cinfo was already initialized, destroyInfo must be called to
    161      *  destroy the old one. Must not be called after startTileDecompress.
    162      */
    163     bool initializeInfoAndReadHeader() {
    164         SkASSERT(!fInfoInitialized && !fDecompressStarted);
    165         initialize_info(&fCInfo, &fSrcMgr);
    166         fInfoInitialized = true;
    167         const bool success = (JPEG_HEADER_OK == jpeg_read_header(&fCInfo, true));
    168         SkDEBUGCODE(fReadHeaderSucceeded = success;)
    169         return success;
    170     }
    171 
    172     jpeg_decompress_struct* cinfo() { return &fCInfo; }
    173 
    174     huffman_index* huffmanIndex() { return &fHuffmanIndex; }
    175 
    176     /**
    177      *  Build the index to be used for tile based decoding.
    178      *  Must only be called after a successful call to
    179      *  initializeInfoAndReadHeader and must not be called more
    180      *  than once.
    181      */
    182     bool buildHuffmanIndex() {
    183         SkASSERT(fReadHeaderSucceeded);
    184         SkASSERT(!fHuffmanCreated);
    185         jpeg_create_huffman_index(&fCInfo, &fHuffmanIndex);
    186         SkASSERT(1 == fCInfo.scale_num && 1 == fCInfo.scale_denom);
    187         fHuffmanCreated = jpeg_build_huffman_index(&fCInfo, &fHuffmanIndex);
    188         return fHuffmanCreated;
    189     }
    190 
    191     /**
    192      *  Start tile based decoding. Must only be called after a
    193      *  successful call to buildHuffmanIndex, and must only be
    194      *  called once.
    195      */
    196     bool startTileDecompress() {
    197         SkASSERT(fHuffmanCreated);
    198         SkASSERT(fReadHeaderSucceeded);
    199         SkASSERT(!fDecompressStarted);
    200         if (jpeg_start_tile_decompress(&fCInfo)) {
    201             fDecompressStarted = true;
    202             return true;
    203         }
    204         return false;
    205     }
    206 
    207 private:
    208     skjpeg_source_mgr  fSrcMgr;
    209     jpeg_decompress_struct fCInfo;
    210     huffman_index fHuffmanIndex;
    211     bool fInfoInitialized;
    212     bool fHuffmanCreated;
    213     bool fDecompressStarted;
    214     SkDEBUGCODE(bool fReadHeaderSucceeded;)
    215 };
    216 #endif
    217 
    218 class SkJPEGImageDecoder : public SkImageDecoder {
    219 public:
    220 #ifdef SK_BUILD_FOR_ANDROID
    221     SkJPEGImageDecoder() {
    222         fImageIndex = NULL;
    223         fImageWidth = 0;
    224         fImageHeight = 0;
    225     }
    226 
    227     virtual ~SkJPEGImageDecoder() {
    228         SkDELETE(fImageIndex);
    229     }
    230 #endif
    231 
    232     virtual Format getFormat() const {
    233         return kJPEG_Format;
    234     }
    235 
    236 protected:
    237 #ifdef SK_BUILD_FOR_ANDROID
    238     virtual bool onBuildTileIndex(SkStreamRewindable *stream, int *width, int *height) SK_OVERRIDE;
    239     virtual bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& rect) SK_OVERRIDE;
    240 #endif
    241     virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE;
    242 
    243 private:
    244 #ifdef SK_BUILD_FOR_ANDROID
    245     SkJPEGImageIndex* fImageIndex;
    246     int fImageWidth;
    247     int fImageHeight;
    248 #endif
    249 
    250     /**
    251      *  Determine the appropriate bitmap colortype and out_color_space based on
    252      *  both the preference of the caller and the jpeg_color_space on the
    253      *  jpeg_decompress_struct passed in.
    254      *  Must be called after jpeg_read_header.
    255      */
    256     SkColorType getBitmapColorType(jpeg_decompress_struct*);
    257 
    258     typedef SkImageDecoder INHERITED;
    259 };
    260 
    261 //////////////////////////////////////////////////////////////////////////
    262 
    263 /* Automatically clean up after throwing an exception */
    264 class JPEGAutoClean {
    265 public:
    266     JPEGAutoClean(): cinfo_ptr(NULL) {}
    267     ~JPEGAutoClean() {
    268         if (cinfo_ptr) {
    269             jpeg_destroy_decompress(cinfo_ptr);
    270         }
    271     }
    272     void set(jpeg_decompress_struct* info) {
    273         cinfo_ptr = info;
    274     }
    275 private:
    276     jpeg_decompress_struct* cinfo_ptr;
    277 };
    278 
    279 ///////////////////////////////////////////////////////////////////////////////
    280 
    281 /*  If we need to better match the request, we might examine the image and
    282      output dimensions, and determine if the downsampling jpeg provided is
    283      not sufficient. If so, we can recompute a modified sampleSize value to
    284      make up the difference.
    285 
    286      To skip this additional scaling, just set sampleSize = 1; below.
    287  */
    288 static int recompute_sampleSize(int sampleSize,
    289                                 const jpeg_decompress_struct& cinfo) {
    290     return sampleSize * cinfo.output_width / cinfo.image_width;
    291 }
    292 
    293 static bool valid_output_dimensions(const jpeg_decompress_struct& cinfo) {
    294     /* These are initialized to 0, so if they have non-zero values, we assume
    295        they are "valid" (i.e. have been computed by libjpeg)
    296      */
    297     return 0 != cinfo.output_width && 0 != cinfo.output_height;
    298 }
    299 
    300 static bool skip_src_rows(jpeg_decompress_struct* cinfo, void* buffer, int count) {
    301     for (int i = 0; i < count; i++) {
    302         JSAMPLE* rowptr = (JSAMPLE*)buffer;
    303         int row_count = jpeg_read_scanlines(cinfo, &rowptr, 1);
    304         if (1 != row_count) {
    305             return false;
    306         }
    307     }
    308     return true;
    309 }
    310 
    311 #ifdef SK_BUILD_FOR_ANDROID
    312 static bool skip_src_rows_tile(jpeg_decompress_struct* cinfo,
    313                                huffman_index *index, void* buffer, int count) {
    314     for (int i = 0; i < count; i++) {
    315         JSAMPLE* rowptr = (JSAMPLE*)buffer;
    316         int row_count = jpeg_read_tile_scanline(cinfo, index, &rowptr);
    317         if (1 != row_count) {
    318             return false;
    319         }
    320     }
    321     return true;
    322 }
    323 #endif
    324 
    325 // This guy exists just to aid in debugging, as it allows debuggers to just
    326 // set a break-point in one place to see all error exists.
    327 static bool return_false(const jpeg_decompress_struct& cinfo,
    328                          const SkBitmap& bm, const char caller[]) {
    329     if (!(c_suppressJPEGImageDecoderErrors)) {
    330         char buffer[JMSG_LENGTH_MAX];
    331         cinfo.err->format_message((const j_common_ptr)&cinfo, buffer);
    332         SkDebugf("libjpeg error %d <%s> from %s [%d %d]\n",
    333                  cinfo.err->msg_code, buffer, caller, bm.width(), bm.height());
    334     }
    335     return false;   // must always return false
    336 }
    337 
    338 // Convert a scanline of CMYK samples to RGBX in place. Note that this
    339 // method moves the "scanline" pointer in its processing
    340 static void convert_CMYK_to_RGB(uint8_t* scanline, unsigned int width) {
    341     // At this point we've received CMYK pixels from libjpeg. We
    342     // perform a crude conversion to RGB (based on the formulae
    343     // from easyrgb.com):
    344     //  CMYK -> CMY
    345     //    C = ( C * (1 - K) + K )      // for each CMY component
    346     //  CMY -> RGB
    347     //    R = ( 1 - C ) * 255          // for each RGB component
    348     // Unfortunately we are seeing inverted CMYK so all the original terms
    349     // are 1-. This yields:
    350     //  CMYK -> CMY
    351     //    C = ( (1-C) * (1 - (1-K) + (1-K) ) -> C = 1 - C*K
    352     // The conversion from CMY->RGB remains the same
    353     for (unsigned int x = 0; x < width; ++x, scanline += 4) {
    354         scanline[0] = SkMulDiv255Round(scanline[0], scanline[3]);
    355         scanline[1] = SkMulDiv255Round(scanline[1], scanline[3]);
    356         scanline[2] = SkMulDiv255Round(scanline[2], scanline[3]);
    357         scanline[3] = 255;
    358     }
    359 }
    360 
    361 /**
    362  *  Common code for setting the error manager.
    363  */
    364 static void set_error_mgr(jpeg_decompress_struct* cinfo, skjpeg_error_mgr* errorManager) {
    365     SkASSERT(cinfo != NULL);
    366     SkASSERT(errorManager != NULL);
    367     cinfo->err = jpeg_std_error(errorManager);
    368     errorManager->error_exit = skjpeg_error_exit;
    369 }
    370 
    371 /**
    372  *  Common code for turning off upsampling and smoothing. Turning these
    373  *  off helps performance without showing noticable differences in the
    374  *  resulting bitmap.
    375  */
    376 static void turn_off_visual_optimizations(jpeg_decompress_struct* cinfo) {
    377     SkASSERT(cinfo != NULL);
    378     /* this gives about 30% performance improvement. In theory it may
    379        reduce the visual quality, in practice I'm not seeing a difference
    380      */
    381     cinfo->do_fancy_upsampling = 0;
    382 
    383     /* this gives another few percents */
    384     cinfo->do_block_smoothing = 0;
    385 }
    386 
    387 /**
    388  * Common code for setting the dct method.
    389  */
    390 static void set_dct_method(const SkImageDecoder& decoder, jpeg_decompress_struct* cinfo) {
    391     SkASSERT(cinfo != NULL);
    392 #ifdef DCT_IFAST_SUPPORTED
    393     if (decoder.getPreferQualityOverSpeed()) {
    394         cinfo->dct_method = JDCT_ISLOW;
    395     } else {
    396         cinfo->dct_method = JDCT_IFAST;
    397     }
    398 #else
    399     cinfo->dct_method = JDCT_ISLOW;
    400 #endif
    401 }
    402 
    403 SkColorType SkJPEGImageDecoder::getBitmapColorType(jpeg_decompress_struct* cinfo) {
    404     SkASSERT(cinfo != NULL);
    405 
    406     SrcDepth srcDepth = k32Bit_SrcDepth;
    407     if (JCS_GRAYSCALE == cinfo->jpeg_color_space) {
    408         srcDepth = k8BitGray_SrcDepth;
    409     }
    410 
    411     SkColorType colorType = this->getPrefColorType(srcDepth, /*hasAlpha*/ false);
    412     switch (colorType) {
    413         case kAlpha_8_SkColorType:
    414             // Only respect A8 colortype if the original is grayscale,
    415             // in which case we will treat the grayscale as alpha
    416             // values.
    417             if (cinfo->jpeg_color_space != JCS_GRAYSCALE) {
    418                 colorType = kN32_SkColorType;
    419             }
    420             break;
    421         case kN32_SkColorType:
    422             // Fall through.
    423         case kARGB_4444_SkColorType:
    424             // Fall through.
    425         case kRGB_565_SkColorType:
    426             // These are acceptable destination colortypes.
    427             break;
    428         default:
    429             // Force all other colortypes to 8888.
    430             colorType = kN32_SkColorType;
    431             break;
    432     }
    433 
    434     switch (cinfo->jpeg_color_space) {
    435         case JCS_CMYK:
    436             // Fall through.
    437         case JCS_YCCK:
    438             // libjpeg cannot convert from CMYK or YCCK to RGB - here we set up
    439             // so libjpeg will give us CMYK samples back and we will later
    440             // manually convert them to RGB
    441             cinfo->out_color_space = JCS_CMYK;
    442             break;
    443         case JCS_GRAYSCALE:
    444             if (kAlpha_8_SkColorType == colorType) {
    445                 cinfo->out_color_space = JCS_GRAYSCALE;
    446                 break;
    447             }
    448             // The data is JCS_GRAYSCALE, but the caller wants some sort of RGB
    449             // colortype. Fall through to set to the default.
    450         default:
    451             cinfo->out_color_space = JCS_RGB;
    452             break;
    453     }
    454     return colorType;
    455 }
    456 
    457 /**
    458  *  Based on the colortype and dither mode, adjust out_color_space and
    459  *  dither_mode of cinfo. Only does work in ANDROID_RGB
    460  */
    461 static void adjust_out_color_space_and_dither(jpeg_decompress_struct* cinfo,
    462                                               SkColorType colorType,
    463                                               const SkImageDecoder& decoder) {
    464     SkASSERT(cinfo != NULL);
    465 #ifdef ANDROID_RGB
    466     cinfo->dither_mode = JDITHER_NONE;
    467     if (JCS_CMYK == cinfo->out_color_space) {
    468         return;
    469     }
    470     switch (colorType) {
    471         case kN32_SkColorType:
    472             cinfo->out_color_space = JCS_RGBA_8888;
    473             break;
    474         case kRGB_565_SkColorType:
    475             cinfo->out_color_space = JCS_RGB_565;
    476             if (decoder.getDitherImage()) {
    477                 cinfo->dither_mode = JDITHER_ORDERED;
    478             }
    479             break;
    480         default:
    481             break;
    482     }
    483 #endif
    484 }
    485 
    486 
    487 /**
    488    Sets all pixels in given bitmap to SK_ColorWHITE for all rows >= y.
    489    Used when decoding fails partway through reading scanlines to fill
    490    remaining lines. */
    491 static void fill_below_level(int y, SkBitmap* bitmap) {
    492     SkIRect rect = SkIRect::MakeLTRB(0, y, bitmap->width(), bitmap->height());
    493     SkCanvas canvas(*bitmap);
    494     canvas.clipRect(SkRect::Make(rect));
    495     canvas.drawColor(SK_ColorWHITE);
    496 }
    497 
    498 /**
    499  *  Get the config and bytes per pixel of the source data. Return
    500  *  whether the data is supported.
    501  */
    502 static bool get_src_config(const jpeg_decompress_struct& cinfo,
    503                            SkScaledBitmapSampler::SrcConfig* sc,
    504                            int* srcBytesPerPixel) {
    505     SkASSERT(sc != NULL && srcBytesPerPixel != NULL);
    506     if (JCS_CMYK == cinfo.out_color_space) {
    507         // In this case we will manually convert the CMYK values to RGB
    508         *sc = SkScaledBitmapSampler::kRGBX;
    509         // The CMYK work-around relies on 4 components per pixel here
    510         *srcBytesPerPixel = 4;
    511     } else if (3 == cinfo.out_color_components && JCS_RGB == cinfo.out_color_space) {
    512         *sc = SkScaledBitmapSampler::kRGB;
    513         *srcBytesPerPixel = 3;
    514 #ifdef ANDROID_RGB
    515     } else if (JCS_RGBA_8888 == cinfo.out_color_space) {
    516         *sc = SkScaledBitmapSampler::kRGBX;
    517         *srcBytesPerPixel = 4;
    518     } else if (JCS_RGB_565 == cinfo.out_color_space) {
    519         *sc = SkScaledBitmapSampler::kRGB_565;
    520         *srcBytesPerPixel = 2;
    521 #endif
    522     } else if (1 == cinfo.out_color_components &&
    523                JCS_GRAYSCALE == cinfo.out_color_space) {
    524         *sc = SkScaledBitmapSampler::kGray;
    525         *srcBytesPerPixel = 1;
    526     } else {
    527         return false;
    528     }
    529     return true;
    530 }
    531 
    532 bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
    533 #ifdef TIME_DECODE
    534     SkAutoTime atm("JPEG Decode");
    535 #endif
    536 
    537     JPEGAutoClean autoClean;
    538 
    539     jpeg_decompress_struct  cinfo;
    540     skjpeg_source_mgr       srcManager(stream, this);
    541 
    542     skjpeg_error_mgr errorManager;
    543     set_error_mgr(&cinfo, &errorManager);
    544 
    545     // All objects need to be instantiated before this setjmp call so that
    546     // they will be cleaned up properly if an error occurs.
    547     if (setjmp(errorManager.fJmpBuf)) {
    548         return return_false(cinfo, *bm, "setjmp");
    549     }
    550 
    551     initialize_info(&cinfo, &srcManager);
    552     autoClean.set(&cinfo);
    553 
    554     int status = jpeg_read_header(&cinfo, true);
    555     if (status != JPEG_HEADER_OK) {
    556         return return_false(cinfo, *bm, "read_header");
    557     }
    558 
    559     /*  Try to fulfill the requested sampleSize. Since jpeg can do it (when it
    560         can) much faster that we, just use their num/denom api to approximate
    561         the size.
    562     */
    563     int sampleSize = this->getSampleSize();
    564 
    565     set_dct_method(*this, &cinfo);
    566 
    567     SkASSERT(1 == cinfo.scale_num);
    568     cinfo.scale_denom = sampleSize;
    569 
    570     turn_off_visual_optimizations(&cinfo);
    571 
    572     const SkColorType colorType = this->getBitmapColorType(&cinfo);
    573     const SkAlphaType alphaType = kAlpha_8_SkColorType == colorType ?
    574                                       kPremul_SkAlphaType : kOpaque_SkAlphaType;
    575 
    576     adjust_out_color_space_and_dither(&cinfo, colorType, *this);
    577 
    578     if (1 == sampleSize && SkImageDecoder::kDecodeBounds_Mode == mode) {
    579         // Assume an A8 bitmap is not opaque to avoid the check of each
    580         // individual pixel. It is very unlikely to be opaque, since
    581         // an opaque A8 bitmap would not be very interesting.
    582         // Otherwise, a jpeg image is opaque.
    583         return bm->setInfo(SkImageInfo::Make(cinfo.image_width, cinfo.image_height,
    584                                              colorType, alphaType));
    585     }
    586 
    587     /*  image_width and image_height are the original dimensions, available
    588         after jpeg_read_header(). To see the scaled dimensions, we have to call
    589         jpeg_start_decompress(), and then read output_width and output_height.
    590     */
    591     if (!jpeg_start_decompress(&cinfo)) {
    592         /*  If we failed here, we may still have enough information to return
    593             to the caller if they just wanted (subsampled bounds). If sampleSize
    594             was 1, then we would have already returned. Thus we just check if
    595             we're in kDecodeBounds_Mode, and that we have valid output sizes.
    596 
    597             One reason to fail here is that we have insufficient stream data
    598             to complete the setup. However, output dimensions seem to get
    599             computed very early, which is why this special check can pay off.
    600          */
    601         if (SkImageDecoder::kDecodeBounds_Mode == mode && valid_output_dimensions(cinfo)) {
    602             SkScaledBitmapSampler smpl(cinfo.output_width, cinfo.output_height,
    603                                        recompute_sampleSize(sampleSize, cinfo));
    604             // Assume an A8 bitmap is not opaque to avoid the check of each
    605             // individual pixel. It is very unlikely to be opaque, since
    606             // an opaque A8 bitmap would not be very interesting.
    607             // Otherwise, a jpeg image is opaque.
    608             return bm->setInfo(SkImageInfo::Make(smpl.scaledWidth(), smpl.scaledHeight(),
    609                                                  colorType, alphaType));
    610         } else {
    611             return return_false(cinfo, *bm, "start_decompress");
    612         }
    613     }
    614     sampleSize = recompute_sampleSize(sampleSize, cinfo);
    615 
    616 #ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER
    617     // should we allow the Chooser (if present) to pick a colortype for us???
    618     if (!this->chooseFromOneChoice(colorType, cinfo.output_width, cinfo.output_height)) {
    619         return return_false(cinfo, *bm, "chooseFromOneChoice");
    620     }
    621 #endif
    622 
    623     SkScaledBitmapSampler sampler(cinfo.output_width, cinfo.output_height, sampleSize);
    624     // Assume an A8 bitmap is not opaque to avoid the check of each
    625     // individual pixel. It is very unlikely to be opaque, since
    626     // an opaque A8 bitmap would not be very interesting.
    627     // Otherwise, a jpeg image is opaque.
    628     bm->setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(),
    629                                   colorType, alphaType));
    630     if (SkImageDecoder::kDecodeBounds_Mode == mode) {
    631         return true;
    632     }
    633     if (!this->allocPixelRef(bm, NULL)) {
    634         return return_false(cinfo, *bm, "allocPixelRef");
    635     }
    636 
    637     SkAutoLockPixels alp(*bm);
    638 
    639 #ifdef ANDROID_RGB
    640     /* short-circuit the SkScaledBitmapSampler when possible, as this gives
    641        a significant performance boost.
    642     */
    643     if (sampleSize == 1 &&
    644         ((kN32_SkColorType == colorType && cinfo.out_color_space == JCS_RGBA_8888) ||
    645          (kRGB_565_SkColorType == colorType && cinfo.out_color_space == JCS_RGB_565)))
    646     {
    647         JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels();
    648         INT32 const bpr =  bm->rowBytes();
    649 
    650         while (cinfo.output_scanline < cinfo.output_height) {
    651             int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1);
    652             if (0 == row_count) {
    653                 // if row_count == 0, then we didn't get a scanline,
    654                 // so return early.  We will return a partial image.
    655                 fill_below_level(cinfo.output_scanline, bm);
    656                 cinfo.output_scanline = cinfo.output_height;
    657                 break;  // Skip to jpeg_finish_decompress()
    658             }
    659             if (this->shouldCancelDecode()) {
    660                 return return_false(cinfo, *bm, "shouldCancelDecode");
    661             }
    662             rowptr += bpr;
    663         }
    664         jpeg_finish_decompress(&cinfo);
    665         return true;
    666     }
    667 #endif
    668 
    669     // check for supported formats
    670     SkScaledBitmapSampler::SrcConfig sc;
    671     int srcBytesPerPixel;
    672 
    673     if (!get_src_config(cinfo, &sc, &srcBytesPerPixel)) {
    674         return return_false(cinfo, *bm, "jpeg colorspace");
    675     }
    676 
    677     if (!sampler.begin(bm, sc, *this)) {
    678         return return_false(cinfo, *bm, "sampler.begin");
    679     }
    680 
    681     SkAutoMalloc srcStorage(cinfo.output_width * srcBytesPerPixel);
    682     uint8_t* srcRow = (uint8_t*)srcStorage.get();
    683 
    684     //  Possibly skip initial rows [sampler.srcY0]
    685     if (!skip_src_rows(&cinfo, srcRow, sampler.srcY0())) {
    686         return return_false(cinfo, *bm, "skip rows");
    687     }
    688 
    689     // now loop through scanlines until y == bm->height() - 1
    690     for (int y = 0;; y++) {
    691         JSAMPLE* rowptr = (JSAMPLE*)srcRow;
    692         int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1);
    693         if (0 == row_count) {
    694             // if row_count == 0, then we didn't get a scanline,
    695             // so return early.  We will return a partial image.
    696             fill_below_level(y, bm);
    697             cinfo.output_scanline = cinfo.output_height;
    698             break;  // Skip to jpeg_finish_decompress()
    699         }
    700         if (this->shouldCancelDecode()) {
    701             return return_false(cinfo, *bm, "shouldCancelDecode");
    702         }
    703 
    704         if (JCS_CMYK == cinfo.out_color_space) {
    705             convert_CMYK_to_RGB(srcRow, cinfo.output_width);
    706         }
    707 
    708         sampler.next(srcRow);
    709         if (bm->height() - 1 == y) {
    710             // we're done
    711             break;
    712         }
    713 
    714         if (!skip_src_rows(&cinfo, srcRow, sampler.srcDY() - 1)) {
    715             return return_false(cinfo, *bm, "skip rows");
    716         }
    717     }
    718 
    719     // we formally skip the rest, so we don't get a complaint from libjpeg
    720     if (!skip_src_rows(&cinfo, srcRow,
    721                        cinfo.output_height - cinfo.output_scanline)) {
    722         return return_false(cinfo, *bm, "skip rows");
    723     }
    724     jpeg_finish_decompress(&cinfo);
    725 
    726     return true;
    727 }
    728 
    729 #ifdef SK_BUILD_FOR_ANDROID
    730 bool SkJPEGImageDecoder::onBuildTileIndex(SkStreamRewindable* stream, int *width, int *height) {
    731 
    732     SkAutoTDelete<SkJPEGImageIndex> imageIndex(SkNEW_ARGS(SkJPEGImageIndex, (stream, this)));
    733     jpeg_decompress_struct* cinfo = imageIndex->cinfo();
    734 
    735     skjpeg_error_mgr sk_err;
    736     set_error_mgr(cinfo, &sk_err);
    737 
    738     // All objects need to be instantiated before this setjmp call so that
    739     // they will be cleaned up properly if an error occurs.
    740     if (setjmp(sk_err.fJmpBuf)) {
    741         return false;
    742     }
    743 
    744     // create the cinfo used to create/build the huffmanIndex
    745     if (!imageIndex->initializeInfoAndReadHeader()) {
    746         return false;
    747     }
    748 
    749     if (!imageIndex->buildHuffmanIndex()) {
    750         return false;
    751     }
    752 
    753     // destroy the cinfo used to create/build the huffman index
    754     imageIndex->destroyInfo();
    755 
    756     // Init decoder to image decode mode
    757     if (!imageIndex->initializeInfoAndReadHeader()) {
    758         return false;
    759     }
    760 
    761     // FIXME: This sets cinfo->out_color_space, which we may change later
    762     // based on the config in onDecodeSubset. This should be fine, since
    763     // jpeg_init_read_tile_scanline will check out_color_space again after
    764     // that change (when it calls jinit_color_deconverter).
    765     (void) this->getBitmapColorType(cinfo);
    766 
    767     turn_off_visual_optimizations(cinfo);
    768 
    769     // instead of jpeg_start_decompress() we start a tiled decompress
    770     if (!imageIndex->startTileDecompress()) {
    771         return false;
    772     }
    773 
    774     SkASSERT(1 == cinfo->scale_num);
    775     fImageWidth = cinfo->output_width;
    776     fImageHeight = cinfo->output_height;
    777 
    778     if (width) {
    779         *width = fImageWidth;
    780     }
    781     if (height) {
    782         *height = fImageHeight;
    783     }
    784 
    785     SkDELETE(fImageIndex);
    786     fImageIndex = imageIndex.detach();
    787 
    788     return true;
    789 }
    790 
    791 bool SkJPEGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) {
    792     if (NULL == fImageIndex) {
    793         return false;
    794     }
    795     jpeg_decompress_struct* cinfo = fImageIndex->cinfo();
    796 
    797     SkIRect rect = SkIRect::MakeWH(fImageWidth, fImageHeight);
    798     if (!rect.intersect(region)) {
    799         // If the requested region is entirely outside the image return false
    800         return false;
    801     }
    802 
    803 
    804     skjpeg_error_mgr errorManager;
    805     set_error_mgr(cinfo, &errorManager);
    806 
    807     if (setjmp(errorManager.fJmpBuf)) {
    808         return false;
    809     }
    810 
    811     int requestedSampleSize = this->getSampleSize();
    812     cinfo->scale_denom = requestedSampleSize;
    813 
    814     set_dct_method(*this, cinfo);
    815 
    816     const SkColorType colorType = this->getBitmapColorType(cinfo);
    817     adjust_out_color_space_and_dither(cinfo, colorType, *this);
    818 
    819     int startX = rect.fLeft;
    820     int startY = rect.fTop;
    821     int width = rect.width();
    822     int height = rect.height();
    823 
    824     jpeg_init_read_tile_scanline(cinfo, fImageIndex->huffmanIndex(),
    825                                  &startX, &startY, &width, &height);
    826     int skiaSampleSize = recompute_sampleSize(requestedSampleSize, *cinfo);
    827     int actualSampleSize = skiaSampleSize * (DCTSIZE / cinfo->min_DCT_scaled_size);
    828 
    829     SkScaledBitmapSampler sampler(width, height, skiaSampleSize);
    830 
    831     SkBitmap bitmap;
    832     // Assume an A8 bitmap is not opaque to avoid the check of each
    833     // individual pixel. It is very unlikely to be opaque, since
    834     // an opaque A8 bitmap would not be very interesting.
    835     // Otherwise, a jpeg image is opaque.
    836     bitmap.setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(), colorType,
    837                                      kAlpha_8_SkColorType == colorType ?
    838                                          kPremul_SkAlphaType : kOpaque_SkAlphaType));
    839 
    840     // Check ahead of time if the swap(dest, src) is possible or not.
    841     // If yes, then we will stick to AllocPixelRef since it's cheaper with the
    842     // swap happening. If no, then we will use alloc to allocate pixels to
    843     // prevent garbage collection.
    844     int w = rect.width() / actualSampleSize;
    845     int h = rect.height() / actualSampleSize;
    846     bool swapOnly = (rect == region) && bm->isNull() &&
    847                     (w == bitmap.width()) && (h == bitmap.height()) &&
    848                     ((startX - rect.x()) / actualSampleSize == 0) &&
    849                     ((startY - rect.y()) / actualSampleSize == 0);
    850     if (swapOnly) {
    851         if (!this->allocPixelRef(&bitmap, NULL)) {
    852             return return_false(*cinfo, bitmap, "allocPixelRef");
    853         }
    854     } else {
    855         if (!bitmap.tryAllocPixels()) {
    856             return return_false(*cinfo, bitmap, "allocPixels");
    857         }
    858     }
    859 
    860     SkAutoLockPixels alp(bitmap);
    861 
    862 #ifdef ANDROID_RGB
    863     /* short-circuit the SkScaledBitmapSampler when possible, as this gives
    864        a significant performance boost.
    865     */
    866     if (skiaSampleSize == 1 &&
    867         ((kN32_SkColorType == colorType && cinfo->out_color_space == JCS_RGBA_8888) ||
    868          (kRGB_565_SkColorType == colorType && cinfo->out_color_space == JCS_RGB_565)))
    869     {
    870         JSAMPLE* rowptr = (JSAMPLE*)bitmap.getPixels();
    871         INT32 const bpr = bitmap.rowBytes();
    872         int rowTotalCount = 0;
    873 
    874         while (rowTotalCount < height) {
    875             int rowCount = jpeg_read_tile_scanline(cinfo,
    876                                                    fImageIndex->huffmanIndex(),
    877                                                    &rowptr);
    878             // if rowCount == 0, then we didn't get a scanline, so abort.
    879             // onDecodeSubset() relies on onBuildTileIndex(), which
    880             // needs a complete image to succeed.
    881             if (0 == rowCount) {
    882                 return return_false(*cinfo, bitmap, "read_scanlines");
    883             }
    884             if (this->shouldCancelDecode()) {
    885                 return return_false(*cinfo, bitmap, "shouldCancelDecode");
    886             }
    887             rowTotalCount += rowCount;
    888             rowptr += bpr;
    889         }
    890 
    891         if (swapOnly) {
    892             bm->swap(bitmap);
    893         } else {
    894             cropBitmap(bm, &bitmap, actualSampleSize, region.x(), region.y(),
    895                        region.width(), region.height(), startX, startY);
    896         }
    897         return true;
    898     }
    899 #endif
    900 
    901     // check for supported formats
    902     SkScaledBitmapSampler::SrcConfig sc;
    903     int srcBytesPerPixel;
    904 
    905     if (!get_src_config(*cinfo, &sc, &srcBytesPerPixel)) {
    906         return return_false(*cinfo, *bm, "jpeg colorspace");
    907     }
    908 
    909     if (!sampler.begin(&bitmap, sc, *this)) {
    910         return return_false(*cinfo, bitmap, "sampler.begin");
    911     }
    912 
    913     SkAutoMalloc  srcStorage(width * srcBytesPerPixel);
    914     uint8_t* srcRow = (uint8_t*)srcStorage.get();
    915 
    916     //  Possibly skip initial rows [sampler.srcY0]
    917     if (!skip_src_rows_tile(cinfo, fImageIndex->huffmanIndex(), srcRow, sampler.srcY0())) {
    918         return return_false(*cinfo, bitmap, "skip rows");
    919     }
    920 
    921     // now loop through scanlines until y == bitmap->height() - 1
    922     for (int y = 0;; y++) {
    923         JSAMPLE* rowptr = (JSAMPLE*)srcRow;
    924         int row_count = jpeg_read_tile_scanline(cinfo, fImageIndex->huffmanIndex(), &rowptr);
    925         // if row_count == 0, then we didn't get a scanline, so abort.
    926         // onDecodeSubset() relies on onBuildTileIndex(), which
    927         // needs a complete image to succeed.
    928         if (0 == row_count) {
    929             return return_false(*cinfo, bitmap, "read_scanlines");
    930         }
    931         if (this->shouldCancelDecode()) {
    932             return return_false(*cinfo, bitmap, "shouldCancelDecode");
    933         }
    934 
    935         if (JCS_CMYK == cinfo->out_color_space) {
    936             convert_CMYK_to_RGB(srcRow, width);
    937         }
    938 
    939         sampler.next(srcRow);
    940         if (bitmap.height() - 1 == y) {
    941             // we're done
    942             break;
    943         }
    944 
    945         if (!skip_src_rows_tile(cinfo, fImageIndex->huffmanIndex(), srcRow,
    946                                 sampler.srcDY() - 1)) {
    947             return return_false(*cinfo, bitmap, "skip rows");
    948         }
    949     }
    950     if (swapOnly) {
    951         bm->swap(bitmap);
    952     } else {
    953         cropBitmap(bm, &bitmap, actualSampleSize, region.x(), region.y(),
    954                    region.width(), region.height(), startX, startY);
    955     }
    956     return true;
    957 }
    958 #endif
    959 
    960 ///////////////////////////////////////////////////////////////////////////////
    961 
    962 #include "SkColorPriv.h"
    963 
    964 // taken from jcolor.c in libjpeg
    965 #if 0   // 16bit - precise but slow
    966     #define CYR     19595   // 0.299
    967     #define CYG     38470   // 0.587
    968     #define CYB      7471   // 0.114
    969 
    970     #define CUR    -11059   // -0.16874
    971     #define CUG    -21709   // -0.33126
    972     #define CUB     32768   // 0.5
    973 
    974     #define CVR     32768   // 0.5
    975     #define CVG    -27439   // -0.41869
    976     #define CVB     -5329   // -0.08131
    977 
    978     #define CSHIFT  16
    979 #else      // 8bit - fast, slightly less precise
    980     #define CYR     77    // 0.299
    981     #define CYG     150    // 0.587
    982     #define CYB      29    // 0.114
    983 
    984     #define CUR     -43    // -0.16874
    985     #define CUG    -85    // -0.33126
    986     #define CUB     128    // 0.5
    987 
    988     #define CVR      128   // 0.5
    989     #define CVG     -107   // -0.41869
    990     #define CVB      -21   // -0.08131
    991 
    992     #define CSHIFT  8
    993 #endif
    994 
    995 static void rgb2yuv_32(uint8_t dst[], SkPMColor c) {
    996     int r = SkGetPackedR32(c);
    997     int g = SkGetPackedG32(c);
    998     int b = SkGetPackedB32(c);
    999 
   1000     int  y = ( CYR*r + CYG*g + CYB*b ) >> CSHIFT;
   1001     int  u = ( CUR*r + CUG*g + CUB*b ) >> CSHIFT;
   1002     int  v = ( CVR*r + CVG*g + CVB*b ) >> CSHIFT;
   1003 
   1004     dst[0] = SkToU8(y);
   1005     dst[1] = SkToU8(u + 128);
   1006     dst[2] = SkToU8(v + 128);
   1007 }
   1008 
   1009 static void rgb2yuv_4444(uint8_t dst[], U16CPU c) {
   1010     int r = SkGetPackedR4444(c);
   1011     int g = SkGetPackedG4444(c);
   1012     int b = SkGetPackedB4444(c);
   1013 
   1014     int  y = ( CYR*r + CYG*g + CYB*b ) >> (CSHIFT - 4);
   1015     int  u = ( CUR*r + CUG*g + CUB*b ) >> (CSHIFT - 4);
   1016     int  v = ( CVR*r + CVG*g + CVB*b ) >> (CSHIFT - 4);
   1017 
   1018     dst[0] = SkToU8(y);
   1019     dst[1] = SkToU8(u + 128);
   1020     dst[2] = SkToU8(v + 128);
   1021 }
   1022 
   1023 static void rgb2yuv_16(uint8_t dst[], U16CPU c) {
   1024     int r = SkGetPackedR16(c);
   1025     int g = SkGetPackedG16(c);
   1026     int b = SkGetPackedB16(c);
   1027 
   1028     int  y = ( 2*CYR*r + CYG*g + 2*CYB*b ) >> (CSHIFT - 2);
   1029     int  u = ( 2*CUR*r + CUG*g + 2*CUB*b ) >> (CSHIFT - 2);
   1030     int  v = ( 2*CVR*r + CVG*g + 2*CVB*b ) >> (CSHIFT - 2);
   1031 
   1032     dst[0] = SkToU8(y);
   1033     dst[1] = SkToU8(u + 128);
   1034     dst[2] = SkToU8(v + 128);
   1035 }
   1036 
   1037 ///////////////////////////////////////////////////////////////////////////////
   1038 
   1039 typedef void (*WriteScanline)(uint8_t* SK_RESTRICT dst,
   1040                               const void* SK_RESTRICT src, int width,
   1041                               const SkPMColor* SK_RESTRICT ctable);
   1042 
   1043 static void Write_32_YUV(uint8_t* SK_RESTRICT dst,
   1044                          const void* SK_RESTRICT srcRow, int width,
   1045                          const SkPMColor*) {
   1046     const uint32_t* SK_RESTRICT src = (const uint32_t*)srcRow;
   1047     while (--width >= 0) {
   1048 #ifdef WE_CONVERT_TO_YUV
   1049         rgb2yuv_32(dst, *src++);
   1050 #else
   1051         uint32_t c = *src++;
   1052         dst[0] = SkGetPackedR32(c);
   1053         dst[1] = SkGetPackedG32(c);
   1054         dst[2] = SkGetPackedB32(c);
   1055 #endif
   1056         dst += 3;
   1057     }
   1058 }
   1059 
   1060 static void Write_4444_YUV(uint8_t* SK_RESTRICT dst,
   1061                            const void* SK_RESTRICT srcRow, int width,
   1062                            const SkPMColor*) {
   1063     const SkPMColor16* SK_RESTRICT src = (const SkPMColor16*)srcRow;
   1064     while (--width >= 0) {
   1065 #ifdef WE_CONVERT_TO_YUV
   1066         rgb2yuv_4444(dst, *src++);
   1067 #else
   1068         SkPMColor16 c = *src++;
   1069         dst[0] = SkPacked4444ToR32(c);
   1070         dst[1] = SkPacked4444ToG32(c);
   1071         dst[2] = SkPacked4444ToB32(c);
   1072 #endif
   1073         dst += 3;
   1074     }
   1075 }
   1076 
   1077 static void Write_16_YUV(uint8_t* SK_RESTRICT dst,
   1078                          const void* SK_RESTRICT srcRow, int width,
   1079                          const SkPMColor*) {
   1080     const uint16_t* SK_RESTRICT src = (const uint16_t*)srcRow;
   1081     while (--width >= 0) {
   1082 #ifdef WE_CONVERT_TO_YUV
   1083         rgb2yuv_16(dst, *src++);
   1084 #else
   1085         uint16_t c = *src++;
   1086         dst[0] = SkPacked16ToR32(c);
   1087         dst[1] = SkPacked16ToG32(c);
   1088         dst[2] = SkPacked16ToB32(c);
   1089 #endif
   1090         dst += 3;
   1091     }
   1092 }
   1093 
   1094 static void Write_Index_YUV(uint8_t* SK_RESTRICT dst,
   1095                             const void* SK_RESTRICT srcRow, int width,
   1096                             const SkPMColor* SK_RESTRICT ctable) {
   1097     const uint8_t* SK_RESTRICT src = (const uint8_t*)srcRow;
   1098     while (--width >= 0) {
   1099 #ifdef WE_CONVERT_TO_YUV
   1100         rgb2yuv_32(dst, ctable[*src++]);
   1101 #else
   1102         uint32_t c = ctable[*src++];
   1103         dst[0] = SkGetPackedR32(c);
   1104         dst[1] = SkGetPackedG32(c);
   1105         dst[2] = SkGetPackedB32(c);
   1106 #endif
   1107         dst += 3;
   1108     }
   1109 }
   1110 
   1111 static WriteScanline ChooseWriter(const SkBitmap& bm) {
   1112     switch (bm.colorType()) {
   1113         case kN32_SkColorType:
   1114             return Write_32_YUV;
   1115         case kRGB_565_SkColorType:
   1116             return Write_16_YUV;
   1117         case kARGB_4444_SkColorType:
   1118             return Write_4444_YUV;
   1119         case kIndex_8_SkColorType:
   1120             return Write_Index_YUV;
   1121         default:
   1122             return NULL;
   1123     }
   1124 }
   1125 
   1126 class SkJPEGImageEncoder : public SkImageEncoder {
   1127 protected:
   1128     virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) {
   1129 #ifdef TIME_ENCODE
   1130         SkAutoTime atm("JPEG Encode");
   1131 #endif
   1132 
   1133         SkAutoLockPixels alp(bm);
   1134         if (NULL == bm.getPixels()) {
   1135             return false;
   1136         }
   1137 
   1138         jpeg_compress_struct    cinfo;
   1139         skjpeg_error_mgr        sk_err;
   1140         skjpeg_destination_mgr  sk_wstream(stream);
   1141 
   1142         // allocate these before set call setjmp
   1143         SkAutoMalloc    oneRow;
   1144         SkAutoLockColors ctLocker;
   1145 
   1146         cinfo.err = jpeg_std_error(&sk_err);
   1147         sk_err.error_exit = skjpeg_error_exit;
   1148         if (setjmp(sk_err.fJmpBuf)) {
   1149             return false;
   1150         }
   1151 
   1152         // Keep after setjmp or mark volatile.
   1153         const WriteScanline writer = ChooseWriter(bm);
   1154         if (NULL == writer) {
   1155             return false;
   1156         }
   1157 
   1158         jpeg_create_compress(&cinfo);
   1159         cinfo.dest = &sk_wstream;
   1160         cinfo.image_width = bm.width();
   1161         cinfo.image_height = bm.height();
   1162         cinfo.input_components = 3;
   1163 #ifdef WE_CONVERT_TO_YUV
   1164         cinfo.in_color_space = JCS_YCbCr;
   1165 #else
   1166         cinfo.in_color_space = JCS_RGB;
   1167 #endif
   1168         cinfo.input_gamma = 1;
   1169 
   1170         jpeg_set_defaults(&cinfo);
   1171         jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
   1172 #ifdef DCT_IFAST_SUPPORTED
   1173         cinfo.dct_method = JDCT_IFAST;
   1174 #endif
   1175 
   1176         jpeg_start_compress(&cinfo, TRUE);
   1177 
   1178         const int       width = bm.width();
   1179         uint8_t*        oneRowP = (uint8_t*)oneRow.reset(width * 3);
   1180 
   1181         const SkPMColor* colors = ctLocker.lockColors(bm);
   1182         const void*      srcRow = bm.getPixels();
   1183 
   1184         while (cinfo.next_scanline < cinfo.image_height) {
   1185             JSAMPROW row_pointer[1];    /* pointer to JSAMPLE row[s] */
   1186 
   1187             writer(oneRowP, srcRow, width, colors);
   1188             row_pointer[0] = oneRowP;
   1189             (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
   1190             srcRow = (const void*)((const char*)srcRow + bm.rowBytes());
   1191         }
   1192 
   1193         jpeg_finish_compress(&cinfo);
   1194         jpeg_destroy_compress(&cinfo);
   1195 
   1196         return true;
   1197     }
   1198 };
   1199 
   1200 ///////////////////////////////////////////////////////////////////////////////
   1201 DEFINE_DECODER_CREATOR(JPEGImageDecoder);
   1202 DEFINE_ENCODER_CREATOR(JPEGImageEncoder);
   1203 ///////////////////////////////////////////////////////////////////////////////
   1204 
   1205 static bool is_jpeg(SkStreamRewindable* stream) {
   1206     static const unsigned char gHeader[] = { 0xFF, 0xD8, 0xFF };
   1207     static const size_t HEADER_SIZE = sizeof(gHeader);
   1208 
   1209     char buffer[HEADER_SIZE];
   1210     size_t len = stream->read(buffer, HEADER_SIZE);
   1211 
   1212     if (len != HEADER_SIZE) {
   1213         return false;   // can't read enough
   1214     }
   1215     if (memcmp(buffer, gHeader, HEADER_SIZE)) {
   1216         return false;
   1217     }
   1218     return true;
   1219 }
   1220 
   1221 
   1222 static SkImageDecoder* sk_libjpeg_dfactory(SkStreamRewindable* stream) {
   1223     if (is_jpeg(stream)) {
   1224         return SkNEW(SkJPEGImageDecoder);
   1225     }
   1226     return NULL;
   1227 }
   1228 
   1229 static SkImageDecoder::Format get_format_jpeg(SkStreamRewindable* stream) {
   1230     if (is_jpeg(stream)) {
   1231         return SkImageDecoder::kJPEG_Format;
   1232     }
   1233     return SkImageDecoder::kUnknown_Format;
   1234 }
   1235 
   1236 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) {
   1237     return (SkImageEncoder::kJPEG_Type == t) ? SkNEW(SkJPEGImageEncoder) : NULL;
   1238 }
   1239 
   1240 static SkImageDecoder_DecodeReg gDReg(sk_libjpeg_dfactory);
   1241 static SkImageDecoder_FormatReg gFormatReg(get_format_jpeg);
   1242 static SkImageEncoder_EncodeReg gEReg(sk_libjpeg_efactory);
   1243