| 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 |