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

Unified Diff: src/images/SkImageDecoder_libjpeg.cpp

Issue 24449003: Make Jpeg decoding more fault resistant. (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: final rebase Created 7 years, 2 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 | « gyp/tools.gyp ('k') | src/images/SkImageDecoder_libpng.cpp » ('j') | 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 3b3ea887e3cde437d7469d2a43126a2cb604a6eb..7652249f5eb0a0bb0f30f94bcb78b3af2fdf6bba 100644
--- a/src/images/SkImageDecoder_libjpeg.cpp
+++ b/src/images/SkImageDecoder_libjpeg.cpp
@@ -19,6 +19,10 @@
#include "SkRect.h"
#include "SkCanvas.h"
+#if defined(SK_DEBUG)
+#include "SkRTConf.h" // SK_CONF_DECLARE
+#endif // defined(SK_DEBUG)
+
#include <stdio.h>
extern "C" {
#include "jpeglib.h"
@@ -35,6 +39,12 @@ extern "C" {
// If ANDROID_RGB is defined by in the jpeg headers it indicates that jpeg offers
// support for two additional formats (1) JCS_RGBA_8888 and (2) JCS_RGB_565.
+#if defined(SK_DEBUG)
+SK_CONF_DECLARE(bool, c_suppressJPEGImageDecoderWarnings,
+ "images.jpeg.suppressDecoderWarnings", false,
+ "Suppress most JPG warnings when calling decode functions.");
+#endif // defined(SK_DEBUG)
+
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
@@ -54,12 +64,27 @@ static void overwrite_mem_buffer_size(jpeg_decompress_struct* cinfo) {
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
+static void do_nothing_emit_message(jpeg_common_struct*, int) {
+ /* do nothing */
+}
+
static void initialize_info(jpeg_decompress_struct* cinfo, skjpeg_source_mgr* src_mgr) {
SkASSERT(cinfo != NULL);
SkASSERT(src_mgr != NULL);
jpeg_create_decompress(cinfo);
overwrite_mem_buffer_size(cinfo);
cinfo->src = src_mgr;
+#if defined(SK_DEBUG)
+ /* To suppress warnings with a SK_DEBUG binary, set the
+ * environment variable "skia_images_jpeg_suppressDecoderWarnings"
+ * to "true". Inside a program that links to skia:
+ * SK_CONF_SET("images.jpeg.suppressDecoderWarnings", true); */
+ if (c_suppressJPEGImageDecoderWarnings) {
+ cinfo->err->emit_message = &do_nothing_emit_message;
+ }
+#else // Always suppress in release mode.
+ cinfo->err->emit_message = &do_nothing_emit_message;
+#endif // defined(SK_DEBUG)
}
#ifdef SK_BUILD_FOR_ANDROID
@@ -443,6 +468,19 @@ static void adjust_out_color_space_and_dither(jpeg_decompress_struct* cinfo,
}
#endif
+
+/**
+ Sets all pixels in given bitmap to SK_ColorWHITE for all rows >= y.
+ Used when decoding fails partway through reading scanlines to fill
+ remaining lines. */
+static void fill_below_level(int y, SkBitmap* bitmap) {
+ SkRect rect = SkRect::MakeLTRB(0, y, bitmap->width(), bitmap->height());
+ SkCanvas canvas(*bitmap);
+ canvas.clipRect(rect);
+ canvas.drawColor(SK_ColorWHITE);
+}
+
+
bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
#ifdef TIME_DECODE
SkAutoTime atm("JPEG Decode");
@@ -553,10 +591,12 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
while (cinfo.output_scanline < cinfo.output_height) {
int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1);
- // if row_count == 0, then we didn't get a scanline, so abort.
- // if we supported partial images, we might return true in this case
if (0 == row_count) {
- return return_false(cinfo, *bm, "read_scanlines");
+ // if row_count == 0, then we didn't get a scanline,
+ // so return early. We will return a partial image.
+ fill_below_level(cinfo.output_scanline, bm);
+ cinfo.output_scanline = cinfo.output_height;
+ break; // Skip to jpeg_finish_decompress()
}
if (this->shouldCancelDecode()) {
return return_false(cinfo, *bm, "shouldCancelDecode");
@@ -606,7 +646,11 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
JSAMPLE* rowptr = (JSAMPLE*)srcRow;
int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1);
if (0 == row_count) {
- return return_false(cinfo, *bm, "read_scanlines");
+ // if row_count == 0, then we didn't get a scanline,
+ // so return early. We will return a partial image.
+ fill_below_level(y, bm);
+ cinfo.output_scanline = cinfo.output_height;
+ break; // Skip to jpeg_finish_decompress()
}
if (this->shouldCancelDecode()) {
return return_false(cinfo, *bm, "shouldCancelDecode");
@@ -785,8 +829,9 @@ bool SkJPEGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) {
int rowCount = jpeg_read_tile_scanline(cinfo,
fImageIndex->huffmanIndex(),
&rowptr);
- // if row_count == 0, then we didn't get a scanline, so abort.
- // if we supported partial images, we might return true in this case
+ // if rowCount == 0, then we didn't get a scanline, so abort.
+ // onDecodeSubset() relies on onBuildTileIndex(), which
+ // needs a complete image to succeed.
if (0 == rowCount) {
return return_false(*cinfo, bitmap, "read_scanlines");
}
@@ -844,6 +889,9 @@ bool SkJPEGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) {
for (int y = 0;; y++) {
JSAMPLE* rowptr = (JSAMPLE*)srcRow;
int row_count = jpeg_read_tile_scanline(cinfo, fImageIndex->huffmanIndex(), &rowptr);
+ // if row_count == 0, then we didn't get a scanline, so abort.
+ // onDecodeSubset() relies on onBuildTileIndex(), which
+ // needs a complete image to succeed.
if (0 == row_count) {
return return_false(*cinfo, bitmap, "read_scanlines");
}
« no previous file with comments | « gyp/tools.gyp ('k') | src/images/SkImageDecoder_libpng.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698