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

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

Issue 2920263002: Delete FORMAT_RGB and legacy libjpeg support from gfx::JpegCodec (Closed)
Patch Set: Fix PFQ chrome build 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
57 // Encoder --------------------------------------------------------------------- 46 // Encoder ---------------------------------------------------------------------
58 // 47 //
59 // This code is based on nsJPEGEncoder from Mozilla. 48 // This code is based on nsJPEGEncoder from Mozilla.
60 // Copyright 2005 Google Inc. (Brett Wilson, contributor) 49 // Copyright 2005 Google Inc. (Brett Wilson, contributor)
61 50
62 namespace { 51 namespace {
63 52
64 // Initial size for the output buffer in the JpegEncoderState below. 53 // Initial size for the output buffer in the JpegEncoderState below.
65 static const int initial_output_buffer_size = 8192; 54 static const int initial_output_buffer_size = 8192;
66 55
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 126
138 // update the used byte based on the next byte libjpeg would write to 127 // update the used byte based on the next byte libjpeg would write to
139 state->image_buffer_used = cinfo->dest->next_output_byte - &(*state->out)[0]; 128 state->image_buffer_used = cinfo->dest->next_output_byte - &(*state->out)[0];
140 DCHECK(state->image_buffer_used < state->out->size()) << 129 DCHECK(state->image_buffer_used < state->out->size()) <<
141 "JPEG library busted, got a bad image buffer size"; 130 "JPEG library busted, got a bad image buffer size";
142 131
143 // update our buffer so that it exactly encompases the desired data 132 // update our buffer so that it exactly encompases the desired data
144 state->out->resize(state->image_buffer_used); 133 state->out->resize(state->image_buffer_used);
145 } 134 }
146 135
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
174 // This class destroys the given jpeg_compress object when it goes out of 136 // This class destroys the given jpeg_compress object when it goes out of
175 // scope. It simplifies the error handling in Encode (and even applies to the 137 // scope. It simplifies the error handling in Encode (and even applies to the
176 // success case). 138 // success case).
177 class CompressDestroyer { 139 class CompressDestroyer {
178 public: 140 public:
179 CompressDestroyer() : cinfo_(NULL) { 141 CompressDestroyer() : cinfo_(NULL) {
180 } 142 }
181 ~CompressDestroyer() { 143 ~CompressDestroyer() {
182 DestroyManagedObject(); 144 DestroyManagedObject();
183 } 145 }
(...skipping 13 matching lines...) Expand all
197 159
198 } // namespace 160 } // namespace
199 161
200 bool JPEGCodec::Encode(const unsigned char* input, ColorFormat format, 162 bool JPEGCodec::Encode(const unsigned char* input, ColorFormat format,
201 int w, int h, int row_byte_width, 163 int w, int h, int row_byte_width,
202 int quality, std::vector<unsigned char>* output) { 164 int quality, std::vector<unsigned char>* output) {
203 jpeg_compress_struct cinfo; 165 jpeg_compress_struct cinfo;
204 CompressDestroyer destroyer; 166 CompressDestroyer destroyer;
205 destroyer.SetManagedObject(&cinfo); 167 destroyer.SetManagedObject(&cinfo);
206 output->clear(); 168 output->clear();
207 #if !defined(JCS_EXTENSIONS)
208 unsigned char* row_buffer = NULL;
209 #endif
210 169
211 // We set up the normal JPEG error routines, then override error_exit. 170 // We set up the normal JPEG error routines, then override error_exit.
212 // This must be done before the call to create_compress. 171 // This must be done before the call to create_compress.
213 CoderErrorMgr errmgr; 172 CoderErrorMgr errmgr;
214 cinfo.err = jpeg_std_error(&errmgr.pub); 173 cinfo.err = jpeg_std_error(&errmgr.pub);
215 errmgr.pub.error_exit = ErrorExit; 174 errmgr.pub.error_exit = ErrorExit;
216 175
217 // Establish the setjmp return context for ErrorExit to use. 176 // Establish the setjmp return context for ErrorExit to use.
218 if (setjmp(errmgr.setjmp_buffer)) { 177 if (setjmp(errmgr.setjmp_buffer)) {
219 // If we get here, the JPEG code has signaled an error. 178 // If we get here, the JPEG code has signaled an error.
220 // MSDN notes: "if you intend your code to be portable, do not rely on 179 // MSDN notes: "if you intend your code to be portable, do not rely on
221 // correct destruction of frame-based objects when executing a nonlocal 180 // correct destruction of frame-based objects when executing a nonlocal
222 // goto using a call to longjmp." So we delete the CompressDestroyer's 181 // goto using a call to longjmp." So we delete the CompressDestroyer's
223 // object manually instead. 182 // object manually instead.
224 destroyer.DestroyManagedObject(); 183 destroyer.DestroyManagedObject();
225 #if !defined(JCS_EXTENSIONS)
226 delete[] row_buffer;
227 #endif
228 return false; 184 return false;
229 } 185 }
230 186
231 // The destroyer will destroy() cinfo on exit. 187 // The destroyer will destroy() cinfo on exit.
232 jpeg_create_compress(&cinfo); 188 jpeg_create_compress(&cinfo);
233 189
234 cinfo.image_width = w; 190 cinfo.image_width = w;
235 cinfo.image_height = h; 191 cinfo.image_height = h;
236 cinfo.input_components = 3; 192 cinfo.input_components = 4;
237 #ifdef JCS_EXTENSIONS
238 // Choose an input colorspace and return if it is an unsupported one. Since 193 // Choose an input colorspace and return if it is an unsupported one. Since
239 // libjpeg-turbo supports all input formats used by Chromium (i.e. RGB, RGBA, 194 // libjpeg-turbo supports all input formats used by Chromium (i.e. RGB, RGBA,
240 // and BGRA), we just map the input parameters to a colorspace used by 195 // and BGRA), we just map the input parameters to a colorspace used by
241 // libjpeg-turbo. 196 // libjpeg-turbo.
242 if (format == FORMAT_RGB) { 197 if (format == FORMAT_RGBA ||
243 cinfo.input_components = 3; 198 (format == FORMAT_SkBitmap && SK_R32_SHIFT == 0)) {
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;
248 cinfo.in_color_space = JCS_EXT_RGBX; 199 cinfo.in_color_space = JCS_EXT_RGBX;
249 } else if (format == FORMAT_BGRA || 200 } else if (format == FORMAT_BGRA ||
250 (format == FORMAT_SkBitmap && SK_B32_SHIFT == 0)) { 201 (format == FORMAT_SkBitmap && SK_B32_SHIFT == 0)) {
251 cinfo.input_components = 4;
252 cinfo.in_color_space = JCS_EXT_BGRX; 202 cinfo.in_color_space = JCS_EXT_BGRX;
253 } else { 203 } else {
254 // We can exit this function without calling jpeg_destroy_compress() because 204 // We can exit this function without calling jpeg_destroy_compress() because
255 // CompressDestroyer automaticaly calls it. 205 // CompressDestroyer automaticaly calls it.
256 NOTREACHED() << "Invalid pixel format"; 206 NOTREACHED() << "Invalid pixel format";
257 return false; 207 return false;
258 } 208 }
259 #else
260 cinfo.in_color_space = JCS_RGB;
261 #endif
262 cinfo.data_precision = 8; 209 cinfo.data_precision = 8;
263 210
264 jpeg_set_defaults(&cinfo); 211 jpeg_set_defaults(&cinfo);
265 jpeg_set_quality(&cinfo, quality, 1); // quality here is 0-100 212 jpeg_set_quality(&cinfo, quality, 1); // quality here is 0-100
266 213
267 // set up the destination manager 214 // set up the destination manager
268 jpeg_destination_mgr destmgr; 215 jpeg_destination_mgr destmgr;
269 destmgr.init_destination = InitDestination; 216 destmgr.init_destination = InitDestination;
270 destmgr.empty_output_buffer = EmptyOutputBuffer; 217 destmgr.empty_output_buffer = EmptyOutputBuffer;
271 destmgr.term_destination = TermDestination; 218 destmgr.term_destination = TermDestination;
272 cinfo.dest = &destmgr; 219 cinfo.dest = &destmgr;
273 220
274 JpegEncoderState state(output); 221 JpegEncoderState state(output);
275 cinfo.client_data = &state; 222 cinfo.client_data = &state;
276 223
277 jpeg_start_compress(&cinfo, 1); 224 jpeg_start_compress(&cinfo, 1);
278 225
279 // feed it the rows, doing necessary conversions for the color format 226 // feed it the rows, doing necessary conversions for the color format
280 #ifdef JCS_EXTENSIONS
281 // This function already returns when the input format is not supported by 227 // This function already returns when the input format is not supported by
282 // libjpeg-turbo and needs conversion. Therefore, we just encode lines without 228 // libjpeg-turbo and needs conversion. Therefore, we just encode lines without
283 // conversions. 229 // conversions.
284 while (cinfo.next_scanline < cinfo.image_height) { 230 while (cinfo.next_scanline < cinfo.image_height) {
285 const unsigned char* row = &input[cinfo.next_scanline * row_byte_width]; 231 const unsigned char* row = &input[cinfo.next_scanline * row_byte_width];
286 jpeg_write_scanlines(&cinfo, const_cast<unsigned char**>(&row), 1); 232 jpeg_write_scanlines(&cinfo, const_cast<unsigned char**>(&row), 1);
287 } 233 }
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
319 234
320 jpeg_finish_compress(&cinfo); 235 jpeg_finish_compress(&cinfo);
321 return true; 236 return true;
322 } 237 }
323 238
324 // Decoder -------------------------------------------------------------------- 239 // Decoder --------------------------------------------------------------------
325 240
326 namespace { 241 namespace {
327 242
328 struct JpegDecoderState { 243 struct JpegDecoderState {
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
391 306
392 // Our source doesn't need any cleanup, so this is a NOP. 307 // Our source doesn't need any cleanup, so this is a NOP.
393 // 308 //
394 // From the JPEG library: 309 // From the JPEG library:
395 // "Terminate source --- called by jpeg_finish_decompress() after all data has 310 // "Terminate source --- called by jpeg_finish_decompress() after all data has
396 // been read to clean up JPEG source manager. NOT called by jpeg_abort() or 311 // been read to clean up JPEG source manager. NOT called by jpeg_abort() or
397 // jpeg_destroy()." 312 // jpeg_destroy()."
398 void TermSource(j_decompress_ptr cinfo) { 313 void TermSource(j_decompress_ptr cinfo) {
399 } 314 }
400 315
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
426 // This class destroys the given jpeg_decompress object when it goes out of 316 // This class destroys the given jpeg_decompress object when it goes out of
427 // scope. It simplifies the error handling in Decode (and even applies to the 317 // scope. It simplifies the error handling in Decode (and even applies to the
428 // success case). 318 // success case).
429 class DecompressDestroyer { 319 class DecompressDestroyer {
430 public: 320 public:
431 DecompressDestroyer() : cinfo_(NULL) { 321 DecompressDestroyer() : cinfo_(NULL) {
432 } 322 }
433 ~DecompressDestroyer() { 323 ~DecompressDestroyer() {
434 DestroyManagedObject(); 324 DestroyManagedObject();
435 } 325 }
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
489 379
490 // fill the file metadata into our buffer 380 // fill the file metadata into our buffer
491 if (jpeg_read_header(&cinfo, true) != JPEG_HEADER_OK) 381 if (jpeg_read_header(&cinfo, true) != JPEG_HEADER_OK)
492 return false; 382 return false;
493 383
494 // we want to always get RGB data out 384 // we want to always get RGB data out
495 switch (cinfo.jpeg_color_space) { 385 switch (cinfo.jpeg_color_space) {
496 case JCS_GRAYSCALE: 386 case JCS_GRAYSCALE:
497 case JCS_RGB: 387 case JCS_RGB:
498 case JCS_YCbCr: 388 case JCS_YCbCr:
499 #ifdef JCS_EXTENSIONS
500 // Choose an output colorspace and return if it is an unsupported one. 389 // Choose an output colorspace and return if it is an unsupported one.
501 // Same as JPEGCodec::Encode(), libjpeg-turbo supports all input formats 390 // Same as JPEGCodec::Encode(), libjpeg-turbo supports all input formats
502 // used by Chromium (i.e. RGB, RGBA, and BGRA) and we just map the input 391 // used by Chromium (i.e. RGB, RGBA, and BGRA) and we just map the input
503 // parameters to a colorspace. 392 // parameters to a colorspace.
504 if (format == FORMAT_RGB) { 393 if (format == FORMAT_RGBA ||
505 cinfo.out_color_space = JCS_RGB; 394 (format == FORMAT_SkBitmap && SK_R32_SHIFT == 0)) {
506 cinfo.output_components = 3;
507 } else if (format == FORMAT_RGBA ||
508 (format == FORMAT_SkBitmap && SK_R32_SHIFT == 0)) {
509 cinfo.out_color_space = JCS_EXT_RGBX; 395 cinfo.out_color_space = JCS_EXT_RGBX;
510 cinfo.output_components = 4; 396 cinfo.output_components = 4;
511 } else if (format == FORMAT_BGRA || 397 } else if (format == FORMAT_BGRA ||
512 (format == FORMAT_SkBitmap && SK_B32_SHIFT == 0)) { 398 (format == FORMAT_SkBitmap && SK_B32_SHIFT == 0)) {
513 cinfo.out_color_space = JCS_EXT_BGRX; 399 cinfo.out_color_space = JCS_EXT_BGRX;
514 cinfo.output_components = 4; 400 cinfo.output_components = 4;
515 } else { 401 } else {
516 // We can exit this function without calling jpeg_destroy_decompress() 402 // We can exit this function without calling jpeg_destroy_decompress()
517 // because DecompressDestroyer automaticaly calls it. 403 // because DecompressDestroyer automaticaly calls it.
518 NOTREACHED() << "Invalid pixel format"; 404 NOTREACHED() << "Invalid pixel format";
519 return false; 405 return false;
520 } 406 }
521 #else
522 cinfo.out_color_space = JCS_RGB;
523 #endif
524 break; 407 break;
525 case JCS_CMYK: 408 case JCS_CMYK:
526 case JCS_YCCK: 409 case JCS_YCCK:
527 default: 410 default:
528 // Mozilla errors out on these color spaces, so I presume that the jpeg 411 // Mozilla errors out on these color spaces, so I presume that the jpeg
529 // library can't do automatic color space conversion for them. We don't 412 // library can't do automatic color space conversion for them. We don't
530 // care about these anyway. 413 // care about these anyway.
531 return false; 414 return false;
532 } 415 }
533 #ifndef JCS_EXTENSIONS
534 cinfo.output_components = 3;
535 #endif
536 416
537 jpeg_calc_output_dimensions(&cinfo); 417 jpeg_calc_output_dimensions(&cinfo);
538 *w = cinfo.output_width; 418 *w = cinfo.output_width;
539 *h = cinfo.output_height; 419 *h = cinfo.output_height;
540 420
541 jpeg_start_decompress(&cinfo); 421 jpeg_start_decompress(&cinfo);
542 422
543 // FIXME(brettw) we may want to allow the capability for callers to request 423 // FIXME(brettw) we may want to allow the capability for callers to request
544 // how to align row lengths as we do for the compressor. 424 // how to align row lengths as we do for the compressor.
545 int row_read_stride = cinfo.output_width * cinfo.output_components; 425 int row_read_stride = cinfo.output_width * cinfo.output_components;
546 426
547 #ifdef JCS_EXTENSIONS
548 // Create memory for a decoded image and write decoded lines to the memory 427 // Create memory for a decoded image and write decoded lines to the memory
549 // without conversions same as JPEGCodec::Encode(). 428 // without conversions same as JPEGCodec::Encode().
550 int row_write_stride = row_read_stride; 429 int row_write_stride = row_read_stride;
551 output->resize(row_write_stride * cinfo.output_height); 430 output->resize(row_write_stride * cinfo.output_height);
552 431
553 for (int row = 0; row < static_cast<int>(cinfo.output_height); row++) { 432 for (int row = 0; row < static_cast<int>(cinfo.output_height); row++) {
554 unsigned char* rowptr = &(*output)[row * row_write_stride]; 433 unsigned char* rowptr = &(*output)[row * row_write_stride];
555 if (!jpeg_read_scanlines(&cinfo, &rowptr, 1)) 434 if (!jpeg_read_scanlines(&cinfo, &rowptr, 1))
556 return false; 435 return false;
557 } 436 }
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
601 437
602 jpeg_finish_decompress(&cinfo); 438 jpeg_finish_decompress(&cinfo);
603 jpeg_destroy_decompress(&cinfo); 439 jpeg_destroy_decompress(&cinfo);
604 return true; 440 return true;
605 } 441 }
606 442
607 // static 443 // static
608 std::unique_ptr<SkBitmap> JPEGCodec::Decode(const unsigned char* input, 444 std::unique_ptr<SkBitmap> JPEGCodec::Decode(const unsigned char* input,
609 size_t input_size) { 445 size_t input_size) {
610 int w, h; 446 int w, h;
611 std::vector<unsigned char> data_vector; 447 std::vector<unsigned char> data_vector;
612 if (!Decode(input, input_size, FORMAT_SkBitmap, &data_vector, &w, &h)) 448 if (!Decode(input, input_size, FORMAT_SkBitmap, &data_vector, &w, &h))
613 return nullptr; 449 return nullptr;
614 450
615 // Skia only handles 32 bit images. 451 // Skia only handles 32 bit images.
616 int data_length = w * h * 4; 452 int data_length = w * h * 4;
617 453
618 std::unique_ptr<SkBitmap> bitmap(new SkBitmap()); 454 std::unique_ptr<SkBitmap> bitmap(new SkBitmap());
619 bitmap->allocN32Pixels(w, h); 455 bitmap->allocN32Pixels(w, h);
620 memcpy(bitmap->getAddr32(0, 0), &data_vector[0], data_length); 456 memcpy(bitmap->getAddr32(0, 0), &data_vector[0], data_length);
621 457
622 return bitmap; 458 return bitmap;
623 } 459 }
624 460
625 } // namespace gfx 461 } // 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