Chromium Code Reviews| 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..0aed35d7ad710a0e62cd7b1da2bd1fe7b6b595ad 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,19 @@ 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; |
| + if (m_info.out_color_space == JCS_YCbCr) { |
| + // 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. |
|
Noel Gordon
2016/03/03 01:25:28
Thanks for this. Where Blink code is very tricky,
msarett
2016/03/04 19:49:08
Done.
|
| + int widthBytes = computeYUVWidthBytes(&m_info, 0); |
| + return (*m_info.mem->alloc_sarray)(reinterpret_cast_ptr<j_common_ptr>(&m_info), JPOOL_IMAGE, widthBytes, 1); |
| + } |
| - return (*m_info.mem->alloc_sarray)(reinterpret_cast_ptr<j_common_ptr>(&m_info), JPOOL_IMAGE, width * 4, 1); |
| + return (*m_info.mem->alloc_sarray)(reinterpret_cast_ptr<j_common_ptr>(&m_info), JPOOL_IMAGE, 4 * m_info.output_width, 1); |
| } |
| void updateRestartPosition() |
| @@ -802,13 +809,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, sizeType); |
| + 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 computeYUVWidthBytes(info, component); |
| } |
| unsigned JPEGImageDecoder::desiredScaleNumerator() const |
| @@ -913,12 +929,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 +942,26 @@ 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 +971,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); |