Index: src/images/SkImageDecoder_libjpeg.cpp |
diff --git a/src/images/SkImageDecoder_libjpeg.cpp b/src/images/SkImageDecoder_libjpeg.cpp |
index 67b17823e262bba903fbd55a4e437efbce5dfd8d..b08835b542303a41932ccb28cd434144c8cf8080 100644 |
--- a/src/images/SkImageDecoder_libjpeg.cpp |
+++ b/src/images/SkImageDecoder_libjpeg.cpp |
@@ -495,6 +495,39 @@ static void fill_below_level(int y, SkBitmap* bitmap) { |
canvas.drawColor(SK_ColorWHITE); |
} |
+/** |
+ * Get the config and bytes per pixel of the source data. Return |
+ * whether the data is supported. |
+ */ |
+static bool get_src_config(const jpeg_decompress_struct& cinfo, |
+ SkScaledBitmapSampler::SrcConfig* sc, |
+ int* srcBytesPerPixel) { |
+ SkASSERT(sc != NULL && srcBytesPerPixel != NULL); |
+ if (JCS_CMYK == cinfo.out_color_space) { |
+ // In this case we will manually convert the CMYK values to RGB |
+ *sc = SkScaledBitmapSampler::kRGBX; |
+ // The CMYK work-around relies on 4 components per pixel here |
+ *srcBytesPerPixel = 4; |
+ } else if (3 == cinfo.out_color_components && JCS_RGB == cinfo.out_color_space) { |
+ *sc = SkScaledBitmapSampler::kRGB; |
+ *srcBytesPerPixel = 3; |
+#ifdef ANDROID_RGB |
+ } else if (JCS_RGBA_8888 == cinfo.out_color_space) { |
+ *sc = SkScaledBitmapSampler::kRGBX; |
+ *srcBytesPerPixel = 4; |
+ } else if (JCS_RGB_565 == cinfo.out_color_space) { |
+ *sc = SkScaledBitmapSampler::kRGB_565; |
+ *srcBytesPerPixel = 2; |
+#endif |
+ } else if (1 == cinfo.out_color_components && |
+ JCS_GRAYSCALE == cinfo.out_color_space) { |
+ *sc = SkScaledBitmapSampler::kGray; |
+ *srcBytesPerPixel = 1; |
+ } else { |
+ return false; |
+ } |
+ return true; |
+} |
bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { |
#ifdef TIME_DECODE |
@@ -543,6 +576,10 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { |
#endif |
if (1 == sampleSize && SkImageDecoder::kDecodeBounds_Mode == mode) { |
+ // Assume an A8 bitmap is not opaque to avoid the check of each |
+ // individual pixel. It is very unlikely to be opaque, since |
+ // an opaque A8 bitmap would not be very interesting. |
+ // Otherwise, a jpeg image is opaque. |
return bm->setConfig(config, cinfo.image_width, cinfo.image_height, 0, |
SkBitmap::kA8_Config == config ? |
kPremul_SkAlphaType : kOpaque_SkAlphaType); |
@@ -565,6 +602,10 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { |
if (SkImageDecoder::kDecodeBounds_Mode == mode && valid_output_dimensions(cinfo)) { |
SkScaledBitmapSampler smpl(cinfo.output_width, cinfo.output_height, |
recompute_sampleSize(sampleSize, cinfo)); |
+ // Assume an A8 bitmap is not opaque to avoid the check of each |
+ // individual pixel. It is very unlikely to be opaque, since |
+ // an opaque A8 bitmap would not be very interesting. |
+ // Otherwise, a jpeg image is opaque. |
return bm->setConfig(config, smpl.scaledWidth(), smpl.scaledHeight(), |
0, SkBitmap::kA8_Config == config ? |
kPremul_SkAlphaType : kOpaque_SkAlphaType); |
@@ -580,6 +621,10 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { |
} |
SkScaledBitmapSampler sampler(cinfo.output_width, cinfo.output_height, sampleSize); |
+ // Assume an A8 bitmap is not opaque to avoid the check of each |
+ // individual pixel. It is very unlikely to be opaque, since |
+ // an opaque A8 bitmap would not be very interesting. |
+ // Otherwise, a jpeg image is opaque. |
bm->setConfig(config, sampler.scaledWidth(), sampler.scaledHeight(), 0, |
SkBitmap::kA8_Config != config ? kOpaque_SkAlphaType : kPremul_SkAlphaType); |
if (SkImageDecoder::kDecodeBounds_Mode == mode) { |
@@ -625,21 +670,9 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { |
// check for supported formats |
SkScaledBitmapSampler::SrcConfig sc; |
- if (JCS_CMYK == cinfo.out_color_space) { |
- // In this case we will manually convert the CMYK values to RGB |
- sc = SkScaledBitmapSampler::kRGBX; |
- } else if (3 == cinfo.out_color_components && JCS_RGB == cinfo.out_color_space) { |
- sc = SkScaledBitmapSampler::kRGB; |
-#ifdef ANDROID_RGB |
- } else if (JCS_RGBA_8888 == cinfo.out_color_space) { |
- sc = SkScaledBitmapSampler::kRGBX; |
- } else if (JCS_RGB_565 == cinfo.out_color_space) { |
- sc = SkScaledBitmapSampler::kRGB_565; |
-#endif |
- } else if (1 == cinfo.out_color_components && |
- JCS_GRAYSCALE == cinfo.out_color_space) { |
- sc = SkScaledBitmapSampler::kGray; |
- } else { |
+ int srcBytesPerPixel; |
+ |
+ if (!get_src_config(cinfo, &sc, &srcBytesPerPixel)) { |
return return_false(cinfo, *bm, "jpeg colorspace"); |
} |
@@ -647,8 +680,7 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { |
return return_false(cinfo, *bm, "sampler.begin"); |
} |
- // The CMYK work-around relies on 4 components per pixel here |
- SkAutoMalloc srcStorage(cinfo.output_width * 4); |
+ SkAutoMalloc srcStorage(cinfo.output_width * srcBytesPerPixel); |
uint8_t* srcRow = (uint8_t*)srcStorage.get(); |
// Possibly skip initial rows [sampler.srcY0] |
@@ -801,7 +833,13 @@ bool SkJPEGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) { |
SkScaledBitmapSampler sampler(width, height, skiaSampleSize); |
SkBitmap bitmap; |
+ bitmap.setConfig(config, sampler.scaledWidth(), sampler.scaledHeight()); |
+ // Assume an A8 bitmap is not opaque to avoid the check of each |
+ // individual pixel. It is very unlikely to be opaque, since |
+ // an opaque A8 bitmap would not be very interesting. |
+ // Otherwise, a jpeg image is opaque. |
bitmap.setConfig(config, sampler.scaledWidth(), sampler.scaledHeight(), 0, |
+ config == SkBitmap::kA8_Config ? kPremul_SkAlphaType : |
kOpaque_SkAlphaType); |
// Check ahead of time if the swap(dest, src) is possible or not. |
@@ -869,21 +907,9 @@ bool SkJPEGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) { |
// check for supported formats |
SkScaledBitmapSampler::SrcConfig sc; |
- if (JCS_CMYK == cinfo->out_color_space) { |
- // In this case we will manually convert the CMYK values to RGB |
- sc = SkScaledBitmapSampler::kRGBX; |
- } else if (3 == cinfo->out_color_components && JCS_RGB == cinfo->out_color_space) { |
- sc = SkScaledBitmapSampler::kRGB; |
-#ifdef ANDROID_RGB |
- } else if (JCS_RGBA_8888 == cinfo->out_color_space) { |
- sc = SkScaledBitmapSampler::kRGBX; |
- } else if (JCS_RGB_565 == cinfo->out_color_space) { |
- sc = SkScaledBitmapSampler::kRGB_565; |
-#endif |
- } else if (1 == cinfo->out_color_components && |
- JCS_GRAYSCALE == cinfo->out_color_space) { |
- sc = SkScaledBitmapSampler::kGray; |
- } else { |
+ int srcBytesPerPixel; |
+ |
+ if (!get_src_config(*cinfo, &sc, &srcBytesPerPixel)) { |
return return_false(*cinfo, *bm, "jpeg colorspace"); |
} |
@@ -891,8 +917,7 @@ bool SkJPEGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) { |
return return_false(*cinfo, bitmap, "sampler.begin"); |
} |
- // The CMYK work-around relies on 4 components per pixel here |
- SkAutoMalloc srcStorage(width * 4); |
+ SkAutoMalloc srcStorage(width * srcBytesPerPixel); |
uint8_t* srcRow = (uint8_t*)srcStorage.get(); |
// Possibly skip initial rows [sampler.srcY0] |