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

Unified Diff: src/images/SkImageDecoder_libjpeg.cpp

Issue 21891007: Fix failure exits from JPEG onBuildTileIndex. (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Set SkJPEGImageIndex state before calling jpeg functions. Created 7 years, 4 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/images/SkImageDecoder_libjpeg.cpp
diff --git a/src/images/SkImageDecoder_libjpeg.cpp b/src/images/SkImageDecoder_libjpeg.cpp
index d4047f197356a15b09bb02cd2a36089caf0d6df8..914ceb7e8aa458a3ea4e011be2db27f73d0ead8a 100644
--- a/src/images/SkImageDecoder_libjpeg.cpp
+++ b/src/images/SkImageDecoder_libjpeg.cpp
@@ -55,45 +55,115 @@ static void overwrite_mem_buffer_size(j_decompress_ptr cinfo) {
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
+#ifdef SK_BUILD_FOR_ANDROID
class SkJPEGImageIndex {
public:
SkJPEGImageIndex(SkStream* stream, SkImageDecoder* decoder)
- : fSrcMgr(stream, decoder) {}
+ : fSrcMgr(stream, decoder)
+ , fInfoInitialized(false)
+ , fHuffmanCreated(false)
+ , fDecompressStarted(false)
+ {
+ SkDEBUGCODE(fReadHeaderSucceeded = false;)
+ }
~SkJPEGImageIndex() {
-#ifdef SK_BUILD_FOR_ANDROID
- jpeg_destroy_huffman_index(&fHuffmanIndex);
-#endif
- jpeg_finish_decompress(&fCInfo);
+ if (fHuffmanCreated) {
+ fHuffmanCreated = false;
+ jpeg_destroy_huffman_index(&fHuffmanIndex);
+ }
+ if (fDecompressStarted) {
+ fDecompressStarted = false;
scroggo 2013/08/05 15:18:41 As mtklein pointed out, in patch set 3, if jpeg_fi
+ jpeg_finish_decompress(&fCInfo);
+ }
+ if (fInfoInitialized) {
+ this->destroyInfo();
+ }
+ }
+
+ /**
+ * Destroy the cinfo struct.
+ * After this call, if a huffman index was already built, it
+ * can be used after calling initializeInfoAndReadHeader
+ * again. Must not be called after startTileDecompress except
+ * in the destructor.
+ */
+ void destroyInfo() {
+ SkASSERT(fInfoInitialized);
+ SkASSERT(!fDecompressStarted);
+ fInfoInitialized = false;
jpeg_destroy_decompress(&fCInfo);
+ SkDEBUGCODE(fReadHeaderSucceeded = false;)
}
/**
- * Init the cinfo struct using libjpeg and apply any necessary
- * customizations.
+ * Initialize the cinfo struct.
+ * Calls jpeg_create_decompress, makes customizations, and
+ * finally calls jpeg_read_header. Returns true if jpeg_read_header
+ * returns JPEG_HEADER_OK.
+ * If cinfo was already initialized, destroyInfo must be called to
+ * destroy the old one. Must not be called after startTileDecompress.
*/
- void initializeInfo() {
+ bool initializeInfoAndReadHeader() {
+ SkASSERT(!fInfoInitialized && !fDecompressStarted);
jpeg_create_decompress(&fCInfo);
overwrite_mem_buffer_size(&fCInfo);
fCInfo.src = &fSrcMgr;
+ fInfoInitialized = true;
+ const bool success = (JPEG_HEADER_OK == jpeg_read_header(&fCInfo, true));
+ SkDEBUGCODE(fReadHeaderSucceeded = success;)
+ return success;
}
jpeg_decompress_struct* cinfo() { return &fCInfo; }
-#ifdef SK_BUILD_FOR_ANDROID
huffman_index* huffmanIndex() { return &fHuffmanIndex; }
-#endif
+
+ /**
+ * Build the index to be used for tile based decoding.
+ * Must only be called after a successful call to
+ * initializeInfoAndReadHeader and must not be called more
+ * than once.
+ */
+ bool buildHuffmanIndex() {
+ SkASSERT(fReadHeaderSucceeded);
+ SkASSERT(!fHuffmanCreated);
+ jpeg_create_huffman_index(&fCInfo, &fHuffmanIndex);
+ fHuffmanCreated = true;
+ SkASSERT(1 == fCInfo.scale_num && 1 == fCInfo.scale_denom);
+ return jpeg_build_huffman_index(&fCInfo, &fHuffmanIndex);
+ }
+
+ /**
+ * Start tile based decoding. Must only be called after a
+ * successful call to buildHuffmanIndex, and must only be
+ * called once.
+ */
+ bool startTileDecompress() {
+ SkASSERT(fHuffmanCreated);
+ SkASSERT(fReadHeaderSucceeded);
+ SkASSERT(!fDecompressStarted);
+ if (jpeg_start_tile_decompress(&fCInfo)) {
+ fDecompressStarted = true;
+ return true;
+ }
+ return false;
+ }
private:
skjpeg_source_mgr fSrcMgr;
jpeg_decompress_struct fCInfo;
-#ifdef SK_BUILD_FOR_ANDROID
huffman_index fHuffmanIndex;
-#endif
+ bool fInfoInitialized;
+ bool fHuffmanCreated;
+ bool fDecompressStarted;
+ SkDEBUGCODE(bool fReadHeaderSucceeded;)
};
+#endif
class SkJPEGImageDecoder : public SkImageDecoder {
public:
+#ifdef SK_BUILD_FOR_ANDROID
SkJPEGImageDecoder() {
fImageIndex = NULL;
fImageWidth = 0;
@@ -103,6 +173,7 @@ public:
virtual ~SkJPEGImageDecoder() {
SkDELETE(fImageIndex);
}
+#endif
virtual Format getFormat() const {
return kJPEG_Format;
@@ -116,9 +187,11 @@ protected:
virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE;
private:
+#ifdef SK_BUILD_FOR_ANDROID
SkJPEGImageIndex* fImageIndex;
int fImageWidth;
int fImageHeight;
+#endif
typedef SkImageDecoder INHERITED;
};
@@ -475,9 +548,8 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
#ifdef SK_BUILD_FOR_ANDROID
bool SkJPEGImageDecoder::onBuildTileIndex(SkStream* stream, int *width, int *height) {
- SkJPEGImageIndex* imageIndex = SkNEW_ARGS(SkJPEGImageIndex, (stream, this));
+ SkAutoTDelete<SkJPEGImageIndex> imageIndex(SkNEW_ARGS(SkJPEGImageIndex, (stream, this)));
jpeg_decompress_struct* cinfo = imageIndex->cinfo();
- huffman_index* huffmanIndex = imageIndex->huffmanIndex();
skjpeg_error_mgr sk_err;
cinfo->err = jpeg_std_error(&sk_err);
@@ -490,33 +562,19 @@ bool SkJPEGImageDecoder::onBuildTileIndex(SkStream* stream, int *width, int *hei
}
// create the cinfo used to create/build the huffmanIndex
- imageIndex->initializeInfo();
- cinfo->do_fancy_upsampling = 0;
- cinfo->do_block_smoothing = 0;
-
- int status = jpeg_read_header(cinfo, true);
- if (JPEG_HEADER_OK != status) {
- SkDELETE(imageIndex);
+ if (!imageIndex->initializeInfoAndReadHeader()) {
return false;
}
- jpeg_create_huffman_index(cinfo, huffmanIndex);
- cinfo->scale_num = 1;
- cinfo->scale_denom = 1;
- if (!jpeg_build_huffman_index(cinfo, huffmanIndex)) {
- SkDELETE(imageIndex);
+ if (!imageIndex->buildHuffmanIndex()) {
return false;
}
// destroy the cinfo used to create/build the huffman index
- jpeg_destroy_decompress(cinfo);
+ imageIndex->destroyInfo();
// Init decoder to image decode mode
- imageIndex->initializeInfo();
-
- status = jpeg_read_header(cinfo, true);
- if (JPEG_HEADER_OK != status) {
- SkDELETE(imageIndex);
+ if (!imageIndex->initializeInfoAndReadHeader()) {
return false;
}
@@ -525,16 +583,18 @@ bool SkJPEGImageDecoder::onBuildTileIndex(SkStream* stream, int *width, int *hei
cinfo->do_block_smoothing = 0;
// instead of jpeg_start_decompress() we start a tiled decompress
- jpeg_start_tile_decompress(cinfo);
+ if (!imageIndex->startTileDecompress()) {
+ return false;
+ }
- cinfo->scale_num = 1;
+ SkASSERT(1 == cinfo->scale_num);
*height = cinfo->output_height;
*width = cinfo->output_width;
fImageWidth = *width;
fImageHeight = *height;
SkDELETE(fImageIndex);
- fImageIndex = imageIndex;
+ fImageIndex = imageIndex.detach();
return true;
}
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698