Home | History | Annotate | Download | only in images
      1 
      2 /*
      3  * Copyright 2007 The Android Open Source Project
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 
     10 #include "SkImageDecoder.h"
     11 #include "SkImageEncoder.h"
     12 #include "SkJpegUtility.h"
     13 #include "SkColorPriv.h"
     14 #include "SkDither.h"
     15 #include "SkScaledBitmapSampler.h"
     16 #include "SkStream.h"
     17 #include "SkTemplates.h"
     18 #include "SkUtils.h"
     19 #include "SkRect.h"
     20 #include "SkCanvas.h"
     21 
     22 #include <stdio.h>
     23 extern "C" {
     24     #include "jpeglib.h"
     25     #include "jerror.h"
     26 }
     27 
     28 #ifdef SK_BUILD_FOR_ANDROID
     29 #include <cutils/properties.h>
     30 
     31 // Key to lookup the size of memory buffer set in system property
     32 static const char KEY_MEM_CAP[] = "ro.media.dec.jpeg.memcap";
     33 #endif
     34 
     35 // this enables timing code to report milliseconds for an encode
     36 //#define TIME_ENCODE
     37 //#define TIME_DECODE
     38 
     39 // this enables our rgb->yuv code, which is faster than libjpeg on ARM
     40 // disable for the moment, as we have some glitches when width != multiple of 4
     41 #define WE_CONVERT_TO_YUV
     42 
     43 //////////////////////////////////////////////////////////////////////////
     44 //////////////////////////////////////////////////////////////////////////
     45 
     46 class SkJPEGImageIndex {
     47 public:
     48     SkJPEGImageIndex() {}
     49     virtual ~SkJPEGImageIndex() {
     50         jpeg_destroy_huffman_index(index);
     51         jpeg_finish_decompress(cinfo);
     52         jpeg_destroy_decompress(cinfo);
     53         delete cinfo->src;
     54         free(cinfo);
     55     }
     56     jpeg_decompress_struct *cinfo;
     57     huffman_index *index;
     58 };
     59 
     60 
     61 class SkJPEGImageDecoder : public SkImageDecoder {
     62 public:
     63     SkJPEGImageDecoder() {
     64         index = NULL;
     65     }
     66     ~SkJPEGImageDecoder() {
     67         if (index)
     68             delete index;
     69     }
     70     virtual Format getFormat() const {
     71         return kJPEG_Format;
     72     }
     73 protected:
     74     virtual bool onBuildTileIndex(SkStream *stream,
     75                                 int *width, int *height);
     76     virtual bool onDecodeRegion(SkBitmap* bitmap, SkIRect rect);
     77     virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode);
     78 private:
     79     SkJPEGImageIndex *index;
     80     int imageWidth;
     81     int imageHeight;
     82 };
     83 
     84 //////////////////////////////////////////////////////////////////////////
     85 
     86 #include "SkTime.h"
     87 
     88 class AutoTimeMillis {
     89 public:
     90     AutoTimeMillis(const char label[]) : fLabel(label) {
     91         if (!fLabel) {
     92             fLabel = "";
     93         }
     94         fNow = SkTime::GetMSecs();
     95     }
     96     ~AutoTimeMillis() {
     97         SkDebugf("---- Time (ms): %s %d\n", fLabel, SkTime::GetMSecs() - fNow);
     98     }
     99 private:
    100     const char* fLabel;
    101     SkMSec      fNow;
    102 };
    103 
    104 /* Automatically clean up after throwing an exception */
    105 class JPEGAutoClean {
    106 public:
    107     JPEGAutoClean(): cinfo_ptr(NULL) {}
    108     ~JPEGAutoClean() {
    109         if (cinfo_ptr) {
    110             jpeg_destroy_decompress(cinfo_ptr);
    111         }
    112     }
    113     void set(jpeg_decompress_struct* info) {
    114         cinfo_ptr = info;
    115     }
    116 private:
    117     jpeg_decompress_struct* cinfo_ptr;
    118 };
    119 
    120 #ifdef SK_BUILD_FOR_ANDROID
    121 /* Check if the memory cap property is set.
    122    If so, use the memory size for jpeg decode.
    123 */
    124 static void overwrite_mem_buffer_size(j_decompress_ptr cinfo) {
    125 #ifdef ANDROID_LARGE_MEMORY_DEVICE
    126     cinfo->mem->max_memory_to_use = 30 * 1024 * 1024;
    127 #else
    128     cinfo->mem->max_memory_to_use = 5 * 1024 * 1024;
    129 #endif
    130 }
    131 #endif
    132 
    133 
    134 ///////////////////////////////////////////////////////////////////////////////
    135 
    136 /*  If we need to better match the request, we might examine the image and
    137      output dimensions, and determine if the downsampling jpeg provided is
    138      not sufficient. If so, we can recompute a modified sampleSize value to
    139      make up the difference.
    140 
    141      To skip this additional scaling, just set sampleSize = 1; below.
    142  */
    143 static int recompute_sampleSize(int sampleSize,
    144                                 const jpeg_decompress_struct& cinfo) {
    145     return sampleSize * cinfo.output_width / cinfo.image_width;
    146 }
    147 
    148 static bool valid_output_dimensions(const jpeg_decompress_struct& cinfo) {
    149     /* These are initialized to 0, so if they have non-zero values, we assume
    150        they are "valid" (i.e. have been computed by libjpeg)
    151      */
    152     return cinfo.output_width != 0 && cinfo.output_height != 0;
    153 }
    154 
    155 static bool skip_src_rows(jpeg_decompress_struct* cinfo, void* buffer,
    156                           int count) {
    157     for (int i = 0; i < count; i++) {
    158         JSAMPLE* rowptr = (JSAMPLE*)buffer;
    159         int row_count = jpeg_read_scanlines(cinfo, &rowptr, 1);
    160         if (row_count != 1) {
    161             return false;
    162         }
    163     }
    164     return true;
    165 }
    166 
    167 static bool skip_src_rows_tile(jpeg_decompress_struct* cinfo,
    168                           huffman_index *index, void* buffer,
    169                           int count) {
    170     for (int i = 0; i < count; i++) {
    171         JSAMPLE* rowptr = (JSAMPLE*)buffer;
    172         int row_count = jpeg_read_tile_scanline(cinfo, index, &rowptr);
    173         if (row_count != 1) {
    174             return false;
    175         }
    176     }
    177     return true;
    178 }
    179 
    180 // This guy exists just to aid in debugging, as it allows debuggers to just
    181 // set a break-point in one place to see all error exists.
    182 static bool return_false(const jpeg_decompress_struct& cinfo,
    183                          const SkBitmap& bm, const char msg[]) {
    184 #ifdef SK_DEBUG
    185     SkDebugf("libjpeg error %d <%s> from %s [%d %d]", cinfo.err->msg_code,
    186              cinfo.err->jpeg_message_table[cinfo.err->msg_code], msg,
    187              bm.width(), bm.height());
    188 #endif
    189     return false;   // must always return false
    190 }
    191 
    192 // Convert a scanline of CMYK samples to RGBX in place. Note that this
    193 // method moves the "scanline" pointer in its processing
    194 static void convert_CMYK_to_RGB(uint8_t* scanline, unsigned int width) {
    195     // At this point we've received CMYK pixels from libjpeg. We
    196     // perform a crude conversion to RGB (based on the formulae
    197     // from easyrgb.com):
    198     //  CMYK -> CMY
    199     //    C = ( C * (1 - K) + K )      // for each CMY component
    200     //  CMY -> RGB
    201     //    R = ( 1 - C ) * 255          // for each RGB component
    202     // Unfortunately we are seeing inverted CMYK so all the original terms
    203     // are 1-. This yields:
    204     //  CMYK -> CMY
    205     //    C = ( (1-C) * (1 - (1-K) + (1-K) ) -> C = 1 - C*K
    206     // The conversion from CMY->RGB remains the same
    207     for (unsigned int x = 0; x < width; ++x, scanline += 4) {
    208         scanline[0] = SkMulDiv255Round(scanline[0], scanline[3]);
    209         scanline[1] = SkMulDiv255Round(scanline[1], scanline[3]);
    210         scanline[2] = SkMulDiv255Round(scanline[2], scanline[3]);
    211         scanline[3] = 255;
    212     }
    213 }
    214 
    215 bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
    216 #ifdef TIME_DECODE
    217     AutoTimeMillis atm("JPEG Decode");
    218 #endif
    219 
    220     SkAutoMalloc  srcStorage;
    221     JPEGAutoClean autoClean;
    222 
    223     jpeg_decompress_struct  cinfo;
    224     skjpeg_error_mgr        sk_err;
    225     skjpeg_source_mgr       sk_stream(stream, this, false);
    226 
    227     cinfo.err = jpeg_std_error(&sk_err);
    228     sk_err.error_exit = skjpeg_error_exit;
    229 
    230     // All objects need to be instantiated before this setjmp call so that
    231     // they will be cleaned up properly if an error occurs.
    232     if (setjmp(sk_err.fJmpBuf)) {
    233         return return_false(cinfo, *bm, "setjmp");
    234     }
    235 
    236     jpeg_create_decompress(&cinfo);
    237     autoClean.set(&cinfo);
    238 
    239 #ifdef SK_BUILD_FOR_ANDROID
    240     overwrite_mem_buffer_size(&cinfo);
    241 #endif
    242 
    243     //jpeg_stdio_src(&cinfo, file);
    244     cinfo.src = &sk_stream;
    245 
    246     int status = jpeg_read_header(&cinfo, true);
    247     if (status != JPEG_HEADER_OK) {
    248         return return_false(cinfo, *bm, "read_header");
    249     }
    250 
    251     /*  Try to fulfill the requested sampleSize. Since jpeg can do it (when it
    252         can) much faster that we, just use their num/denom api to approximate
    253         the size.
    254     */
    255     int sampleSize = this->getSampleSize();
    256 
    257     if (this->getPreferQualityOverSpeed()) {
    258         cinfo.dct_method = JDCT_ISLOW;
    259     } else {
    260         cinfo.dct_method = JDCT_IFAST;
    261     }
    262 
    263     cinfo.scale_num = 1;
    264     cinfo.scale_denom = sampleSize;
    265 
    266     /* this gives about 30% performance improvement. In theory it may
    267        reduce the visual quality, in practice I'm not seeing a difference
    268      */
    269     cinfo.do_fancy_upsampling = 0;
    270 
    271     /* this gives another few percents */
    272     cinfo.do_block_smoothing = 0;
    273 
    274     /* default format is RGB */
    275     if (cinfo.jpeg_color_space == JCS_CMYK) {
    276         // libjpeg cannot convert from CMYK to RGB - here we set up
    277         // so libjpeg will give us CMYK samples back and we will
    278         // later manually convert them to RGB
    279         cinfo.out_color_space = JCS_CMYK;
    280     } else {
    281         cinfo.out_color_space = JCS_RGB;
    282     }
    283 
    284     SkBitmap::Config config = this->getPrefConfig(k32Bit_SrcDepth, false);
    285     // only these make sense for jpegs
    286     if (config != SkBitmap::kARGB_8888_Config &&
    287         config != SkBitmap::kARGB_4444_Config &&
    288         config != SkBitmap::kRGB_565_Config) {
    289         config = SkBitmap::kARGB_8888_Config;
    290     }
    291 
    292 #ifdef ANDROID_RGB
    293     cinfo.dither_mode = JDITHER_NONE;
    294     if (SkBitmap::kARGB_8888_Config == config && JCS_CMYK != cinfo.out_color_space) {
    295         cinfo.out_color_space = JCS_RGBA_8888;
    296     } else if (SkBitmap::kRGB_565_Config == config && JCS_CMYK != cinfo.out_color_space) {
    297         cinfo.out_color_space = JCS_RGB_565;
    298         if (this->getDitherImage()) {
    299             cinfo.dither_mode = JDITHER_ORDERED;
    300         }
    301     }
    302 #endif
    303 
    304     if (sampleSize == 1 && mode == SkImageDecoder::kDecodeBounds_Mode) {
    305         bm->setConfig(config, cinfo.image_width, cinfo.image_height);
    306         bm->setIsOpaque(true);
    307         return true;
    308     }
    309 
    310     /*  image_width and image_height are the original dimensions, available
    311         after jpeg_read_header(). To see the scaled dimensions, we have to call
    312         jpeg_start_decompress(), and then read output_width and output_height.
    313     */
    314     if (!jpeg_start_decompress(&cinfo)) {
    315         /*  If we failed here, we may still have enough information to return
    316             to the caller if they just wanted (subsampled bounds). If sampleSize
    317             was 1, then we would have already returned. Thus we just check if
    318             we're in kDecodeBounds_Mode, and that we have valid output sizes.
    319 
    320             One reason to fail here is that we have insufficient stream data
    321             to complete the setup. However, output dimensions seem to get
    322             computed very early, which is why this special check can pay off.
    323          */
    324         if (SkImageDecoder::kDecodeBounds_Mode == mode &&
    325                 valid_output_dimensions(cinfo)) {
    326             SkScaledBitmapSampler smpl(cinfo.output_width, cinfo.output_height,
    327                                        recompute_sampleSize(sampleSize, cinfo));
    328             bm->setConfig(config, smpl.scaledWidth(), smpl.scaledHeight());
    329             bm->setIsOpaque(true);
    330             return true;
    331         } else {
    332             return return_false(cinfo, *bm, "start_decompress");
    333         }
    334     }
    335     sampleSize = recompute_sampleSize(sampleSize, cinfo);
    336 
    337     // should we allow the Chooser (if present) to pick a config for us???
    338     if (!this->chooseFromOneChoice(config, cinfo.output_width,
    339                                    cinfo.output_height)) {
    340         return return_false(cinfo, *bm, "chooseFromOneChoice");
    341     }
    342 
    343 #ifdef ANDROID_RGB
    344     /* short-circuit the SkScaledBitmapSampler when possible, as this gives
    345        a significant performance boost.
    346     */
    347     if (sampleSize == 1 &&
    348         ((config == SkBitmap::kARGB_8888_Config &&
    349                 cinfo.out_color_space == JCS_RGBA_8888) ||
    350         (config == SkBitmap::kRGB_565_Config &&
    351                 cinfo.out_color_space == JCS_RGB_565)))
    352     {
    353         bm->lockPixels();
    354         JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels();
    355         bm->unlockPixels();
    356         bool reuseBitmap = (rowptr != NULL);
    357         if (reuseBitmap && ((int) cinfo.output_width != bm->width() ||
    358                 (int) cinfo.output_height != bm->height())) {
    359             // Dimensions must match
    360             return false;
    361         }
    362 
    363         if (!reuseBitmap) {
    364             bm->setConfig(config, cinfo.output_width, cinfo.output_height);
    365             bm->setIsOpaque(true);
    366             if (SkImageDecoder::kDecodeBounds_Mode == mode) {
    367                 return true;
    368             }
    369             if (!this->allocPixelRef(bm, NULL)) {
    370                 return return_false(cinfo, *bm, "allocPixelRef");
    371             }
    372         } else if (SkImageDecoder::kDecodeBounds_Mode == mode) {
    373             return true;
    374         }
    375         SkAutoLockPixels alp(*bm);
    376         rowptr = (JSAMPLE*)bm->getPixels();
    377         INT32 const bpr =  bm->rowBytes();
    378 
    379         while (cinfo.output_scanline < cinfo.output_height) {
    380             int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1);
    381             // if row_count == 0, then we didn't get a scanline, so abort.
    382             // if we supported partial images, we might return true in this case
    383             if (0 == row_count) {
    384                 return return_false(cinfo, *bm, "read_scanlines");
    385             }
    386             if (this->shouldCancelDecode()) {
    387                 return return_false(cinfo, *bm, "shouldCancelDecode");
    388             }
    389             rowptr += bpr;
    390         }
    391         if (reuseBitmap) {
    392             bm->notifyPixelsChanged();
    393         }
    394         jpeg_finish_decompress(&cinfo);
    395         return true;
    396     }
    397 #endif
    398 
    399     // check for supported formats
    400     SkScaledBitmapSampler::SrcConfig sc;
    401     if (JCS_CMYK == cinfo.out_color_space) {
    402         // In this case we will manually convert the CMYK values to RGB
    403         sc = SkScaledBitmapSampler::kRGBX;
    404     } else if (3 == cinfo.out_color_components && JCS_RGB == cinfo.out_color_space) {
    405         sc = SkScaledBitmapSampler::kRGB;
    406 #ifdef ANDROID_RGB
    407     } else if (JCS_RGBA_8888 == cinfo.out_color_space) {
    408         sc = SkScaledBitmapSampler::kRGBX;
    409     } else if (JCS_RGB_565 == cinfo.out_color_space) {
    410         sc = SkScaledBitmapSampler::kRGB_565;
    411 #endif
    412     } else if (1 == cinfo.out_color_components &&
    413                JCS_GRAYSCALE == cinfo.out_color_space) {
    414         sc = SkScaledBitmapSampler::kGray;
    415     } else {
    416         return return_false(cinfo, *bm, "jpeg colorspace");
    417     }
    418 
    419     SkScaledBitmapSampler sampler(cinfo.output_width, cinfo.output_height,
    420                                   sampleSize);
    421 
    422     bm->lockPixels();
    423     JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels();
    424     bool reuseBitmap = (rowptr != NULL);
    425     bm->unlockPixels();
    426     if (reuseBitmap && (sampler.scaledWidth() != bm->width() ||
    427             sampler.scaledHeight() != bm->height())) {
    428         // Dimensions must match
    429         return false;
    430     }
    431 
    432     if (!reuseBitmap) {
    433         bm->setConfig(config, sampler.scaledWidth(), sampler.scaledHeight());
    434         // jpegs are always opaque (i.e. have no per-pixel alpha)
    435         bm->setIsOpaque(true);
    436 
    437         if (SkImageDecoder::kDecodeBounds_Mode == mode) {
    438             return true;
    439         }
    440         if (!this->allocPixelRef(bm, NULL)) {
    441             return return_false(cinfo, *bm, "allocPixelRef");
    442         }
    443     } else if (SkImageDecoder::kDecodeBounds_Mode == mode) {
    444         return true;
    445     }
    446 
    447     SkAutoLockPixels alp(*bm);
    448     if (!sampler.begin(bm, sc, this->getDitherImage())) {
    449         return return_false(cinfo, *bm, "sampler.begin");
    450     }
    451 
    452     // The CMYK work-around relies on 4 components per pixel here
    453     uint8_t* srcRow = (uint8_t*)srcStorage.reset(cinfo.output_width * 4);
    454 
    455     //  Possibly skip initial rows [sampler.srcY0]
    456     if (!skip_src_rows(&cinfo, srcRow, sampler.srcY0())) {
    457         return return_false(cinfo, *bm, "skip rows");
    458     }
    459 
    460     // now loop through scanlines until y == bm->height() - 1
    461     for (int y = 0;; y++) {
    462         JSAMPLE* rowptr = (JSAMPLE*)srcRow;
    463         int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1);
    464         if (0 == row_count) {
    465             return return_false(cinfo, *bm, "read_scanlines");
    466         }
    467         if (this->shouldCancelDecode()) {
    468             return return_false(cinfo, *bm, "shouldCancelDecode");
    469         }
    470 
    471         if (JCS_CMYK == cinfo.out_color_space) {
    472             convert_CMYK_to_RGB(srcRow, cinfo.output_width);
    473         }
    474 
    475         sampler.next(srcRow);
    476         if (bm->height() - 1 == y) {
    477             // we're done
    478             break;
    479         }
    480 
    481         if (!skip_src_rows(&cinfo, srcRow, sampler.srcDY() - 1)) {
    482             return return_false(cinfo, *bm, "skip rows");
    483         }
    484     }
    485 
    486     // we formally skip the rest, so we don't get a complaint from libjpeg
    487     if (!skip_src_rows(&cinfo, srcRow,
    488                        cinfo.output_height - cinfo.output_scanline)) {
    489         return return_false(cinfo, *bm, "skip rows");
    490     }
    491     if (reuseBitmap) {
    492         bm->notifyPixelsChanged();
    493     }
    494     jpeg_finish_decompress(&cinfo);
    495 
    496 //    SkDebugf("------------------- bm2 size %d [%d %d] %d\n", bm->getSize(), bm->width(), bm->height(), bm->config());
    497     return true;
    498 }
    499 
    500 bool SkJPEGImageDecoder::onBuildTileIndex(SkStream* stream,
    501                                         int *width, int *height) {
    502     SkAutoMalloc  srcStorage;
    503     SkJPEGImageIndex *index = new SkJPEGImageIndex;
    504 
    505     jpeg_decompress_struct  *cinfo = (jpeg_decompress_struct*)
    506                                         malloc(sizeof(jpeg_decompress_struct));
    507     skjpeg_error_mgr        sk_err;
    508     skjpeg_source_mgr       *sk_stream =
    509         new skjpeg_source_mgr(stream, this, true);
    510     if (cinfo == NULL || sk_stream == NULL) {
    511         return false;
    512     }
    513 
    514     cinfo->err = jpeg_std_error(&sk_err);
    515     sk_err.error_exit = skjpeg_error_exit;
    516 
    517     // All objects need to be instantiated before this setjmp call so that
    518     // they will be cleaned up properly if an error occurs.
    519     if (setjmp(sk_err.fJmpBuf)) {
    520         return false;
    521     }
    522 
    523     jpeg_create_decompress(cinfo);
    524     cinfo->do_fancy_upsampling = 0;
    525     cinfo->do_block_smoothing = 0;
    526 
    527 #ifdef SK_BUILD_FOR_ANDROID
    528     overwrite_mem_buffer_size(cinfo);
    529 #endif
    530 
    531     cinfo->src = sk_stream;
    532     int status = jpeg_read_header(cinfo, true);
    533     if (status != JPEG_HEADER_OK) {
    534         return false;
    535     }
    536     index->index = (huffman_index*)malloc(sizeof(huffman_index));
    537     jpeg_create_huffman_index(cinfo, index->index);
    538 
    539     cinfo->scale_num = 1;
    540     cinfo->scale_denom = 1;
    541     if (!jpeg_build_huffman_index(cinfo, index->index)) {
    542         return false;
    543     }
    544     if (fReporter)
    545         fReporter->reportMemory(index->index->mem_used);
    546     jpeg_destroy_decompress(cinfo);
    547 
    548 
    549     // Init decoder to image decode mode
    550     jpeg_create_decompress(cinfo);
    551 
    552 #ifdef SK_BUILD_FOR_ANDROID
    553     overwrite_mem_buffer_size(cinfo);
    554 #endif
    555 
    556     cinfo->src = sk_stream;
    557     status = jpeg_read_header(cinfo,true);
    558     if (status != JPEG_HEADER_OK) {
    559         return false;
    560     }
    561     cinfo->out_color_space = JCS_RGBA_8888;
    562     cinfo->do_fancy_upsampling = 0;
    563     cinfo->do_block_smoothing = 0;
    564     //jpeg_start_decompress(cinfo);
    565     jpeg_start_tile_decompress(cinfo);
    566 
    567     cinfo->scale_num = 1;
    568     index->cinfo = cinfo;
    569     *height = cinfo->output_height;
    570     *width = cinfo->output_width;
    571     this->imageWidth = *width;
    572     this->imageHeight = *height;
    573     this->index = index;
    574     return true;
    575 }
    576 
    577 bool SkJPEGImageDecoder::onDecodeRegion(SkBitmap* bm, SkIRect region) {
    578     if (index == NULL) {
    579         return false;
    580     }
    581     jpeg_decompress_struct *cinfo = index->cinfo;
    582 
    583     SkIRect rect = SkIRect::MakeWH(this->imageWidth, this->imageHeight);
    584     if (!rect.intersect(region)) {
    585         // If the requested region is entirely outsides the image, just
    586         // returns false
    587         return false;
    588     }
    589     SkAutoMalloc  srcStorage;
    590     skjpeg_error_mgr        sk_err;
    591     cinfo->err = jpeg_std_error(&sk_err);
    592     sk_err.error_exit = skjpeg_error_exit;
    593     if (setjmp(sk_err.fJmpBuf)) {
    594         return false;
    595     }
    596     int requestedSampleSize = this->getSampleSize();
    597     cinfo->scale_denom = requestedSampleSize;
    598 
    599     if (this->getPreferQualityOverSpeed()) {
    600         cinfo->dct_method = JDCT_ISLOW;
    601     } else {
    602         cinfo->dct_method = JDCT_IFAST;
    603     }
    604 
    605     SkBitmap::Config config = this->getPrefConfig(k32Bit_SrcDepth, false);
    606     if (config != SkBitmap::kARGB_8888_Config &&
    607         config != SkBitmap::kARGB_4444_Config &&
    608         config != SkBitmap::kRGB_565_Config) {
    609         config = SkBitmap::kARGB_8888_Config;
    610     }
    611 
    612     /* default format is RGB */
    613     cinfo->out_color_space = JCS_RGB;
    614 
    615 #ifdef ANDROID_RGB
    616     cinfo->dither_mode = JDITHER_NONE;
    617     if (config == SkBitmap::kARGB_8888_Config) {
    618         cinfo->out_color_space = JCS_RGBA_8888;
    619     } else if (config == SkBitmap::kRGB_565_Config) {
    620         cinfo->out_color_space = JCS_RGB_565;
    621         if (this->getDitherImage()) {
    622             cinfo->dither_mode = JDITHER_ORDERED;
    623         }
    624     }
    625 #endif
    626     int startX = rect.fLeft;
    627     int startY = rect.fTop;
    628     int width = rect.width();
    629     int height = rect.height();
    630 
    631     jpeg_init_read_tile_scanline(cinfo, index->index,
    632                                  &startX, &startY, &width, &height);
    633     int skiaSampleSize = recompute_sampleSize(requestedSampleSize, *cinfo);
    634     int actualSampleSize = skiaSampleSize * (DCTSIZE / cinfo->min_DCT_scaled_size);
    635 
    636     SkBitmap *bitmap = new SkBitmap;
    637     SkAutoTDelete<SkBitmap> adb(bitmap);
    638 
    639 #ifdef ANDROID_RGB
    640     /* short-circuit the SkScaledBitmapSampler when possible, as this gives
    641        a significant performance boost.
    642     */
    643     if (skiaSampleSize == 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         bitmap->setConfig(config, cinfo->output_width, height);
    650         bitmap->setIsOpaque(true);
    651 
    652         // Check ahead of time if the swap(dest, src) is possible or not.
    653         // If yes, then we will stick to AllocPixelRef since it's cheaper
    654         // with the swap happening. If no, then we will use alloc to allocate
    655         // pixels to prevent garbage collection.
    656         //
    657         // Not using a recycled-bitmap and the output rect is same as the
    658         // decoded region.
    659         int w = rect.width() / actualSampleSize;
    660         int h = rect.height() / actualSampleSize;
    661         bool swapOnly = (rect == region) && bm->isNull() &&
    662                         (w == bitmap->width()) && (h == bitmap->height()) &&
    663                         ((startX - rect.x()) / actualSampleSize == 0) &&
    664                         ((startY - rect.y()) / actualSampleSize == 0);
    665         if (swapOnly) {
    666             if (!this->allocPixelRef(bitmap, NULL)) {
    667                 return return_false(*cinfo, *bitmap, "allocPixelRef");
    668             }
    669         } else {
    670             if (!bitmap->allocPixels()) {
    671                 return return_false(*cinfo, *bitmap, "allocPixels");
    672             }
    673         }
    674 
    675         SkAutoLockPixels alp(*bitmap);
    676         JSAMPLE* rowptr = (JSAMPLE*)bitmap->getPixels();
    677         INT32 const bpr = bitmap->rowBytes();
    678         int row_total_count = 0;
    679 
    680         while (row_total_count < height) {
    681             int row_count = jpeg_read_tile_scanline(cinfo,
    682                     index->index, &rowptr);
    683             // if row_count == 0, then we didn't get a scanline, so abort.
    684             // if we supported partial images, we might return true in this case
    685             if (0 == row_count) {
    686                 return return_false(*cinfo, *bitmap, "read_scanlines");
    687             }
    688             if (this->shouldCancelDecode()) {
    689                 return return_false(*cinfo, *bitmap, "shouldCancelDecode");
    690             }
    691             row_total_count += row_count;
    692             rowptr += bpr;
    693         }
    694 
    695         if (swapOnly) {
    696             bm->swap(*bitmap);
    697         } else {
    698             cropBitmap(bm, bitmap, actualSampleSize, region.x(), region.y(),
    699                        region.width(), region.height(), startX, startY);
    700         }
    701         return true;
    702     }
    703 #endif
    704     // check for supported formats
    705     SkScaledBitmapSampler::SrcConfig sc;
    706     if (3 == cinfo->out_color_components && JCS_RGB == cinfo->out_color_space) {
    707         sc = SkScaledBitmapSampler::kRGB;
    708 #ifdef ANDROID_RGB
    709     } else if (JCS_RGBA_8888 == cinfo->out_color_space) {
    710         sc = SkScaledBitmapSampler::kRGBX;
    711     } else if (JCS_RGB_565 == cinfo->out_color_space) {
    712         sc = SkScaledBitmapSampler::kRGB_565;
    713 #endif
    714     } else if (1 == cinfo->out_color_components &&
    715                JCS_GRAYSCALE == cinfo->out_color_space) {
    716         sc = SkScaledBitmapSampler::kGray;
    717     } else {
    718         return return_false(*cinfo, *bm, "jpeg colorspace");
    719     }
    720 
    721     SkScaledBitmapSampler sampler(width, height, skiaSampleSize);
    722 
    723     bitmap->setConfig(config, sampler.scaledWidth(), sampler.scaledHeight());
    724     bitmap->setIsOpaque(true);
    725 
    726     // Check ahead of time if the swap(dest, src) is possible or not.
    727     // If yes, then we will stick to AllocPixelRef since it's cheaper with the
    728     // swap happening. If no, then we will use alloc to allocate pixels to
    729     // prevent garbage collection.
    730     int w = rect.width() / actualSampleSize;
    731     int h = rect.height() / actualSampleSize;
    732     bool swapOnly = (rect == region) && bm->isNull() &&
    733                     (w == bitmap->width()) && (h == bitmap->height()) &&
    734                     ((startX - rect.x()) / actualSampleSize == 0) &&
    735                     ((startY - rect.y()) / actualSampleSize == 0);
    736     if (swapOnly) {
    737         if (!this->allocPixelRef(bitmap, NULL)) {
    738             return return_false(*cinfo, *bitmap, "allocPixelRef");
    739         }
    740     } else {
    741         if (!bitmap->allocPixels()) {
    742             return return_false(*cinfo, *bitmap, "allocPixels");
    743         }
    744     }
    745 
    746     SkAutoLockPixels alp(*bitmap);
    747     if (!sampler.begin(bitmap, sc, this->getDitherImage())) {
    748         return return_false(*cinfo, *bitmap, "sampler.begin");
    749     }
    750 
    751     uint8_t* srcRow = (uint8_t*)srcStorage.reset(width * 4);
    752 
    753     //  Possibly skip initial rows [sampler.srcY0]
    754     if (!skip_src_rows_tile(cinfo, index->index, srcRow, sampler.srcY0())) {
    755         return return_false(*cinfo, *bitmap, "skip rows");
    756     }
    757 
    758     // now loop through scanlines until y == bitmap->height() - 1
    759     for (int y = 0;; y++) {
    760         JSAMPLE* rowptr = (JSAMPLE*)srcRow;
    761         int row_count = jpeg_read_tile_scanline(cinfo, index->index, &rowptr);
    762         if (0 == row_count) {
    763             return return_false(*cinfo, *bitmap, "read_scanlines");
    764         }
    765         if (this->shouldCancelDecode()) {
    766             return return_false(*cinfo, *bitmap, "shouldCancelDecode");
    767         }
    768 
    769         sampler.next(srcRow);
    770         if (bitmap->height() - 1 == y) {
    771             // we're done
    772             break;
    773         }
    774 
    775         if (!skip_src_rows_tile(cinfo, index->index, srcRow,
    776                                 sampler.srcDY() - 1)) {
    777             return return_false(*cinfo, *bitmap, "skip rows");
    778         }
    779     }
    780     if (swapOnly) {
    781         bm->swap(*bitmap);
    782     } else {
    783         cropBitmap(bm, bitmap, actualSampleSize, region.x(), region.y(),
    784                    region.width(), region.height(), startX, startY);
    785     }
    786     return true;
    787 }
    788 
    789 ///////////////////////////////////////////////////////////////////////////////
    790 
    791 #include "SkColorPriv.h"
    792 
    793 // taken from jcolor.c in libjpeg
    794 #if 0   // 16bit - precise but slow
    795     #define CYR     19595   // 0.299
    796     #define CYG     38470   // 0.587
    797     #define CYB      7471   // 0.114
    798 
    799     #define CUR    -11059   // -0.16874
    800     #define CUG    -21709   // -0.33126
    801     #define CUB     32768   // 0.5
    802 
    803     #define CVR     32768   // 0.5
    804     #define CVG    -27439   // -0.41869
    805     #define CVB     -5329   // -0.08131
    806 
    807     #define CSHIFT  16
    808 #else      // 8bit - fast, slightly less precise
    809     #define CYR     77    // 0.299
    810     #define CYG     150    // 0.587
    811     #define CYB      29    // 0.114
    812 
    813     #define CUR     -43    // -0.16874
    814     #define CUG    -85    // -0.33126
    815     #define CUB     128    // 0.5
    816 
    817     #define CVR      128   // 0.5
    818     #define CVG     -107   // -0.41869
    819     #define CVB      -21   // -0.08131
    820 
    821     #define CSHIFT  8
    822 #endif
    823 
    824 static void rgb2yuv_32(uint8_t dst[], SkPMColor c) {
    825     int r = SkGetPackedR32(c);
    826     int g = SkGetPackedG32(c);
    827     int b = SkGetPackedB32(c);
    828 
    829     int  y = ( CYR*r + CYG*g + CYB*b ) >> CSHIFT;
    830     int  u = ( CUR*r + CUG*g + CUB*b ) >> CSHIFT;
    831     int  v = ( CVR*r + CVG*g + CVB*b ) >> CSHIFT;
    832 
    833     dst[0] = SkToU8(y);
    834     dst[1] = SkToU8(u + 128);
    835     dst[2] = SkToU8(v + 128);
    836 }
    837 
    838 static void rgb2yuv_4444(uint8_t dst[], U16CPU c) {
    839     int r = SkGetPackedR4444(c);
    840     int g = SkGetPackedG4444(c);
    841     int b = SkGetPackedB4444(c);
    842 
    843     int  y = ( CYR*r + CYG*g + CYB*b ) >> (CSHIFT - 4);
    844     int  u = ( CUR*r + CUG*g + CUB*b ) >> (CSHIFT - 4);
    845     int  v = ( CVR*r + CVG*g + CVB*b ) >> (CSHIFT - 4);
    846 
    847     dst[0] = SkToU8(y);
    848     dst[1] = SkToU8(u + 128);
    849     dst[2] = SkToU8(v + 128);
    850 }
    851 
    852 static void rgb2yuv_16(uint8_t dst[], U16CPU c) {
    853     int r = SkGetPackedR16(c);
    854     int g = SkGetPackedG16(c);
    855     int b = SkGetPackedB16(c);
    856 
    857     int  y = ( 2*CYR*r + CYG*g + 2*CYB*b ) >> (CSHIFT - 2);
    858     int  u = ( 2*CUR*r + CUG*g + 2*CUB*b ) >> (CSHIFT - 2);
    859     int  v = ( 2*CVR*r + CVG*g + 2*CVB*b ) >> (CSHIFT - 2);
    860 
    861     dst[0] = SkToU8(y);
    862     dst[1] = SkToU8(u + 128);
    863     dst[2] = SkToU8(v + 128);
    864 }
    865 
    866 ///////////////////////////////////////////////////////////////////////////////
    867 
    868 typedef void (*WriteScanline)(uint8_t* SK_RESTRICT dst,
    869                               const void* SK_RESTRICT src, int width,
    870                               const SkPMColor* SK_RESTRICT ctable);
    871 
    872 static void Write_32_YUV(uint8_t* SK_RESTRICT dst,
    873                          const void* SK_RESTRICT srcRow, int width,
    874                          const SkPMColor*) {
    875     const uint32_t* SK_RESTRICT src = (const uint32_t*)srcRow;
    876     while (--width >= 0) {
    877 #ifdef WE_CONVERT_TO_YUV
    878         rgb2yuv_32(dst, *src++);
    879 #else
    880         uint32_t c = *src++;
    881         dst[0] = SkGetPackedR32(c);
    882         dst[1] = SkGetPackedG32(c);
    883         dst[2] = SkGetPackedB32(c);
    884 #endif
    885         dst += 3;
    886     }
    887 }
    888 
    889 static void Write_4444_YUV(uint8_t* SK_RESTRICT dst,
    890                            const void* SK_RESTRICT srcRow, int width,
    891                            const SkPMColor*) {
    892     const SkPMColor16* SK_RESTRICT src = (const SkPMColor16*)srcRow;
    893     while (--width >= 0) {
    894 #ifdef WE_CONVERT_TO_YUV
    895         rgb2yuv_4444(dst, *src++);
    896 #else
    897         SkPMColor16 c = *src++;
    898         dst[0] = SkPacked4444ToR32(c);
    899         dst[1] = SkPacked4444ToG32(c);
    900         dst[2] = SkPacked4444ToB32(c);
    901 #endif
    902         dst += 3;
    903     }
    904 }
    905 
    906 static void Write_16_YUV(uint8_t* SK_RESTRICT dst,
    907                          const void* SK_RESTRICT srcRow, int width,
    908                          const SkPMColor*) {
    909     const uint16_t* SK_RESTRICT src = (const uint16_t*)srcRow;
    910     while (--width >= 0) {
    911 #ifdef WE_CONVERT_TO_YUV
    912         rgb2yuv_16(dst, *src++);
    913 #else
    914         uint16_t c = *src++;
    915         dst[0] = SkPacked16ToR32(c);
    916         dst[1] = SkPacked16ToG32(c);
    917         dst[2] = SkPacked16ToB32(c);
    918 #endif
    919         dst += 3;
    920     }
    921 }
    922 
    923 static void Write_Index_YUV(uint8_t* SK_RESTRICT dst,
    924                             const void* SK_RESTRICT srcRow, int width,
    925                             const SkPMColor* SK_RESTRICT ctable) {
    926     const uint8_t* SK_RESTRICT src = (const uint8_t*)srcRow;
    927     while (--width >= 0) {
    928 #ifdef WE_CONVERT_TO_YUV
    929         rgb2yuv_32(dst, ctable[*src++]);
    930 #else
    931         uint32_t c = ctable[*src++];
    932         dst[0] = SkGetPackedR32(c);
    933         dst[1] = SkGetPackedG32(c);
    934         dst[2] = SkGetPackedB32(c);
    935 #endif
    936         dst += 3;
    937     }
    938 }
    939 
    940 static WriteScanline ChooseWriter(const SkBitmap& bm) {
    941     switch (bm.config()) {
    942         case SkBitmap::kARGB_8888_Config:
    943             return Write_32_YUV;
    944         case SkBitmap::kRGB_565_Config:
    945             return Write_16_YUV;
    946         case SkBitmap::kARGB_4444_Config:
    947             return Write_4444_YUV;
    948         case SkBitmap::kIndex8_Config:
    949             return Write_Index_YUV;
    950         default:
    951             return NULL;
    952     }
    953 }
    954 
    955 class SkJPEGImageEncoder : public SkImageEncoder {
    956 protected:
    957     virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) {
    958 #ifdef TIME_ENCODE
    959         AutoTimeMillis atm("JPEG Encode");
    960 #endif
    961 
    962         const WriteScanline writer = ChooseWriter(bm);
    963         if (NULL == writer) {
    964             return false;
    965         }
    966 
    967         SkAutoLockPixels alp(bm);
    968         if (NULL == bm.getPixels()) {
    969             return false;
    970         }
    971 
    972         jpeg_compress_struct    cinfo;
    973         skjpeg_error_mgr        sk_err;
    974         skjpeg_destination_mgr  sk_wstream(stream);
    975 
    976         // allocate these before set call setjmp
    977         SkAutoMalloc    oneRow;
    978         SkAutoLockColors ctLocker;
    979 
    980         cinfo.err = jpeg_std_error(&sk_err);
    981         sk_err.error_exit = skjpeg_error_exit;
    982         if (setjmp(sk_err.fJmpBuf)) {
    983             return false;
    984         }
    985         jpeg_create_compress(&cinfo);
    986 
    987         cinfo.dest = &sk_wstream;
    988         cinfo.image_width = bm.width();
    989         cinfo.image_height = bm.height();
    990         cinfo.input_components = 3;
    991 #ifdef WE_CONVERT_TO_YUV
    992         cinfo.in_color_space = JCS_YCbCr;
    993 #else
    994         cinfo.in_color_space = JCS_RGB;
    995 #endif
    996         cinfo.input_gamma = 1;
    997 
    998         jpeg_set_defaults(&cinfo);
    999         jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
   1000         cinfo.dct_method = JDCT_IFAST;
   1001 
   1002         jpeg_start_compress(&cinfo, TRUE);
   1003 
   1004         const int       width = bm.width();
   1005         uint8_t*        oneRowP = (uint8_t*)oneRow.reset(width * 3);
   1006 
   1007         const SkPMColor* colors = ctLocker.lockColors(bm);
   1008         const void*      srcRow = bm.getPixels();
   1009 
   1010         while (cinfo.next_scanline < cinfo.image_height) {
   1011             JSAMPROW row_pointer[1];    /* pointer to JSAMPLE row[s] */
   1012 
   1013             writer(oneRowP, srcRow, width, colors);
   1014             row_pointer[0] = oneRowP;
   1015             (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
   1016             srcRow = (const void*)((const char*)srcRow + bm.rowBytes());
   1017         }
   1018 
   1019         jpeg_finish_compress(&cinfo);
   1020         jpeg_destroy_compress(&cinfo);
   1021 
   1022         return true;
   1023     }
   1024 };
   1025 
   1026 ///////////////////////////////////////////////////////////////////////////////
   1027 DEFINE_DECODER_CREATOR(JPEGImageDecoder);
   1028 DEFINE_ENCODER_CREATOR(JPEGImageEncoder);
   1029 ///////////////////////////////////////////////////////////////////////////////
   1030 
   1031 #include "SkTRegistry.h"
   1032 
   1033 static SkImageDecoder* sk_libjpeg_dfactory(SkStream* stream) {
   1034     static const unsigned char gHeader[] = { 0xFF, 0xD8, 0xFF };
   1035     static const size_t HEADER_SIZE = sizeof(gHeader);
   1036 
   1037     char buffer[HEADER_SIZE];
   1038     size_t len = stream->read(buffer, HEADER_SIZE);
   1039 
   1040     if (len != HEADER_SIZE) {
   1041         return NULL;   // can't read enough
   1042     }
   1043     if (memcmp(buffer, gHeader, HEADER_SIZE)) {
   1044         return NULL;
   1045     }
   1046     return SkNEW(SkJPEGImageDecoder);
   1047 }
   1048 
   1049 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) {
   1050     return (SkImageEncoder::kJPEG_Type == t) ? SkNEW(SkJPEGImageEncoder) : NULL;
   1051 }
   1052 
   1053 
   1054 static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(sk_libjpeg_dfactory);
   1055 static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(sk_libjpeg_efactory);
   1056