| Index: third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
|
| diff --git a/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoder.cpp b/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
|
| index b940a89422b145bc6945c61eb426658016c51d68..c092b30aa72fd7ecd2debfdcc6c37c7790cab0dc 100644
|
| --- a/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
|
| +++ b/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
|
| @@ -38,6 +38,9 @@
|
| #include "platform/image-decoders/jpeg/JPEGImageDecoder.h"
|
|
|
| #include "platform/PlatformInstrumentation.h"
|
| +#include "public/platform/Platform.h"
|
| +
|
| +#include <stdint.h>
|
|
|
| extern "C" {
|
| #include <stdio.h> // jpeglib.h needs stdio FILE.
|
| @@ -76,6 +79,38 @@ const int exifMarker = JPEG_APP0 + 1;
|
| // JPEG only supports a denominator of 8.
|
| const unsigned scaleDenominator = 8;
|
|
|
| +
|
| +// Returns a 16-bit integer with big-endian representation from a byte array.
|
| +unsigned getUint16(const char* p)
|
| +{
|
| + return ((*((unsigned char*)p)) << 8) + *((unsigned char*)(p + 1));
|
| +}
|
| +
|
| +// Returns the number of bytes that must be fetched before the image dimensions can be determined.
|
| +// Used for metrics only. Returns 0 if dimensions not found.
|
| +size_t getDimensionsOffset(const RefPtr<blink::SharedBuffer>& m_data)
|
| +{
|
| + const char* segment;
|
| + size_t pos = 0;
|
| + int height = 0, width = 0;
|
| + size_t length = m_data->getSomeData(segment, pos);
|
| + if (length < 2 || 0xFFD8 != getUint16(&segment[0]))
|
| + return 0;
|
| + pos += 2;
|
| + while ((length = m_data->getSomeData(segment, pos))) {
|
| + if (length < 2)
|
| + return 0;
|
| + int marker = getUint16(&segment[0]) & 0xfffc;
|
| + if (marker == 0xffc0)
|
| + break;
|
| + pos += 2 + getUint16(&segment[2]);
|
| + }
|
| + if (length < 8)
|
| + return 0;
|
| + // Height and width are two bytes each and are at bytes 5 and 7 of this segment, respectively.
|
| + return pos + 8;
|
| +}
|
| +
|
| } // namespace
|
|
|
| namespace blink {
|
| @@ -470,6 +505,7 @@ public:
|
| if (m_info.scale_num != m_info.scale_denom)
|
| overrideColorSpace = JCS_UNKNOWN;
|
| jpeg_calc_output_dimensions(&m_info);
|
| + m_decoder->setSizeOffset(m_nextReadPosition);
|
| m_decoder->setDecodedSize(m_info.output_width, m_info.output_height);
|
|
|
| m_decoder->setOrientation(readImageOrientation(info()));
|
| @@ -771,7 +807,7 @@ void term_source(j_decompress_ptr jd)
|
|
|
| JPEGImageDecoder::JPEGImageDecoder(AlphaOption alphaOption, GammaAndColorProfileOption colorOptions, size_t maxDecodedBytes)
|
| : ImageDecoder(alphaOption, colorOptions, maxDecodedBytes)
|
| - , m_hasColorProfile(false)
|
| + , m_sizeOffset(0), m_sizeOffsetOptimized(0), m_hasColorProfile(false)
|
| {
|
| }
|
|
|
| @@ -1070,6 +1106,13 @@ void JPEGImageDecoder::decode(bool onlySize)
|
| // has failed.
|
| if (!m_reader->decode(onlySize) && isAllDataReceived())
|
| setFailed();
|
| + // Decoding should happen only once.
|
| + if (!onlySize && isComplete(this, onlySize)) {
|
| + Platform::current()->histogramCustomCounts(
|
| + "Blink.Images.SizeOffsetOptimized_JPEG", getDimensionsOffset(m_data), 1, 1000000, 50);
|
| + Platform::current()->histogramCustomCounts(
|
| + "Blink.Images.SizeOffset_JPEG", m_sizeOffset, 1, 1000000, 50);
|
| + }
|
|
|
| // If decoding is done or failed, we don't need the JPEGImageReader anymore.
|
| if (isComplete(this, onlySize) || failed())
|
|
|