diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp')
-rw-r--r-- | Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp | 162 |
1 files changed, 33 insertions, 129 deletions
diff --git a/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp b/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp index 38e18d3ee..40bd88bbc 100644 --- a/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp +++ b/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 Apple Computer, Inc. + * Copyright (C) 2006 Apple Inc. * * Portions are Copyright (C) 2001-6 mozilla.org * @@ -39,14 +39,10 @@ #include "config.h" #include "JPEGImageDecoder.h" -#include <wtf/PassOwnPtr.h> extern "C" { #if USE(ICCJPEG) -#include "iccjpeg.h" -#endif -#if USE(QCMSLIB) -#include "qcms.h" +#include <iccjpeg.h> #endif #include <setjmp.h> } @@ -200,36 +196,6 @@ static ImageOrientation readImageOrientation(jpeg_decompress_struct* info) return ImageOrientation(); } -static ColorProfile readColorProfile(jpeg_decompress_struct* info) -{ -#if USE(ICCJPEG) - JOCTET* profile; - unsigned int profileLength; - - if (!read_icc_profile(info, &profile, &profileLength)) - return ColorProfile(); - - // Only accept RGB color profiles from input class devices. - bool ignoreProfile = false; - char* profileData = reinterpret_cast<char*>(profile); - if (profileLength < ImageDecoder::iccColorProfileHeaderLength) - ignoreProfile = true; - else if (!ImageDecoder::rgbColorProfile(profileData, profileLength)) - ignoreProfile = true; - else if (!ImageDecoder::inputDeviceColorProfile(profileData, profileLength)) - ignoreProfile = true; - - ColorProfile colorProfile; - if (!ignoreProfile) - colorProfile.append(profileData, profileLength); - free(profile); - return colorProfile; -#else - UNUSED_PARAM(info); - return ColorProfile(); -#endif -} - class JPEGImageReader { WTF_MAKE_FAST_ALLOCATED; public: @@ -239,9 +205,6 @@ public: , m_bytesToSkip(0) , m_state(JPEG_HEADER) , m_samples(0) -#if USE(QCMSLIB) - , m_transform(0) -#endif { memset(&m_info, 0, sizeof(jpeg_decompress_struct)); @@ -292,11 +255,6 @@ public: fastFree(src); m_info.src = 0; -#if USE(QCMSLIB) - if (m_transform) - qcms_transform_release(m_transform); - m_transform = 0; -#endif jpeg_destroy_decompress(&m_info); } @@ -333,7 +291,7 @@ public: switch (m_state) { case JPEG_HEADER: // Read file parameters with jpeg_read_header(). - if (jpeg_read_header(&m_info, true) == JPEG_SUSPENDED) + if (jpeg_read_header(&m_info, TRUE) == JPEG_SUSPENDED) return false; // I/O suspension. switch (m_info.jpeg_color_space) { @@ -364,7 +322,7 @@ public: m_state = JPEG_START_DECOMPRESS; // We can fill in the size now that the header is available. - if (!m_decoder->setSize(m_info.image_width, m_info.image_height)) + if (!m_decoder->setSize(IntSize(m_info.image_width, m_info.image_height))) return false; m_decoder->setOrientation(readImageOrientation(info())); @@ -375,21 +333,6 @@ public: if (m_decoder->willDownSample() && turboSwizzled(m_info.out_color_space)) m_info.out_color_space = JCS_RGB; #endif - // Allow color management of the decoded RGBA pixels if possible. - if (!m_decoder->ignoresGammaAndColorProfile()) { - ColorProfile rgbInputDeviceColorProfile = readColorProfile(info()); - if (!rgbInputDeviceColorProfile.isEmpty()) - m_decoder->setColorProfile(rgbInputDeviceColorProfile); -#if USE(QCMSLIB) - createColorTransform(rgbInputDeviceColorProfile, colorSpaceHasAlpha(m_info.out_color_space)); -#if defined(TURBO_JPEG_RGB_SWIZZLE) - // Input RGBA data to qcms. Note: restored to BGRA on output. - if (m_transform && m_info.out_color_space == JCS_EXT_BGRA) - m_info.out_color_space = JCS_EXT_RGBA; -#endif -#endif - } - // Don't allocate a giant and superfluous memory buffer when the // image is a sequential JPEG. m_info.buffered_image = jpeg_has_multiple_scans(&m_info); @@ -419,9 +362,9 @@ public: // of progressive JPEG. m_info.dct_method = dctMethod(); m_info.dither_mode = ditherMode(); - m_info.do_fancy_upsampling = doFancyUpsampling(); - m_info.enable_2pass_quant = false; - m_info.do_block_smoothing = true; + m_info.do_fancy_upsampling = doFancyUpsampling() ? TRUE : FALSE; + m_info.enable_2pass_quant = FALSE; + m_info.do_block_smoothing = TRUE; // Start decompressor. if (!jpeg_start_decompress(&m_info)) @@ -467,7 +410,13 @@ public: if (m_info.output_scanline == 0xffffff) m_info.output_scanline = 0; - if (!m_decoder->outputScanlines()) { + // If outputScanlines() fails, it deletes |this|. Therefore, + // copy the decoder pointer and use it to check for failure + // to avoid member access in the failure case. + JPEGImageDecoder* decoder = m_decoder; + if (!decoder->outputScanlines()) { + if (decoder->failed()) // Careful; |this| is deleted. + return false; if (!m_info.output_scanline) // Didn't manage to read any lines - flag so we // don't call jpeg_start_output() multiple times for @@ -506,31 +455,6 @@ public: jpeg_decompress_struct* info() { return &m_info; } JSAMPARRAY samples() const { return m_samples; } JPEGImageDecoder* decoder() { return m_decoder; } -#if USE(QCMSLIB) - qcms_transform* colorTransform() const { return m_transform; } - - void createColorTransform(const ColorProfile& colorProfile, bool hasAlpha) - { - if (m_transform) - qcms_transform_release(m_transform); - m_transform = 0; - - if (colorProfile.isEmpty()) - return; - qcms_profile* deviceProfile = ImageDecoder::qcmsOutputDeviceProfile(); - if (!deviceProfile) - return; - qcms_profile* inputProfile = qcms_profile_from_memory(colorProfile.data(), colorProfile.size()); - if (!inputProfile) - return; - // We currently only support color profiles for RGB profiled images. - ASSERT(icSigRgbData == qcms_profile_get_color_space(inputProfile)); - qcms_data_type dataFormat = hasAlpha ? QCMS_DATA_RGBA_8 : QCMS_DATA_RGB_8; - // FIXME: Don't force perceptual intent if the image profile contains an intent. - m_transform = qcms_transform_create(inputProfile, dataFormat, deviceProfile, dataFormat, QCMS_INTENT_PERCEPTUAL); - qcms_profile_release(inputProfile); - } -#endif private: JPEGImageDecoder* m_decoder; @@ -543,10 +467,6 @@ private: jstate m_state; JSAMPARRAY m_samples; - -#if USE(QCMSLIB) - qcms_transform* m_transform; -#endif }; // Override the standard error method in the IJG JPEG decoder code. @@ -572,7 +492,7 @@ boolean fill_input_buffer(j_decompress_ptr) // Our decode step always sets things up properly, so if this method is ever // called, then we have hit the end of the buffer. A return value of false // indicates that we have no data to supply yet. - return false; + return FALSE; } void term_source(j_decompress_ptr jd) @@ -581,8 +501,7 @@ void term_source(j_decompress_ptr jd) src->decoder->decoder()->jpegComplete(); } -JPEGImageDecoder::JPEGImageDecoder(ImageSource::AlphaOption alphaOption, - ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption) +JPEGImageDecoder::JPEGImageDecoder(AlphaOption alphaOption, GammaAndColorProfileOption gammaAndColorProfileOption) : ImageDecoder(alphaOption, gammaAndColorProfileOption) { } @@ -599,9 +518,9 @@ bool JPEGImageDecoder::isSizeAvailable() return ImageDecoder::isSizeAvailable(); } -bool JPEGImageDecoder::setSize(unsigned width, unsigned height) +bool JPEGImageDecoder::setSize(const IntSize& size) { - if (!ImageDecoder::setSize(width, height)) + if (!ImageDecoder::setSize(size)) return false; prepareScaleDataIfNecessary(); @@ -613,31 +532,29 @@ ImageFrame* JPEGImageDecoder::frameBufferAtIndex(size_t index) if (index) return 0; - if (m_frameBufferCache.isEmpty()) { + if (m_frameBufferCache.isEmpty()) m_frameBufferCache.resize(1); - m_frameBufferCache[0].setPremultiplyAlpha(m_premultiplyAlpha); - } ImageFrame& frame = m_frameBufferCache[0]; - if (frame.status() != ImageFrame::FrameComplete) + if (!frame.isComplete()) decode(false); return &frame; } bool JPEGImageDecoder::setFailed() { - m_reader.clear(); + m_reader = nullptr; return ImageDecoder::setFailed(); } template <J_COLOR_SPACE colorSpace> -void setPixel(ImageFrame& buffer, ImageFrame::PixelData* currentAddress, JSAMPARRAY samples, int column) +void setPixel(ImageFrame& buffer, RGBA32* currentAddress, JSAMPARRAY samples, int column) { JSAMPLE* jsample = *samples + column * (colorSpace == JCS_RGB ? 3 : 4); switch (colorSpace) { case JCS_RGB: - buffer.setRGBA(currentAddress, jsample[0], jsample[1], jsample[2], 0xFF); + buffer.backingStore()->setPixel(currentAddress, jsample[0], jsample[1], jsample[2], 0xFF); break; case JCS_CMYK: // Source is 'Inverted CMYK', output is RGB. @@ -650,7 +567,7 @@ void setPixel(ImageFrame& buffer, ImageFrame::PixelData* currentAddress, JSAMPAR // From CMY (0..1) to RGB (0..1): // R = 1 - C => 1 - (1 - iC*iK) => iC*iK [G and B similar] unsigned k = jsample[3]; - buffer.setRGBA(currentAddress, jsample[0] * k / 255, jsample[1] * k / 255, jsample[2] * k / 255, 0xFF); + buffer.backingStore()->setPixel(currentAddress, jsample[0] * k / 255, jsample[1] * k / 255, jsample[2] * k / 255, 0xFF); break; } } @@ -674,12 +591,7 @@ bool JPEGImageDecoder::outputScanlines(ImageFrame& buffer) if (destY < 0) continue; -#if USE(QCMSLIB) - if (m_reader->colorTransform() && colorSpace == JCS_RGB) - qcms_transform_data(m_reader->colorTransform(), *samples, *samples, info->output_width); -#endif - - ImageFrame::PixelData* currentAddress = buffer.getAddr(0, destY); + RGBA32* currentAddress = buffer.backingStore()->pixelAt(0, destY); for (int x = 0; x < width; ++x) { setPixel<colorSpace>(buffer, currentAddress, samples, isScaled ? m_scaledColumns[x] : x); ++currentAddress; @@ -701,17 +613,13 @@ bool JPEGImageDecoder::outputScanlines() // Initialize the framebuffer if needed. ImageFrame& buffer = m_frameBufferCache[0]; - if (buffer.status() == ImageFrame::FrameEmpty) { - if (!buffer.setSize(scaledSize().width(), scaledSize().height())) + if (buffer.isEmpty()) { + if (!buffer.initialize(scaledSize(), m_premultiplyAlpha)) return setFailed(); - buffer.setStatus(ImageFrame::FramePartial); + buffer.setDecoding(ImageFrame::Decoding::Partial); // The buffer is transparent outside the decoded area while the image is // loading. The completed image will be marked fully opaque in jpegComplete(). buffer.setHasAlpha(true); - buffer.setColorProfile(m_colorProfile); - - // For JPEGs, the frame always fills the entire image. - buffer.setOriginalFrameRect(IntRect(IntPoint(), size())); } jpeg_decompress_struct* info = m_reader->info(); @@ -719,13 +627,9 @@ bool JPEGImageDecoder::outputScanlines() #if defined(TURBO_JPEG_RGB_SWIZZLE) if (!m_scaled && turboSwizzled(info->out_color_space)) { while (info->output_scanline < info->output_height) { - unsigned char* row = reinterpret_cast<unsigned char*>(buffer.getAddr(0, info->output_scanline)); + unsigned char* row = reinterpret_cast<unsigned char*>(buffer.backingStore()->pixelAt(0, info->output_scanline)); if (jpeg_read_scanlines(info, &row, 1) != 1) return false; -#if USE(QCMSLIB) - if (qcms_transform* transform = m_reader->colorTransform()) - qcms_transform_data_type(transform, row, row, info->output_width, rgbOutputColorSpace() == JCS_EXT_BGRA ? QCMS_OUTPUT_BGRX : QCMS_OUTPUT_RGBX); -#endif } return true; } @@ -756,7 +660,7 @@ void JPEGImageDecoder::jpegComplete() // empty. ImageFrame& buffer = m_frameBufferCache[0]; buffer.setHasAlpha(false); - buffer.setStatus(ImageFrame::FrameComplete); + buffer.setDecoding(ImageFrame::Decoding::Complete); } void JPEGImageDecoder::decode(bool onlySize) @@ -765,7 +669,7 @@ void JPEGImageDecoder::decode(bool onlySize) return; if (!m_reader) - m_reader = adoptPtr(new JPEGImageReader(this)); + m_reader = std::make_unique<JPEGImageReader>(this); // If we couldn't decode the image but we've received all the data, decoding // has failed. @@ -773,8 +677,8 @@ void JPEGImageDecoder::decode(bool onlySize) setFailed(); // If we're done decoding the image, we don't need the JPEGImageReader // anymore. (If we failed, |m_reader| has already been cleared.) - else if (!m_frameBufferCache.isEmpty() && (m_frameBufferCache[0].status() == ImageFrame::FrameComplete)) - m_reader.clear(); + else if (!m_frameBufferCache.isEmpty() && (m_frameBufferCache[0].isComplete())) + m_reader = nullptr; } } |