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