Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2006 Apple Computer, Inc. | 2 * Copyright (C) 2006 Apple Computer, Inc. |
| 3 * | 3 * |
| 4 * Portions are Copyright (C) 2001-6 mozilla.org | 4 * Portions are Copyright (C) 2001-6 mozilla.org |
| 5 * | 5 * |
| 6 * Other contributors: | 6 * Other contributors: |
| 7 * Stuart Parmenter <stuart@mozilla.com> | 7 * Stuart Parmenter <stuart@mozilla.com> |
| 8 * | 8 * |
| 9 * This library is free software; you can redistribute it and/or | 9 * This library is free software; you can redistribute it and/or |
| 10 * modify it under the terms of the GNU Lesser General Public | 10 * modify it under the terms of the GNU Lesser General Public |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 226 ignoreProfile = true; | 226 ignoreProfile = true; |
| 227 | 227 |
| 228 ASSERT(colorProfile.isEmpty()); | 228 ASSERT(colorProfile.isEmpty()); |
| 229 if (!ignoreProfile) | 229 if (!ignoreProfile) |
| 230 colorProfile.append(profileData, profileLength); | 230 colorProfile.append(profileData, profileLength); |
| 231 free(profile); | 231 free(profile); |
| 232 #endif | 232 #endif |
| 233 } | 233 } |
| 234 #endif | 234 #endif |
| 235 | 235 |
| 236 static IntSize computeYUVSize(const jpeg_decompress_struct* info, int component, ImageDecoder::SizeType sizeType) | 236 static IntSize computeYUVSize(const jpeg_decompress_struct* info, int component) |
| 237 { | 237 { |
| 238 if (sizeType == ImageDecoder::SizeForMemoryAllocation) { | |
| 239 return IntSize(info->cur_comp_info[component]->width_in_blocks * DCTSIZE , info->cur_comp_info[component]->height_in_blocks * DCTSIZE); | |
| 240 } | |
| 241 return IntSize(info->cur_comp_info[component]->downsampled_width, info->cur_ comp_info[component]->downsampled_height); | 238 return IntSize(info->cur_comp_info[component]->downsampled_width, info->cur_ comp_info[component]->downsampled_height); |
| 242 } | 239 } |
| 243 | 240 |
| 241 static size_t computeYUVWidthBytes(const jpeg_decompress_struct* info, int compo nent) | |
| 242 { | |
| 243 return info->cur_comp_info[component]->width_in_blocks * DCTSIZE; | |
| 244 } | |
| 245 | |
| 244 static yuv_subsampling yuvSubsampling(const jpeg_decompress_struct& info) | 246 static yuv_subsampling yuvSubsampling(const jpeg_decompress_struct& info) |
| 245 { | 247 { |
| 246 if ((DCTSIZE == 8) | 248 if ((DCTSIZE == 8) |
| 247 && (info.num_components == 3) | 249 && (info.num_components == 3) |
| 248 && (info.comps_in_scan >= info.num_components) | 250 && (info.comps_in_scan >= info.num_components) |
| 249 && (info.scale_denom <= 8) | 251 && (info.scale_denom <= 8) |
| 250 && (info.cur_comp_info[0]) | 252 && (info.cur_comp_info[0]) |
| 251 && (info.cur_comp_info[1]) | 253 && (info.cur_comp_info[1]) |
| 252 && (info.cur_comp_info[2]) | 254 && (info.cur_comp_info[2]) |
| 253 && (info.cur_comp_info[1]->h_samp_factor == 1) | 255 && (info.cur_comp_info[1]->h_samp_factor == 1) |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 487 if (m_info.out_color_space == JCS_EXT_BGRA) | 489 if (m_info.out_color_space == JCS_EXT_BGRA) |
| 488 m_info.out_color_space = JCS_EXT_RGBA; | 490 m_info.out_color_space = JCS_EXT_RGBA; |
| 489 #endif | 491 #endif |
| 490 } | 492 } |
| 491 m_decoder->setHasColorProfile(!!m_transform); | 493 m_decoder->setHasColorProfile(!!m_transform); |
| 492 } | 494 } |
| 493 #endif | 495 #endif |
| 494 if (overrideColorSpace == JCS_YCbCr) { | 496 if (overrideColorSpace == JCS_YCbCr) { |
| 495 m_info.out_color_space = JCS_YCbCr; | 497 m_info.out_color_space = JCS_YCbCr; |
| 496 m_info.raw_data_out = TRUE; | 498 m_info.raw_data_out = TRUE; |
| 497 m_uvSize = computeYUVSize(&m_info, 1, ImageDecoder::SizeForMemor yAllocation); // U size and V size have to be the same if we got here | 499 m_uvSize = computeYUVSize(&m_info, 1); // U size and V size have to be the same if we got here |
| 498 } | 500 } |
| 499 | 501 |
| 500 // Don't allocate a giant and superfluous memory buffer when the | 502 // Don't allocate a giant and superfluous memory buffer when the |
| 501 // image is a sequential JPEG. | 503 // image is a sequential JPEG. |
| 502 m_info.buffered_image = jpeg_has_multiple_scans(&m_info); | 504 m_info.buffered_image = jpeg_has_multiple_scans(&m_info); |
| 503 if (m_info.buffered_image) { | 505 if (m_info.buffered_image) { |
| 504 m_err.pub.emit_message = emit_message; | 506 m_err.pub.emit_message = emit_message; |
| 505 m_err.num_corrupt_warnings = 0; | 507 m_err.num_corrupt_warnings = 0; |
| 506 } | 508 } |
| 507 | 509 |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 667 #endif | 669 #endif |
| 668 | 670 |
| 669 private: | 671 private: |
| 670 JSAMPARRAY allocateSampleArray() | 672 JSAMPARRAY allocateSampleArray() |
| 671 { | 673 { |
| 672 // Some output color spaces don't need the sample array: don't allocate in that case. | 674 // Some output color spaces don't need the sample array: don't allocate in that case. |
| 673 #if defined(TURBO_JPEG_RGB_SWIZZLE) | 675 #if defined(TURBO_JPEG_RGB_SWIZZLE) |
| 674 if (turboSwizzled(m_info.out_color_space)) | 676 if (turboSwizzled(m_info.out_color_space)) |
| 675 return nullptr; | 677 return nullptr; |
| 676 #endif | 678 #endif |
| 677 int width; | |
| 678 | 679 |
| 679 if (m_info.out_color_space == JCS_YCbCr) | 680 if (m_info.out_color_space == JCS_YCbCr) { |
| 680 width = computeYUVSize(&m_info, 0, ImageDecoder::SizeForMemoryAlloca tion).width(); | 681 // Compute the width of the Y plane in bytes. This may be larger th an the output |
| 681 else | 682 // width, since the jpeg library requires that the allocated width b e a multiple of |
| 682 width = m_info.output_width; | 683 // DCTSIZE. Note that this buffer will be used as garbage memory fo r rows that |
| 684 // extend below the actual height of the image. We can reuse the sa me memory for | |
| 685 // the U and V planes, since we are guaranteed that the Y plane widt h is at least | |
| 686 // 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.
| |
| 687 int widthBytes = computeYUVWidthBytes(&m_info, 0); | |
| 688 return (*m_info.mem->alloc_sarray)(reinterpret_cast_ptr<j_common_ptr >(&m_info), JPOOL_IMAGE, widthBytes, 1); | |
| 689 } | |
| 683 | 690 |
| 684 return (*m_info.mem->alloc_sarray)(reinterpret_cast_ptr<j_common_ptr>(&m _info), JPOOL_IMAGE, width * 4, 1); | 691 return (*m_info.mem->alloc_sarray)(reinterpret_cast_ptr<j_common_ptr>(&m _info), JPOOL_IMAGE, 4 * m_info.output_width, 1); |
| 685 } | 692 } |
| 686 | 693 |
| 687 void updateRestartPosition() | 694 void updateRestartPosition() |
| 688 { | 695 { |
| 689 if (m_lastSetByte != m_info.src->next_input_byte) { | 696 if (m_lastSetByte != m_info.src->next_input_byte) { |
| 690 // next_input_byte was updated by jpeg, meaning that it found a rest art position. | 697 // next_input_byte was updated by jpeg, meaning that it found a rest art position. |
| 691 m_restartPosition = m_nextReadPosition - m_info.src->bytes_in_buffer ; | 698 m_restartPosition = m_nextReadPosition - m_info.src->bytes_in_buffer ; |
| 692 } | 699 } |
| 693 } | 700 } |
| 694 | 701 |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 795 { | 802 { |
| 796 if (m_reader) | 803 if (m_reader) |
| 797 m_reader->setData(data); | 804 m_reader->setData(data); |
| 798 } | 805 } |
| 799 | 806 |
| 800 void JPEGImageDecoder::setDecodedSize(unsigned width, unsigned height) | 807 void JPEGImageDecoder::setDecodedSize(unsigned width, unsigned height) |
| 801 { | 808 { |
| 802 m_decodedSize = IntSize(width, height); | 809 m_decodedSize = IntSize(width, height); |
| 803 } | 810 } |
| 804 | 811 |
| 805 IntSize JPEGImageDecoder::decodedYUVSize(int component, ImageDecoder::SizeType s izeType) const | 812 IntSize JPEGImageDecoder::decodedYUVSize(int component) const |
| 806 { | 813 { |
| 807 ASSERT((component >= 0) && (component <= 2) && m_reader); | 814 ASSERT((component >= 0) && (component <= 2) && m_reader); |
| 808 const jpeg_decompress_struct* info = m_reader->info(); | 815 const jpeg_decompress_struct* info = m_reader->info(); |
| 809 | 816 |
| 810 ASSERT(info->out_color_space == JCS_YCbCr); | 817 ASSERT(info->out_color_space == JCS_YCbCr); |
| 811 return computeYUVSize(info, component, sizeType); | 818 return computeYUVSize(info, component); |
| 819 } | |
| 820 | |
| 821 size_t JPEGImageDecoder::decodedYUVWidthBytes(int component) const | |
| 822 { | |
| 823 ASSERT((component >= 0) && (component <= 2) && m_reader); | |
| 824 const jpeg_decompress_struct* info = m_reader->info(); | |
| 825 | |
| 826 ASSERT(info->out_color_space == JCS_YCbCr); | |
| 827 return computeYUVWidthBytes(info, component); | |
| 812 } | 828 } |
| 813 | 829 |
| 814 unsigned JPEGImageDecoder::desiredScaleNumerator() const | 830 unsigned JPEGImageDecoder::desiredScaleNumerator() const |
| 815 { | 831 { |
| 816 size_t originalBytes = size().width() * size().height() * 4; | 832 size_t originalBytes = size().width() * size().height() * 4; |
| 817 | 833 |
| 818 if (originalBytes <= m_maxDecodedBytes) | 834 if (originalBytes <= m_maxDecodedBytes) |
| 819 return scaleDenominator; | 835 return scaleDenominator; |
| 820 | 836 |
| 821 // Downsample according to the maximum decoded size. | 837 // Downsample according to the maximum decoded size. |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 906 static bool outputRawData(JPEGImageReader* reader, ImagePlanes* imagePlanes) | 922 static bool outputRawData(JPEGImageReader* reader, ImagePlanes* imagePlanes) |
| 907 { | 923 { |
| 908 JSAMPARRAY samples = reader->samples(); | 924 JSAMPARRAY samples = reader->samples(); |
| 909 jpeg_decompress_struct* info = reader->info(); | 925 jpeg_decompress_struct* info = reader->info(); |
| 910 | 926 |
| 911 JSAMPARRAY bufferraw[3]; | 927 JSAMPARRAY bufferraw[3]; |
| 912 JSAMPROW bufferraw2[32]; | 928 JSAMPROW bufferraw2[32]; |
| 913 bufferraw[0] = &bufferraw2[0]; // Y channel rows (8 or 16) | 929 bufferraw[0] = &bufferraw2[0]; // Y channel rows (8 or 16) |
| 914 bufferraw[1] = &bufferraw2[16]; // U channel rows (8) | 930 bufferraw[1] = &bufferraw2[16]; // U channel rows (8) |
| 915 bufferraw[2] = &bufferraw2[24]; // V channel rows (8) | 931 bufferraw[2] = &bufferraw2[24]; // V channel rows (8) |
| 916 int yWidth = info->output_width; | |
| 917 int yHeight = info->output_height; | 932 int yHeight = info->output_height; |
| 918 int yMaxH = yHeight - 1; | |
| 919 int v = info->cur_comp_info[0]->v_samp_factor; | 933 int v = info->cur_comp_info[0]->v_samp_factor; |
| 920 IntSize uvSize = reader->uvSize(); | 934 IntSize uvSize = reader->uvSize(); |
| 921 int uvMaxH = uvSize.height() - 1; | 935 int uvHeight = uvSize.height(); |
| 922 JSAMPROW outputY = static_cast<JSAMPROW>(imagePlanes->plane(0)); | 936 JSAMPROW outputY = static_cast<JSAMPROW>(imagePlanes->plane(0)); |
| 923 JSAMPROW outputU = static_cast<JSAMPROW>(imagePlanes->plane(1)); | 937 JSAMPROW outputU = static_cast<JSAMPROW>(imagePlanes->plane(1)); |
| 924 JSAMPROW outputV = static_cast<JSAMPROW>(imagePlanes->plane(2)); | 938 JSAMPROW outputV = static_cast<JSAMPROW>(imagePlanes->plane(2)); |
| 925 size_t rowBytesY = imagePlanes->rowBytes(0); | 939 size_t rowBytesY = imagePlanes->rowBytes(0); |
| 926 size_t rowBytesU = imagePlanes->rowBytes(1); | 940 size_t rowBytesU = imagePlanes->rowBytes(1); |
| 927 size_t rowBytesV = imagePlanes->rowBytes(2); | 941 size_t rowBytesV = imagePlanes->rowBytes(2); |
| 928 | 942 |
| 929 // Request 8 or 16 scanlines: returns 0 or more scanlines. | 943 // Request 8 or 16 scanlines: returns 0 or more scanlines. |
| 930 int yScanlinesToRead = DCTSIZE * v; | 944 int yScanlinesToRead = DCTSIZE * v; |
| 931 JSAMPROW yLastRow = *samples; | 945 JSAMPROW dummyRow = *samples; |
| 932 JSAMPROW uLastRow = yLastRow + rowBytesY; | |
| 933 JSAMPROW vLastRow = uLastRow + rowBytesY; | |
| 934 JSAMPROW dummyRow = vLastRow + rowBytesY; | |
| 935 | 946 |
| 936 while (info->output_scanline < info->output_height) { | 947 while (info->output_scanline < info->output_height) { |
| 937 // Assign 8 or 16 rows of memory to read the Y channel. | 948 // Assign 8 or 16 rows of memory to read the Y channel. |
| 938 bool hasYLastRow = false; | |
| 939 for (int i = 0; i < yScanlinesToRead; ++i) { | 949 for (int i = 0; i < yScanlinesToRead; ++i) { |
| 940 int scanline = info->output_scanline + i; | 950 int scanline = info->output_scanline + i; |
| 941 if (scanline < yMaxH) { | 951 if (scanline < yHeight) { |
| 942 bufferraw2[i] = &outputY[scanline * rowBytesY]; | 952 bufferraw2[i] = &outputY[scanline * rowBytesY]; |
| 943 } else if (scanline == yMaxH) { | |
| 944 bufferraw2[i] = yLastRow; | |
| 945 hasYLastRow = true; | |
| 946 } else { | 953 } else { |
| 947 bufferraw2[i] = dummyRow; | 954 bufferraw2[i] = dummyRow; |
| 948 } | 955 } |
| 949 } | 956 } |
| 950 | 957 |
| 951 // Assign 8 rows of memory to read the U and V channels. | 958 // Assign 8 rows of memory to read the U and V channels. |
| 952 bool hasUVLastRow = false; | |
| 953 int scaledScanline = info->output_scanline / v; | 959 int scaledScanline = info->output_scanline / v; |
| 954 for (int i = 0; i < 8; ++i) { | 960 for (int i = 0; i < 8; ++i) { |
| 955 int scanline = scaledScanline + i; | 961 int scanline = scaledScanline + i; |
| 956 if (scanline < uvMaxH) { | 962 if (scanline < uvHeight) { |
| 957 bufferraw2[16 + i] = &outputU[scanline * rowBytesU]; | 963 bufferraw2[16 + i] = &outputU[scanline * rowBytesU]; |
| 958 bufferraw2[24 + i] = &outputV[scanline * rowBytesV]; | 964 bufferraw2[24 + i] = &outputV[scanline * rowBytesV]; |
| 959 } else if (scanline == uvMaxH) { | |
| 960 bufferraw2[16 + i] = uLastRow; | |
| 961 bufferraw2[24 + i] = vLastRow; | |
| 962 hasUVLastRow = true; | |
| 963 } else { | 965 } else { |
| 964 bufferraw2[16 + i] = dummyRow; | 966 bufferraw2[16 + i] = dummyRow; |
| 965 bufferraw2[24 + i] = dummyRow; | 967 bufferraw2[24 + i] = dummyRow; |
| 966 } | 968 } |
| 967 } | 969 } |
| 968 | 970 |
| 969 JDIMENSION scanlinesRead = jpeg_read_raw_data(info, bufferraw, yScanline sToRead); | 971 JDIMENSION scanlinesRead = jpeg_read_raw_data(info, bufferraw, yScanline sToRead); |
| 970 if (!scanlinesRead) | 972 if (!scanlinesRead) |
| 971 return false; | 973 return false; |
| 972 | |
| 973 if (hasYLastRow) | |
| 974 memcpy(&outputY[yMaxH * rowBytesY], yLastRow, yWidth); | |
| 975 | |
| 976 if (hasUVLastRow) { | |
| 977 memcpy(&outputU[uvMaxH * rowBytesU], uLastRow, uvSize.width()); | |
| 978 memcpy(&outputV[uvMaxH * rowBytesV], vLastRow, uvSize.width()); | |
| 979 } | |
| 980 } | 974 } |
| 981 | 975 |
| 982 info->output_scanline = std::min(info->output_scanline, info->output_height) ; | 976 info->output_scanline = std::min(info->output_scanline, info->output_height) ; |
| 983 return true; | 977 return true; |
| 984 } | 978 } |
| 985 | 979 |
| 986 bool JPEGImageDecoder::outputScanlines() | 980 bool JPEGImageDecoder::outputScanlines() |
| 987 { | 981 { |
| 988 if (hasImagePlanes()) | 982 if (hasImagePlanes()) |
| 989 return outputRawData(m_reader.get(), m_imagePlanes.get()); | 983 return outputRawData(m_reader.get(), m_imagePlanes.get()); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1070 // has failed. | 1064 // has failed. |
| 1071 if (!m_reader->decode(onlySize) && isAllDataReceived()) | 1065 if (!m_reader->decode(onlySize) && isAllDataReceived()) |
| 1072 setFailed(); | 1066 setFailed(); |
| 1073 | 1067 |
| 1074 // If decoding is done or failed, we don't need the JPEGImageReader anymore. | 1068 // If decoding is done or failed, we don't need the JPEGImageReader anymore. |
| 1075 if (isComplete(this, onlySize) || failed()) | 1069 if (isComplete(this, onlySize) || failed()) |
| 1076 m_reader.clear(); | 1070 m_reader.clear(); |
| 1077 } | 1071 } |
| 1078 | 1072 |
| 1079 } // namespace blink | 1073 } // namespace blink |
| OLD | NEW |