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

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: Rebase 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
« no previous file with comments | « no previous file | src/images/SkImageDecoder_libpng.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 477 matching lines...) Expand 10 before | Expand all | Expand 10 after
488 Sets all pixels in given bitmap to SK_ColorWHITE for all rows >= y. 488 Sets all pixels in given bitmap to SK_ColorWHITE for all rows >= y.
489 Used when decoding fails partway through reading scanlines to fill 489 Used when decoding fails partway through reading scanlines to fill
490 remaining lines. */ 490 remaining lines. */
491 static void fill_below_level(int y, SkBitmap* bitmap) { 491 static void fill_below_level(int y, SkBitmap* bitmap) {
492 SkIRect rect = SkIRect::MakeLTRB(0, y, bitmap->width(), bitmap->height()); 492 SkIRect rect = SkIRect::MakeLTRB(0, y, bitmap->width(), bitmap->height());
493 SkCanvas canvas(*bitmap); 493 SkCanvas canvas(*bitmap);
494 canvas.clipRect(SkRect::Make(rect)); 494 canvas.clipRect(SkRect::Make(rect));
495 canvas.drawColor(SK_ColorWHITE); 495 canvas.drawColor(SK_ColorWHITE);
496 } 496 }
497 497
498 /**
499 * Get the config and bytes per pixel of the source data. Return
500 * whether the data is supported.
501 */
502 static bool get_src_config(const jpeg_decompress_struct& cinfo,
503 SkScaledBitmapSampler::SrcConfig* sc,
504 int* srcBytesPerPixel) {
505 SkASSERT(sc != NULL && srcBytesPerPixel != NULL);
506 if (JCS_CMYK == cinfo.out_color_space) {
507 // In this case we will manually convert the CMYK values to RGB
508 *sc = SkScaledBitmapSampler::kRGBX;
509 // The CMYK work-around relies on 4 components per pixel here
510 *srcBytesPerPixel = 4;
511 } else if (3 == cinfo.out_color_components && JCS_RGB == cinfo.out_color_spa ce) {
512 *sc = SkScaledBitmapSampler::kRGB;
513 *srcBytesPerPixel = 3;
514 #ifdef ANDROID_RGB
515 } else if (JCS_RGBA_8888 == cinfo.out_color_space) {
516 *sc = SkScaledBitmapSampler::kRGBX;
517 *srcBytesPerPixel = 4;
518 } else if (JCS_RGB_565 == cinfo.out_color_space) {
519 *sc = SkScaledBitmapSampler::kRGB_565;
520 *srcBytesPerPixel = 2;
521 #endif
522 } else if (1 == cinfo.out_color_components &&
523 JCS_GRAYSCALE == cinfo.out_color_space) {
524 *sc = SkScaledBitmapSampler::kGray;
525 *srcBytesPerPixel = 1;
526 } else {
527 return false;
528 }
529 return true;
530 }
498 531
499 bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { 532 bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
500 #ifdef TIME_DECODE 533 #ifdef TIME_DECODE
501 SkAutoTime atm("JPEG Decode"); 534 SkAutoTime atm("JPEG Decode");
502 #endif 535 #endif
503 536
504 JPEGAutoClean autoClean; 537 JPEGAutoClean autoClean;
505 538
506 jpeg_decompress_struct cinfo; 539 jpeg_decompress_struct cinfo;
507 skjpeg_source_mgr srcManager(stream, this); 540 skjpeg_source_mgr srcManager(stream, this);
(...skipping 28 matching lines...) Expand all
536 569
537 turn_off_visual_optimizations(&cinfo); 570 turn_off_visual_optimizations(&cinfo);
538 571
539 const SkBitmap::Config config = this->getBitmapConfig(&cinfo); 572 const SkBitmap::Config config = this->getBitmapConfig(&cinfo);
540 573
541 #ifdef ANDROID_RGB 574 #ifdef ANDROID_RGB
542 adjust_out_color_space_and_dither(&cinfo, config, *this); 575 adjust_out_color_space_and_dither(&cinfo, config, *this);
543 #endif 576 #endif
544 577
545 if (1 == sampleSize && SkImageDecoder::kDecodeBounds_Mode == mode) { 578 if (1 == sampleSize && SkImageDecoder::kDecodeBounds_Mode == mode) {
579 // Assume an A8 bitmap is not opaque to avoid the check of each
580 // individual pixel. It is very unlikely to be opaque, since
581 // an opaque A8 bitmap would not be very interesting.
582 // Otherwise, a jpeg image is opaque.
546 return bm->setConfig(config, cinfo.image_width, cinfo.image_height, 0, 583 return bm->setConfig(config, cinfo.image_width, cinfo.image_height, 0,
547 SkBitmap::kA8_Config == config ? 584 SkBitmap::kA8_Config == config ?
548 kPremul_SkAlphaType : kOpaque_SkAlphaType); 585 kPremul_SkAlphaType : kOpaque_SkAlphaType);
549 } 586 }
550 587
551 /* image_width and image_height are the original dimensions, available 588 /* image_width and image_height are the original dimensions, available
552 after jpeg_read_header(). To see the scaled dimensions, we have to call 589 after jpeg_read_header(). To see the scaled dimensions, we have to call
553 jpeg_start_decompress(), and then read output_width and output_height. 590 jpeg_start_decompress(), and then read output_width and output_height.
554 */ 591 */
555 if (!jpeg_start_decompress(&cinfo)) { 592 if (!jpeg_start_decompress(&cinfo)) {
556 /* If we failed here, we may still have enough information to return 593 /* If we failed here, we may still have enough information to return
557 to the caller if they just wanted (subsampled bounds). If sampleSize 594 to the caller if they just wanted (subsampled bounds). If sampleSize
558 was 1, then we would have already returned. Thus we just check if 595 was 1, then we would have already returned. Thus we just check if
559 we're in kDecodeBounds_Mode, and that we have valid output sizes. 596 we're in kDecodeBounds_Mode, and that we have valid output sizes.
560 597
561 One reason to fail here is that we have insufficient stream data 598 One reason to fail here is that we have insufficient stream data
562 to complete the setup. However, output dimensions seem to get 599 to complete the setup. However, output dimensions seem to get
563 computed very early, which is why this special check can pay off. 600 computed very early, which is why this special check can pay off.
564 */ 601 */
565 if (SkImageDecoder::kDecodeBounds_Mode == mode && valid_output_dimension s(cinfo)) { 602 if (SkImageDecoder::kDecodeBounds_Mode == mode && valid_output_dimension s(cinfo)) {
566 SkScaledBitmapSampler smpl(cinfo.output_width, cinfo.output_height, 603 SkScaledBitmapSampler smpl(cinfo.output_width, cinfo.output_height,
567 recompute_sampleSize(sampleSize, cinfo)); 604 recompute_sampleSize(sampleSize, cinfo));
605 // Assume an A8 bitmap is not opaque to avoid the check of each
606 // individual pixel. It is very unlikely to be opaque, since
607 // an opaque A8 bitmap would not be very interesting.
608 // Otherwise, a jpeg image is opaque.
568 return bm->setConfig(config, smpl.scaledWidth(), smpl.scaledHeight() , 609 return bm->setConfig(config, smpl.scaledWidth(), smpl.scaledHeight() ,
569 0, SkBitmap::kA8_Config == config ? 610 0, SkBitmap::kA8_Config == config ?
570 kPremul_SkAlphaType : kOpaque_SkAlphaType); 611 kPremul_SkAlphaType : kOpaque_SkAlphaType);
571 } else { 612 } else {
572 return return_false(cinfo, *bm, "start_decompress"); 613 return return_false(cinfo, *bm, "start_decompress");
573 } 614 }
574 } 615 }
575 sampleSize = recompute_sampleSize(sampleSize, cinfo); 616 sampleSize = recompute_sampleSize(sampleSize, cinfo);
576 617
577 // should we allow the Chooser (if present) to pick a config for us??? 618 // should we allow the Chooser (if present) to pick a config for us???
578 if (!this->chooseFromOneChoice(config, cinfo.output_width, cinfo.output_heig ht)) { 619 if (!this->chooseFromOneChoice(config, cinfo.output_width, cinfo.output_heig ht)) {
579 return return_false(cinfo, *bm, "chooseFromOneChoice"); 620 return return_false(cinfo, *bm, "chooseFromOneChoice");
580 } 621 }
581 622
582 SkScaledBitmapSampler sampler(cinfo.output_width, cinfo.output_height, sampl eSize); 623 SkScaledBitmapSampler sampler(cinfo.output_width, cinfo.output_height, sampl eSize);
624 // Assume an A8 bitmap is not opaque to avoid the check of each
625 // individual pixel. It is very unlikely to be opaque, since
626 // an opaque A8 bitmap would not be very interesting.
627 // Otherwise, a jpeg image is opaque.
583 bm->setConfig(config, sampler.scaledWidth(), sampler.scaledHeight(), 0, 628 bm->setConfig(config, sampler.scaledWidth(), sampler.scaledHeight(), 0,
584 SkBitmap::kA8_Config != config ? kOpaque_SkAlphaType : kPremul _SkAlphaType); 629 SkBitmap::kA8_Config != config ? kOpaque_SkAlphaType : kPremul _SkAlphaType);
585 if (SkImageDecoder::kDecodeBounds_Mode == mode) { 630 if (SkImageDecoder::kDecodeBounds_Mode == mode) {
586 return true; 631 return true;
587 } 632 }
588 if (!this->allocPixelRef(bm, NULL)) { 633 if (!this->allocPixelRef(bm, NULL)) {
589 return return_false(cinfo, *bm, "allocPixelRef"); 634 return return_false(cinfo, *bm, "allocPixelRef");
590 } 635 }
591 636
592 SkAutoLockPixels alp(*bm); 637 SkAutoLockPixels alp(*bm);
(...skipping 25 matching lines...) Expand all
618 } 663 }
619 rowptr += bpr; 664 rowptr += bpr;
620 } 665 }
621 jpeg_finish_decompress(&cinfo); 666 jpeg_finish_decompress(&cinfo);
622 return true; 667 return true;
623 } 668 }
624 #endif 669 #endif
625 670
626 // check for supported formats 671 // check for supported formats
627 SkScaledBitmapSampler::SrcConfig sc; 672 SkScaledBitmapSampler::SrcConfig sc;
628 if (JCS_CMYK == cinfo.out_color_space) { 673 int srcBytesPerPixel;
629 // In this case we will manually convert the CMYK values to RGB 674
630 sc = SkScaledBitmapSampler::kRGBX; 675 if (!get_src_config(cinfo, &sc, &srcBytesPerPixel)) {
631 } else if (3 == cinfo.out_color_components && JCS_RGB == cinfo.out_color_spa ce) {
632 sc = SkScaledBitmapSampler::kRGB;
633 #ifdef ANDROID_RGB
634 } else if (JCS_RGBA_8888 == cinfo.out_color_space) {
635 sc = SkScaledBitmapSampler::kRGBX;
636 } else if (JCS_RGB_565 == cinfo.out_color_space) {
637 sc = SkScaledBitmapSampler::kRGB_565;
638 #endif
639 } else if (1 == cinfo.out_color_components &&
640 JCS_GRAYSCALE == cinfo.out_color_space) {
641 sc = SkScaledBitmapSampler::kGray;
642 } else {
643 return return_false(cinfo, *bm, "jpeg colorspace"); 676 return return_false(cinfo, *bm, "jpeg colorspace");
644 } 677 }
645 678
646 if (!sampler.begin(bm, sc, *this)) { 679 if (!sampler.begin(bm, sc, *this)) {
647 return return_false(cinfo, *bm, "sampler.begin"); 680 return return_false(cinfo, *bm, "sampler.begin");
648 } 681 }
649 682
650 // The CMYK work-around relies on 4 components per pixel here 683 SkAutoMalloc srcStorage(cinfo.output_width * srcBytesPerPixel);
651 SkAutoMalloc srcStorage(cinfo.output_width * 4);
652 uint8_t* srcRow = (uint8_t*)srcStorage.get(); 684 uint8_t* srcRow = (uint8_t*)srcStorage.get();
653 685
654 // Possibly skip initial rows [sampler.srcY0] 686 // Possibly skip initial rows [sampler.srcY0]
655 if (!skip_src_rows(&cinfo, srcRow, sampler.srcY0())) { 687 if (!skip_src_rows(&cinfo, srcRow, sampler.srcY0())) {
656 return return_false(cinfo, *bm, "skip rows"); 688 return return_false(cinfo, *bm, "skip rows");
657 } 689 }
658 690
659 // now loop through scanlines until y == bm->height() - 1 691 // now loop through scanlines until y == bm->height() - 1
660 for (int y = 0;; y++) { 692 for (int y = 0;; y++) {
661 JSAMPLE* rowptr = (JSAMPLE*)srcRow; 693 JSAMPLE* rowptr = (JSAMPLE*)srcRow;
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
794 int height = rect.height(); 826 int height = rect.height();
795 827
796 jpeg_init_read_tile_scanline(cinfo, fImageIndex->huffmanIndex(), 828 jpeg_init_read_tile_scanline(cinfo, fImageIndex->huffmanIndex(),
797 &startX, &startY, &width, &height); 829 &startX, &startY, &width, &height);
798 int skiaSampleSize = recompute_sampleSize(requestedSampleSize, *cinfo); 830 int skiaSampleSize = recompute_sampleSize(requestedSampleSize, *cinfo);
799 int actualSampleSize = skiaSampleSize * (DCTSIZE / cinfo->min_DCT_scaled_siz e); 831 int actualSampleSize = skiaSampleSize * (DCTSIZE / cinfo->min_DCT_scaled_siz e);
800 832
801 SkScaledBitmapSampler sampler(width, height, skiaSampleSize); 833 SkScaledBitmapSampler sampler(width, height, skiaSampleSize);
802 834
803 SkBitmap bitmap; 835 SkBitmap bitmap;
836 bitmap.setConfig(config, sampler.scaledWidth(), sampler.scaledHeight());
837 // Assume an A8 bitmap is not opaque to avoid the check of each
838 // individual pixel. It is very unlikely to be opaque, since
839 // an opaque A8 bitmap would not be very interesting.
840 // Otherwise, a jpeg image is opaque.
804 bitmap.setConfig(config, sampler.scaledWidth(), sampler.scaledHeight(), 0, 841 bitmap.setConfig(config, sampler.scaledWidth(), sampler.scaledHeight(), 0,
842 config == SkBitmap::kA8_Config ? kPremul_SkAlphaType :
805 kOpaque_SkAlphaType); 843 kOpaque_SkAlphaType);
806 844
807 // Check ahead of time if the swap(dest, src) is possible or not. 845 // Check ahead of time if the swap(dest, src) is possible or not.
808 // If yes, then we will stick to AllocPixelRef since it's cheaper with the 846 // If yes, then we will stick to AllocPixelRef since it's cheaper with the
809 // swap happening. If no, then we will use alloc to allocate pixels to 847 // swap happening. If no, then we will use alloc to allocate pixels to
810 // prevent garbage collection. 848 // prevent garbage collection.
811 int w = rect.width() / actualSampleSize; 849 int w = rect.width() / actualSampleSize;
812 int h = rect.height() / actualSampleSize; 850 int h = rect.height() / actualSampleSize;
813 bool swapOnly = (rect == region) && bm->isNull() && 851 bool swapOnly = (rect == region) && bm->isNull() &&
814 (w == bitmap.width()) && (h == bitmap.height()) && 852 (w == bitmap.width()) && (h == bitmap.height()) &&
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
862 } else { 900 } else {
863 cropBitmap(bm, &bitmap, actualSampleSize, region.x(), region.y(), 901 cropBitmap(bm, &bitmap, actualSampleSize, region.x(), region.y(),
864 region.width(), region.height(), startX, startY); 902 region.width(), region.height(), startX, startY);
865 } 903 }
866 return true; 904 return true;
867 } 905 }
868 #endif 906 #endif
869 907
870 // check for supported formats 908 // check for supported formats
871 SkScaledBitmapSampler::SrcConfig sc; 909 SkScaledBitmapSampler::SrcConfig sc;
872 if (JCS_CMYK == cinfo->out_color_space) { 910 int srcBytesPerPixel;
873 // In this case we will manually convert the CMYK values to RGB 911
874 sc = SkScaledBitmapSampler::kRGBX; 912 if (!get_src_config(*cinfo, &sc, &srcBytesPerPixel)) {
875 } else if (3 == cinfo->out_color_components && JCS_RGB == cinfo->out_color_s pace) {
876 sc = SkScaledBitmapSampler::kRGB;
877 #ifdef ANDROID_RGB
878 } else if (JCS_RGBA_8888 == cinfo->out_color_space) {
879 sc = SkScaledBitmapSampler::kRGBX;
880 } else if (JCS_RGB_565 == cinfo->out_color_space) {
881 sc = SkScaledBitmapSampler::kRGB_565;
882 #endif
883 } else if (1 == cinfo->out_color_components &&
884 JCS_GRAYSCALE == cinfo->out_color_space) {
885 sc = SkScaledBitmapSampler::kGray;
886 } else {
887 return return_false(*cinfo, *bm, "jpeg colorspace"); 913 return return_false(*cinfo, *bm, "jpeg colorspace");
888 } 914 }
889 915
890 if (!sampler.begin(&bitmap, sc, *this)) { 916 if (!sampler.begin(&bitmap, sc, *this)) {
891 return return_false(*cinfo, bitmap, "sampler.begin"); 917 return return_false(*cinfo, bitmap, "sampler.begin");
892 } 918 }
893 919
894 // The CMYK work-around relies on 4 components per pixel here 920 SkAutoMalloc srcStorage(width * srcBytesPerPixel);
895 SkAutoMalloc srcStorage(width * 4);
896 uint8_t* srcRow = (uint8_t*)srcStorage.get(); 921 uint8_t* srcRow = (uint8_t*)srcStorage.get();
897 922
898 // Possibly skip initial rows [sampler.srcY0] 923 // Possibly skip initial rows [sampler.srcY0]
899 if (!skip_src_rows_tile(cinfo, fImageIndex->huffmanIndex(), srcRow, sampler. srcY0())) { 924 if (!skip_src_rows_tile(cinfo, fImageIndex->huffmanIndex(), srcRow, sampler. srcY0())) {
900 return return_false(*cinfo, bitmap, "skip rows"); 925 return return_false(*cinfo, bitmap, "skip rows");
901 } 926 }
902 927
903 // now loop through scanlines until y == bitmap->height() - 1 928 // now loop through scanlines until y == bitmap->height() - 1
904 for (int y = 0;; y++) { 929 for (int y = 0;; y++) {
905 JSAMPLE* rowptr = (JSAMPLE*)srcRow; 930 JSAMPLE* rowptr = (JSAMPLE*)srcRow;
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after
1215 return SkImageDecoder::kUnknown_Format; 1240 return SkImageDecoder::kUnknown_Format;
1216 } 1241 }
1217 1242
1218 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) { 1243 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) {
1219 return (SkImageEncoder::kJPEG_Type == t) ? SkNEW(SkJPEGImageEncoder) : NULL; 1244 return (SkImageEncoder::kJPEG_Type == t) ? SkNEW(SkJPEGImageEncoder) : NULL;
1220 } 1245 }
1221 1246
1222 static SkImageDecoder_DecodeReg gDReg(sk_libjpeg_dfactory); 1247 static SkImageDecoder_DecodeReg gDReg(sk_libjpeg_dfactory);
1223 static SkImageDecoder_FormatReg gFormatReg(get_format_jpeg); 1248 static SkImageDecoder_FormatReg gFormatReg(get_format_jpeg);
1224 static SkImageEncoder_EncodeReg gEReg(sk_libjpeg_efactory); 1249 static SkImageEncoder_EncodeReg gEReg(sk_libjpeg_efactory);
OLDNEW
« no previous file with comments | « no previous file | src/images/SkImageDecoder_libpng.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698