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

Side by Side Diff: src/images/SkImageDecoder_libjpeg.cpp

Issue 26210007: Image decoder fixes (mostly) around A8. (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Created 7 years, 2 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
OLDNEW
1 /* 1 /*
2 * Copyright 2007 The Android Open Source Project 2 * Copyright 2007 The Android Open Source Project
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 8
9 #include "SkImageDecoder.h" 9 #include "SkImageDecoder.h"
10 #include "SkImageEncoder.h" 10 #include "SkImageEncoder.h"
(...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after
473 Sets all pixels in given bitmap to SK_ColorWHITE for all rows >= y. 473 Sets all pixels in given bitmap to SK_ColorWHITE for all rows >= y.
474 Used when decoding fails partway through reading scanlines to fill 474 Used when decoding fails partway through reading scanlines to fill
475 remaining lines. */ 475 remaining lines. */
476 static void fill_below_level(int y, SkBitmap* bitmap) { 476 static void fill_below_level(int y, SkBitmap* bitmap) {
477 SkIRect rect = SkIRect::MakeLTRB(0, y, bitmap->width(), bitmap->height()); 477 SkIRect rect = SkIRect::MakeLTRB(0, y, bitmap->width(), bitmap->height());
478 SkCanvas canvas(*bitmap); 478 SkCanvas canvas(*bitmap);
479 canvas.clipRect(SkRect::Make(rect)); 479 canvas.clipRect(SkRect::Make(rect));
480 canvas.drawColor(SK_ColorWHITE); 480 canvas.drawColor(SK_ColorWHITE);
481 } 481 }
482 482
483 /**
484 * Get the config and bytes per pixel of the source data. Return
485 * whether the data is supported.
486 */
487 static bool get_src_config(const jpeg_decompress_struct& cinfo,
488 SkScaledBitmapSampler::SrcConfig* sc,
489 int* srcBytesPerPixel) {
490 SkASSERT(sc != NULL && srcBytesPerPixel != NULL);
491 if (JCS_CMYK == cinfo.out_color_space) {
492 // In this case we will manually convert the CMYK values to RGB
493 *sc = SkScaledBitmapSampler::kRGBX;
494 // The CMYK work-around relies on 4 components per pixel here
495 *srcBytesPerPixel = 4;
496 } else if (3 == cinfo.out_color_components && JCS_RGB == cinfo.out_color_spa ce) {
497 *sc = SkScaledBitmapSampler::kRGB;
498 *srcBytesPerPixel = 3;
499 #ifdef ANDROID_RGB
500 } else if (JCS_RGBA_8888 == cinfo.out_color_space) {
501 *sc = SkScaledBitmapSampler::kRGBX;
502 *srcBytesPerPixel = 4;
503 } else if (JCS_RGB_565 == cinfo.out_color_space) {
504 *sc = SkScaledBitmapSampler::kRGB_565;
505 *srcBytesPerPixel = 2;
506 #endif
507 } else if (1 == cinfo.out_color_components &&
508 JCS_GRAYSCALE == cinfo.out_color_space) {
509 *sc = SkScaledBitmapSampler::kGray;
510 *srcBytesPerPixel = 1;
511 } else {
512 return false;
513 }
514 return true;
515 }
483 516
484 bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { 517 bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
485 #ifdef TIME_DECODE 518 #ifdef TIME_DECODE
486 SkAutoTime atm("JPEG Decode"); 519 SkAutoTime atm("JPEG Decode");
487 #endif 520 #endif
488 521
489 JPEGAutoClean autoClean; 522 JPEGAutoClean autoClean;
490 523
491 jpeg_decompress_struct cinfo; 524 jpeg_decompress_struct cinfo;
492 skjpeg_source_mgr srcManager(stream, this); 525 skjpeg_source_mgr srcManager(stream, this);
(...skipping 29 matching lines...) Expand all
522 turn_off_visual_optimizations(&cinfo); 555 turn_off_visual_optimizations(&cinfo);
523 556
524 const SkBitmap::Config config = this->getBitmapConfig(&cinfo); 557 const SkBitmap::Config config = this->getBitmapConfig(&cinfo);
525 558
526 #ifdef ANDROID_RGB 559 #ifdef ANDROID_RGB
527 adjust_out_color_space_and_dither(&cinfo, config, *this); 560 adjust_out_color_space_and_dither(&cinfo, config, *this);
528 #endif 561 #endif
529 562
530 if (1 == sampleSize && SkImageDecoder::kDecodeBounds_Mode == mode) { 563 if (1 == sampleSize && SkImageDecoder::kDecodeBounds_Mode == mode) {
531 bm->setConfig(config, cinfo.image_width, cinfo.image_height); 564 bm->setConfig(config, cinfo.image_width, cinfo.image_height);
565 // Assume an A8 bitmap is opaque to avoid the check of each
reed1 2013/10/08 16:24:17 "is not" ? same question for all copies of this c
scroggo 2013/10/10 21:46:59 Done.
566 // individual pixel. It is very unlikely to be opaque, since
567 // an opaque A8 bitmap would not be very interesting.
568 // Otherwise, a jpeg image is opaque.
532 bm->setIsOpaque(config != SkBitmap::kA8_Config); 569 bm->setIsOpaque(config != SkBitmap::kA8_Config);
533 return true; 570 return true;
534 } 571 }
535 572
536 /* image_width and image_height are the original dimensions, available 573 /* image_width and image_height are the original dimensions, available
537 after jpeg_read_header(). To see the scaled dimensions, we have to call 574 after jpeg_read_header(). To see the scaled dimensions, we have to call
538 jpeg_start_decompress(), and then read output_width and output_height. 575 jpeg_start_decompress(), and then read output_width and output_height.
539 */ 576 */
540 if (!jpeg_start_decompress(&cinfo)) { 577 if (!jpeg_start_decompress(&cinfo)) {
541 /* If we failed here, we may still have enough information to return 578 /* If we failed here, we may still have enough information to return
542 to the caller if they just wanted (subsampled bounds). If sampleSize 579 to the caller if they just wanted (subsampled bounds). If sampleSize
543 was 1, then we would have already returned. Thus we just check if 580 was 1, then we would have already returned. Thus we just check if
544 we're in kDecodeBounds_Mode, and that we have valid output sizes. 581 we're in kDecodeBounds_Mode, and that we have valid output sizes.
545 582
546 One reason to fail here is that we have insufficient stream data 583 One reason to fail here is that we have insufficient stream data
547 to complete the setup. However, output dimensions seem to get 584 to complete the setup. However, output dimensions seem to get
548 computed very early, which is why this special check can pay off. 585 computed very early, which is why this special check can pay off.
549 */ 586 */
550 if (SkImageDecoder::kDecodeBounds_Mode == mode && valid_output_dimension s(cinfo)) { 587 if (SkImageDecoder::kDecodeBounds_Mode == mode && valid_output_dimension s(cinfo)) {
551 SkScaledBitmapSampler smpl(cinfo.output_width, cinfo.output_height, 588 SkScaledBitmapSampler smpl(cinfo.output_width, cinfo.output_height,
552 recompute_sampleSize(sampleSize, cinfo)); 589 recompute_sampleSize(sampleSize, cinfo));
553 bm->setConfig(config, smpl.scaledWidth(), smpl.scaledHeight()); 590 bm->setConfig(config, smpl.scaledWidth(), smpl.scaledHeight());
591 // Assume an A8 bitmap is opaque to avoid the check of each
592 // individual pixel. It is very unlikely to be opaque, since
593 // an opaque A8 bitmap would not be very interesting.
594 // Otherwise, a jpeg image is opaque.
554 bm->setIsOpaque(config != SkBitmap::kA8_Config); 595 bm->setIsOpaque(config != SkBitmap::kA8_Config);
555 return true; 596 return true;
556 } else { 597 } else {
557 return return_false(cinfo, *bm, "start_decompress"); 598 return return_false(cinfo, *bm, "start_decompress");
558 } 599 }
559 } 600 }
560 sampleSize = recompute_sampleSize(sampleSize, cinfo); 601 sampleSize = recompute_sampleSize(sampleSize, cinfo);
561 602
562 // should we allow the Chooser (if present) to pick a config for us??? 603 // should we allow the Chooser (if present) to pick a config for us???
563 if (!this->chooseFromOneChoice(config, cinfo.output_width, cinfo.output_heig ht)) { 604 if (!this->chooseFromOneChoice(config, cinfo.output_width, cinfo.output_heig ht)) {
564 return return_false(cinfo, *bm, "chooseFromOneChoice"); 605 return return_false(cinfo, *bm, "chooseFromOneChoice");
565 } 606 }
566 607
567 SkScaledBitmapSampler sampler(cinfo.output_width, cinfo.output_height, sampl eSize); 608 SkScaledBitmapSampler sampler(cinfo.output_width, cinfo.output_height, sampl eSize);
568 bm->setConfig(config, sampler.scaledWidth(), sampler.scaledHeight()); 609 bm->setConfig(config, sampler.scaledWidth(), sampler.scaledHeight());
610 // Assume an A8 bitmap is opaque to avoid the check of each
611 // individual pixel. It is very unlikely to be opaque, since
612 // an opaque A8 bitmap would not be very interesting.
613 // Otherwise, a jpeg image is opaque.
569 bm->setIsOpaque(config != SkBitmap::kA8_Config); 614 bm->setIsOpaque(config != SkBitmap::kA8_Config);
570 if (SkImageDecoder::kDecodeBounds_Mode == mode) { 615 if (SkImageDecoder::kDecodeBounds_Mode == mode) {
571 return true; 616 return true;
572 } 617 }
573 if (!this->allocPixelRef(bm, NULL)) { 618 if (!this->allocPixelRef(bm, NULL)) {
574 return return_false(cinfo, *bm, "allocPixelRef"); 619 return return_false(cinfo, *bm, "allocPixelRef");
575 } 620 }
576 621
577 SkAutoLockPixels alp(*bm); 622 SkAutoLockPixels alp(*bm);
578 623
(...skipping 24 matching lines...) Expand all
603 } 648 }
604 rowptr += bpr; 649 rowptr += bpr;
605 } 650 }
606 jpeg_finish_decompress(&cinfo); 651 jpeg_finish_decompress(&cinfo);
607 return true; 652 return true;
608 } 653 }
609 #endif 654 #endif
610 655
611 // check for supported formats 656 // check for supported formats
612 SkScaledBitmapSampler::SrcConfig sc; 657 SkScaledBitmapSampler::SrcConfig sc;
613 if (JCS_CMYK == cinfo.out_color_space) { 658 int srcBytesPerPixel;
614 // In this case we will manually convert the CMYK values to RGB 659
615 sc = SkScaledBitmapSampler::kRGBX; 660 if (!get_src_config(cinfo, &sc, &srcBytesPerPixel)) {
616 } else if (3 == cinfo.out_color_components && JCS_RGB == cinfo.out_color_spa ce) {
617 sc = SkScaledBitmapSampler::kRGB;
618 #ifdef ANDROID_RGB
619 } else if (JCS_RGBA_8888 == cinfo.out_color_space) {
620 sc = SkScaledBitmapSampler::kRGBX;
621 } else if (JCS_RGB_565 == cinfo.out_color_space) {
622 sc = SkScaledBitmapSampler::kRGB_565;
623 #endif
624 } else if (1 == cinfo.out_color_components &&
625 JCS_GRAYSCALE == cinfo.out_color_space) {
626 sc = SkScaledBitmapSampler::kGray;
627 } else {
628 return return_false(cinfo, *bm, "jpeg colorspace"); 661 return return_false(cinfo, *bm, "jpeg colorspace");
629 } 662 }
630 663
631 if (!sampler.begin(bm, sc, *this)) { 664 if (!sampler.begin(bm, sc, *this)) {
632 return return_false(cinfo, *bm, "sampler.begin"); 665 return return_false(cinfo, *bm, "sampler.begin");
633 } 666 }
634 667
635 // The CMYK work-around relies on 4 components per pixel here 668 SkAutoMalloc srcStorage(cinfo.output_width * srcBytesPerPixel);
636 SkAutoMalloc srcStorage(cinfo.output_width * 4);
637 uint8_t* srcRow = (uint8_t*)srcStorage.get(); 669 uint8_t* srcRow = (uint8_t*)srcStorage.get();
638 670
639 // Possibly skip initial rows [sampler.srcY0] 671 // Possibly skip initial rows [sampler.srcY0]
640 if (!skip_src_rows(&cinfo, srcRow, sampler.srcY0())) { 672 if (!skip_src_rows(&cinfo, srcRow, sampler.srcY0())) {
641 return return_false(cinfo, *bm, "skip rows"); 673 return return_false(cinfo, *bm, "skip rows");
642 } 674 }
643 675
644 // now loop through scanlines until y == bm->height() - 1 676 // now loop through scanlines until y == bm->height() - 1
645 for (int y = 0;; y++) { 677 for (int y = 0;; y++) {
646 JSAMPLE* rowptr = (JSAMPLE*)srcRow; 678 JSAMPLE* rowptr = (JSAMPLE*)srcRow;
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
780 812
781 jpeg_init_read_tile_scanline(cinfo, fImageIndex->huffmanIndex(), 813 jpeg_init_read_tile_scanline(cinfo, fImageIndex->huffmanIndex(),
782 &startX, &startY, &width, &height); 814 &startX, &startY, &width, &height);
783 int skiaSampleSize = recompute_sampleSize(requestedSampleSize, *cinfo); 815 int skiaSampleSize = recompute_sampleSize(requestedSampleSize, *cinfo);
784 int actualSampleSize = skiaSampleSize * (DCTSIZE / cinfo->min_DCT_scaled_siz e); 816 int actualSampleSize = skiaSampleSize * (DCTSIZE / cinfo->min_DCT_scaled_siz e);
785 817
786 SkScaledBitmapSampler sampler(width, height, skiaSampleSize); 818 SkScaledBitmapSampler sampler(width, height, skiaSampleSize);
787 819
788 SkBitmap bitmap; 820 SkBitmap bitmap;
789 bitmap.setConfig(config, sampler.scaledWidth(), sampler.scaledHeight()); 821 bitmap.setConfig(config, sampler.scaledWidth(), sampler.scaledHeight());
790 bitmap.setIsOpaque(true); 822 // Assume an A8 bitmap is opaque to avoid the check of each
823 // individual pixel. It is very unlikely to be opaque, since
824 // an opaque A8 bitmap would not be very interesting.
825 // Otherwise, a jpeg image is opaque.
826 bitmap.setIsOpaque(config != SkBitmap::kA8_Config);
791 827
792 // Check ahead of time if the swap(dest, src) is possible or not. 828 // Check ahead of time if the swap(dest, src) is possible or not.
793 // If yes, then we will stick to AllocPixelRef since it's cheaper with the 829 // If yes, then we will stick to AllocPixelRef since it's cheaper with the
794 // swap happening. If no, then we will use alloc to allocate pixels to 830 // swap happening. If no, then we will use alloc to allocate pixels to
795 // prevent garbage collection. 831 // prevent garbage collection.
796 int w = rect.width() / actualSampleSize; 832 int w = rect.width() / actualSampleSize;
797 int h = rect.height() / actualSampleSize; 833 int h = rect.height() / actualSampleSize;
798 bool swapOnly = (rect == region) && bm->isNull() && 834 bool swapOnly = (rect == region) && bm->isNull() &&
799 (w == bitmap.width()) && (h == bitmap.height()) && 835 (w == bitmap.width()) && (h == bitmap.height()) &&
800 ((startX - rect.x()) / actualSampleSize == 0) && 836 ((startX - rect.x()) / actualSampleSize == 0) &&
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
847 } else { 883 } else {
848 cropBitmap(bm, &bitmap, actualSampleSize, region.x(), region.y(), 884 cropBitmap(bm, &bitmap, actualSampleSize, region.x(), region.y(),
849 region.width(), region.height(), startX, startY); 885 region.width(), region.height(), startX, startY);
850 } 886 }
851 return true; 887 return true;
852 } 888 }
853 #endif 889 #endif
854 890
855 // check for supported formats 891 // check for supported formats
856 SkScaledBitmapSampler::SrcConfig sc; 892 SkScaledBitmapSampler::SrcConfig sc;
857 if (JCS_CMYK == cinfo->out_color_space) { 893 int srcBytesPerPixel;
858 // In this case we will manually convert the CMYK values to RGB 894
859 sc = SkScaledBitmapSampler::kRGBX; 895 if (!get_src_config(*cinfo, &sc, &srcBytesPerPixel)) {
860 } else if (3 == cinfo->out_color_components && JCS_RGB == cinfo->out_color_s pace) {
861 sc = SkScaledBitmapSampler::kRGB;
862 #ifdef ANDROID_RGB
863 } else if (JCS_RGBA_8888 == cinfo->out_color_space) {
864 sc = SkScaledBitmapSampler::kRGBX;
865 } else if (JCS_RGB_565 == cinfo->out_color_space) {
866 sc = SkScaledBitmapSampler::kRGB_565;
867 #endif
868 } else if (1 == cinfo->out_color_components &&
869 JCS_GRAYSCALE == cinfo->out_color_space) {
870 sc = SkScaledBitmapSampler::kGray;
871 } else {
872 return return_false(*cinfo, *bm, "jpeg colorspace"); 896 return return_false(*cinfo, *bm, "jpeg colorspace");
873 } 897 }
874 898
875 if (!sampler.begin(&bitmap, sc, *this)) { 899 if (!sampler.begin(&bitmap, sc, *this)) {
876 return return_false(*cinfo, bitmap, "sampler.begin"); 900 return return_false(*cinfo, bitmap, "sampler.begin");
877 } 901 }
878 902
879 // The CMYK work-around relies on 4 components per pixel here 903 SkAutoMalloc srcStorage(width * srcBytesPerPixel);
880 SkAutoMalloc srcStorage(width * 4);
881 uint8_t* srcRow = (uint8_t*)srcStorage.get(); 904 uint8_t* srcRow = (uint8_t*)srcStorage.get();
882 905
883 // Possibly skip initial rows [sampler.srcY0] 906 // Possibly skip initial rows [sampler.srcY0]
884 if (!skip_src_rows_tile(cinfo, fImageIndex->huffmanIndex(), srcRow, sampler. srcY0())) { 907 if (!skip_src_rows_tile(cinfo, fImageIndex->huffmanIndex(), srcRow, sampler. srcY0())) {
885 return return_false(*cinfo, bitmap, "skip rows"); 908 return return_false(*cinfo, bitmap, "skip rows");
886 } 909 }
887 910
888 // now loop through scanlines until y == bitmap->height() - 1 911 // now loop through scanlines until y == bitmap->height() - 1
889 for (int y = 0;; y++) { 912 for (int y = 0;; y++) {
890 JSAMPLE* rowptr = (JSAMPLE*)srcRow; 913 JSAMPLE* rowptr = (JSAMPLE*)srcRow;
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after
1200 return SkImageDecoder::kUnknown_Format; 1223 return SkImageDecoder::kUnknown_Format;
1201 } 1224 }
1202 1225
1203 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) { 1226 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) {
1204 return (SkImageEncoder::kJPEG_Type == t) ? SkNEW(SkJPEGImageEncoder) : NULL; 1227 return (SkImageEncoder::kJPEG_Type == t) ? SkNEW(SkJPEGImageEncoder) : NULL;
1205 } 1228 }
1206 1229
1207 static SkImageDecoder_DecodeReg gDReg(sk_libjpeg_dfactory); 1230 static SkImageDecoder_DecodeReg gDReg(sk_libjpeg_dfactory);
1208 static SkImageDecoder_FormatReg gFormatReg(get_format_jpeg); 1231 static SkImageDecoder_FormatReg gFormatReg(get_format_jpeg);
1209 static SkImageEncoder_EncodeReg gEReg(sk_libjpeg_efactory); 1232 static SkImageEncoder_EncodeReg gEReg(sk_libjpeg_efactory);
OLDNEW
« no previous file with comments | « no previous file | src/images/SkImageDecoder_libpng.cpp » ('j') | src/images/SkImageDecoder_libpng.cpp » ('J')

Powered by Google App Engine
This is Rietveld 408576698