OLD | NEW |
1 | |
2 /* | 1 /* |
3 * Copyright 2007 The Android Open Source Project | 2 * Copyright 2007 The Android Open Source Project |
4 * | 3 * |
5 * 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 |
6 * found in the LICENSE file. | 5 * found in the LICENSE file. |
7 */ | 6 */ |
8 | 7 |
9 | 8 |
10 #include "SkImageDecoder.h" | 9 #include "SkImageDecoder.h" |
11 #include "SkImageEncoder.h" | 10 #include "SkImageEncoder.h" |
12 #include "SkJpegUtility.h" | 11 #include "SkJpegUtility.h" |
13 #include "SkColorPriv.h" | 12 #include "SkColorPriv.h" |
14 #include "SkDither.h" | 13 #include "SkDither.h" |
15 #include "SkScaledBitmapSampler.h" | 14 #include "SkScaledBitmapSampler.h" |
16 #include "SkStream.h" | 15 #include "SkStream.h" |
17 #include "SkTemplates.h" | 16 #include "SkTemplates.h" |
18 #include "SkTime.h" | 17 #include "SkTime.h" |
19 #include "SkUtils.h" | 18 #include "SkUtils.h" |
20 #include "SkRect.h" | 19 #include "SkRect.h" |
21 #include "SkCanvas.h" | 20 #include "SkCanvas.h" |
22 | 21 |
23 #include <stdio.h> | 22 #include <stdio.h> |
24 extern "C" { | 23 extern "C" { |
25 #include "jpeglib.h" | 24 #include "jpeglib.h" |
26 #include "jerror.h" | 25 #include "jerror.h" |
27 } | 26 } |
28 | 27 |
29 // Uncomment to enable the code path used by the Android framework with their | |
30 // custom image decoders. | |
31 //#if defined(SK_BUILD_FOR_ANDROID) && defined(SK_DEBUG) | |
32 // #define SK_BUILD_FOR_ANDROID_FRAMEWORK | |
33 //#endif | |
34 | |
35 // These enable timing code that report milliseconds for an encoding/decoding | 28 // These enable timing code that report milliseconds for an encoding/decoding |
36 //#define TIME_ENCODE | 29 //#define TIME_ENCODE |
37 //#define TIME_DECODE | 30 //#define TIME_DECODE |
38 | 31 |
39 // this enables our rgb->yuv code, which is faster than libjpeg on ARM | 32 // this enables our rgb->yuv code, which is faster than libjpeg on ARM |
40 // disable for the moment, as we have some glitches when width != multiple of 4 | 33 // disable for the moment, as we have some glitches when width != multiple of 4 |
41 #define WE_CONVERT_TO_YUV | 34 #define WE_CONVERT_TO_YUV |
42 | 35 |
43 // If ANDROID_RGB is defined by in the jpeg headers it indicates that jpeg offer
s | 36 // If ANDROID_RGB is defined by in the jpeg headers it indicates that jpeg offer
s |
44 // support for two additional formats (1) JCS_RGBA_8888 and (2) JCS_RGB_565. | 37 // support for two additional formats (1) JCS_RGBA_8888 and (2) JCS_RGB_565. |
(...skipping 16 matching lines...) Expand all Loading... |
61 | 54 |
62 ////////////////////////////////////////////////////////////////////////// | 55 ////////////////////////////////////////////////////////////////////////// |
63 ////////////////////////////////////////////////////////////////////////// | 56 ////////////////////////////////////////////////////////////////////////// |
64 | 57 |
65 class SkJPEGImageIndex { | 58 class SkJPEGImageIndex { |
66 public: | 59 public: |
67 SkJPEGImageIndex(SkStream* stream, SkImageDecoder* decoder) | 60 SkJPEGImageIndex(SkStream* stream, SkImageDecoder* decoder) |
68 : fSrcMgr(stream, decoder) {} | 61 : fSrcMgr(stream, decoder) {} |
69 | 62 |
70 ~SkJPEGImageIndex() { | 63 ~SkJPEGImageIndex() { |
71 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK | 64 #ifdef SK_BUILD_FOR_ANDROID |
72 jpeg_destroy_huffman_index(&fHuffmanIndex); | 65 jpeg_destroy_huffman_index(&fHuffmanIndex); |
73 #endif | 66 #endif |
74 jpeg_finish_decompress(&fCInfo); | 67 jpeg_finish_decompress(&fCInfo); |
75 jpeg_destroy_decompress(&fCInfo); | 68 jpeg_destroy_decompress(&fCInfo); |
76 } | 69 } |
77 | 70 |
78 /** | 71 /** |
79 * Init the cinfo struct using libjpeg and apply any necessary | 72 * Init the cinfo struct using libjpeg and apply any necessary |
80 * customizations. | 73 * customizations. |
81 */ | 74 */ |
82 void initializeInfo() { | 75 void initializeInfo() { |
83 jpeg_create_decompress(&fCInfo); | 76 jpeg_create_decompress(&fCInfo); |
84 overwrite_mem_buffer_size(&fCInfo); | 77 overwrite_mem_buffer_size(&fCInfo); |
85 fCInfo.src = &fSrcMgr; | 78 fCInfo.src = &fSrcMgr; |
86 } | 79 } |
87 | 80 |
88 jpeg_decompress_struct* cinfo() { return &fCInfo; } | 81 jpeg_decompress_struct* cinfo() { return &fCInfo; } |
89 | 82 |
90 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK | 83 #ifdef SK_BUILD_FOR_ANDROID |
91 huffman_index* huffmanIndex() { return &fHuffmanIndex; } | 84 huffman_index* huffmanIndex() { return &fHuffmanIndex; } |
92 #endif | 85 #endif |
93 | 86 |
94 private: | 87 private: |
95 skjpeg_source_mgr fSrcMgr; | 88 skjpeg_source_mgr fSrcMgr; |
96 jpeg_decompress_struct fCInfo; | 89 jpeg_decompress_struct fCInfo; |
97 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK | 90 #ifdef SK_BUILD_FOR_ANDROID |
98 huffman_index fHuffmanIndex; | 91 huffman_index fHuffmanIndex; |
99 #endif | 92 #endif |
100 }; | 93 }; |
101 | 94 |
102 class SkJPEGImageDecoder : public SkImageDecoder { | 95 class SkJPEGImageDecoder : public SkImageDecoder { |
103 public: | 96 public: |
104 SkJPEGImageDecoder() { | 97 SkJPEGImageDecoder() { |
105 fImageIndex = NULL; | 98 fImageIndex = NULL; |
106 fImageWidth = 0; | 99 fImageWidth = 0; |
107 fImageHeight = 0; | 100 fImageHeight = 0; |
108 } | 101 } |
109 | 102 |
110 virtual ~SkJPEGImageDecoder() { | 103 virtual ~SkJPEGImageDecoder() { |
111 SkDELETE(fImageIndex); | 104 SkDELETE(fImageIndex); |
112 } | 105 } |
113 | 106 |
114 virtual Format getFormat() const { | 107 virtual Format getFormat() const { |
115 return kJPEG_Format; | 108 return kJPEG_Format; |
116 } | 109 } |
117 | 110 |
118 protected: | 111 protected: |
119 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK | 112 #ifdef SK_BUILD_FOR_ANDROID |
120 virtual bool onBuildTileIndex(SkStream *stream, int *width, int *height) SK_
OVERRIDE; | 113 virtual bool onBuildTileIndex(SkStream *stream, int *width, int *height) SK_
OVERRIDE; |
121 virtual bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& rect) SK_OVERRI
DE; | 114 virtual bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& rect) SK_OVERRI
DE; |
122 #endif | 115 #endif |
123 virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE; | 116 virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE; |
124 | 117 |
125 private: | 118 private: |
126 SkJPEGImageIndex* fImageIndex; | 119 SkJPEGImageIndex* fImageIndex; |
127 int fImageWidth; | 120 int fImageWidth; |
128 int fImageHeight; | 121 int fImageHeight; |
129 | 122 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
173 for (int i = 0; i < count; i++) { | 166 for (int i = 0; i < count; i++) { |
174 JSAMPLE* rowptr = (JSAMPLE*)buffer; | 167 JSAMPLE* rowptr = (JSAMPLE*)buffer; |
175 int row_count = jpeg_read_scanlines(cinfo, &rowptr, 1); | 168 int row_count = jpeg_read_scanlines(cinfo, &rowptr, 1); |
176 if (1 != row_count) { | 169 if (1 != row_count) { |
177 return false; | 170 return false; |
178 } | 171 } |
179 } | 172 } |
180 return true; | 173 return true; |
181 } | 174 } |
182 | 175 |
183 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK | 176 #ifdef SK_BUILD_FOR_ANDROID |
184 static bool skip_src_rows_tile(jpeg_decompress_struct* cinfo, | 177 static bool skip_src_rows_tile(jpeg_decompress_struct* cinfo, |
185 huffman_index *index, void* buffer, int count) { | 178 huffman_index *index, void* buffer, int count) { |
186 for (int i = 0; i < count; i++) { | 179 for (int i = 0; i < count; i++) { |
187 JSAMPLE* rowptr = (JSAMPLE*)buffer; | 180 JSAMPLE* rowptr = (JSAMPLE*)buffer; |
188 int row_count = jpeg_read_tile_scanline(cinfo, index, &rowptr); | 181 int row_count = jpeg_read_tile_scanline(cinfo, index, &rowptr); |
189 if (1 != row_count) { | 182 if (1 != row_count) { |
190 return false; | 183 return false; |
191 } | 184 } |
192 } | 185 } |
193 return true; | 186 return true; |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
472 // we formally skip the rest, so we don't get a complaint from libjpeg | 465 // we formally skip the rest, so we don't get a complaint from libjpeg |
473 if (!skip_src_rows(&cinfo, srcRow, | 466 if (!skip_src_rows(&cinfo, srcRow, |
474 cinfo.output_height - cinfo.output_scanline)) { | 467 cinfo.output_height - cinfo.output_scanline)) { |
475 return return_false(cinfo, *bm, "skip rows"); | 468 return return_false(cinfo, *bm, "skip rows"); |
476 } | 469 } |
477 jpeg_finish_decompress(&cinfo); | 470 jpeg_finish_decompress(&cinfo); |
478 | 471 |
479 return true; | 472 return true; |
480 } | 473 } |
481 | 474 |
482 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK | 475 #ifdef SK_BUILD_FOR_ANDROID |
483 bool SkJPEGImageDecoder::onBuildTileIndex(SkStream* stream, int *width, int *hei
ght) { | 476 bool SkJPEGImageDecoder::onBuildTileIndex(SkStream* stream, int *width, int *hei
ght) { |
484 | 477 |
485 SkJPEGImageIndex* imageIndex = SkNEW_ARGS(SkJPEGImageIndex, (stream, this)); | 478 SkJPEGImageIndex* imageIndex = SkNEW_ARGS(SkJPEGImageIndex, (stream, this)); |
486 jpeg_decompress_struct* cinfo = imageIndex->cinfo(); | 479 jpeg_decompress_struct* cinfo = imageIndex->cinfo(); |
487 huffman_index* huffmanIndex = imageIndex->huffmanIndex(); | 480 huffman_index* huffmanIndex = imageIndex->huffmanIndex(); |
488 | 481 |
489 skjpeg_error_mgr sk_err; | 482 skjpeg_error_mgr sk_err; |
490 cinfo->err = jpeg_std_error(&sk_err); | 483 cinfo->err = jpeg_std_error(&sk_err); |
491 sk_err.error_exit = skjpeg_error_exit; | 484 sk_err.error_exit = skjpeg_error_exit; |
492 | 485 |
(...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1022 } | 1015 } |
1023 | 1016 |
1024 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) { | 1017 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) { |
1025 return (SkImageEncoder::kJPEG_Type == t) ? SkNEW(SkJPEGImageEncoder) : NULL; | 1018 return (SkImageEncoder::kJPEG_Type == t) ? SkNEW(SkJPEGImageEncoder) : NULL; |
1026 } | 1019 } |
1027 | 1020 |
1028 | 1021 |
1029 static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(sk_libjpeg_dfactory); | 1022 static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(sk_libjpeg_dfactory); |
1030 static SkTRegistry<SkImageDecoder::Format, SkStream*> gFormatReg(get_format_jpeg
); | 1023 static SkTRegistry<SkImageDecoder::Format, SkStream*> gFormatReg(get_format_jpeg
); |
1031 static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(sk_libjpeg_efact
ory); | 1024 static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(sk_libjpeg_efact
ory); |
OLD | NEW |