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; | 679 int width, bpp; |
| 678 | 680 |
| 679 if (m_info.out_color_space == JCS_YCbCr) | 681 if (m_info.out_color_space == JCS_YCbCr) { |
| 680 width = computeYUVSize(&m_info, 0, ImageDecoder::SizeForMemoryAlloca tion).width(); | 682 width = computeYUVWidthBytes(&m_info, 0); |
| 681 else | 683 bpp = 1; |
| 684 } else { | |
| 682 width = m_info.output_width; | 685 width = m_info.output_width; |
| 686 bpp = 4; | |
|
msarett
2016/02/22 20:56:31
I suspect that this can/should be 3. But that is
scroggo_chromium
2016/02/24 13:09:43
According to a comment at the call site [1], it sh
| |
| 687 } | |
| 683 | 688 |
| 684 return (*m_info.mem->alloc_sarray)(reinterpret_cast_ptr<j_common_ptr>(&m _info), JPOOL_IMAGE, width * 4, 1); | 689 return (*m_info.mem->alloc_sarray)(reinterpret_cast_ptr<j_common_ptr>(&m _info), JPOOL_IMAGE, width * bpp, 1); |
| 685 } | 690 } |
| 686 | 691 |
| 687 void updateRestartPosition() | 692 void updateRestartPosition() |
| 688 { | 693 { |
| 689 if (m_lastSetByte != m_info.src->next_input_byte) { | 694 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. | 695 // 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 ; | 696 m_restartPosition = m_nextReadPosition - m_info.src->bytes_in_buffer ; |
| 692 } | 697 } |
| 693 } | 698 } |
| 694 | 699 |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 795 { | 800 { |
| 796 if (m_reader) | 801 if (m_reader) |
| 797 m_reader->setData(data); | 802 m_reader->setData(data); |
| 798 } | 803 } |
| 799 | 804 |
| 800 void JPEGImageDecoder::setDecodedSize(unsigned width, unsigned height) | 805 void JPEGImageDecoder::setDecodedSize(unsigned width, unsigned height) |
| 801 { | 806 { |
| 802 m_decodedSize = IntSize(width, height); | 807 m_decodedSize = IntSize(width, height); |
| 803 } | 808 } |
| 804 | 809 |
| 805 IntSize JPEGImageDecoder::decodedYUVSize(int component, ImageDecoder::SizeType s izeType) const | 810 IntSize JPEGImageDecoder::decodedYUVSize(int component) const |
| 806 { | 811 { |
| 807 ASSERT((component >= 0) && (component <= 2) && m_reader); | 812 ASSERT((component >= 0) && (component <= 2) && m_reader); |
| 808 const jpeg_decompress_struct* info = m_reader->info(); | 813 const jpeg_decompress_struct* info = m_reader->info(); |
| 809 | 814 |
| 810 ASSERT(info->out_color_space == JCS_YCbCr); | 815 ASSERT(info->out_color_space == JCS_YCbCr); |
| 811 return computeYUVSize(info, component, sizeType); | 816 return computeYUVSize(info, component); |
| 817 } | |
| 818 | |
| 819 size_t JPEGImageDecoder::decodedYUVWidthBytes(int component) const | |
| 820 { | |
| 821 ASSERT((component >= 0) && (component <= 2) && m_reader); | |
| 822 const jpeg_decompress_struct* info = m_reader->info(); | |
| 823 | |
| 824 ASSERT(info->out_color_space == JCS_YCbCr); | |
| 825 return computeYUVWidthBytes(info, component); | |
| 812 } | 826 } |
| 813 | 827 |
| 814 unsigned JPEGImageDecoder::desiredScaleNumerator() const | 828 unsigned JPEGImageDecoder::desiredScaleNumerator() const |
| 815 { | 829 { |
| 816 size_t originalBytes = size().width() * size().height() * 4; | 830 size_t originalBytes = size().width() * size().height() * 4; |
| 817 | 831 |
| 818 if (originalBytes <= m_maxDecodedBytes) | 832 if (originalBytes <= m_maxDecodedBytes) |
| 819 return scaleDenominator; | 833 return scaleDenominator; |
| 820 | 834 |
| 821 // Downsample according to the maximum decoded size. | 835 // 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) | 920 static bool outputRawData(JPEGImageReader* reader, ImagePlanes* imagePlanes) |
| 907 { | 921 { |
| 908 JSAMPARRAY samples = reader->samples(); | 922 JSAMPARRAY samples = reader->samples(); |
| 909 jpeg_decompress_struct* info = reader->info(); | 923 jpeg_decompress_struct* info = reader->info(); |
| 910 | 924 |
| 911 JSAMPARRAY bufferraw[3]; | 925 JSAMPARRAY bufferraw[3]; |
| 912 JSAMPROW bufferraw2[32]; | 926 JSAMPROW bufferraw2[32]; |
| 913 bufferraw[0] = &bufferraw2[0]; // Y channel rows (8 or 16) | 927 bufferraw[0] = &bufferraw2[0]; // Y channel rows (8 or 16) |
| 914 bufferraw[1] = &bufferraw2[16]; // U channel rows (8) | 928 bufferraw[1] = &bufferraw2[16]; // U channel rows (8) |
| 915 bufferraw[2] = &bufferraw2[24]; // V channel rows (8) | 929 bufferraw[2] = &bufferraw2[24]; // V channel rows (8) |
| 916 int yWidth = info->output_width; | |
| 917 int yHeight = info->output_height; | 930 int yHeight = info->output_height; |
| 918 int yMaxH = yHeight - 1; | 931 int yMaxH = yHeight - 1; |
| 919 int v = info->cur_comp_info[0]->v_samp_factor; | 932 int v = info->cur_comp_info[0]->v_samp_factor; |
| 920 IntSize uvSize = reader->uvSize(); | 933 IntSize uvSize = reader->uvSize(); |
| 921 int uvMaxH = uvSize.height() - 1; | 934 int uvMaxH = uvSize.height() - 1; |
| 922 JSAMPROW outputY = static_cast<JSAMPROW>(imagePlanes->plane(0)); | 935 JSAMPROW outputY = static_cast<JSAMPROW>(imagePlanes->plane(0)); |
| 923 JSAMPROW outputU = static_cast<JSAMPROW>(imagePlanes->plane(1)); | 936 JSAMPROW outputU = static_cast<JSAMPROW>(imagePlanes->plane(1)); |
| 924 JSAMPROW outputV = static_cast<JSAMPROW>(imagePlanes->plane(2)); | 937 JSAMPROW outputV = static_cast<JSAMPROW>(imagePlanes->plane(2)); |
| 925 size_t rowBytesY = imagePlanes->rowBytes(0); | 938 size_t rowBytesY = imagePlanes->rowBytes(0); |
| 926 size_t rowBytesU = imagePlanes->rowBytes(1); | 939 size_t rowBytesU = imagePlanes->rowBytes(1); |
| 927 size_t rowBytesV = imagePlanes->rowBytes(2); | 940 size_t rowBytesV = imagePlanes->rowBytes(2); |
| 928 | 941 |
| 929 // Request 8 or 16 scanlines: returns 0 or more scanlines. | 942 // Request 8 or 16 scanlines: returns 0 or more scanlines. |
| 930 int yScanlinesToRead = DCTSIZE * v; | 943 int yScanlinesToRead = DCTSIZE * v; |
| 931 JSAMPROW yLastRow = *samples; | 944 JSAMPROW dummyRow = *samples; |
|
msarett
2016/02/22 20:56:31
No need to track the last row and perform a memcpy
|
msarett
2016/02/22 20:56:31
Notice that we use a dummy row when the height of
|
| 932 JSAMPROW uLastRow = yLastRow + rowBytesY; | |
| 933 JSAMPROW vLastRow = uLastRow + rowBytesY; | |
| 934 JSAMPROW dummyRow = vLastRow + rowBytesY; | |
| 935 | 945 |
| 936 while (info->output_scanline < info->output_height) { | 946 while (info->output_scanline < info->output_height) { |
| 937 // Assign 8 or 16 rows of memory to read the Y channel. | 947 // Assign 8 or 16 rows of memory to read the Y channel. |
| 938 bool hasYLastRow = false; | |
| 939 for (int i = 0; i < yScanlinesToRead; ++i) { | 948 for (int i = 0; i < yScanlinesToRead; ++i) { |
| 940 int scanline = info->output_scanline + i; | 949 int scanline = info->output_scanline + i; |
| 941 if (scanline < yMaxH) { | 950 if (scanline < yMaxH) { |
| 942 bufferraw2[i] = &outputY[scanline * rowBytesY]; | 951 bufferraw2[i] = &outputY[scanline * rowBytesY]; |
| 943 } else if (scanline == yMaxH) { | |
| 944 bufferraw2[i] = yLastRow; | |
| 945 hasYLastRow = true; | |
| 946 } else { | 952 } else { |
| 947 bufferraw2[i] = dummyRow; | 953 bufferraw2[i] = dummyRow; |
| 948 } | 954 } |
| 949 } | 955 } |
| 950 | 956 |
| 951 // Assign 8 rows of memory to read the U and V channels. | 957 // Assign 8 rows of memory to read the U and V channels. |
| 952 bool hasUVLastRow = false; | |
| 953 int scaledScanline = info->output_scanline / v; | 958 int scaledScanline = info->output_scanline / v; |
| 954 for (int i = 0; i < 8; ++i) { | 959 for (int i = 0; i < 8; ++i) { |
| 955 int scanline = scaledScanline + i; | 960 int scanline = scaledScanline + i; |
| 956 if (scanline < uvMaxH) { | 961 if (scanline < uvMaxH) { |
| 957 bufferraw2[16 + i] = &outputU[scanline * rowBytesU]; | 962 bufferraw2[16 + i] = &outputU[scanline * rowBytesU]; |
| 958 bufferraw2[24 + i] = &outputV[scanline * rowBytesV]; | 963 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 { | 964 } else { |
| 964 bufferraw2[16 + i] = dummyRow; | 965 bufferraw2[16 + i] = dummyRow; |
| 965 bufferraw2[24 + i] = dummyRow; | 966 bufferraw2[24 + i] = dummyRow; |
| 966 } | 967 } |
| 967 } | 968 } |
| 968 | 969 |
| 969 JDIMENSION scanlinesRead = jpeg_read_raw_data(info, bufferraw, yScanline sToRead); | 970 JDIMENSION scanlinesRead = jpeg_read_raw_data(info, bufferraw, yScanline sToRead); |
| 970 if (!scanlinesRead) | 971 if (!scanlinesRead) |
| 971 return false; | 972 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 } | 973 } |
| 981 | 974 |
| 982 info->output_scanline = std::min(info->output_scanline, info->output_height) ; | 975 info->output_scanline = std::min(info->output_scanline, info->output_height) ; |
| 983 return true; | 976 return true; |
| 984 } | 977 } |
| 985 | 978 |
| 986 bool JPEGImageDecoder::outputScanlines() | 979 bool JPEGImageDecoder::outputScanlines() |
| 987 { | 980 { |
| 988 if (hasImagePlanes()) | 981 if (hasImagePlanes()) |
| 989 return outputRawData(m_reader.get(), m_imagePlanes.get()); | 982 return outputRawData(m_reader.get(), m_imagePlanes.get()); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1070 // has failed. | 1063 // has failed. |
| 1071 if (!m_reader->decode(onlySize) && isAllDataReceived()) | 1064 if (!m_reader->decode(onlySize) && isAllDataReceived()) |
| 1072 setFailed(); | 1065 setFailed(); |
| 1073 | 1066 |
| 1074 // If decoding is done or failed, we don't need the JPEGImageReader anymore. | 1067 // If decoding is done or failed, we don't need the JPEGImageReader anymore. |
| 1075 if (isComplete(this, onlySize) || failed()) | 1068 if (isComplete(this, onlySize) || failed()) |
| 1076 m_reader.clear(); | 1069 m_reader.clear(); |
| 1077 } | 1070 } |
| 1078 | 1071 |
| 1079 } // namespace blink | 1072 } // namespace blink |
| OLD | NEW |