| 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 return (*m_info.mem->alloc_sarray)(reinterpret_cast_ptr<j_common_ptr
>(&m_info), JPOOL_IMAGE, 4 * m_info.output_width, 1); |
| 681 else | |
| 682 width = m_info.output_width; | |
| 683 | 682 |
| 684 return (*m_info.mem->alloc_sarray)(reinterpret_cast_ptr<j_common_ptr>(&m
_info), JPOOL_IMAGE, width * 4, 1); | 683 // Compute the width of the Y plane in bytes. This may be larger than t
he output |
| 684 // width, since the jpeg library requires that the allocated width be a
multiple of |
| 685 // DCTSIZE. Note that this buffer will be used as garbage memory for ro
ws that |
| 686 // extend below the actual height of the image. We can reuse the same m
emory for |
| 687 // the U and V planes, since we are guaranteed that the Y plane width is
at least |
| 688 // as large as the U and V plane widths. |
| 689 int widthBytes = computeYUVWidthBytes(&m_info, 0); |
| 690 return (*m_info.mem->alloc_sarray)(reinterpret_cast_ptr<j_common_ptr>(&m
_info), JPOOL_IMAGE, widthBytes, 1); |
| 685 } | 691 } |
| 686 | 692 |
| 687 void updateRestartPosition() | 693 void updateRestartPosition() |
| 688 { | 694 { |
| 689 if (m_lastSetByte != m_info.src->next_input_byte) { | 695 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. | 696 // 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
; | 697 m_restartPosition = m_nextReadPosition - m_info.src->bytes_in_buffer
; |
| 692 } | 698 } |
| 693 } | 699 } |
| 694 | 700 |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 795 { | 801 { |
| 796 if (m_reader) | 802 if (m_reader) |
| 797 m_reader->setData(data); | 803 m_reader->setData(data); |
| 798 } | 804 } |
| 799 | 805 |
| 800 void JPEGImageDecoder::setDecodedSize(unsigned width, unsigned height) | 806 void JPEGImageDecoder::setDecodedSize(unsigned width, unsigned height) |
| 801 { | 807 { |
| 802 m_decodedSize = IntSize(width, height); | 808 m_decodedSize = IntSize(width, height); |
| 803 } | 809 } |
| 804 | 810 |
| 805 IntSize JPEGImageDecoder::decodedYUVSize(int component, ImageDecoder::SizeType s
izeType) const | 811 IntSize JPEGImageDecoder::decodedYUVSize(int component) const |
| 806 { | 812 { |
| 807 ASSERT((component >= 0) && (component <= 2) && m_reader); | 813 ASSERT((component >= 0) && (component <= 2) && m_reader); |
| 808 const jpeg_decompress_struct* info = m_reader->info(); | 814 const jpeg_decompress_struct* info = m_reader->info(); |
| 809 | 815 |
| 810 ASSERT(info->out_color_space == JCS_YCbCr); | 816 ASSERT(info->out_color_space == JCS_YCbCr); |
| 811 return computeYUVSize(info, component, sizeType); | 817 return computeYUVSize(info, component); |
| 818 } |
| 819 |
| 820 size_t JPEGImageDecoder::decodedYUVWidthBytes(int component) const |
| 821 { |
| 822 ASSERT((component >= 0) && (component <= 2) && m_reader); |
| 823 const jpeg_decompress_struct* info = m_reader->info(); |
| 824 |
| 825 ASSERT(info->out_color_space == JCS_YCbCr); |
| 826 return computeYUVWidthBytes(info, component); |
| 812 } | 827 } |
| 813 | 828 |
| 814 unsigned JPEGImageDecoder::desiredScaleNumerator() const | 829 unsigned JPEGImageDecoder::desiredScaleNumerator() const |
| 815 { | 830 { |
| 816 size_t originalBytes = size().width() * size().height() * 4; | 831 size_t originalBytes = size().width() * size().height() * 4; |
| 817 | 832 |
| 818 if (originalBytes <= m_maxDecodedBytes) | 833 if (originalBytes <= m_maxDecodedBytes) |
| 819 return scaleDenominator; | 834 return scaleDenominator; |
| 820 | 835 |
| 821 // Downsample according to the maximum decoded size. | 836 // 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) | 921 static bool outputRawData(JPEGImageReader* reader, ImagePlanes* imagePlanes) |
| 907 { | 922 { |
| 908 JSAMPARRAY samples = reader->samples(); | 923 JSAMPARRAY samples = reader->samples(); |
| 909 jpeg_decompress_struct* info = reader->info(); | 924 jpeg_decompress_struct* info = reader->info(); |
| 910 | 925 |
| 911 JSAMPARRAY bufferraw[3]; | 926 JSAMPARRAY bufferraw[3]; |
| 912 JSAMPROW bufferraw2[32]; | 927 JSAMPROW bufferraw2[32]; |
| 913 bufferraw[0] = &bufferraw2[0]; // Y channel rows (8 or 16) | 928 bufferraw[0] = &bufferraw2[0]; // Y channel rows (8 or 16) |
| 914 bufferraw[1] = &bufferraw2[16]; // U channel rows (8) | 929 bufferraw[1] = &bufferraw2[16]; // U channel rows (8) |
| 915 bufferraw[2] = &bufferraw2[24]; // V channel rows (8) | 930 bufferraw[2] = &bufferraw2[24]; // V channel rows (8) |
| 916 int yWidth = info->output_width; | |
| 917 int yHeight = info->output_height; | 931 int yHeight = info->output_height; |
| 918 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 uvHeight = uvSize.height(); |
| 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; |
| 932 JSAMPROW uLastRow = yLastRow + rowBytesY; | |
| 933 JSAMPROW vLastRow = uLastRow + rowBytesY; | |
| 934 JSAMPROW dummyRow = vLastRow + rowBytesY; | |
| 935 | |
| 936 while (info->output_scanline < info->output_height) { | 945 while (info->output_scanline < info->output_height) { |
| 937 // Assign 8 or 16 rows of memory to read the Y channel. | 946 // Assign 8 or 16 rows of memory to read the Y channel. |
| 938 bool hasYLastRow = false; | |
| 939 for (int i = 0; i < yScanlinesToRead; ++i) { | 947 for (int i = 0; i < yScanlinesToRead; ++i) { |
| 940 int scanline = info->output_scanline + i; | 948 int scanline = info->output_scanline + i; |
| 941 if (scanline < yMaxH) { | 949 if (scanline < yHeight) { |
| 942 bufferraw2[i] = &outputY[scanline * rowBytesY]; | 950 bufferraw2[i] = &outputY[scanline * rowBytesY]; |
| 943 } else if (scanline == yMaxH) { | |
| 944 bufferraw2[i] = yLastRow; | |
| 945 hasYLastRow = true; | |
| 946 } else { | 951 } else { |
| 947 bufferraw2[i] = dummyRow; | 952 bufferraw2[i] = dummyRow; |
| 948 } | 953 } |
| 949 } | 954 } |
| 950 | 955 |
| 951 // Assign 8 rows of memory to read the U and V channels. | 956 // Assign 8 rows of memory to read the U and V channels. |
| 952 bool hasUVLastRow = false; | |
| 953 int scaledScanline = info->output_scanline / v; | 957 int scaledScanline = info->output_scanline / v; |
| 954 for (int i = 0; i < 8; ++i) { | 958 for (int i = 0; i < 8; ++i) { |
| 955 int scanline = scaledScanline + i; | 959 int scanline = scaledScanline + i; |
| 956 if (scanline < uvMaxH) { | 960 if (scanline < uvHeight) { |
| 957 bufferraw2[16 + i] = &outputU[scanline * rowBytesU]; | 961 bufferraw2[16 + i] = &outputU[scanline * rowBytesU]; |
| 958 bufferraw2[24 + i] = &outputV[scanline * rowBytesV]; | 962 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 { | 963 } else { |
| 964 bufferraw2[16 + i] = dummyRow; | 964 bufferraw2[16 + i] = dummyRow; |
| 965 bufferraw2[24 + i] = dummyRow; | 965 bufferraw2[24 + i] = dummyRow; |
| 966 } | 966 } |
| 967 } | 967 } |
| 968 | 968 |
| 969 JDIMENSION scanlinesRead = jpeg_read_raw_data(info, bufferraw, yScanline
sToRead); | 969 JDIMENSION scanlinesRead = jpeg_read_raw_data(info, bufferraw, yScanline
sToRead); |
| 970 if (!scanlinesRead) | 970 if (!scanlinesRead) |
| 971 return false; | 971 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 } | 972 } |
| 981 | 973 |
| 982 info->output_scanline = std::min(info->output_scanline, info->output_height)
; | 974 info->output_scanline = std::min(info->output_scanline, info->output_height)
; |
| 983 return true; | 975 return true; |
| 984 } | 976 } |
| 985 | 977 |
| 986 bool JPEGImageDecoder::outputScanlines() | 978 bool JPEGImageDecoder::outputScanlines() |
| 987 { | 979 { |
| 988 if (hasImagePlanes()) | 980 if (hasImagePlanes()) |
| 989 return outputRawData(m_reader.get(), m_imagePlanes.get()); | 981 return outputRawData(m_reader.get(), m_imagePlanes.get()); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1070 // has failed. | 1062 // has failed. |
| 1071 if (!m_reader->decode(onlySize) && isAllDataReceived()) | 1063 if (!m_reader->decode(onlySize) && isAllDataReceived()) |
| 1072 setFailed(); | 1064 setFailed(); |
| 1073 | 1065 |
| 1074 // If decoding is done or failed, we don't need the JPEGImageReader anymore. | 1066 // If decoding is done or failed, we don't need the JPEGImageReader anymore. |
| 1075 if (isComplete(this, onlySize) || failed()) | 1067 if (isComplete(this, onlySize) || failed()) |
| 1076 m_reader.clear(); | 1068 m_reader.clear(); |
| 1077 } | 1069 } |
| 1078 | 1070 |
| 1079 } // namespace blink | 1071 } // namespace blink |
| OLD | NEW |