Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(34)

Side by Side Diff: ui/gfx/codec/jpeg_codec.cc

Issue 2924733002: Revert of Delete FORMAT_RGB and legacy libjpeg support from gfx::JpegCodec (Closed)
Patch Set: Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ui/gfx/codec/jpeg_codec.h ('k') | ui/gfx/codec/jpeg_codec_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/gfx/codec/jpeg_codec.h" 5 #include "ui/gfx/codec/jpeg_codec.h"
6 6
7 #include <setjmp.h> 7 #include <setjmp.h>
8 8
9 #include <memory> 9 #include <memory>
10 10
(...skipping 25 matching lines...) Expand all
36 36
37 void ErrorExit(jpeg_common_struct* cinfo) { 37 void ErrorExit(jpeg_common_struct* cinfo) {
38 CoderErrorMgr *err = reinterpret_cast<CoderErrorMgr*>(cinfo->err); 38 CoderErrorMgr *err = reinterpret_cast<CoderErrorMgr*>(cinfo->err);
39 39
40 // Return control to the setjmp point. 40 // Return control to the setjmp point.
41 longjmp(err->setjmp_buffer, false); 41 longjmp(err->setjmp_buffer, false);
42 } 42 }
43 43
44 } // namespace 44 } // namespace
45 45
46 // This method helps identify at run time which library chromium is using.
47 JPEGCodec::LibraryVariant JPEGCodec::JpegLibraryVariant() {
48 #if defined(USE_SYSTEM_LIBJPEG)
49 return SYSTEM_LIBJPEG;
50 #elif defined(USE_LIBJPEG_TURBO)
51 return LIBJPEG_TURBO;
52 #else
53 return IJG_LIBJPEG;
54 #endif
55 }
56
46 // Encoder --------------------------------------------------------------------- 57 // Encoder ---------------------------------------------------------------------
47 // 58 //
48 // This code is based on nsJPEGEncoder from Mozilla. 59 // This code is based on nsJPEGEncoder from Mozilla.
49 // Copyright 2005 Google Inc. (Brett Wilson, contributor) 60 // Copyright 2005 Google Inc. (Brett Wilson, contributor)
50 61
51 namespace { 62 namespace {
52 63
53 // Initial size for the output buffer in the JpegEncoderState below. 64 // Initial size for the output buffer in the JpegEncoderState below.
54 static const int initial_output_buffer_size = 8192; 65 static const int initial_output_buffer_size = 8192;
55 66
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 137
127 // update the used byte based on the next byte libjpeg would write to 138 // update the used byte based on the next byte libjpeg would write to
128 state->image_buffer_used = cinfo->dest->next_output_byte - &(*state->out)[0]; 139 state->image_buffer_used = cinfo->dest->next_output_byte - &(*state->out)[0];
129 DCHECK(state->image_buffer_used < state->out->size()) << 140 DCHECK(state->image_buffer_used < state->out->size()) <<
130 "JPEG library busted, got a bad image buffer size"; 141 "JPEG library busted, got a bad image buffer size";
131 142
132 // update our buffer so that it exactly encompases the desired data 143 // update our buffer so that it exactly encompases the desired data
133 state->out->resize(state->image_buffer_used); 144 state->out->resize(state->image_buffer_used);
134 } 145 }
135 146
147 #if !defined(JCS_EXTENSIONS)
148 // Converts RGBA to RGB (removing the alpha values) to prepare to send data to
149 // libjpeg. 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 StripAlpha(const unsigned char* rgba, int pixel_width, unsigned char* rgb)
153 {
154 for (int x = 0; x < pixel_width; x++)
155 memcpy(&rgb[x * 3], &rgba[x * 4], 3);
156 }
157
158 // Converts BGRA to RGB by reordering the color components and dropping the
159 // alpha. This converts one row of data in rgba with the given width in
160 // pixels the the given rgb destination buffer (which should have enough space
161 // reserved for the final data).
162 void BGRAtoRGB(const unsigned char* bgra, int pixel_width, unsigned char* rgb)
163 {
164 for (int x = 0; x < pixel_width; x++) {
165 const unsigned char* pixel_in = &bgra[x * 4];
166 unsigned char* pixel_out = &rgb[x * 3];
167 pixel_out[0] = pixel_in[2];
168 pixel_out[1] = pixel_in[1];
169 pixel_out[2] = pixel_in[0];
170 }
171 }
172 #endif // !defined(JCS_EXTENSIONS)
173
136 // This class destroys the given jpeg_compress object when it goes out of 174 // This class destroys the given jpeg_compress object when it goes out of
137 // scope. It simplifies the error handling in Encode (and even applies to the 175 // scope. It simplifies the error handling in Encode (and even applies to the
138 // success case). 176 // success case).
139 class CompressDestroyer { 177 class CompressDestroyer {
140 public: 178 public:
141 CompressDestroyer() : cinfo_(NULL) { 179 CompressDestroyer() : cinfo_(NULL) {
142 } 180 }
143 ~CompressDestroyer() { 181 ~CompressDestroyer() {
144 DestroyManagedObject(); 182 DestroyManagedObject();
145 } 183 }
(...skipping 13 matching lines...) Expand all
159 197
160 } // namespace 198 } // namespace
161 199
162 bool JPEGCodec::Encode(const unsigned char* input, ColorFormat format, 200 bool JPEGCodec::Encode(const unsigned char* input, ColorFormat format,
163 int w, int h, int row_byte_width, 201 int w, int h, int row_byte_width,
164 int quality, std::vector<unsigned char>* output) { 202 int quality, std::vector<unsigned char>* output) {
165 jpeg_compress_struct cinfo; 203 jpeg_compress_struct cinfo;
166 CompressDestroyer destroyer; 204 CompressDestroyer destroyer;
167 destroyer.SetManagedObject(&cinfo); 205 destroyer.SetManagedObject(&cinfo);
168 output->clear(); 206 output->clear();
207 #if !defined(JCS_EXTENSIONS)
208 unsigned char* row_buffer = NULL;
209 #endif
169 210
170 // We set up the normal JPEG error routines, then override error_exit. 211 // We set up the normal JPEG error routines, then override error_exit.
171 // This must be done before the call to create_compress. 212 // This must be done before the call to create_compress.
172 CoderErrorMgr errmgr; 213 CoderErrorMgr errmgr;
173 cinfo.err = jpeg_std_error(&errmgr.pub); 214 cinfo.err = jpeg_std_error(&errmgr.pub);
174 errmgr.pub.error_exit = ErrorExit; 215 errmgr.pub.error_exit = ErrorExit;
175 216
176 // Establish the setjmp return context for ErrorExit to use. 217 // Establish the setjmp return context for ErrorExit to use.
177 if (setjmp(errmgr.setjmp_buffer)) { 218 if (setjmp(errmgr.setjmp_buffer)) {
178 // If we get here, the JPEG code has signaled an error. 219 // If we get here, the JPEG code has signaled an error.
179 // MSDN notes: "if you intend your code to be portable, do not rely on 220 // MSDN notes: "if you intend your code to be portable, do not rely on
180 // correct destruction of frame-based objects when executing a nonlocal 221 // correct destruction of frame-based objects when executing a nonlocal
181 // goto using a call to longjmp." So we delete the CompressDestroyer's 222 // goto using a call to longjmp." So we delete the CompressDestroyer's
182 // object manually instead. 223 // object manually instead.
183 destroyer.DestroyManagedObject(); 224 destroyer.DestroyManagedObject();
225 #if !defined(JCS_EXTENSIONS)
226 delete[] row_buffer;
227 #endif
184 return false; 228 return false;
185 } 229 }
186 230
187 // The destroyer will destroy() cinfo on exit. 231 // The destroyer will destroy() cinfo on exit.
188 jpeg_create_compress(&cinfo); 232 jpeg_create_compress(&cinfo);
189 233
190 cinfo.image_width = w; 234 cinfo.image_width = w;
191 cinfo.image_height = h; 235 cinfo.image_height = h;
192 cinfo.input_components = 4; 236 cinfo.input_components = 3;
237 #ifdef JCS_EXTENSIONS
193 // Choose an input colorspace and return if it is an unsupported one. Since 238 // Choose an input colorspace and return if it is an unsupported one. Since
194 // libjpeg-turbo supports all input formats used by Chromium (i.e. RGB, RGBA, 239 // libjpeg-turbo supports all input formats used by Chromium (i.e. RGB, RGBA,
195 // and BGRA), we just map the input parameters to a colorspace used by 240 // and BGRA), we just map the input parameters to a colorspace used by
196 // libjpeg-turbo. 241 // libjpeg-turbo.
197 if (format == FORMAT_RGBA || 242 if (format == FORMAT_RGB) {
198 (format == FORMAT_SkBitmap && SK_R32_SHIFT == 0)) { 243 cinfo.input_components = 3;
244 cinfo.in_color_space = JCS_RGB;
245 } else if (format == FORMAT_RGBA ||
246 (format == FORMAT_SkBitmap && SK_R32_SHIFT == 0)) {
247 cinfo.input_components = 4;
199 cinfo.in_color_space = JCS_EXT_RGBX; 248 cinfo.in_color_space = JCS_EXT_RGBX;
200 } else if (format == FORMAT_BGRA || 249 } else if (format == FORMAT_BGRA ||
201 (format == FORMAT_SkBitmap && SK_B32_SHIFT == 0)) { 250 (format == FORMAT_SkBitmap && SK_B32_SHIFT == 0)) {
251 cinfo.input_components = 4;
202 cinfo.in_color_space = JCS_EXT_BGRX; 252 cinfo.in_color_space = JCS_EXT_BGRX;
203 } else { 253 } else {
204 // We can exit this function without calling jpeg_destroy_compress() because 254 // We can exit this function without calling jpeg_destroy_compress() because
205 // CompressDestroyer automaticaly calls it. 255 // CompressDestroyer automaticaly calls it.
206 NOTREACHED() << "Invalid pixel format"; 256 NOTREACHED() << "Invalid pixel format";
207 return false; 257 return false;
208 } 258 }
259 #else
260 cinfo.in_color_space = JCS_RGB;
261 #endif
209 cinfo.data_precision = 8; 262 cinfo.data_precision = 8;
210 263
211 jpeg_set_defaults(&cinfo); 264 jpeg_set_defaults(&cinfo);
212 jpeg_set_quality(&cinfo, quality, 1); // quality here is 0-100 265 jpeg_set_quality(&cinfo, quality, 1); // quality here is 0-100
213 266
214 // set up the destination manager 267 // set up the destination manager
215 jpeg_destination_mgr destmgr; 268 jpeg_destination_mgr destmgr;
216 destmgr.init_destination = InitDestination; 269 destmgr.init_destination = InitDestination;
217 destmgr.empty_output_buffer = EmptyOutputBuffer; 270 destmgr.empty_output_buffer = EmptyOutputBuffer;
218 destmgr.term_destination = TermDestination; 271 destmgr.term_destination = TermDestination;
219 cinfo.dest = &destmgr; 272 cinfo.dest = &destmgr;
220 273
221 JpegEncoderState state(output); 274 JpegEncoderState state(output);
222 cinfo.client_data = &state; 275 cinfo.client_data = &state;
223 276
224 jpeg_start_compress(&cinfo, 1); 277 jpeg_start_compress(&cinfo, 1);
225 278
226 // feed it the rows, doing necessary conversions for the color format 279 // feed it the rows, doing necessary conversions for the color format
280 #ifdef JCS_EXTENSIONS
227 // This function already returns when the input format is not supported by 281 // This function already returns when the input format is not supported by
228 // libjpeg-turbo and needs conversion. Therefore, we just encode lines without 282 // libjpeg-turbo and needs conversion. Therefore, we just encode lines without
229 // conversions. 283 // conversions.
230 while (cinfo.next_scanline < cinfo.image_height) { 284 while (cinfo.next_scanline < cinfo.image_height) {
231 const unsigned char* row = &input[cinfo.next_scanline * row_byte_width]; 285 const unsigned char* row = &input[cinfo.next_scanline * row_byte_width];
232 jpeg_write_scanlines(&cinfo, const_cast<unsigned char**>(&row), 1); 286 jpeg_write_scanlines(&cinfo, const_cast<unsigned char**>(&row), 1);
233 } 287 }
288 #else
289 if (format == FORMAT_RGB) {
290 // no conversion necessary
291 while (cinfo.next_scanline < cinfo.image_height) {
292 const unsigned char* row = &input[cinfo.next_scanline * row_byte_width];
293 jpeg_write_scanlines(&cinfo, const_cast<unsigned char**>(&row), 1);
294 }
295 } else {
296 // get the correct format converter
297 void (*converter)(const unsigned char* in, int w, unsigned char* rgb);
298 if (format == FORMAT_RGBA ||
299 (format == FORMAT_SkBitmap && SK_R32_SHIFT == 0)) {
300 converter = StripAlpha;
301 } else if (format == FORMAT_BGRA ||
302 (format == FORMAT_SkBitmap && SK_B32_SHIFT == 0)) {
303 converter = BGRAtoRGB;
304 } else {
305 NOTREACHED() << "Invalid pixel format";
306 return false;
307 }
308
309 // output row after converting
310 row_buffer = new unsigned char[w * 3];
311
312 while (cinfo.next_scanline < cinfo.image_height) {
313 converter(&input[cinfo.next_scanline * row_byte_width], w, row_buffer);
314 jpeg_write_scanlines(&cinfo, &row_buffer, 1);
315 }
316 delete[] row_buffer;
317 }
318 #endif
234 319
235 jpeg_finish_compress(&cinfo); 320 jpeg_finish_compress(&cinfo);
236 return true; 321 return true;
237 } 322 }
238 323
239 // Decoder -------------------------------------------------------------------- 324 // Decoder --------------------------------------------------------------------
240 325
241 namespace { 326 namespace {
242 327
243 struct JpegDecoderState { 328 struct JpegDecoderState {
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
306 391
307 // Our source doesn't need any cleanup, so this is a NOP. 392 // Our source doesn't need any cleanup, so this is a NOP.
308 // 393 //
309 // From the JPEG library: 394 // From the JPEG library:
310 // "Terminate source --- called by jpeg_finish_decompress() after all data has 395 // "Terminate source --- called by jpeg_finish_decompress() after all data has
311 // been read to clean up JPEG source manager. NOT called by jpeg_abort() or 396 // been read to clean up JPEG source manager. NOT called by jpeg_abort() or
312 // jpeg_destroy()." 397 // jpeg_destroy()."
313 void TermSource(j_decompress_ptr cinfo) { 398 void TermSource(j_decompress_ptr cinfo) {
314 } 399 }
315 400
401 #if !defined(JCS_EXTENSIONS)
402 // Converts one row of rgb data to rgba data by adding a fully-opaque alpha
403 // value.
404 void AddAlpha(const unsigned char* rgb, int pixel_width, unsigned char* rgba) {
405 for (int x = 0; x < pixel_width; x++) {
406 memcpy(&rgba[x * 4], &rgb[x * 3], 3);
407 rgba[x * 4 + 3] = 0xff;
408 }
409 }
410
411 // Converts one row of RGB data to BGRA by reordering the color components and
412 // adding alpha values of 0xff.
413 void RGBtoBGRA(const unsigned char* bgra, int pixel_width, unsigned char* rgb)
414 {
415 for (int x = 0; x < pixel_width; x++) {
416 const unsigned char* pixel_in = &bgra[x * 3];
417 unsigned char* pixel_out = &rgb[x * 4];
418 pixel_out[0] = pixel_in[2];
419 pixel_out[1] = pixel_in[1];
420 pixel_out[2] = pixel_in[0];
421 pixel_out[3] = 0xff;
422 }
423 }
424 #endif // !defined(JCS_EXTENSIONS)
425
316 // This class destroys the given jpeg_decompress object when it goes out of 426 // This class destroys the given jpeg_decompress object when it goes out of
317 // scope. It simplifies the error handling in Decode (and even applies to the 427 // scope. It simplifies the error handling in Decode (and even applies to the
318 // success case). 428 // success case).
319 class DecompressDestroyer { 429 class DecompressDestroyer {
320 public: 430 public:
321 DecompressDestroyer() : cinfo_(NULL) { 431 DecompressDestroyer() : cinfo_(NULL) {
322 } 432 }
323 ~DecompressDestroyer() { 433 ~DecompressDestroyer() {
324 DestroyManagedObject(); 434 DestroyManagedObject();
325 } 435 }
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
379 489
380 // fill the file metadata into our buffer 490 // fill the file metadata into our buffer
381 if (jpeg_read_header(&cinfo, true) != JPEG_HEADER_OK) 491 if (jpeg_read_header(&cinfo, true) != JPEG_HEADER_OK)
382 return false; 492 return false;
383 493
384 // we want to always get RGB data out 494 // we want to always get RGB data out
385 switch (cinfo.jpeg_color_space) { 495 switch (cinfo.jpeg_color_space) {
386 case JCS_GRAYSCALE: 496 case JCS_GRAYSCALE:
387 case JCS_RGB: 497 case JCS_RGB:
388 case JCS_YCbCr: 498 case JCS_YCbCr:
499 #ifdef JCS_EXTENSIONS
389 // Choose an output colorspace and return if it is an unsupported one. 500 // Choose an output colorspace and return if it is an unsupported one.
390 // Same as JPEGCodec::Encode(), libjpeg-turbo supports all input formats 501 // Same as JPEGCodec::Encode(), libjpeg-turbo supports all input formats
391 // used by Chromium (i.e. RGB, RGBA, and BGRA) and we just map the input 502 // used by Chromium (i.e. RGB, RGBA, and BGRA) and we just map the input
392 // parameters to a colorspace. 503 // parameters to a colorspace.
393 if (format == FORMAT_RGBA || 504 if (format == FORMAT_RGB) {
394 (format == FORMAT_SkBitmap && SK_R32_SHIFT == 0)) { 505 cinfo.out_color_space = JCS_RGB;
506 cinfo.output_components = 3;
507 } else if (format == FORMAT_RGBA ||
508 (format == FORMAT_SkBitmap && SK_R32_SHIFT == 0)) {
395 cinfo.out_color_space = JCS_EXT_RGBX; 509 cinfo.out_color_space = JCS_EXT_RGBX;
396 cinfo.output_components = 4; 510 cinfo.output_components = 4;
397 } else if (format == FORMAT_BGRA || 511 } else if (format == FORMAT_BGRA ||
398 (format == FORMAT_SkBitmap && SK_B32_SHIFT == 0)) { 512 (format == FORMAT_SkBitmap && SK_B32_SHIFT == 0)) {
399 cinfo.out_color_space = JCS_EXT_BGRX; 513 cinfo.out_color_space = JCS_EXT_BGRX;
400 cinfo.output_components = 4; 514 cinfo.output_components = 4;
401 } else { 515 } else {
402 // We can exit this function without calling jpeg_destroy_decompress() 516 // We can exit this function without calling jpeg_destroy_decompress()
403 // because DecompressDestroyer automaticaly calls it. 517 // because DecompressDestroyer automaticaly calls it.
404 NOTREACHED() << "Invalid pixel format"; 518 NOTREACHED() << "Invalid pixel format";
405 return false; 519 return false;
406 } 520 }
521 #else
522 cinfo.out_color_space = JCS_RGB;
523 #endif
407 break; 524 break;
408 case JCS_CMYK: 525 case JCS_CMYK:
409 case JCS_YCCK: 526 case JCS_YCCK:
410 default: 527 default:
411 // Mozilla errors out on these color spaces, so I presume that the jpeg 528 // Mozilla errors out on these color spaces, so I presume that the jpeg
412 // library can't do automatic color space conversion for them. We don't 529 // library can't do automatic color space conversion for them. We don't
413 // care about these anyway. 530 // care about these anyway.
414 return false; 531 return false;
415 } 532 }
533 #ifndef JCS_EXTENSIONS
534 cinfo.output_components = 3;
535 #endif
416 536
417 jpeg_calc_output_dimensions(&cinfo); 537 jpeg_calc_output_dimensions(&cinfo);
418 *w = cinfo.output_width; 538 *w = cinfo.output_width;
419 *h = cinfo.output_height; 539 *h = cinfo.output_height;
420 540
421 jpeg_start_decompress(&cinfo); 541 jpeg_start_decompress(&cinfo);
422 542
423 // FIXME(brettw) we may want to allow the capability for callers to request 543 // FIXME(brettw) we may want to allow the capability for callers to request
424 // how to align row lengths as we do for the compressor. 544 // how to align row lengths as we do for the compressor.
425 int row_read_stride = cinfo.output_width * cinfo.output_components; 545 int row_read_stride = cinfo.output_width * cinfo.output_components;
426 546
547 #ifdef JCS_EXTENSIONS
427 // Create memory for a decoded image and write decoded lines to the memory 548 // Create memory for a decoded image and write decoded lines to the memory
428 // without conversions same as JPEGCodec::Encode(). 549 // without conversions same as JPEGCodec::Encode().
429 int row_write_stride = row_read_stride; 550 int row_write_stride = row_read_stride;
430 output->resize(row_write_stride * cinfo.output_height); 551 output->resize(row_write_stride * cinfo.output_height);
431 552
432 for (int row = 0; row < static_cast<int>(cinfo.output_height); row++) { 553 for (int row = 0; row < static_cast<int>(cinfo.output_height); row++) {
433 unsigned char* rowptr = &(*output)[row * row_write_stride]; 554 unsigned char* rowptr = &(*output)[row * row_write_stride];
434 if (!jpeg_read_scanlines(&cinfo, &rowptr, 1)) 555 if (!jpeg_read_scanlines(&cinfo, &rowptr, 1))
435 return false; 556 return false;
436 } 557 }
558 #else
559 if (format == FORMAT_RGB) {
560 // easy case, row needs no conversion
561 int row_write_stride = row_read_stride;
562 output->resize(row_write_stride * cinfo.output_height);
563
564 for (int row = 0; row < static_cast<int>(cinfo.output_height); row++) {
565 unsigned char* rowptr = &(*output)[row * row_write_stride];
566 if (!jpeg_read_scanlines(&cinfo, &rowptr, 1))
567 return false;
568 }
569 } else {
570 // Rows need conversion to output format: read into a temporary buffer and
571 // expand to the final one. Performance: we could avoid the extra
572 // allocation by doing the expansion in-place.
573 int row_write_stride;
574 void (*converter)(const unsigned char* rgb, int w, unsigned char* out);
575 if (format == FORMAT_RGBA ||
576 (format == FORMAT_SkBitmap && SK_R32_SHIFT == 0)) {
577 row_write_stride = cinfo.output_width * 4;
578 converter = AddAlpha;
579 } else if (format == FORMAT_BGRA ||
580 (format == FORMAT_SkBitmap && SK_B32_SHIFT == 0)) {
581 row_write_stride = cinfo.output_width * 4;
582 converter = RGBtoBGRA;
583 } else {
584 NOTREACHED() << "Invalid pixel format";
585 jpeg_destroy_decompress(&cinfo);
586 return false;
587 }
588
589 output->resize(row_write_stride * cinfo.output_height);
590
591 std::unique_ptr<unsigned char[]> row_data(
592 new unsigned char[row_read_stride]);
593 unsigned char* rowptr = row_data.get();
594 for (int row = 0; row < static_cast<int>(cinfo.output_height); row++) {
595 if (!jpeg_read_scanlines(&cinfo, &rowptr, 1))
596 return false;
597 converter(rowptr, *w, &(*output)[row * row_write_stride]);
598 }
599 }
600 #endif
437 601
438 jpeg_finish_decompress(&cinfo); 602 jpeg_finish_decompress(&cinfo);
439 jpeg_destroy_decompress(&cinfo); 603 jpeg_destroy_decompress(&cinfo);
440 return true; 604 return true;
441 } 605 }
442 606
443 // static 607 // static
444 std::unique_ptr<SkBitmap> JPEGCodec::Decode(const unsigned char* input, 608 std::unique_ptr<SkBitmap> JPEGCodec::Decode(const unsigned char* input,
445 size_t input_size) { 609 size_t input_size) {
446 int w, h; 610 int w, h;
447 std::vector<unsigned char> data_vector; 611 std::vector<unsigned char> data_vector;
448 if (!Decode(input, input_size, FORMAT_SkBitmap, &data_vector, &w, &h)) 612 if (!Decode(input, input_size, FORMAT_SkBitmap, &data_vector, &w, &h))
449 return nullptr; 613 return nullptr;
450 614
451 // Skia only handles 32 bit images. 615 // Skia only handles 32 bit images.
452 int data_length = w * h * 4; 616 int data_length = w * h * 4;
453 617
454 std::unique_ptr<SkBitmap> bitmap(new SkBitmap()); 618 std::unique_ptr<SkBitmap> bitmap(new SkBitmap());
455 bitmap->allocN32Pixels(w, h); 619 bitmap->allocN32Pixels(w, h);
456 memcpy(bitmap->getAddr32(0, 0), &data_vector[0], data_length); 620 memcpy(bitmap->getAddr32(0, 0), &data_vector[0], data_length);
457 621
458 return bitmap; 622 return bitmap;
459 } 623 }
460 624
461 } // namespace gfx 625 } // namespace gfx
OLDNEW
« no previous file with comments | « ui/gfx/codec/jpeg_codec.h ('k') | ui/gfx/codec/jpeg_codec_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698