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 <memory>
10 #include <ostream>
11 
12 #include "base/notreached.h"
13 #include "third_party/skia/include/core/SkBitmap.h"
14 #include "third_party/skia/include/core/SkColorPriv.h"
15 #include "ui/gfx/codec/vector_wstream.h"
16 
17 extern "C" {
18 #if defined(USE_SYSTEM_LIBJPEG)
19 #include <jpeglib.h>
20 #elif defined(USE_LIBJPEG_TURBO)
21 #include "third_party/libjpeg_turbo/jpeglib.h"
22 #else
23 #include "third_party/libjpeg/jpeglib.h"
24 #endif
25 }
26 
27 namespace gfx {
28 
29 // Encoder/decoder shared stuff ------------------------------------------------
30 
31 namespace {
32 
33 // used to pass error info through the JPEG library
34 struct CoderErrorMgr {
35   jpeg_error_mgr pub;
36   jmp_buf setjmp_buffer;
37 };
38 
ErrorExit(jpeg_common_struct * cinfo)39 void ErrorExit(jpeg_common_struct* cinfo) {
40   CoderErrorMgr *err = reinterpret_cast<CoderErrorMgr*>(cinfo->err);
41 
42   // Return control to the setjmp point.
43   longjmp(err->setjmp_buffer, false);
44 }
45 
46 }  // namespace
47 
48 // Encoder ---------------------------------------------------------------------
49 
Encode(const SkPixmap & input,int quality,SkJpegEncoder::Downsample downsample,std::vector<unsigned char> * output)50 bool JPEGCodec::Encode(const SkPixmap& input,
51                        int quality,
52                        SkJpegEncoder::Downsample downsample,
53                        std::vector<unsigned char>* output) {
54   output->clear();
55   VectorWStream dst(output);
56 
57   SkJpegEncoder::Options options;
58   options.fQuality = quality;
59   options.fDownsample = downsample;
60   return SkJpegEncoder::Encode(&dst, input, options);
61 }
62 
Encode(const SkPixmap & input,int quality,std::vector<unsigned char> * output)63 bool JPEGCodec::Encode(const SkPixmap& input,
64                        int quality,
65                        std::vector<unsigned char>* output) {
66   return Encode(input, quality, SkJpegEncoder::Downsample::k420, output);
67 }
68 
Encode(const SkBitmap & src,int quality,std::vector<unsigned char> * output)69 bool JPEGCodec::Encode(const SkBitmap& src,
70                        int quality,
71                        std::vector<unsigned char>* output) {
72   SkPixmap pixmap;
73   if (!src.peekPixels(&pixmap)) {
74     return false;
75   }
76 
77   return JPEGCodec::Encode(pixmap, quality, output);
78 }
79 
80 // Decoder --------------------------------------------------------------------
81 
82 namespace {
83 
84 struct JpegDecoderState {
JpegDecoderStategfx::__anon9a8da3aa0211::JpegDecoderState85   JpegDecoderState(const unsigned char* in, size_t len)
86       : input_buffer(in), input_buffer_length(len) {
87   }
88 
89   const unsigned char* input_buffer;
90   size_t input_buffer_length;
91 };
92 
93 // Callback to initialize the source.
94 //
95 // From the JPEG library:
96 //  "Initialize source. This is called by jpeg_read_header() before any data is
97 //   actually read. May leave bytes_in_buffer set to 0 (in which case a
98 //   fill_input_buffer() call will occur immediately)."
InitSource(j_decompress_ptr cinfo)99 void InitSource(j_decompress_ptr cinfo) {
100   JpegDecoderState* state = static_cast<JpegDecoderState*>(cinfo->client_data);
101   cinfo->src->next_input_byte = state->input_buffer;
102   cinfo->src->bytes_in_buffer = state->input_buffer_length;
103 }
104 
105 // Callback to fill the buffer. Since our buffer already contains all the data,
106 // we should never need to provide more data. If libjpeg thinks it needs more
107 // data, our input is probably corrupt.
108 //
109 // From the JPEG library:
110 //  "This is called whenever bytes_in_buffer has reached zero and more data is
111 //   wanted. In typical applications, it should read fresh data into the buffer
112 //   (ignoring the current state of next_input_byte and bytes_in_buffer), reset
113 //   the pointer & count to the start of the buffer, and return TRUE indicating
114 //   that the buffer has been reloaded. It is not necessary to fill the buffer
115 //   entirely, only to obtain at least one more byte. bytes_in_buffer MUST be
116 //   set to a positive value if TRUE is returned. A FALSE return should only
117 //   be used when I/O suspension is desired."
FillInputBuffer(j_decompress_ptr cinfo)118 boolean FillInputBuffer(j_decompress_ptr cinfo) {
119   return false;
120 }
121 
122 // Skip data in the buffer. Since we have all the data at once, this operation
123 // is easy. It is not clear if this ever gets called because the JPEG library
124 // should be able to do the skip itself (it has all the data).
125 //
126 // From the JPEG library:
127 //  "Skip num_bytes worth of data. The buffer pointer and count should be
128 //   advanced over num_bytes input bytes, refilling the buffer as needed. This
129 //   is used to skip over a potentially large amount of uninteresting data
130 //   (such as an APPn marker). In some applications it may be possible to
131 //   optimize away the reading of the skipped data, but it's not clear that
132 //   being smart is worth much trouble; large skips are uncommon.
133 //   bytes_in_buffer may be zero on return. A zero or negative skip count
134 //   should be treated as a no-op."
SkipInputData(j_decompress_ptr cinfo,long num_bytes)135 void SkipInputData(j_decompress_ptr cinfo, long num_bytes) {
136   if (num_bytes > static_cast<long>(cinfo->src->bytes_in_buffer)) {
137     // Since all our data should be in the buffer, trying to skip beyond it
138     // means that there is some kind of error or corrupt input data. A 0 for
139     // bytes left means it will call FillInputBuffer which will then fail.
140     cinfo->src->next_input_byte += cinfo->src->bytes_in_buffer;
141     cinfo->src->bytes_in_buffer = 0;
142   } else if (num_bytes > 0) {
143     cinfo->src->bytes_in_buffer -= static_cast<size_t>(num_bytes);
144     cinfo->src->next_input_byte += num_bytes;
145   }
146 }
147 
148 // Our source doesn't need any cleanup, so this is a NOP.
149 //
150 // From the JPEG library:
151 //  "Terminate source --- called by jpeg_finish_decompress() after all data has
152 //   been read to clean up JPEG source manager. NOT called by jpeg_abort() or
153 //   jpeg_destroy()."
TermSource(j_decompress_ptr cinfo)154 void TermSource(j_decompress_ptr cinfo) {}
155 
156 // jpeg_decompress_struct Deleter.
157 struct JpegDecompressStructDeleter {
operator ()gfx::__anon9a8da3aa0211::JpegDecompressStructDeleter158   void operator()(jpeg_decompress_struct* ptr) {
159     jpeg_destroy_decompress(ptr);
160     delete ptr;
161   }
162 };
163 
164 }  // namespace
165 
Decode(const unsigned char * input,size_t input_size,ColorFormat format,std::vector<unsigned char> * output,int * w,int * h)166 bool JPEGCodec::Decode(const unsigned char* input, size_t input_size,
167                        ColorFormat format, std::vector<unsigned char>* output,
168                        int* w, int* h) {
169   std::unique_ptr<jpeg_decompress_struct, JpegDecompressStructDeleter> cinfo(
170       new jpeg_decompress_struct);
171   output->clear();
172 
173   // We set up the normal JPEG error routines, then override error_exit.
174   // This must be done before the call to jpeg_create_decompress.
175   CoderErrorMgr errmgr;
176   cinfo->err = jpeg_std_error(&errmgr.pub);
177   errmgr.pub.error_exit = ErrorExit;
178   // Establish the setjmp return context for ErrorExit to use.
179   if (setjmp(errmgr.setjmp_buffer)) {
180     // If we get here, the JPEG code has signaled an error.
181     // Release |cinfo| by hand to avoid use-after-free of |errmgr|.
182     cinfo.reset();
183     return false;
184   }
185 
186   // The destroyer will destroy() cinfo on exit.  We don't want to set the
187   // destroyer's object until cinfo is initialized.
188   jpeg_create_decompress(cinfo.get());
189 
190   // set up the source manager
191   jpeg_source_mgr srcmgr;
192   srcmgr.init_source = InitSource;
193   srcmgr.fill_input_buffer = FillInputBuffer;
194   srcmgr.skip_input_data = SkipInputData;
195   srcmgr.resync_to_restart = jpeg_resync_to_restart;  // use default routine
196   srcmgr.term_source = TermSource;
197   cinfo->src = &srcmgr;
198 
199   JpegDecoderState state(input, input_size);
200   cinfo->client_data = &state;
201 
202   // fill the file metadata into our buffer
203   if (jpeg_read_header(cinfo.get(), true) != JPEG_HEADER_OK)
204     return false;
205 
206   // we want to always get RGB data out
207   switch (cinfo->jpeg_color_space) {
208     case JCS_GRAYSCALE:
209     case JCS_RGB:
210     case JCS_YCbCr:
211 #ifdef JCS_EXTENSIONS
212       // Choose an output colorspace and return if it is an unsupported one.
213       // Same as JPEGCodec::Encode(), libjpeg-turbo supports all input formats
214       // used by Chromium (i.e. RGBA and BGRA) and we just map the input
215       // parameters to a colorspace.
216       if (format == FORMAT_RGBA ||
217           (format == FORMAT_SkBitmap && SK_R32_SHIFT == 0)) {
218         cinfo->out_color_space = JCS_EXT_RGBX;
219         cinfo->output_components = 4;
220       } else if (format == FORMAT_BGRA ||
221                  (format == FORMAT_SkBitmap && SK_B32_SHIFT == 0)) {
222         cinfo->out_color_space = JCS_EXT_BGRX;
223         cinfo->output_components = 4;
224       } else {
225         NOTREACHED() << "Invalid pixel format";
226         return false;
227       }
228 #else
229       cinfo.out_color_space = JCS_RGB;
230 #endif
231       break;
232     case JCS_CMYK:
233     case JCS_YCCK:
234     default:
235       // Mozilla errors out on these color spaces, so I presume that the jpeg
236       // library can't do automatic color space conversion for them. We don't
237       // care about these anyway.
238       return false;
239   }
240 
241   jpeg_calc_output_dimensions(cinfo.get());
242   *w = cinfo->output_width;
243   *h = cinfo->output_height;
244 
245   jpeg_start_decompress(cinfo.get());
246 
247   // FIXME(brettw) we may want to allow the capability for callers to request
248   // how to align row lengths as we do for the compressor.
249   int row_read_stride = cinfo->output_width * cinfo->output_components;
250 
251   // Create memory for a decoded image and write decoded lines to the memory
252   // without conversions same as JPEGCodec::Encode().
253   int row_write_stride = row_read_stride;
254   output->resize(row_write_stride * cinfo->output_height);
255 
256   for (int row = 0; row < static_cast<int>(cinfo->output_height); row++) {
257     unsigned char* rowptr = &(*output)[row * row_write_stride];
258     if (!jpeg_read_scanlines(cinfo.get(), &rowptr, 1))
259       return false;
260   }
261 
262   jpeg_finish_decompress(cinfo.get());
263   return true;
264 }
265 
266 // static
Decode(const unsigned char * input,size_t input_size)267 std::unique_ptr<SkBitmap> JPEGCodec::Decode(const unsigned char* input,
268                                             size_t input_size) {
269   int w, h;
270   std::vector<unsigned char> data_vector;
271   if (!Decode(input, input_size, FORMAT_SkBitmap, &data_vector, &w, &h))
272     return nullptr;
273 
274   // Skia only handles 32 bit images.
275   int data_length = w * h * 4;
276 
277   std::unique_ptr<SkBitmap> bitmap(new SkBitmap());
278   bitmap->allocN32Pixels(w, h);
279   memcpy(bitmap->getAddr32(0, 0), &data_vector[0], data_length);
280 
281   return bitmap;
282 }
283 
284 }  // namespace gfx
285