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" |
11 #include "SkJpegUtility.h" | 11 #include "SkJpegUtility.h" |
12 #include "SkColorPriv.h" | 12 #include "SkColorPriv.h" |
13 #include "SkDither.h" | 13 #include "SkDither.h" |
14 #include "SkScaledBitmapSampler.h" | 14 #include "SkScaledBitmapSampler.h" |
15 #include "SkStream.h" | 15 #include "SkStream.h" |
16 #include "SkTemplates.h" | 16 #include "SkTemplates.h" |
17 #include "SkTime.h" | 17 #include "SkTime.h" |
18 #include "SkUtils.h" | 18 #include "SkUtils.h" |
19 #include "SkRect.h" | 19 #include "SkRect.h" |
20 #include "SkCanvas.h" | 20 #include "SkCanvas.h" |
21 | 21 |
22 #if defined(SK_DEBUG) | |
23 #include "SkRTConf.h" // SK_CONF_DECLARE | |
24 #endif // defined(SK_DEBUG) | |
25 | |
22 #include <stdio.h> | 26 #include <stdio.h> |
23 extern "C" { | 27 extern "C" { |
24 #include "jpeglib.h" | 28 #include "jpeglib.h" |
25 #include "jerror.h" | 29 #include "jerror.h" |
26 } | 30 } |
27 | 31 |
28 // These enable timing code that report milliseconds for an encoding/decoding | 32 // These enable timing code that report milliseconds for an encoding/decoding |
29 //#define TIME_ENCODE | 33 //#define TIME_ENCODE |
30 //#define TIME_DECODE | 34 //#define TIME_DECODE |
31 | 35 |
32 // this enables our rgb->yuv code, which is faster than libjpeg on ARM | 36 // this enables our rgb->yuv code, which is faster than libjpeg on ARM |
33 #define WE_CONVERT_TO_YUV | 37 #define WE_CONVERT_TO_YUV |
34 | 38 |
35 // If ANDROID_RGB is defined by in the jpeg headers it indicates that jpeg offer s | 39 // If ANDROID_RGB is defined by in the jpeg headers it indicates that jpeg offer s |
36 // support for two additional formats (1) JCS_RGBA_8888 and (2) JCS_RGB_565. | 40 // support for two additional formats (1) JCS_RGBA_8888 and (2) JCS_RGB_565. |
37 | 41 |
42 #if defined(SK_DEBUG) | |
43 SK_CONF_DECLARE(bool, c_suppressJPEGImageDecoderWarnings, | |
44 "images.jpeg.suppressDecoderWarnings", false, | |
45 "Suppress most JPG warnings when calling decode functions."); | |
46 #endif // defined(SK_DEBUG) | |
47 | |
38 ////////////////////////////////////////////////////////////////////////// | 48 ////////////////////////////////////////////////////////////////////////// |
39 ////////////////////////////////////////////////////////////////////////// | 49 ////////////////////////////////////////////////////////////////////////// |
40 | 50 |
41 static void overwrite_mem_buffer_size(jpeg_decompress_struct* cinfo) { | 51 static void overwrite_mem_buffer_size(jpeg_decompress_struct* cinfo) { |
42 #ifdef SK_BUILD_FOR_ANDROID | 52 #ifdef SK_BUILD_FOR_ANDROID |
43 /* Check if the device indicates that it has a large amount of system memory | 53 /* Check if the device indicates that it has a large amount of system memory |
44 * if so, increase the memory allocation to 30MB instead of the default 5MB. | 54 * if so, increase the memory allocation to 30MB instead of the default 5MB. |
45 */ | 55 */ |
46 #ifdef ANDROID_LARGE_MEMORY_DEVICE | 56 #ifdef ANDROID_LARGE_MEMORY_DEVICE |
47 cinfo->mem->max_memory_to_use = 30 * 1024 * 1024; | 57 cinfo->mem->max_memory_to_use = 30 * 1024 * 1024; |
48 #else | 58 #else |
49 cinfo->mem->max_memory_to_use = 5 * 1024 * 1024; | 59 cinfo->mem->max_memory_to_use = 5 * 1024 * 1024; |
50 #endif | 60 #endif |
51 #endif // SK_BUILD_FOR_ANDROID | 61 #endif // SK_BUILD_FOR_ANDROID |
52 } | 62 } |
53 | 63 |
54 ////////////////////////////////////////////////////////////////////////// | 64 ////////////////////////////////////////////////////////////////////////// |
55 ////////////////////////////////////////////////////////////////////////// | 65 ////////////////////////////////////////////////////////////////////////// |
56 | 66 |
67 static void do_nothing_emit_message(jpeg_common_struct*, int) { | |
68 /* do nothing */ | |
69 } | |
70 | |
57 static void initialize_info(jpeg_decompress_struct* cinfo, skjpeg_source_mgr* sr c_mgr) { | 71 static void initialize_info(jpeg_decompress_struct* cinfo, skjpeg_source_mgr* sr c_mgr) { |
58 SkASSERT(cinfo != NULL); | 72 SkASSERT(cinfo != NULL); |
59 SkASSERT(src_mgr != NULL); | 73 SkASSERT(src_mgr != NULL); |
60 jpeg_create_decompress(cinfo); | 74 jpeg_create_decompress(cinfo); |
61 overwrite_mem_buffer_size(cinfo); | 75 overwrite_mem_buffer_size(cinfo); |
62 cinfo->src = src_mgr; | 76 cinfo->src = src_mgr; |
77 #if defined(SK_DEBUG) | |
78 /* To suppress warnings with a SK_DEBUG binary, set the | |
79 * environment variable "skia_images_jpeg_suppressDecoderWarnings" | |
80 * to "true". Inside a program that links to skia: | |
81 * SK_CONF_SET("images.jpeg.suppressDecoderWarnings", true); */ | |
82 if (c_suppressJPEGImageDecoderWarnings) { | |
83 cinfo->err->emit_message = &do_nothing_emit_message; | |
84 } | |
85 #else // Always suppress in release mode. | |
86 cinfo->err->emit_message = &do_nothing_emit_message; | |
87 #endif //defined(SK_DEBUG) | |
63 } | 88 } |
64 | 89 |
65 #ifdef SK_BUILD_FOR_ANDROID | 90 #ifdef SK_BUILD_FOR_ANDROID |
66 class SkJPEGImageIndex { | 91 class SkJPEGImageIndex { |
67 public: | 92 public: |
68 SkJPEGImageIndex(SkStreamRewindable* stream, SkImageDecoder* decoder) | 93 SkJPEGImageIndex(SkStreamRewindable* stream, SkImageDecoder* decoder) |
69 : fSrcMgr(stream, decoder) | 94 : fSrcMgr(stream, decoder) |
70 , fInfoInitialized(false) | 95 , fInfoInitialized(false) |
71 , fHuffmanCreated(false) | 96 , fHuffmanCreated(false) |
72 , fDecompressStarted(false) | 97 , fDecompressStarted(false) |
(...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
549 cinfo.out_color_space == JCS_RGB_565))) | 574 cinfo.out_color_space == JCS_RGB_565))) |
550 { | 575 { |
551 JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels(); | 576 JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels(); |
552 INT32 const bpr = bm->rowBytes(); | 577 INT32 const bpr = bm->rowBytes(); |
553 | 578 |
554 while (cinfo.output_scanline < cinfo.output_height) { | 579 while (cinfo.output_scanline < cinfo.output_height) { |
555 int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1); | 580 int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1); |
556 // if row_count == 0, then we didn't get a scanline, so abort. | 581 // if row_count == 0, then we didn't get a scanline, so abort. |
557 // if we supported partial images, we might return true in this case | 582 // if we supported partial images, we might return true in this case |
558 if (0 == row_count) { | 583 if (0 == row_count) { |
559 return return_false(cinfo, *bm, "read_scanlines"); | 584 return true; |
scroggo
2013/10/02 17:05:04
The remaining rows will still be uninitialized.
| |
560 } | 585 } |
561 if (this->shouldCancelDecode()) { | 586 if (this->shouldCancelDecode()) { |
562 return return_false(cinfo, *bm, "shouldCancelDecode"); | 587 return return_false(cinfo, *bm, "shouldCancelDecode"); |
563 } | 588 } |
564 rowptr += bpr; | 589 rowptr += bpr; |
565 } | 590 } |
566 jpeg_finish_decompress(&cinfo); | 591 jpeg_finish_decompress(&cinfo); |
567 return true; | 592 return true; |
568 } | 593 } |
569 #endif | 594 #endif |
(...skipping 29 matching lines...) Expand all Loading... | |
599 // Possibly skip initial rows [sampler.srcY0] | 624 // Possibly skip initial rows [sampler.srcY0] |
600 if (!skip_src_rows(&cinfo, srcRow, sampler.srcY0())) { | 625 if (!skip_src_rows(&cinfo, srcRow, sampler.srcY0())) { |
601 return return_false(cinfo, *bm, "skip rows"); | 626 return return_false(cinfo, *bm, "skip rows"); |
602 } | 627 } |
603 | 628 |
604 // now loop through scanlines until y == bm->height() - 1 | 629 // now loop through scanlines until y == bm->height() - 1 |
605 for (int y = 0;; y++) { | 630 for (int y = 0;; y++) { |
606 JSAMPLE* rowptr = (JSAMPLE*)srcRow; | 631 JSAMPLE* rowptr = (JSAMPLE*)srcRow; |
607 int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1); | 632 int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1); |
608 if (0 == row_count) { | 633 if (0 == row_count) { |
609 return return_false(cinfo, *bm, "read_scanlines"); | 634 return true; |
scroggo
2013/10/02 17:05:04
Ditto
| |
610 } | 635 } |
611 if (this->shouldCancelDecode()) { | 636 if (this->shouldCancelDecode()) { |
612 return return_false(cinfo, *bm, "shouldCancelDecode"); | 637 return return_false(cinfo, *bm, "shouldCancelDecode"); |
613 } | 638 } |
614 | 639 |
615 if (JCS_CMYK == cinfo.out_color_space) { | 640 if (JCS_CMYK == cinfo.out_color_space) { |
616 convert_CMYK_to_RGB(srcRow, cinfo.output_width); | 641 convert_CMYK_to_RGB(srcRow, cinfo.output_width); |
617 } | 642 } |
618 | 643 |
619 sampler.next(srcRow); | 644 sampler.next(srcRow); |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
781 INT32 const bpr = bitmap.rowBytes(); | 806 INT32 const bpr = bitmap.rowBytes(); |
782 int rowTotalCount = 0; | 807 int rowTotalCount = 0; |
783 | 808 |
784 while (rowTotalCount < height) { | 809 while (rowTotalCount < height) { |
785 int rowCount = jpeg_read_tile_scanline(cinfo, | 810 int rowCount = jpeg_read_tile_scanline(cinfo, |
786 fImageIndex->huffmanIndex(), | 811 fImageIndex->huffmanIndex(), |
787 &rowptr); | 812 &rowptr); |
788 // if row_count == 0, then we didn't get a scanline, so abort. | 813 // if row_count == 0, then we didn't get a scanline, so abort. |
789 // if we supported partial images, we might return true in this case | 814 // if we supported partial images, we might return true in this case |
790 if (0 == rowCount) { | 815 if (0 == rowCount) { |
791 return return_false(*cinfo, bitmap, "read_scanlines"); | 816 return true; |
scroggo
2013/10/02 17:05:04
Ditto
| |
792 } | 817 } |
793 if (this->shouldCancelDecode()) { | 818 if (this->shouldCancelDecode()) { |
794 return return_false(*cinfo, bitmap, "shouldCancelDecode"); | 819 return return_false(*cinfo, bitmap, "shouldCancelDecode"); |
795 } | 820 } |
796 rowTotalCount += rowCount; | 821 rowTotalCount += rowCount; |
797 rowptr += bpr; | 822 rowptr += bpr; |
798 } | 823 } |
799 | 824 |
800 if (swapOnly) { | 825 if (swapOnly) { |
801 bm->swap(bitmap); | 826 bm->swap(bitmap); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
838 // Possibly skip initial rows [sampler.srcY0] | 863 // Possibly skip initial rows [sampler.srcY0] |
839 if (!skip_src_rows_tile(cinfo, fImageIndex->huffmanIndex(), srcRow, sampler. srcY0())) { | 864 if (!skip_src_rows_tile(cinfo, fImageIndex->huffmanIndex(), srcRow, sampler. srcY0())) { |
840 return return_false(*cinfo, bitmap, "skip rows"); | 865 return return_false(*cinfo, bitmap, "skip rows"); |
841 } | 866 } |
842 | 867 |
843 // now loop through scanlines until y == bitmap->height() - 1 | 868 // now loop through scanlines until y == bitmap->height() - 1 |
844 for (int y = 0;; y++) { | 869 for (int y = 0;; y++) { |
845 JSAMPLE* rowptr = (JSAMPLE*)srcRow; | 870 JSAMPLE* rowptr = (JSAMPLE*)srcRow; |
846 int row_count = jpeg_read_tile_scanline(cinfo, fImageIndex->huffmanIndex (), &rowptr); | 871 int row_count = jpeg_read_tile_scanline(cinfo, fImageIndex->huffmanIndex (), &rowptr); |
847 if (0 == row_count) { | 872 if (0 == row_count) { |
848 return return_false(*cinfo, bitmap, "read_scanlines"); | 873 return true; |
scroggo
2013/10/02 17:05:04
Ditto
| |
849 } | 874 } |
850 if (this->shouldCancelDecode()) { | 875 if (this->shouldCancelDecode()) { |
851 return return_false(*cinfo, bitmap, "shouldCancelDecode"); | 876 return return_false(*cinfo, bitmap, "shouldCancelDecode"); |
852 } | 877 } |
853 | 878 |
854 if (JCS_CMYK == cinfo->out_color_space) { | 879 if (JCS_CMYK == cinfo->out_color_space) { |
855 convert_CMYK_to_RGB(srcRow, width); | 880 convert_CMYK_to_RGB(srcRow, width); |
856 } | 881 } |
857 | 882 |
858 sampler.next(srcRow); | 883 sampler.next(srcRow); |
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1152 return SkImageDecoder::kUnknown_Format; | 1177 return SkImageDecoder::kUnknown_Format; |
1153 } | 1178 } |
1154 | 1179 |
1155 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) { | 1180 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) { |
1156 return (SkImageEncoder::kJPEG_Type == t) ? SkNEW(SkJPEGImageEncoder) : NULL; | 1181 return (SkImageEncoder::kJPEG_Type == t) ? SkNEW(SkJPEGImageEncoder) : NULL; |
1157 } | 1182 } |
1158 | 1183 |
1159 static SkImageDecoder_DecodeReg gDReg(sk_libjpeg_dfactory); | 1184 static SkImageDecoder_DecodeReg gDReg(sk_libjpeg_dfactory); |
1160 static SkImageDecoder_FormatReg gFormatReg(get_format_jpeg); | 1185 static SkImageDecoder_FormatReg gFormatReg(get_format_jpeg); |
1161 static SkImageEncoder_EncodeReg gEReg(sk_libjpeg_efactory); | 1186 static SkImageEncoder_EncodeReg gEReg(sk_libjpeg_efactory); |
OLD | NEW |