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

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

Issue 6603010: Optimizes JPEGCodec for libjpeg-turbo... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 9 years, 9 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | 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) 2006-2008 The Chromium Authors. All rights reserved. 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 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 "base/logging.h" 9 #include "base/logging.h"
10 #include "base/scoped_ptr.h" 10 #include "base/scoped_ptr.h"
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
209 destroyer.DestroyManagedObject(); 209 destroyer.DestroyManagedObject();
210 return false; 210 return false;
211 } 211 }
212 212
213 // The destroyer will destroy() cinfo on exit. 213 // The destroyer will destroy() cinfo on exit.
214 jpeg_create_compress(&cinfo); 214 jpeg_create_compress(&cinfo);
215 215
216 cinfo.image_width = w; 216 cinfo.image_width = w;
217 cinfo.image_height = h; 217 cinfo.image_height = h;
218 cinfo.input_components = 3; 218 cinfo.input_components = 3;
219 #ifdef JCS_EXTENSIONS
220 // Choose an input colorspace and return if it is an unsupported one. Since
221 // libjpeg-turbo supports all input formats used by Chromium (i.e. RGB, RGBA,
222 // and BGRA), we just map the input parameters to a colorspace used by
223 // libjpeg-turbo.
224 if (format == FORMAT_RGB) {
225 cinfo.input_components = 3;
226 cinfo.in_color_space = JCS_RGB;
227 } else if (format == FORMAT_RGBA ||
228 format == FORMAT_SkBitmap && SK_R32_SHIFT == 0) {
229 cinfo.input_components = 4;
230 cinfo.in_color_space = JCS_EXT_RGBX;
231 } else if (format == FORMAT_BGRA ||
232 format == FORMAT_SkBitmap && SK_B32_SHIFT == 0) {
233 cinfo.input_components = 4;
234 cinfo.in_color_space = JCS_EXT_BGRX;
235 } else {
236 // We can exit this function without calling jpeg_destroy_compress() because
237 // CompressDestroyer automaticaly calls it.
238 NOTREACHED() << "Invalid pixel format";
239 return false;
240 }
241 #else
219 cinfo.in_color_space = JCS_RGB; 242 cinfo.in_color_space = JCS_RGB;
243 #endif
220 cinfo.data_precision = 8; 244 cinfo.data_precision = 8;
221 245
222 jpeg_set_defaults(&cinfo); 246 jpeg_set_defaults(&cinfo);
223 jpeg_set_quality(&cinfo, quality, 1); // quality here is 0-100 247 jpeg_set_quality(&cinfo, quality, 1); // quality here is 0-100
224 248
225 // set up the destination manager 249 // set up the destination manager
226 jpeg_destination_mgr destmgr; 250 jpeg_destination_mgr destmgr;
227 destmgr.init_destination = InitDestination; 251 destmgr.init_destination = InitDestination;
228 destmgr.empty_output_buffer = EmptyOutputBuffer; 252 destmgr.empty_output_buffer = EmptyOutputBuffer;
229 destmgr.term_destination = TermDestination; 253 destmgr.term_destination = TermDestination;
230 cinfo.dest = &destmgr; 254 cinfo.dest = &destmgr;
231 255
232 JpegEncoderState state(output); 256 JpegEncoderState state(output);
233 cinfo.client_data = &state; 257 cinfo.client_data = &state;
234 258
235 jpeg_start_compress(&cinfo, 1); 259 jpeg_start_compress(&cinfo, 1);
236 260
237 // feed it the rows, doing necessary conversions for the color format 261 // feed it the rows, doing necessary conversions for the color format
262 #ifdef JCS_EXTENSIONS
263 // This function already returns when the input format is not supported by
264 // libjpeg-turbo and needs conversion. Therefore, we just encode lines without
265 // conversions.
266 while (cinfo.next_scanline < cinfo.image_height) {
267 const unsigned char* row = &input[cinfo.next_scanline * row_byte_width];
268 jpeg_write_scanlines(&cinfo, const_cast<unsigned char**>(&row), 1);
269 }
270 #else
238 if (format == FORMAT_RGB) { 271 if (format == FORMAT_RGB) {
239 // no conversion necessary 272 // no conversion necessary
240 while (cinfo.next_scanline < cinfo.image_height) { 273 while (cinfo.next_scanline < cinfo.image_height) {
241 const unsigned char* row = &input[cinfo.next_scanline * row_byte_width]; 274 const unsigned char* row = &input[cinfo.next_scanline * row_byte_width];
242 jpeg_write_scanlines(&cinfo, const_cast<unsigned char**>(&row), 1); 275 jpeg_write_scanlines(&cinfo, const_cast<unsigned char**>(&row), 1);
243 } 276 }
244 } else { 277 } else {
245 // get the correct format converter 278 // get the correct format converter
246 void (*converter)(const unsigned char* in, int w, unsigned char* rgb); 279 void (*converter)(const unsigned char* in, int w, unsigned char* rgb);
247 if (format == FORMAT_RGBA || 280 if (format == FORMAT_RGBA ||
248 (format == FORMAT_SkBitmap && SK_R32_SHIFT == 0)) { 281 (format == FORMAT_SkBitmap && SK_R32_SHIFT == 0)) {
249 converter = StripAlpha; 282 converter = StripAlpha;
250 } else if (format == FORMAT_BGRA || 283 } else if (format == FORMAT_BGRA ||
251 (format == FORMAT_SkBitmap && SK_B32_SHIFT == 0)) { 284 (format == FORMAT_SkBitmap && SK_B32_SHIFT == 0)) {
252 converter = BGRAtoRGB; 285 converter = BGRAtoRGB;
253 } else { 286 } else {
254 NOTREACHED() << "Invalid pixel format"; 287 NOTREACHED() << "Invalid pixel format";
255 return false; 288 return false;
256 } 289 }
257 290
258 // output row after converting 291 // output row after converting
259 unsigned char* row = new unsigned char[w * 3]; 292 unsigned char* row = new unsigned char[w * 3];
260 293
261 while (cinfo.next_scanline < cinfo.image_height) { 294 while (cinfo.next_scanline < cinfo.image_height) {
262 converter(&input[cinfo.next_scanline * row_byte_width], w, row); 295 converter(&input[cinfo.next_scanline * row_byte_width], w, row);
263 jpeg_write_scanlines(&cinfo, &row, 1); 296 jpeg_write_scanlines(&cinfo, &row, 1);
264 } 297 }
265 delete[] row; 298 delete[] row;
266 } 299 }
300 #endif
267 301
268 jpeg_finish_compress(&cinfo); 302 jpeg_finish_compress(&cinfo);
269 return true; 303 return true;
270 } 304 }
271 305
272 // Decoder -------------------------------------------------------------------- 306 // Decoder --------------------------------------------------------------------
273 307
274 namespace { 308 namespace {
275 309
276 struct JpegDecoderState { 310 struct JpegDecoderState {
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
439 473
440 // fill the file metadata into our buffer 474 // fill the file metadata into our buffer
441 if (jpeg_read_header(&cinfo, true) != JPEG_HEADER_OK) 475 if (jpeg_read_header(&cinfo, true) != JPEG_HEADER_OK)
442 return false; 476 return false;
443 477
444 // we want to always get RGB data out 478 // we want to always get RGB data out
445 switch (cinfo.jpeg_color_space) { 479 switch (cinfo.jpeg_color_space) {
446 case JCS_GRAYSCALE: 480 case JCS_GRAYSCALE:
447 case JCS_RGB: 481 case JCS_RGB:
448 case JCS_YCbCr: 482 case JCS_YCbCr:
483 #ifdef JCS_EXTENSIONS
484 // Choose an output colorspace and return if it is an unsupported one.
485 // Same as JPEGCodec::Encode(), libjpeg-turbo supports all input formats
486 // used by Chromium (i.e. RGB, RGBA, and BGRA) and we just map the input
487 // parameters to a colorspace.
488 if (format == FORMAT_RGB) {
489 cinfo.out_color_space = JCS_RGB;
490 cinfo.output_components = 3;
491 } else if (format == FORMAT_RGBA ||
492 format == FORMAT_SkBitmap && SK_R32_SHIFT == 0) {
493 cinfo.out_color_space = JCS_EXT_RGBX;
494 cinfo.output_components = 4;
495 } else if (format == FORMAT_BGRA ||
496 format == FORMAT_SkBitmap && SK_B32_SHIFT == 0) {
497 cinfo.out_color_space = JCS_EXT_BGRX;
498 cinfo.output_components = 4;
499 } else {
500 // We can exit this function without calling jpeg_destroy_decompress()
501 // because DecompressDestroyer automaticaly calls it.
502 NOTREACHED() << "Invalid pixel format";
503 return false;
504 }
505 #else
449 cinfo.out_color_space = JCS_RGB; 506 cinfo.out_color_space = JCS_RGB;
507 #endif
450 break; 508 break;
451 case JCS_CMYK: 509 case JCS_CMYK:
452 case JCS_YCCK: 510 case JCS_YCCK:
453 default: 511 default:
454 // Mozilla errors out on these color spaces, so I presume that the jpeg 512 // 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 513 // library can't do automatic color space conversion for them. We don't
456 // care about these anyway. 514 // care about these anyway.
457 return false; 515 return false;
458 } 516 }
517 #ifndef JCS_EXTENSIONS
459 cinfo.output_components = 3; 518 cinfo.output_components = 3;
519 #endif
460 520
461 jpeg_calc_output_dimensions(&cinfo); 521 jpeg_calc_output_dimensions(&cinfo);
462 *w = cinfo.output_width; 522 *w = cinfo.output_width;
463 *h = cinfo.output_height; 523 *h = cinfo.output_height;
464 524
465 jpeg_start_decompress(&cinfo); 525 jpeg_start_decompress(&cinfo);
466 526
467 // FIXME(brettw) we may want to allow the capability for callers to request 527 // 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. 528 // how to align row lengths as we do for the compressor.
469 int row_read_stride = cinfo.output_width * cinfo.output_components; 529 int row_read_stride = cinfo.output_width * cinfo.output_components;
470 530
531 #ifdef JCS_EXTENSIONS
532 // Create memory for a decoded image and write decoded lines to the memory
533 // without conversions same as JPEGCodec::Encode().
534 int row_write_stride = row_read_stride;
535 output->resize(row_write_stride * cinfo.output_height);
536
537 for (int row = 0; row < static_cast<int>(cinfo.output_height); row++) {
538 unsigned char* rowptr = &(*output)[row * row_write_stride];
539 if (!jpeg_read_scanlines(&cinfo, &rowptr, 1))
540 return false;
541 }
542 #else
471 if (format == FORMAT_RGB) { 543 if (format == FORMAT_RGB) {
472 // easy case, row needs no conversion 544 // easy case, row needs no conversion
473 int row_write_stride = row_read_stride; 545 int row_write_stride = row_read_stride;
474 output->resize(row_write_stride * cinfo.output_height); 546 output->resize(row_write_stride * cinfo.output_height);
475 547
476 for (int row = 0; row < static_cast<int>(cinfo.output_height); row++) { 548 for (int row = 0; row < static_cast<int>(cinfo.output_height); row++) {
477 unsigned char* rowptr = &(*output)[row * row_write_stride]; 549 unsigned char* rowptr = &(*output)[row * row_write_stride];
478 if (!jpeg_read_scanlines(&cinfo, &rowptr, 1)) 550 if (!jpeg_read_scanlines(&cinfo, &rowptr, 1))
479 return false; 551 return false;
480 } 552 }
(...skipping 20 matching lines...) Expand all
501 output->resize(row_write_stride * cinfo.output_height); 573 output->resize(row_write_stride * cinfo.output_height);
502 574
503 scoped_array<unsigned char> row_data(new unsigned char[row_read_stride]); 575 scoped_array<unsigned char> row_data(new unsigned char[row_read_stride]);
504 unsigned char* rowptr = row_data.get(); 576 unsigned char* rowptr = row_data.get();
505 for (int row = 0; row < static_cast<int>(cinfo.output_height); row++) { 577 for (int row = 0; row < static_cast<int>(cinfo.output_height); row++) {
506 if (!jpeg_read_scanlines(&cinfo, &rowptr, 1)) 578 if (!jpeg_read_scanlines(&cinfo, &rowptr, 1))
507 return false; 579 return false;
508 converter(rowptr, *w, &(*output)[row * row_write_stride]); 580 converter(rowptr, *w, &(*output)[row * row_write_stride]);
509 } 581 }
510 } 582 }
583 #endif
511 584
512 jpeg_finish_decompress(&cinfo); 585 jpeg_finish_decompress(&cinfo);
513 jpeg_destroy_decompress(&cinfo); 586 jpeg_destroy_decompress(&cinfo);
514 return true; 587 return true;
515 } 588 }
516 589
517 // static 590 // static
518 SkBitmap* JPEGCodec::Decode(const unsigned char* input, size_t input_size) { 591 SkBitmap* JPEGCodec::Decode(const unsigned char* input, size_t input_size) {
519 int w, h; 592 int w, h;
520 std::vector<unsigned char> data_vector; 593 std::vector<unsigned char> data_vector;
521 if (!Decode(input, input_size, FORMAT_SkBitmap, &data_vector, &w, &h)) 594 if (!Decode(input, input_size, FORMAT_SkBitmap, &data_vector, &w, &h))
522 return NULL; 595 return NULL;
523 596
524 // Skia only handles 32 bit images. 597 // Skia only handles 32 bit images.
525 int data_length = w * h * 4; 598 int data_length = w * h * 4;
526 599
527 SkBitmap* bitmap = new SkBitmap(); 600 SkBitmap* bitmap = new SkBitmap();
528 bitmap->setConfig(SkBitmap::kARGB_8888_Config, w, h); 601 bitmap->setConfig(SkBitmap::kARGB_8888_Config, w, h);
529 bitmap->allocPixels(); 602 bitmap->allocPixels();
530 memcpy(bitmap->getAddr32(0, 0), &data_vector[0], data_length); 603 memcpy(bitmap->getAddr32(0, 0), &data_vector[0], data_length);
531 604
532 return bitmap; 605 return bitmap;
533 } 606 }
534 607
535 } // namespace gfx 608 } // namespace gfx
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698