Home | History | Annotate | Download | only in codec
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "ui/gfx/codec/jpeg_codec.h"
      6 
      7 #include <setjmp.h>
      8 
      9 #include "base/logging.h"
     10 #include "base/memory/scoped_ptr.h"
     11 #include "third_party/skia/include/core/SkBitmap.h"
     12 #include "third_party/skia/include/core/SkColorPriv.h"
     13 
     14 extern "C" {
     15 #if defined(USE_SYSTEM_LIBJPEG)
     16 #include <jpeglib.h>
     17 #elif defined(USE_LIBJPEG_TURBO)
     18 #include "third_party/libjpeg_turbo/jpeglib.h"
     19 #else
     20 #include "third_party/libjpeg/jpeglib.h"
     21 #endif
     22 }
     23 
     24 namespace gfx {
     25 
     26 // Encoder/decoder shared stuff ------------------------------------------------
     27 
     28 namespace {
     29 
     30 // used to pass error info through the JPEG library
     31 struct CoderErrorMgr {
     32   jpeg_error_mgr pub;
     33   jmp_buf setjmp_buffer;
     34 };
     35 
     36 void ErrorExit(jpeg_common_struct* cinfo) {
     37   CoderErrorMgr *err = reinterpret_cast<CoderErrorMgr*>(cinfo->err);
     38 
     39   // Return control to the setjmp point.
     40   longjmp(err->setjmp_buffer, false);
     41 }
     42 
     43 }  // namespace
     44 
     45 // This method helps identify at run time which library chromium is using.
     46 JPEGCodec::LibraryVariant JPEGCodec::JpegLibraryVariant() {
     47 #if defined(USE_SYSTEM_LIBJPEG)
     48   return SYSTEM_LIBJPEG;
     49 #elif defined(USE_LIBJPEG_TURBO)
     50   return LIBJPEG_TURBO;
     51 #else
     52   return IJG_LIBJPEG;
     53 #endif
     54 }
     55 
     56 // Encoder ---------------------------------------------------------------------
     57 //
     58 // This code is based on nsJPEGEncoder from Mozilla.
     59 // Copyright 2005 Google Inc. (Brett Wilson, contributor)
     60 
     61 namespace {
     62 
     63 // Initial size for the output buffer in the JpegEncoderState below.
     64 static const int initial_output_buffer_size = 8192;
     65 
     66 struct JpegEncoderState {
     67   explicit JpegEncoderState(std::vector<unsigned char>* o)
     68       : out(o),
     69         image_buffer_used(0) {
     70   }
     71 
     72   // Output buffer, of which 'image_buffer_used' bytes are actually used (this
     73   // will often be less than the actual size of the vector because we size it
     74   // so that libjpeg can write directly into it.
     75   std::vector<unsigned char>* out;
     76 
     77   // Number of bytes in the 'out' buffer that are actually used (see above).
     78   size_t image_buffer_used;
     79 };
     80 
     81 // Initializes the JpegEncoderState for encoding, and tells libjpeg about where
     82 // the output buffer is.
     83 //
     84 // From the JPEG library:
     85 //  "Initialize destination. This is called by jpeg_start_compress() before
     86 //   any data is actually written. It must initialize next_output_byte and
     87 //   free_in_buffer. free_in_buffer must be initialized to a positive value."
     88 void InitDestination(jpeg_compress_struct* cinfo) {
     89   JpegEncoderState* state = static_cast<JpegEncoderState*>(cinfo->client_data);
     90   DCHECK(state->image_buffer_used == 0) << "initializing after use";
     91 
     92   state->out->resize(initial_output_buffer_size);
     93   state->image_buffer_used = 0;
     94 
     95   cinfo->dest->next_output_byte = &(*state->out)[0];
     96   cinfo->dest->free_in_buffer = initial_output_buffer_size;
     97 }
     98 
     99 // Resize the buffer that we give to libjpeg and update our and its state.
    100 //
    101 // From the JPEG library:
    102 //  "Callback used by libjpeg whenever the buffer has filled (free_in_buffer
    103 //   reaches zero). In typical applications, it should write out the *entire*
    104 //   buffer (use the saved start address and buffer length; ignore the current
    105 //   state of next_output_byte and free_in_buffer). Then reset the pointer &
    106 //   count to the start of the buffer, and return TRUE indicating that the
    107 //   buffer has been dumped. free_in_buffer must be set to a positive value
    108 //   when TRUE is returned. A FALSE return should only be used when I/O
    109 //   suspension is desired (this operating mode is discussed in the next
    110 //   section)."
    111 boolean EmptyOutputBuffer(jpeg_compress_struct* cinfo) {
    112   JpegEncoderState* state = static_cast<JpegEncoderState*>(cinfo->client_data);
    113 
    114   // note the new size, the buffer is full
    115   state->image_buffer_used = state->out->size();
    116 
    117   // expand buffer, just double size each time
    118   state->out->resize(state->out->size() * 2);
    119 
    120   // tell libjpeg where to write the next data
    121   cinfo->dest->next_output_byte = &(*state->out)[state->image_buffer_used];
    122   cinfo->dest->free_in_buffer = state->out->size() - state->image_buffer_used;
    123   return 1;
    124 }
    125 
    126 // Cleans up the JpegEncoderState to prepare for returning in the final form.
    127 //
    128 // From the JPEG library:
    129 //  "Terminate destination --- called by jpeg_finish_compress() after all data
    130 //   has been written. In most applications, this must flush any data
    131 //   remaining in the buffer. Use either next_output_byte or free_in_buffer to
    132 //   determine how much data is in the buffer."
    133 void TermDestination(jpeg_compress_struct* cinfo) {
    134   JpegEncoderState* state = static_cast<JpegEncoderState*>(cinfo->client_data);
    135   DCHECK(state->out->size() >= state->image_buffer_used);
    136 
    137   // update the used byte based on the next byte libjpeg would write to
    138   state->image_buffer_used = cinfo->dest->next_output_byte - &(*state->out)[0];
    139   DCHECK(state->image_buffer_used < state->out->size()) <<
    140     "JPEG library busted, got a bad image buffer size";
    141 
    142   // update our buffer so that it exactly encompases the desired data
    143   state->out->resize(state->image_buffer_used);
    144 }
    145 
    146 #if !defined(JCS_EXTENSIONS)
    147 // Converts RGBA to RGB (removing the alpha values) to prepare to send data to
    148 // libjpeg. This converts one row of data in rgba with the given width in
    149 // pixels the the given rgb destination buffer (which should have enough space
    150 // reserved for the final data).
    151 void StripAlpha(const unsigned char* rgba, int pixel_width, unsigned char* rgb)
    152 {
    153   for (int x = 0; x < pixel_width; x++) {
    154     const unsigned char* pixel_in = &rgba[x * 4];
    155     unsigned char* pixel_out = &rgb[x * 3];
    156     pixel_out[0] = pixel_in[0];
    157     pixel_out[1] = pixel_in[1];
    158     pixel_out[2] = pixel_in[2];
    159   }
    160 }
    161 
    162 // Converts BGRA to RGB by reordering the color components and dropping the
    163 // alpha. This converts  one row of data in rgba with the given width in
    164 // pixels the the given rgb destination buffer (which should have enough space
    165 // reserved for the final data).
    166 void BGRAtoRGB(const unsigned char* bgra, int pixel_width, unsigned char* rgb)
    167 {
    168   for (int x = 0; x < pixel_width; x++) {
    169     const unsigned char* pixel_in = &bgra[x * 4];
    170     unsigned char* pixel_out = &rgb[x * 3];
    171     pixel_out[0] = pixel_in[2];
    172     pixel_out[1] = pixel_in[1];
    173     pixel_out[2] = pixel_in[0];
    174   }
    175 }
    176 #endif  // !defined(JCS_EXTENSIONS)
    177 
    178 // This class destroys the given jpeg_compress object when it goes out of
    179 // scope. It simplifies the error handling in Encode (and even applies to the
    180 // success case).
    181 class CompressDestroyer {
    182  public:
    183   CompressDestroyer() : cinfo_(NULL) {
    184   }
    185   ~CompressDestroyer() {
    186     DestroyManagedObject();
    187   }
    188   void SetManagedObject(jpeg_compress_struct* ci) {
    189     DestroyManagedObject();
    190     cinfo_ = ci;
    191   }
    192   void DestroyManagedObject() {
    193     if (cinfo_) {
    194       jpeg_destroy_compress(cinfo_);
    195       cinfo_ = NULL;
    196     }
    197   }
    198  private:
    199   jpeg_compress_struct* cinfo_;
    200 };
    201 
    202 }  // namespace
    203 
    204 bool JPEGCodec::Encode(const unsigned char* input, ColorFormat format,
    205                        int w, int h, int row_byte_width,
    206                        int quality, std::vector<unsigned char>* output) {
    207   jpeg_compress_struct cinfo;
    208   CompressDestroyer destroyer;
    209   destroyer.SetManagedObject(&cinfo);
    210   output->clear();
    211 #if !defined(JCS_EXTENSIONS)
    212   unsigned char* row_buffer = NULL;
    213 #endif
    214 
    215   // We set up the normal JPEG error routines, then override error_exit.
    216   // This must be done before the call to create_compress.
    217   CoderErrorMgr errmgr;
    218   cinfo.err = jpeg_std_error(&errmgr.pub);
    219   errmgr.pub.error_exit = ErrorExit;
    220 
    221   // Establish the setjmp return context for ErrorExit to use.
    222   if (setjmp(errmgr.setjmp_buffer)) {
    223     // If we get here, the JPEG code has signaled an error.
    224     // MSDN notes: "if you intend your code to be portable, do not rely on
    225     // correct destruction of frame-based objects when executing a nonlocal
    226     // goto using a call to longjmp."  So we delete the CompressDestroyer's
    227     // object manually instead.
    228     destroyer.DestroyManagedObject();
    229 #if !defined(JCS_EXTENSIONS)
    230     delete[] row_buffer;
    231 #endif
    232     return false;
    233   }
    234 
    235   // The destroyer will destroy() cinfo on exit.
    236   jpeg_create_compress(&cinfo);
    237 
    238   cinfo.image_width = w;
    239   cinfo.image_height = h;
    240   cinfo.input_components = 3;
    241 #ifdef JCS_EXTENSIONS
    242   // Choose an input colorspace and return if it is an unsupported one. Since
    243   // libjpeg-turbo supports all input formats used by Chromium (i.e. RGB, RGBA,
    244   // and BGRA), we just map the input parameters to a colorspace used by
    245   // libjpeg-turbo.
    246   if (format == FORMAT_RGB) {
    247     cinfo.input_components = 3;
    248     cinfo.in_color_space = JCS_RGB;
    249   } else if (format == FORMAT_RGBA ||
    250              (format == FORMAT_SkBitmap && SK_R32_SHIFT == 0)) {
    251     cinfo.input_components = 4;
    252     cinfo.in_color_space = JCS_EXT_RGBX;
    253   } else if (format == FORMAT_BGRA ||
    254              (format == FORMAT_SkBitmap && SK_B32_SHIFT == 0)) {
    255     cinfo.input_components = 4;
    256     cinfo.in_color_space = JCS_EXT_BGRX;
    257   } else {
    258     // We can exit this function without calling jpeg_destroy_compress() because
    259     // CompressDestroyer automaticaly calls it.
    260     NOTREACHED() << "Invalid pixel format";
    261     return false;
    262   }
    263 #else
    264   cinfo.in_color_space = JCS_RGB;
    265 #endif
    266   cinfo.data_precision = 8;
    267 
    268   jpeg_set_defaults(&cinfo);
    269   jpeg_set_quality(&cinfo, quality, 1);  // quality here is 0-100
    270 
    271   // set up the destination manager
    272   jpeg_destination_mgr destmgr;
    273   destmgr.init_destination = InitDestination;
    274   destmgr.empty_output_buffer = EmptyOutputBuffer;
    275   destmgr.term_destination = TermDestination;
    276   cinfo.dest = &destmgr;
    277 
    278   JpegEncoderState state(output);
    279   cinfo.client_data = &state;
    280 
    281   jpeg_start_compress(&cinfo, 1);
    282 
    283   // feed it the rows, doing necessary conversions for the color format
    284 #ifdef JCS_EXTENSIONS
    285   // This function already returns when the input format is not supported by
    286   // libjpeg-turbo and needs conversion. Therefore, we just encode lines without
    287   // conversions.
    288   while (cinfo.next_scanline < cinfo.image_height) {
    289     const unsigned char* row = &input[cinfo.next_scanline * row_byte_width];
    290     jpeg_write_scanlines(&cinfo, const_cast<unsigned char**>(&row), 1);
    291   }
    292 #else
    293   if (format == FORMAT_RGB) {
    294     // no conversion necessary
    295     while (cinfo.next_scanline < cinfo.image_height) {
    296       const unsigned char* row = &input[cinfo.next_scanline * row_byte_width];
    297       jpeg_write_scanlines(&cinfo, const_cast<unsigned char**>(&row), 1);
    298     }
    299   } else {
    300     // get the correct format converter
    301     void (*converter)(const unsigned char* in, int w, unsigned char* rgb);
    302     if (format == FORMAT_RGBA ||
    303         (format == FORMAT_SkBitmap && SK_R32_SHIFT == 0)) {
    304       converter = StripAlpha;
    305     } else if (format == FORMAT_BGRA ||
    306                (format == FORMAT_SkBitmap && SK_B32_SHIFT == 0)) {
    307       converter = BGRAtoRGB;
    308     } else {
    309       NOTREACHED() << "Invalid pixel format";
    310       return false;
    311     }
    312 
    313     // output row after converting
    314     row_buffer = new unsigned char[w * 3];
    315 
    316     while (cinfo.next_scanline < cinfo.image_height) {
    317       converter(&input[cinfo.next_scanline * row_byte_width], w, row_buffer);
    318       jpeg_write_scanlines(&cinfo, &row_buffer, 1);
    319     }
    320     delete[] row_buffer;
    321   }
    322 #endif
    323 
    324   jpeg_finish_compress(&cinfo);
    325   return true;
    326 }
    327 
    328 // Decoder --------------------------------------------------------------------
    329 
    330 namespace {
    331 
    332 struct JpegDecoderState {
    333   JpegDecoderState(const unsigned char* in, size_t len)
    334       : input_buffer(in), input_buffer_length(len) {
    335   }
    336 
    337   const unsigned char* input_buffer;
    338   size_t input_buffer_length;
    339 };
    340 
    341 // Callback to initialize the source.
    342 //
    343 // From the JPEG library:
    344 //  "Initialize source. This is called by jpeg_read_header() before any data is
    345 //   actually read. May leave bytes_in_buffer set to 0 (in which case a
    346 //   fill_input_buffer() call will occur immediately)."
    347 void InitSource(j_decompress_ptr cinfo) {
    348   JpegDecoderState* state = static_cast<JpegDecoderState*>(cinfo->client_data);
    349   cinfo->src->next_input_byte = state->input_buffer;
    350   cinfo->src->bytes_in_buffer = state->input_buffer_length;
    351 }
    352 
    353 // Callback to fill the buffer. Since our buffer already contains all the data,
    354 // we should never need to provide more data. If libjpeg thinks it needs more
    355 // data, our input is probably corrupt.
    356 //
    357 // From the JPEG library:
    358 //  "This is called whenever bytes_in_buffer has reached zero and more data is
    359 //   wanted. In typical applications, it should read fresh data into the buffer
    360 //   (ignoring the current state of next_input_byte and bytes_in_buffer), reset
    361 //   the pointer & count to the start of the buffer, and return TRUE indicating
    362 //   that the buffer has been reloaded. It is not necessary to fill the buffer
    363 //   entirely, only to obtain at least one more byte. bytes_in_buffer MUST be
    364 //   set to a positive value if TRUE is returned. A FALSE return should only
    365 //   be used when I/O suspension is desired."
    366 boolean FillInputBuffer(j_decompress_ptr cinfo) {
    367   return false;
    368 }
    369 
    370 // Skip data in the buffer. Since we have all the data at once, this operation
    371 // is easy. It is not clear if this ever gets called because the JPEG library
    372 // should be able to do the skip itself (it has all the data).
    373 //
    374 // From the JPEG library:
    375 //  "Skip num_bytes worth of data. The buffer pointer and count should be
    376 //   advanced over num_bytes input bytes, refilling the buffer as needed. This
    377 //   is used to skip over a potentially large amount of uninteresting data
    378 //   (such as an APPn marker). In some applications it may be possible to
    379 //   optimize away the reading of the skipped data, but it's not clear that
    380 //   being smart is worth much trouble; large skips are uncommon.
    381 //   bytes_in_buffer may be zero on return. A zero or negative skip count
    382 //   should be treated as a no-op."
    383 void SkipInputData(j_decompress_ptr cinfo, long num_bytes) {
    384   if (num_bytes > static_cast<long>(cinfo->src->bytes_in_buffer)) {
    385     // Since all our data should be in the buffer, trying to skip beyond it
    386     // means that there is some kind of error or corrupt input data. A 0 for
    387     // bytes left means it will call FillInputBuffer which will then fail.
    388     cinfo->src->next_input_byte += cinfo->src->bytes_in_buffer;
    389     cinfo->src->bytes_in_buffer = 0;
    390   } else if (num_bytes > 0) {
    391     cinfo->src->bytes_in_buffer -= static_cast<size_t>(num_bytes);
    392     cinfo->src->next_input_byte += num_bytes;
    393   }
    394 }
    395 
    396 // Our source doesn't need any cleanup, so this is a NOP.
    397 //
    398 // From the JPEG library:
    399 //  "Terminate source --- called by jpeg_finish_decompress() after all data has
    400 //   been read to clean up JPEG source manager. NOT called by jpeg_abort() or
    401 //   jpeg_destroy()."
    402 void TermSource(j_decompress_ptr cinfo) {
    403 }
    404 
    405 #if !defined(JCS_EXTENSIONS)
    406 // Converts one row of rgb data to rgba data by adding a fully-opaque alpha
    407 // value.
    408 void AddAlpha(const unsigned char* rgb, int pixel_width, unsigned char* rgba) {
    409   for (int x = 0; x < pixel_width; x++) {
    410     const unsigned char* pixel_in = &rgb[x * 3];
    411     unsigned char* pixel_out = &rgba[x * 4];
    412     pixel_out[0] = pixel_in[0];
    413     pixel_out[1] = pixel_in[1];
    414     pixel_out[2] = pixel_in[2];
    415     pixel_out[3] = 0xff;
    416   }
    417 }
    418 
    419 // Converts one row of RGB data to BGRA by reordering the color components and
    420 // adding alpha values of 0xff.
    421 void RGBtoBGRA(const unsigned char* bgra, int pixel_width, unsigned char* rgb)
    422 {
    423   for (int x = 0; x < pixel_width; x++) {
    424     const unsigned char* pixel_in = &bgra[x * 3];
    425     unsigned char* pixel_out = &rgb[x * 4];
    426     pixel_out[0] = pixel_in[2];
    427     pixel_out[1] = pixel_in[1];
    428     pixel_out[2] = pixel_in[0];
    429     pixel_out[3] = 0xff;
    430   }
    431 }
    432 #endif  // !defined(JCS_EXTENSIONS)
    433 
    434 // This class destroys the given jpeg_decompress object when it goes out of
    435 // scope. It simplifies the error handling in Decode (and even applies to the
    436 // success case).
    437 class DecompressDestroyer {
    438  public:
    439   DecompressDestroyer() : cinfo_(NULL) {
    440   }
    441   ~DecompressDestroyer() {
    442     DestroyManagedObject();
    443   }
    444   void SetManagedObject(jpeg_decompress_struct* ci) {
    445     DestroyManagedObject();
    446     cinfo_ = ci;
    447   }
    448   void DestroyManagedObject() {
    449     if (cinfo_) {
    450       jpeg_destroy_decompress(cinfo_);
    451       cinfo_ = NULL;
    452     }
    453   }
    454  private:
    455   jpeg_decompress_struct* cinfo_;
    456 };
    457 
    458 }  // namespace
    459 
    460 bool JPEGCodec::Decode(const unsigned char* input, size_t input_size,
    461                        ColorFormat format, std::vector<unsigned char>* output,
    462                        int* w, int* h) {
    463   jpeg_decompress_struct cinfo;
    464   DecompressDestroyer destroyer;
    465   destroyer.SetManagedObject(&cinfo);
    466   output->clear();
    467 
    468   // We set up the normal JPEG error routines, then override error_exit.
    469   // This must be done before the call to create_decompress.
    470   CoderErrorMgr errmgr;
    471   cinfo.err = jpeg_std_error(&errmgr.pub);
    472   errmgr.pub.error_exit = ErrorExit;
    473   // Establish the setjmp return context for ErrorExit to use.
    474   if (setjmp(errmgr.setjmp_buffer)) {
    475     // If we get here, the JPEG code has signaled an error.
    476     // See note in JPEGCodec::Encode() for why we need to destroy the cinfo
    477     // manually here.
    478     destroyer.DestroyManagedObject();
    479     return false;
    480   }
    481 
    482   // The destroyer will destroy() cinfo on exit.  We don't want to set the
    483   // destroyer's object until cinfo is initialized.
    484   jpeg_create_decompress(&cinfo);
    485 
    486   // set up the source manager
    487   jpeg_source_mgr srcmgr;
    488   srcmgr.init_source = InitSource;
    489   srcmgr.fill_input_buffer = FillInputBuffer;
    490   srcmgr.skip_input_data = SkipInputData;
    491   srcmgr.resync_to_restart = jpeg_resync_to_restart;  // use default routine
    492   srcmgr.term_source = TermSource;
    493   cinfo.src = &srcmgr;
    494 
    495   JpegDecoderState state(input, input_size);
    496   cinfo.client_data = &state;
    497 
    498   // fill the file metadata into our buffer
    499   if (jpeg_read_header(&cinfo, true) != JPEG_HEADER_OK)
    500     return false;
    501 
    502   // we want to always get RGB data out
    503   switch (cinfo.jpeg_color_space) {
    504     case JCS_GRAYSCALE:
    505     case JCS_RGB:
    506     case JCS_YCbCr:
    507 #ifdef JCS_EXTENSIONS
    508       // Choose an output colorspace and return if it is an unsupported one.
    509       // Same as JPEGCodec::Encode(), libjpeg-turbo supports all input formats
    510       // used by Chromium (i.e. RGB, RGBA, and BGRA) and we just map the input
    511       // parameters to a colorspace.
    512       if (format == FORMAT_RGB) {
    513         cinfo.out_color_space = JCS_RGB;
    514         cinfo.output_components = 3;
    515       } else if (format == FORMAT_RGBA ||
    516                  (format == FORMAT_SkBitmap && SK_R32_SHIFT == 0)) {
    517         cinfo.out_color_space = JCS_EXT_RGBX;
    518         cinfo.output_components = 4;
    519       } else if (format == FORMAT_BGRA ||
    520                  (format == FORMAT_SkBitmap && SK_B32_SHIFT == 0)) {
    521         cinfo.out_color_space = JCS_EXT_BGRX;
    522         cinfo.output_components = 4;
    523       } else {
    524         // We can exit this function without calling jpeg_destroy_decompress()
    525         // because DecompressDestroyer automaticaly calls it.
    526         NOTREACHED() << "Invalid pixel format";
    527         return false;
    528       }
    529 #else
    530       cinfo.out_color_space = JCS_RGB;
    531 #endif
    532       break;
    533     case JCS_CMYK:
    534     case JCS_YCCK:
    535     default:
    536       // Mozilla errors out on these color spaces, so I presume that the jpeg
    537       // library can't do automatic color space conversion for them. We don't
    538       // care about these anyway.
    539       return false;
    540   }
    541 #ifndef JCS_EXTENSIONS
    542   cinfo.output_components = 3;
    543 #endif
    544 
    545   jpeg_calc_output_dimensions(&cinfo);
    546   *w = cinfo.output_width;
    547   *h = cinfo.output_height;
    548 
    549   jpeg_start_decompress(&cinfo);
    550 
    551   // FIXME(brettw) we may want to allow the capability for callers to request
    552   // how to align row lengths as we do for the compressor.
    553   int row_read_stride = cinfo.output_width * cinfo.output_components;
    554 
    555 #ifdef JCS_EXTENSIONS
    556   // Create memory for a decoded image and write decoded lines to the memory
    557   // without conversions same as JPEGCodec::Encode().
    558   int row_write_stride = row_read_stride;
    559   output->resize(row_write_stride * cinfo.output_height);
    560 
    561   for (int row = 0; row < static_cast<int>(cinfo.output_height); row++) {
    562     unsigned char* rowptr = &(*output)[row * row_write_stride];
    563     if (!jpeg_read_scanlines(&cinfo, &rowptr, 1))
    564       return false;
    565   }
    566 #else
    567   if (format == FORMAT_RGB) {
    568     // easy case, row needs no conversion
    569     int row_write_stride = row_read_stride;
    570     output->resize(row_write_stride * cinfo.output_height);
    571 
    572     for (int row = 0; row < static_cast<int>(cinfo.output_height); row++) {
    573       unsigned char* rowptr = &(*output)[row * row_write_stride];
    574       if (!jpeg_read_scanlines(&cinfo, &rowptr, 1))
    575         return false;
    576     }
    577   } else {
    578     // Rows need conversion to output format: read into a temporary buffer and
    579     // expand to the final one. Performance: we could avoid the extra
    580     // allocation by doing the expansion in-place.
    581     int row_write_stride;
    582     void (*converter)(const unsigned char* rgb, int w, unsigned char* out);
    583     if (format == FORMAT_RGBA ||
    584         (format == FORMAT_SkBitmap && SK_R32_SHIFT == 0)) {
    585       row_write_stride = cinfo.output_width * 4;
    586       converter = AddAlpha;
    587     } else if (format == FORMAT_BGRA ||
    588                (format == FORMAT_SkBitmap && SK_B32_SHIFT == 0)) {
    589       row_write_stride = cinfo.output_width * 4;
    590       converter = RGBtoBGRA;
    591     } else {
    592       NOTREACHED() << "Invalid pixel format";
    593       jpeg_destroy_decompress(&cinfo);
    594       return false;
    595     }
    596 
    597     output->resize(row_write_stride * cinfo.output_height);
    598 
    599     scoped_ptr<unsigned char[]> row_data(new unsigned char[row_read_stride]);
    600     unsigned char* rowptr = row_data.get();
    601     for (int row = 0; row < static_cast<int>(cinfo.output_height); row++) {
    602       if (!jpeg_read_scanlines(&cinfo, &rowptr, 1))
    603         return false;
    604       converter(rowptr, *w, &(*output)[row * row_write_stride]);
    605     }
    606   }
    607 #endif
    608 
    609   jpeg_finish_decompress(&cinfo);
    610   jpeg_destroy_decompress(&cinfo);
    611   return true;
    612 }
    613 
    614 // static
    615 SkBitmap* JPEGCodec::Decode(const unsigned char* input, size_t input_size) {
    616   int w, h;
    617   std::vector<unsigned char> data_vector;
    618   if (!Decode(input, input_size, FORMAT_SkBitmap, &data_vector, &w, &h))
    619     return NULL;
    620 
    621   // Skia only handles 32 bit images.
    622   int data_length = w * h * 4;
    623 
    624   SkBitmap* bitmap = new SkBitmap();
    625   bitmap->setConfig(SkBitmap::kARGB_8888_Config, w, h);
    626   bitmap->allocPixels();
    627   memcpy(bitmap->getAddr32(0, 0), &data_vector[0], data_length);
    628 
    629   return bitmap;
    630 }
    631 
    632 }  // namespace gfx
    633