OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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); |
OLD | NEW |