Cherry-pick: Fix JPEGDecode downsampled output size
Cherry-pick of Chromium Blink r167620
https://src.chromium.org/viewvc/blink?revision=167620&view=revision
Original description:
Do not assume the desired decode size is supported by libjpeg.
Instead query jpeg_calc_output_dimensions and use the returned
decoded size instead.
BUG: 12724078
Change-Id: I3b51f3b4aa379262aa48039dc78dfa0d8d24101a
diff --git a/Source/platform/image-decoders/jpeg/JPEGImageDecoder.cpp b/Source/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
index 334bf6b..816e308 100644
--- a/Source/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
+++ b/Source/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
@@ -377,6 +377,12 @@
if (!m_decoder->setSize(m_info.image_width, m_info.image_height))
return false;
+ // Calculate and set decoded size.
+ m_info.scale_num = m_decoder->desiredScaleNumerator();
+ m_info.scale_denom = scaleDenominator;
+ jpeg_calc_output_dimensions(&m_info);
+ m_decoder->setDecodedSize(m_info.output_width, m_info.output_height);
+
m_decoder->setOrientation(readImageOrientation(info()));
#if USE(QCMSLIB)
@@ -414,14 +420,6 @@
m_info.enable_2pass_quant = false;
m_info.do_block_smoothing = true;
- if (m_decoder->size() != m_decoder->decodedSize()) {
- m_info.scale_denom = scaleDenominator;
- m_info.scale_num = m_decoder->decodedSize().width() * scaleDenominator / m_info.image_width;
- }
-
- // Used to set up image size so arrays can be allocated.
- jpeg_calc_output_dimensions(&m_info);
-
// Make a one-row-high sample array that will go away when done with
// image. Always make it big enough to hold an RGB row. Since this
// uses the IJG memory manager, it must be allocated before the call
@@ -617,25 +615,31 @@
if (!ImageDecoder::setSize(width, height))
return false;
- size_t originalBytes = width * height * 4;
+ if (!desiredScaleNumerator())
+ return setFailed();
+
+ setDecodedSize(width, height);
+ return true;
+}
+
+void JPEGImageDecoder::setDecodedSize(unsigned width, unsigned height)
+{
+ m_decodedSize = IntSize(width, height);
+}
+
+unsigned JPEGImageDecoder::desiredScaleNumerator() const
+{
+ size_t originalBytes = size().width() * size().height() * 4;
if (originalBytes <= m_maxDecodedBytes) {
- m_decodedSize = IntSize(width, height);
- return true;
+ return scaleDenominator;
}
// Downsample according to the maximum decoded size.
unsigned scaleNumerator = static_cast<unsigned>(floor(sqrt(
// MSVC needs explicit parameter type for sqrt().
static_cast<float>(m_maxDecodedBytes * scaleDenominator * scaleDenominator / originalBytes))));
- m_decodedSize = IntSize((scaleNumerator * width + scaleDenominator - 1) / scaleDenominator,
- (scaleNumerator * height + scaleDenominator - 1) / scaleDenominator);
- // The image is too big to be downsampled by libjpeg.
- // FIXME: Post-process to downsample the image.
- if (m_decodedSize.isEmpty())
- return setFailed();
-
- return true;
+ return scaleNumerator;
}
ImageFrame* JPEGImageDecoder::frameBufferAtIndex(size_t index)
diff --git a/Source/platform/image-decoders/jpeg/JPEGImageDecoder.h b/Source/platform/image-decoders/jpeg/JPEGImageDecoder.h
index 090d69d..e254f64 100644
--- a/Source/platform/image-decoders/jpeg/JPEGImageDecoder.h
+++ b/Source/platform/image-decoders/jpeg/JPEGImageDecoder.h
@@ -55,9 +55,11 @@
virtual bool setFailed() OVERRIDE;
bool outputScanlines();
+ unsigned desiredScaleNumerator() const;
void jpegComplete();
void setOrientation(ImageOrientation orientation) { m_orientation = orientation; }
+ void setDecodedSize(unsigned width, unsigned height);
private:
// Decodes the image. If |onlySize| is true, stops decoding after