| 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 a423aabab93b2cc3fad4de5811033fbdc425ecef..11593f1b8b4c1d5a4e7efedf3d4350cf69b8d62f 100644
|
| --- a/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
|
| +++ b/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
|
| @@ -233,14 +233,16 @@ static void readColorProfile(jpeg_decompress_struct* info, ColorProfile& colorPr
|
| }
|
| #endif
|
|
|
| -static IntSize computeYUVSize(const jpeg_decompress_struct* info, int component, ImageDecoder::SizeType sizeType)
|
| +static IntSize computeYUVSize(const jpeg_decompress_struct* info, int component)
|
| {
|
| - if (sizeType == ImageDecoder::SizeForMemoryAllocation) {
|
| - return IntSize(info->cur_comp_info[component]->width_in_blocks * DCTSIZE, info->cur_comp_info[component]->height_in_blocks * DCTSIZE);
|
| - }
|
| return IntSize(info->cur_comp_info[component]->downsampled_width, info->cur_comp_info[component]->downsampled_height);
|
| }
|
|
|
| +static size_t computeYUVWidthBytes(const jpeg_decompress_struct* info, int component)
|
| +{
|
| + return info->cur_comp_info[component]->width_in_blocks * DCTSIZE;
|
| +}
|
| +
|
| static yuv_subsampling yuvSubsampling(const jpeg_decompress_struct& info)
|
| {
|
| if ((DCTSIZE == 8)
|
| @@ -494,7 +496,7 @@ public:
|
| if (overrideColorSpace == JCS_YCbCr) {
|
| m_info.out_color_space = JCS_YCbCr;
|
| m_info.raw_data_out = TRUE;
|
| - m_uvSize = computeYUVSize(&m_info, 1, ImageDecoder::SizeForMemoryAllocation); // U size and V size have to be the same if we got here
|
| + m_uvSize = computeYUVSize(&m_info, 1); // U size and V size have to be the same if we got here
|
| }
|
|
|
| // Don't allocate a giant and superfluous memory buffer when the
|
| @@ -674,14 +676,18 @@ private:
|
| if (turboSwizzled(m_info.out_color_space))
|
| return nullptr;
|
| #endif
|
| - int width;
|
|
|
| - if (m_info.out_color_space == JCS_YCbCr)
|
| - width = computeYUVSize(&m_info, 0, ImageDecoder::SizeForMemoryAllocation).width();
|
| - else
|
| - width = m_info.output_width;
|
| -
|
| - return (*m_info.mem->alloc_sarray)(reinterpret_cast_ptr<j_common_ptr>(&m_info), JPOOL_IMAGE, width * 4, 1);
|
| + if (m_info.out_color_space != JCS_YCbCr)
|
| + return (*m_info.mem->alloc_sarray)(reinterpret_cast_ptr<j_common_ptr>(&m_info), JPOOL_IMAGE, 4 * m_info.output_width, 1);
|
| +
|
| + // Compute the width of the Y plane in bytes. This may be larger than the output
|
| + // width, since the jpeg library requires that the allocated width be a multiple of
|
| + // DCTSIZE. Note that this buffer will be used as garbage memory for rows that
|
| + // extend below the actual height of the image. We can reuse the same memory for
|
| + // the U and V planes, since we are guaranteed that the Y plane width is at least
|
| + // as large as the U and V plane widths.
|
| + int widthBytes = computeYUVWidthBytes(&m_info, 0);
|
| + return (*m_info.mem->alloc_sarray)(reinterpret_cast_ptr<j_common_ptr>(&m_info), JPOOL_IMAGE, widthBytes, 1);
|
| }
|
|
|
| void updateRestartPosition()
|
| @@ -802,13 +808,22 @@ void JPEGImageDecoder::setDecodedSize(unsigned width, unsigned height)
|
| m_decodedSize = IntSize(width, height);
|
| }
|
|
|
| -IntSize JPEGImageDecoder::decodedYUVSize(int component, ImageDecoder::SizeType sizeType) const
|
| +IntSize JPEGImageDecoder::decodedYUVSize(int component) const
|
| +{
|
| + ASSERT((component >= 0) && (component <= 2) && m_reader);
|
| + const jpeg_decompress_struct* info = m_reader->info();
|
| +
|
| + ASSERT(info->out_color_space == JCS_YCbCr);
|
| + return computeYUVSize(info, component);
|
| +}
|
| +
|
| +size_t JPEGImageDecoder::decodedYUVWidthBytes(int component) const
|
| {
|
| ASSERT((component >= 0) && (component <= 2) && m_reader);
|
| const jpeg_decompress_struct* info = m_reader->info();
|
|
|
| ASSERT(info->out_color_space == JCS_YCbCr);
|
| - return computeYUVSize(info, component, sizeType);
|
| + return computeYUVWidthBytes(info, component);
|
| }
|
|
|
| unsigned JPEGImageDecoder::desiredScaleNumerator() const
|
| @@ -913,12 +928,10 @@ static bool outputRawData(JPEGImageReader* reader, ImagePlanes* imagePlanes)
|
| bufferraw[0] = &bufferraw2[0]; // Y channel rows (8 or 16)
|
| bufferraw[1] = &bufferraw2[16]; // U channel rows (8)
|
| bufferraw[2] = &bufferraw2[24]; // V channel rows (8)
|
| - int yWidth = info->output_width;
|
| int yHeight = info->output_height;
|
| - int yMaxH = yHeight - 1;
|
| int v = info->cur_comp_info[0]->v_samp_factor;
|
| IntSize uvSize = reader->uvSize();
|
| - int uvMaxH = uvSize.height() - 1;
|
| + int uvHeight = uvSize.height();
|
| JSAMPROW outputY = static_cast<JSAMPROW>(imagePlanes->plane(0));
|
| JSAMPROW outputU = static_cast<JSAMPROW>(imagePlanes->plane(1));
|
| JSAMPROW outputV = static_cast<JSAMPROW>(imagePlanes->plane(2));
|
| @@ -928,38 +941,25 @@ static bool outputRawData(JPEGImageReader* reader, ImagePlanes* imagePlanes)
|
|
|
| // Request 8 or 16 scanlines: returns 0 or more scanlines.
|
| int yScanlinesToRead = DCTSIZE * v;
|
| - JSAMPROW yLastRow = *samples;
|
| - JSAMPROW uLastRow = yLastRow + rowBytesY;
|
| - JSAMPROW vLastRow = uLastRow + rowBytesY;
|
| - JSAMPROW dummyRow = vLastRow + rowBytesY;
|
| -
|
| + JSAMPROW dummyRow = *samples;
|
| while (info->output_scanline < info->output_height) {
|
| // Assign 8 or 16 rows of memory to read the Y channel.
|
| - bool hasYLastRow = false;
|
| for (int i = 0; i < yScanlinesToRead; ++i) {
|
| int scanline = info->output_scanline + i;
|
| - if (scanline < yMaxH) {
|
| + if (scanline < yHeight) {
|
| bufferraw2[i] = &outputY[scanline * rowBytesY];
|
| - } else if (scanline == yMaxH) {
|
| - bufferraw2[i] = yLastRow;
|
| - hasYLastRow = true;
|
| } else {
|
| bufferraw2[i] = dummyRow;
|
| }
|
| }
|
|
|
| // Assign 8 rows of memory to read the U and V channels.
|
| - bool hasUVLastRow = false;
|
| int scaledScanline = info->output_scanline / v;
|
| for (int i = 0; i < 8; ++i) {
|
| int scanline = scaledScanline + i;
|
| - if (scanline < uvMaxH) {
|
| + if (scanline < uvHeight) {
|
| bufferraw2[16 + i] = &outputU[scanline * rowBytesU];
|
| bufferraw2[24 + i] = &outputV[scanline * rowBytesV];
|
| - } else if (scanline == uvMaxH) {
|
| - bufferraw2[16 + i] = uLastRow;
|
| - bufferraw2[24 + i] = vLastRow;
|
| - hasUVLastRow = true;
|
| } else {
|
| bufferraw2[16 + i] = dummyRow;
|
| bufferraw2[24 + i] = dummyRow;
|
| @@ -969,14 +969,6 @@ static bool outputRawData(JPEGImageReader* reader, ImagePlanes* imagePlanes)
|
| JDIMENSION scanlinesRead = jpeg_read_raw_data(info, bufferraw, yScanlinesToRead);
|
| if (!scanlinesRead)
|
| return false;
|
| -
|
| - if (hasYLastRow)
|
| - memcpy(&outputY[yMaxH * rowBytesY], yLastRow, yWidth);
|
| -
|
| - if (hasUVLastRow) {
|
| - memcpy(&outputU[uvMaxH * rowBytesU], uLastRow, uvSize.width());
|
| - memcpy(&outputV[uvMaxH * rowBytesV], vLastRow, uvSize.width());
|
| - }
|
| }
|
|
|
| info->output_scanline = std::min(info->output_scanline, info->output_height);
|
|
|