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 config 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     SkBitmap::Config getBitmapConfig(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 SkBitmap::Config SkJPEGImageDecoder::getBitmapConfig(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     SkBitmap::Config config = this->getPrefConfig(srcDepth, /*hasAlpha*/ false);
    412     switch (config) {
    413         case SkBitmap::kA8_Config:
    414             // Only respect A8 config 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                 config = SkBitmap::kARGB_8888_Config;
    419             }
    420             break;
    421         case SkBitmap::kARGB_8888_Config:
    422             // Fall through.
    423         case SkBitmap::kARGB_4444_Config:
    424             // Fall through.
    425         case SkBitmap::kRGB_565_Config:
    426             // These are acceptable destination configs.
    427             break;
    428         default:
    429             // Force all other configs to 8888.
    430             config = SkBitmap::kARGB_8888_Config;
    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 (SkBitmap::kA8_Config == config) {
    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             // config. Fall through to set to the default.
    450         default:
    451             cinfo->out_color_space = JCS_RGB;
    452             break;
    453     }
    454     return config;
    455 }
    456 
    457 #ifdef ANDROID_RGB
    458 /**
    459  *  Based on the config and dither mode, adjust out_color_space and
    460  *  dither_mode of cinfo.
    461  */
    462 static void adjust_out_color_space_and_dither(jpeg_decompress_struct* cinfo,
    463                                               SkBitmap::Config config,
    464                                               const SkImageDecoder& decoder) {
    465     SkASSERT(cinfo != NULL);
    466     cinfo->dither_mode = JDITHER_NONE;
    467     if (JCS_CMYK == cinfo->out_color_space) {
    468         return;
    469     }
    470     switch(config) {
    471         case SkBitmap::kARGB_8888_Config:
    472             cinfo->out_color_space = JCS_RGBA_8888;
    473             break;
    474         case SkBitmap::kRGB_565_Config:
    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 }
    484 #endif
    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 SkBitmap::Config config = this->getBitmapConfig(&cinfo);
    573 
    574 #ifdef ANDROID_RGB
    575     adjust_out_color_space_and_dither(&cinfo, config, *this);
    576 #endif
    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->setConfig(config, cinfo.image_width, cinfo.image_height, 0,
    584                              SkBitmap::kA8_Config == config ?
    585                                 kPremul_SkAlphaType : kOpaque_SkAlphaType);
    586     }
    587 
    588     /*  image_width and image_height are the original dimensions, available
    589         after jpeg_read_header(). To see the scaled dimensions, we have to call
    590         jpeg_start_decompress(), and then read output_width and output_height.
    591     */
    592     if (!jpeg_start_decompress(&cinfo)) {
    593         /*  If we failed here, we may still have enough information to return
    594             to the caller if they just wanted (subsampled bounds). If sampleSize
    595             was 1, then we would have already returned. Thus we just check if
    596             we're in kDecodeBounds_Mode, and that we have valid output sizes.
    597 
    598             One reason to fail here is that we have insufficient stream data
    599             to complete the setup. However, output dimensions seem to get
    600             computed very early, which is why this special check can pay off.
    601          */
    602         if (SkImageDecoder::kDecodeBounds_Mode == mode && valid_output_dimensions(cinfo)) {
    603             SkScaledBitmapSampler smpl(cinfo.output_width, cinfo.output_height,
    604                                        recompute_sampleSize(sampleSize, cinfo));
    605             // Assume an A8 bitmap is not opaque to avoid the check of each
    606             // individual pixel. It is very unlikely to be opaque, since
    607             // an opaque A8 bitmap would not be very interesting.
    608             // Otherwise, a jpeg image is opaque.
    609             return bm->setConfig(config, smpl.scaledWidth(), smpl.scaledHeight(),
    610                                  0, SkBitmap::kA8_Config == config ?
    611                                     kPremul_SkAlphaType : kOpaque_SkAlphaType);
    612         } else {
    613             return return_false(cinfo, *bm, "start_decompress");
    614         }
    615     }
    616     sampleSize = recompute_sampleSize(sampleSize, cinfo);
    617 
    618     // should we allow the Chooser (if present) to pick a config for us???
    619     if (!this->chooseFromOneChoice(config, cinfo.output_width, cinfo.output_height)) {
    620         return return_false(cinfo, *bm, "chooseFromOneChoice");
    621     }
    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->setConfig(config, sampler.scaledWidth(), sampler.scaledHeight(), 0,
    629                   SkBitmap::kA8_Config != config ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
    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         ((config == SkBitmap::kARGB_8888_Config &&
    645                 cinfo.out_color_space == JCS_RGBA_8888) ||
    646         (config == SkBitmap::kRGB_565_Config &&
    647                 cinfo.out_color_space == JCS_RGB_565)))
    648     {
    649         JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels();
    650         INT32 const bpr =  bm->rowBytes();
    651 
    652         while (cinfo.output_scanline < cinfo.output_height) {
    653             int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1);
    654             if (0 == row_count) {
    655                 // if row_count == 0, then we didn't get a scanline,
    656                 // so return early.  We will return a partial image.
    657                 fill_below_level(cinfo.output_scanline, bm);
    658                 cinfo.output_scanline = cinfo.output_height;
    659                 break;  // Skip to jpeg_finish_decompress()
    660             }
    661             if (this->shouldCancelDecode()) {
    662                 return return_false(cinfo, *bm, "shouldCancelDecode");
    663             }
    664             rowptr += bpr;
    665         }
    666         jpeg_finish_decompress(&cinfo);
    667         return true;
    668     }
    669 #endif
    670 
    671     // check for supported formats
    672     SkScaledBitmapSampler::SrcConfig sc;
    673     int srcBytesPerPixel;
    674 
    675     if (!get_src_config(cinfo, &sc, &srcBytesPerPixel)) {
    676         return return_false(cinfo, *bm, "jpeg colorspace");
    677     }
    678 
    679     if (!sampler.begin(bm, sc, *this)) {
    680         return return_false(cinfo, *bm, "sampler.begin");
    681     }
    682 
    683     SkAutoMalloc srcStorage(cinfo.output_width * srcBytesPerPixel);
    684     uint8_t* srcRow = (uint8_t*)srcStorage.get();
    685 
    686     //  Possibly skip initial rows [sampler.srcY0]
    687     if (!skip_src_rows(&cinfo, srcRow, sampler.srcY0())) {
    688         return return_false(cinfo, *bm, "skip rows");
    689     }
    690 
    691     // now loop through scanlines until y == bm->height() - 1
    692     for (int y = 0;; y++) {
    693         JSAMPLE* rowptr = (JSAMPLE*)srcRow;
    694         int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1);
    695         if (0 == row_count) {
    696             // if row_count == 0, then we didn't get a scanline,
    697             // so return early.  We will return a partial image.
    698             fill_below_level(y, bm);
    699             cinfo.output_scanline = cinfo.output_height;
    700             break;  // Skip to jpeg_finish_decompress()
    701         }
    702         if (this->shouldCancelDecode()) {
    703             return return_false(cinfo, *bm, "shouldCancelDecode");
    704         }
    705 
    706         if (JCS_CMYK == cinfo.out_color_space) {
    707             convert_CMYK_to_RGB(srcRow, cinfo.output_width);
    708         }
    709 
    710         sampler.next(srcRow);
    711         if (bm->height() - 1 == y) {
    712             // we're done
    713             break;
    714         }
    715 
    716         if (!skip_src_rows(&cinfo, srcRow, sampler.srcDY() - 1)) {
    717             return return_false(cinfo, *bm, "skip rows");
    718         }
    719     }
    720 
    721     // we formally skip the rest, so we don't get a complaint from libjpeg
    722     if (!skip_src_rows(&cinfo, srcRow,
    723                        cinfo.output_height - cinfo.output_scanline)) {
    724         return return_false(cinfo, *bm, "skip rows");
    725     }
    726     jpeg_finish_decompress(&cinfo);
    727 
    728     return true;
    729 }
    730 
    731 #ifdef SK_BUILD_FOR_ANDROID
    732 bool SkJPEGImageDecoder::onBuildTileIndex(SkStreamRewindable* stream, int *width, int *height) {
    733 
    734     SkAutoTDelete<SkJPEGImageIndex> imageIndex(SkNEW_ARGS(SkJPEGImageIndex, (stream, this)));
    735     jpeg_decompress_struct* cinfo = imageIndex->cinfo();
    736 
    737     skjpeg_error_mgr sk_err;
    738     set_error_mgr(cinfo, &sk_err);
    739 
    740     // All objects need to be instantiated before this setjmp call so that
    741     // they will be cleaned up properly if an error occurs.
    742     if (setjmp(sk_err.fJmpBuf)) {
    743         return false;
    744     }
    745 
    746     // create the cinfo used to create/build the huffmanIndex
    747     if (!imageIndex->initializeInfoAndReadHeader()) {
    748         return false;
    749     }
    750 
    751     if (!imageIndex->buildHuffmanIndex()) {
    752         return false;
    753     }
    754 
    755     // destroy the cinfo used to create/build the huffman index
    756     imageIndex->destroyInfo();
    757 
    758     // Init decoder to image decode mode
    759     if (!imageIndex->initializeInfoAndReadHeader()) {
    760         return false;
    761     }
    762 
    763     // FIXME: This sets cinfo->out_color_space, which we may change later
    764     // based on the config in onDecodeSubset. This should be fine, since
    765     // jpeg_init_read_tile_scanline will check out_color_space again after
    766     // that change (when it calls jinit_color_deconverter).
    767     (void) this->getBitmapConfig(cinfo);
    768 
    769     turn_off_visual_optimizations(cinfo);
    770 
    771     // instead of jpeg_start_decompress() we start a tiled decompress
    772     if (!imageIndex->startTileDecompress()) {
    773         return false;
    774     }
    775 
    776     SkASSERT(1 == cinfo->scale_num);
    777     fImageWidth = cinfo->output_width;
    778     fImageHeight = cinfo->output_height;
    779 
    780     if (width) {
    781         *width = fImageWidth;
    782     }
    783     if (height) {
    784         *height = fImageHeight;
    785     }
    786 
    787     SkDELETE(fImageIndex);
    788     fImageIndex = imageIndex.detach();
    789 
    790     return true;
    791 }
    792 
    793 bool SkJPEGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) {
    794     if (NULL == fImageIndex) {
    795         return false;
    796     }
    797     jpeg_decompress_struct* cinfo = fImageIndex->cinfo();
    798 
    799     SkIRect rect = SkIRect::MakeWH(fImageWidth, fImageHeight);
    800     if (!rect.intersect(region)) {
    801         // If the requested region is entirely outside the image return false
    802         return false;
    803     }
    804 
    805 
    806     skjpeg_error_mgr errorManager;
    807     set_error_mgr(cinfo, &errorManager);
    808 
    809     if (setjmp(errorManager.fJmpBuf)) {
    810         return false;
    811     }
    812 
    813     int requestedSampleSize = this->getSampleSize();
    814     cinfo->scale_denom = requestedSampleSize;
    815 
    816     set_dct_method(*this, cinfo);
    817 
    818     const SkBitmap::Config config = this->getBitmapConfig(cinfo);
    819 #ifdef ANDROID_RGB
    820     adjust_out_color_space_and_dither(cinfo, config, *this);
    821 #endif
    822 
    823     int startX = rect.fLeft;
    824     int startY = rect.fTop;
    825     int width = rect.width();
    826     int height = rect.height();
    827 
    828     jpeg_init_read_tile_scanline(cinfo, fImageIndex->huffmanIndex(),
    829                                  &startX, &startY, &width, &height);
    830     int skiaSampleSize = recompute_sampleSize(requestedSampleSize, *cinfo);
    831     int actualSampleSize = skiaSampleSize * (DCTSIZE / cinfo->min_DCT_scaled_size);
    832 
    833     SkScaledBitmapSampler sampler(width, height, skiaSampleSize);
    834 
    835     SkBitmap bitmap;
    836     bitmap.setConfig(config, sampler.scaledWidth(), sampler.scaledHeight());
    837     // Assume an A8 bitmap is not opaque to avoid the check of each
    838     // individual pixel. It is very unlikely to be opaque, since
    839     // an opaque A8 bitmap would not be very interesting.
    840     // Otherwise, a jpeg image is opaque.
    841     bitmap.setConfig(config, sampler.scaledWidth(), sampler.scaledHeight(), 0,
    842                      config == SkBitmap::kA8_Config ? kPremul_SkAlphaType :
    843                      kOpaque_SkAlphaType);
    844 
    845     // Check ahead of time if the swap(dest, src) is possible or not.
    846     // If yes, then we will stick to AllocPixelRef since it's cheaper with the
    847     // swap happening. If no, then we will use alloc to allocate pixels to
    848     // prevent garbage collection.
    849     int w = rect.width() / actualSampleSize;
    850     int h = rect.height() / actualSampleSize;
    851     bool swapOnly = (rect == region) && bm->isNull() &&
    852                     (w == bitmap.width()) && (h == bitmap.height()) &&
    853                     ((startX - rect.x()) / actualSampleSize == 0) &&
    854                     ((startY - rect.y()) / actualSampleSize == 0);
    855     if (swapOnly) {
    856         if (!this->allocPixelRef(&bitmap, NULL)) {
    857             return return_false(*cinfo, bitmap, "allocPixelRef");
    858         }
    859     } else {
    860         if (!bitmap.allocPixels()) {
    861             return return_false(*cinfo, bitmap, "allocPixels");
    862         }
    863     }
    864 
    865     SkAutoLockPixels alp(bitmap);
    866 
    867 #ifdef ANDROID_RGB
    868     /* short-circuit the SkScaledBitmapSampler when possible, as this gives
    869        a significant performance boost.
    870     */
    871     if (skiaSampleSize == 1 &&
    872         ((config == SkBitmap::kARGB_8888_Config &&
    873                 cinfo->out_color_space == JCS_RGBA_8888) ||
    874         (config == SkBitmap::kRGB_565_Config &&
    875                 cinfo->out_color_space == JCS_RGB_565)))
    876     {
    877         JSAMPLE* rowptr = (JSAMPLE*)bitmap.getPixels();
    878         INT32 const bpr = bitmap.rowBytes();
    879         int rowTotalCount = 0;
    880 
    881         while (rowTotalCount < height) {
    882             int rowCount = jpeg_read_tile_scanline(cinfo,
    883                                                    fImageIndex->huffmanIndex(),
    884                                                    &rowptr);
    885             // if rowCount == 0, then we didn't get a scanline, so abort.
    886             // onDecodeSubset() relies on onBuildTileIndex(), which
    887             // needs a complete image to succeed.
    888             if (0 == rowCount) {
    889                 return return_false(*cinfo, bitmap, "read_scanlines");
    890             }
    891             if (this->shouldCancelDecode()) {
    892                 return return_false(*cinfo, bitmap, "shouldCancelDecode");
    893             }
    894             rowTotalCount += rowCount;
    895             rowptr += bpr;
    896         }
    897 
    898         if (swapOnly) {
    899             bm->swap(bitmap);
    900         } else {
    901             cropBitmap(bm, &bitmap, actualSampleSize, region.x(), region.y(),
    902                        region.width(), region.height(), startX, startY);
    903         }
    904         return true;
    905     }
    906 #endif
    907 
    908     // check for supported formats
    909     SkScaledBitmapSampler::SrcConfig sc;
    910     int srcBytesPerPixel;
    911 
    912     if (!get_src_config(*cinfo, &sc, &srcBytesPerPixel)) {
    913         return return_false(*cinfo, *bm, "jpeg colorspace");
    914     }
    915 
    916     if (!sampler.begin(&bitmap, sc, *this)) {
    917         return return_false(*cinfo, bitmap, "sampler.begin");
    918     }
    919 
    920     SkAutoMalloc  srcStorage(width * srcBytesPerPixel);
    921     uint8_t* srcRow = (uint8_t*)srcStorage.get();
    922 
    923     //  Possibly skip initial rows [sampler.srcY0]
    924     if (!skip_src_rows_tile(cinfo, fImageIndex->huffmanIndex(), srcRow, sampler.srcY0())) {
    925         return return_false(*cinfo, bitmap, "skip rows");
    926     }
    927 
    928     // now loop through scanlines until y == bitmap->height() - 1
    929     for (int y = 0;; y++) {
    930         JSAMPLE* rowptr = (JSAMPLE*)srcRow;
    931         int row_count = jpeg_read_tile_scanline(cinfo, fImageIndex->huffmanIndex(), &rowptr);
    932         // if row_count == 0, then we didn't get a scanline, so abort.
    933         // onDecodeSubset() relies on onBuildTileIndex(), which
    934         // needs a complete image to succeed.
    935         if (0 == row_count) {
    936             return return_false(*cinfo, bitmap, "read_scanlines");
    937         }
    938         if (this->shouldCancelDecode()) {
    939             return return_false(*cinfo, bitmap, "shouldCancelDecode");
    940         }
    941 
    942         if (JCS_CMYK == cinfo->out_color_space) {
    943             convert_CMYK_to_RGB(srcRow, width);
    944         }
    945 
    946         sampler.next(srcRow);
    947         if (bitmap.height() - 1 == y) {
    948             // we're done
    949             break;
    950         }
    951 
    952         if (!skip_src_rows_tile(cinfo, fImageIndex->huffmanIndex(), srcRow,
    953                                 sampler.srcDY() - 1)) {
    954             return return_false(*cinfo, bitmap, "skip rows");
    955         }
    956     }
    957     if (swapOnly) {
    958         bm->swap(bitmap);
    959     } else {
    960         cropBitmap(bm, &bitmap, actualSampleSize, region.x(), region.y(),
    961                    region.width(), region.height(), startX, startY);
    962     }
    963     return true;
    964 }
    965 #endif
    966 
    967 ///////////////////////////////////////////////////////////////////////////////
    968 
    969 #include "SkColorPriv.h"
    970 
    971 // taken from jcolor.c in libjpeg
    972 #if 0   // 16bit - precise but slow
    973     #define CYR     19595   // 0.299
    974     #define CYG     38470   // 0.587
    975     #define CYB      7471   // 0.114
    976 
    977     #define CUR    -11059   // -0.16874
    978     #define CUG    -21709   // -0.33126
    979     #define CUB     32768   // 0.5
    980 
    981     #define CVR     32768   // 0.5
    982     #define CVG    -27439   // -0.41869
    983     #define CVB     -5329   // -0.08131
    984 
    985     #define CSHIFT  16
    986 #else      // 8bit - fast, slightly less precise
    987     #define CYR     77    // 0.299
    988     #define CYG     150    // 0.587
    989     #define CYB      29    // 0.114
    990 
    991     #define CUR     -43    // -0.16874
    992     #define CUG    -85    // -0.33126
    993     #define CUB     128    // 0.5
    994 
    995     #define CVR      128   // 0.5
    996     #define CVG     -107   // -0.41869
    997     #define CVB      -21   // -0.08131
    998 
    999     #define CSHIFT  8
   1000 #endif
   1001 
   1002 static void rgb2yuv_32(uint8_t dst[], SkPMColor c) {
   1003     int r = SkGetPackedR32(c);
   1004     int g = SkGetPackedG32(c);
   1005     int b = SkGetPackedB32(c);
   1006 
   1007     int  y = ( CYR*r + CYG*g + CYB*b ) >> CSHIFT;
   1008     int  u = ( CUR*r + CUG*g + CUB*b ) >> CSHIFT;
   1009     int  v = ( CVR*r + CVG*g + CVB*b ) >> CSHIFT;
   1010 
   1011     dst[0] = SkToU8(y);
   1012     dst[1] = SkToU8(u + 128);
   1013     dst[2] = SkToU8(v + 128);
   1014 }
   1015 
   1016 static void rgb2yuv_4444(uint8_t dst[], U16CPU c) {
   1017     int r = SkGetPackedR4444(c);
   1018     int g = SkGetPackedG4444(c);
   1019     int b = SkGetPackedB4444(c);
   1020 
   1021     int  y = ( CYR*r + CYG*g + CYB*b ) >> (CSHIFT - 4);
   1022     int  u = ( CUR*r + CUG*g + CUB*b ) >> (CSHIFT - 4);
   1023     int  v = ( CVR*r + CVG*g + CVB*b ) >> (CSHIFT - 4);
   1024 
   1025     dst[0] = SkToU8(y);
   1026     dst[1] = SkToU8(u + 128);
   1027     dst[2] = SkToU8(v + 128);
   1028 }
   1029 
   1030 static void rgb2yuv_16(uint8_t dst[], U16CPU c) {
   1031     int r = SkGetPackedR16(c);
   1032     int g = SkGetPackedG16(c);
   1033     int b = SkGetPackedB16(c);
   1034 
   1035     int  y = ( 2*CYR*r + CYG*g + 2*CYB*b ) >> (CSHIFT - 2);
   1036     int  u = ( 2*CUR*r + CUG*g + 2*CUB*b ) >> (CSHIFT - 2);
   1037     int  v = ( 2*CVR*r + CVG*g + 2*CVB*b ) >> (CSHIFT - 2);
   1038 
   1039     dst[0] = SkToU8(y);
   1040     dst[1] = SkToU8(u + 128);
   1041     dst[2] = SkToU8(v + 128);
   1042 }
   1043 
   1044 ///////////////////////////////////////////////////////////////////////////////
   1045 
   1046 typedef void (*WriteScanline)(uint8_t* SK_RESTRICT dst,
   1047                               const void* SK_RESTRICT src, int width,
   1048                               const SkPMColor* SK_RESTRICT ctable);
   1049 
   1050 static void Write_32_YUV(uint8_t* SK_RESTRICT dst,
   1051                          const void* SK_RESTRICT srcRow, int width,
   1052                          const SkPMColor*) {
   1053     const uint32_t* SK_RESTRICT src = (const uint32_t*)srcRow;
   1054     while (--width >= 0) {
   1055 #ifdef WE_CONVERT_TO_YUV
   1056         rgb2yuv_32(dst, *src++);
   1057 #else
   1058         uint32_t c = *src++;
   1059         dst[0] = SkGetPackedR32(c);
   1060         dst[1] = SkGetPackedG32(c);
   1061         dst[2] = SkGetPackedB32(c);
   1062 #endif
   1063         dst += 3;
   1064     }
   1065 }
   1066 
   1067 static void Write_4444_YUV(uint8_t* SK_RESTRICT dst,
   1068                            const void* SK_RESTRICT srcRow, int width,
   1069                            const SkPMColor*) {
   1070     const SkPMColor16* SK_RESTRICT src = (const SkPMColor16*)srcRow;
   1071     while (--width >= 0) {
   1072 #ifdef WE_CONVERT_TO_YUV
   1073         rgb2yuv_4444(dst, *src++);
   1074 #else
   1075         SkPMColor16 c = *src++;
   1076         dst[0] = SkPacked4444ToR32(c);
   1077         dst[1] = SkPacked4444ToG32(c);
   1078         dst[2] = SkPacked4444ToB32(c);
   1079 #endif
   1080         dst += 3;
   1081     }
   1082 }
   1083 
   1084 static void Write_16_YUV(uint8_t* SK_RESTRICT dst,
   1085                          const void* SK_RESTRICT srcRow, int width,
   1086                          const SkPMColor*) {
   1087     const uint16_t* SK_RESTRICT src = (const uint16_t*)srcRow;
   1088     while (--width >= 0) {
   1089 #ifdef WE_CONVERT_TO_YUV
   1090         rgb2yuv_16(dst, *src++);
   1091 #else
   1092         uint16_t c = *src++;
   1093         dst[0] = SkPacked16ToR32(c);
   1094         dst[1] = SkPacked16ToG32(c);
   1095         dst[2] = SkPacked16ToB32(c);
   1096 #endif
   1097         dst += 3;
   1098     }
   1099 }
   1100 
   1101 static void Write_Index_YUV(uint8_t* SK_RESTRICT dst,
   1102                             const void* SK_RESTRICT srcRow, int width,
   1103                             const SkPMColor* SK_RESTRICT ctable) {
   1104     const uint8_t* SK_RESTRICT src = (const uint8_t*)srcRow;
   1105     while (--width >= 0) {
   1106 #ifdef WE_CONVERT_TO_YUV
   1107         rgb2yuv_32(dst, ctable[*src++]);
   1108 #else
   1109         uint32_t c = ctable[*src++];
   1110         dst[0] = SkGetPackedR32(c);
   1111         dst[1] = SkGetPackedG32(c);
   1112         dst[2] = SkGetPackedB32(c);
   1113 #endif
   1114         dst += 3;
   1115     }
   1116 }
   1117 
   1118 static WriteScanline ChooseWriter(const SkBitmap& bm) {
   1119     switch (bm.config()) {
   1120         case SkBitmap::kARGB_8888_Config:
   1121             return Write_32_YUV;
   1122         case SkBitmap::kRGB_565_Config:
   1123             return Write_16_YUV;
   1124         case SkBitmap::kARGB_4444_Config:
   1125             return Write_4444_YUV;
   1126         case SkBitmap::kIndex8_Config:
   1127             return Write_Index_YUV;
   1128         default:
   1129             return NULL;
   1130     }
   1131 }
   1132 
   1133 class SkJPEGImageEncoder : public SkImageEncoder {
   1134 protected:
   1135     virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) {
   1136 #ifdef TIME_ENCODE
   1137         SkAutoTime atm("JPEG Encode");
   1138 #endif
   1139 
   1140         SkAutoLockPixels alp(bm);
   1141         if (NULL == bm.getPixels()) {
   1142             return false;
   1143         }
   1144 
   1145         jpeg_compress_struct    cinfo;
   1146         skjpeg_error_mgr        sk_err;
   1147         skjpeg_destination_mgr  sk_wstream(stream);
   1148 
   1149         // allocate these before set call setjmp
   1150         SkAutoMalloc    oneRow;
   1151         SkAutoLockColors ctLocker;
   1152 
   1153         cinfo.err = jpeg_std_error(&sk_err);
   1154         sk_err.error_exit = skjpeg_error_exit;
   1155         if (setjmp(sk_err.fJmpBuf)) {
   1156             return false;
   1157         }
   1158 
   1159         // Keep after setjmp or mark volatile.
   1160         const WriteScanline writer = ChooseWriter(bm);
   1161         if (NULL == writer) {
   1162             return false;
   1163         }
   1164 
   1165         jpeg_create_compress(&cinfo);
   1166         cinfo.dest = &sk_wstream;
   1167         cinfo.image_width = bm.width();
   1168         cinfo.image_height = bm.height();
   1169         cinfo.input_components = 3;
   1170 #ifdef WE_CONVERT_TO_YUV
   1171         cinfo.in_color_space = JCS_YCbCr;
   1172 #else
   1173         cinfo.in_color_space = JCS_RGB;
   1174 #endif
   1175         cinfo.input_gamma = 1;
   1176 
   1177         jpeg_set_defaults(&cinfo);
   1178         jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
   1179 #ifdef DCT_IFAST_SUPPORTED
   1180         cinfo.dct_method = JDCT_IFAST;
   1181 #endif
   1182 
   1183         jpeg_start_compress(&cinfo, TRUE);
   1184 
   1185         const int       width = bm.width();
   1186         uint8_t*        oneRowP = (uint8_t*)oneRow.reset(width * 3);
   1187 
   1188         const SkPMColor* colors = ctLocker.lockColors(bm);
   1189         const void*      srcRow = bm.getPixels();
   1190 
   1191         while (cinfo.next_scanline < cinfo.image_height) {
   1192             JSAMPROW row_pointer[1];    /* pointer to JSAMPLE row[s] */
   1193 
   1194             writer(oneRowP, srcRow, width, colors);
   1195             row_pointer[0] = oneRowP;
   1196             (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
   1197             srcRow = (const void*)((const char*)srcRow + bm.rowBytes());
   1198         }
   1199 
   1200         jpeg_finish_compress(&cinfo);
   1201         jpeg_destroy_compress(&cinfo);
   1202 
   1203         return true;
   1204     }
   1205 };
   1206 
   1207 ///////////////////////////////////////////////////////////////////////////////
   1208 DEFINE_DECODER_CREATOR(JPEGImageDecoder);
   1209 DEFINE_ENCODER_CREATOR(JPEGImageEncoder);
   1210 ///////////////////////////////////////////////////////////////////////////////
   1211 
   1212 static bool is_jpeg(SkStreamRewindable* stream) {
   1213     static const unsigned char gHeader[] = { 0xFF, 0xD8, 0xFF };
   1214     static const size_t HEADER_SIZE = sizeof(gHeader);
   1215 
   1216     char buffer[HEADER_SIZE];
   1217     size_t len = stream->read(buffer, HEADER_SIZE);
   1218 
   1219     if (len != HEADER_SIZE) {
   1220         return false;   // can't read enough
   1221     }
   1222     if (memcmp(buffer, gHeader, HEADER_SIZE)) {
   1223         return false;
   1224     }
   1225     return true;
   1226 }
   1227 
   1228 
   1229 static SkImageDecoder* sk_libjpeg_dfactory(SkStreamRewindable* stream) {
   1230     if (is_jpeg(stream)) {
   1231         return SkNEW(SkJPEGImageDecoder);
   1232     }
   1233     return NULL;
   1234 }
   1235 
   1236 static SkImageDecoder::Format get_format_jpeg(SkStreamRewindable* stream) {
   1237     if (is_jpeg(stream)) {
   1238         return SkImageDecoder::kJPEG_Format;
   1239     }
   1240     return SkImageDecoder::kUnknown_Format;
   1241 }
   1242 
   1243 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) {
   1244     return (SkImageEncoder::kJPEG_Type == t) ? SkNEW(SkJPEGImageEncoder) : NULL;
   1245 }
   1246 
   1247 static SkImageDecoder_DecodeReg gDReg(sk_libjpeg_dfactory);
   1248 static SkImageDecoder_FormatReg gFormatReg(get_format_jpeg);
   1249 static SkImageEncoder_EncodeReg gEReg(sk_libjpeg_efactory);
   1250