unsigned ImageDecoder::frameBytesAtIndex(size_t index, SubsamplingLevel subsamplingLevel) const { if (!m_nativeDecoder) return 0; auto frameSize = frameSizeAtIndex(index, subsamplingLevel); return (frameSize.area() * 4).unsafeGet(); }
IntSize ImageSource::frameSizeAtIndex(size_t index, ImageOrientationDescription description) const { RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyPropertiesAtIndex(m_decoder, index, imageSourceOptions(SkipMetadata))); if (!properties) return IntSize(); int w = 0, h = 0; CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyPixelWidth); if (num) CFNumberGetValue(num, kCFNumberIntType, &w); num = (CFNumberRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyPixelHeight); if (num) CFNumberGetValue(num, kCFNumberIntType, &h); #if PLATFORM(IOS) if (!m_isProgressive) { CFDictionaryRef jfifProperties = static_cast<CFDictionaryRef>(CFDictionaryGetValue(properties.get(), kCGImagePropertyJFIFDictionary)); if (jfifProperties) { CFBooleanRef isProgCFBool = static_cast<CFBooleanRef>(CFDictionaryGetValue(jfifProperties, kCGImagePropertyJFIFIsProgressive)); if (isProgCFBool) m_isProgressive = CFBooleanGetValue(isProgCFBool); // Workaround for <rdar://problem/5184655> - Hang rendering very large progressive JPEG. Decoding progressive // images hangs for a very long time right now. Until this is fixed, don't sub-sample progressive images. This // will cause them to fail our large image check and they won't be decoded. // FIXME: Remove once underlying issue is fixed (<rdar://problem/5191418>) } } if ((m_baseSubsampling == 0) && !m_isProgressive) { IntSize subsampledSize(w, h); const int cMaximumImageSizeBeforeSubsampling = 5 * 1024 * 1024; while ((m_baseSubsampling < 3) && subsampledSize.width() * subsampledSize.height() > cMaximumImageSizeBeforeSubsampling) { // We know the size, but the actual image is very large and should be sub-sampled. // Increase the base subsampling and ask for the size again. If the image can be subsampled, the size will be // greatly reduced. 4x sub-sampling will make us support up to 320MP (5MP * 4^3) images, which should be plenty. // There's no callback from ImageIO when the size is available, so we do the check when we happen // to check the size and its non - zero. // Note: Some clients of this class don't call isSizeAvailable() so we can't rely on that. ++m_baseSubsampling; subsampledSize = frameSizeAtIndex(index, description.respectImageOrientation()); } w = subsampledSize.width(); h = subsampledSize.height(); } #endif if ((description.respectImageOrientation() == RespectImageOrientation) && orientationFromProperties(properties.get()).usesWidthAsHeight()) return IntSize(h, w); return IntSize(w, h); }
size_t ImageDecoder::frameBytesAtIndex(size_t index) const { if (index >= m_frameBufferCache.size() || m_frameBufferCache[index].getStatus() == ImageFrame::FrameEmpty) return 0; struct ImageSize { explicit ImageSize(IntSize size) { area = static_cast<uint64_t>(size.width()) * size.height(); } uint64_t area; }; return ImageSize(frameSizeAtIndex(index)).area * sizeof(ImageFrame::PixelData); }
IntSize ImageSource::originalSize(RespectImageOrientationEnum shouldRespectOrientation) const { frameSizeAtIndex(0, shouldRespectOrientation); RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyPropertiesAtIndex(m_decoder, 0, imageSourceOptions(SkipMetadata, -1))); if (!properties) return IntSize(); int width = 0; int height = 0; CFNumberRef number = (CFNumberRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyPixelWidth); if (number) CFNumberGetValue(number, kCFNumberIntType, &width); number = static_cast<CFNumberRef>(CFDictionaryGetValue(properties.get(), kCGImagePropertyPixelHeight)); if (number) CFNumberGetValue(number, kCFNumberIntType, &height); if ((shouldRespectOrientation == RespectImageOrientation) && orientationFromProperties(properties.get()).usesWidthAsHeight()) return IntSize(height, width); return IntSize(width, height); }
IntSize ImageSource::size() const { return frameSizeAtIndex(0); }
unsigned ImageDecoder::frameBytesAtIndex(size_t index, SubsamplingLevel subsamplingLevel) const { IntSize frameSize = frameSizeAtIndex(index, subsamplingLevel); return (frameSize.area() * 4).unsafeGet(); }
unsigned ImageSource::frameBytesAtIndex(size_t index, SubsamplingLevel subsamplingLevel) const { IntSize frameSize = frameSizeAtIndex(index, subsamplingLevel, ImageOrientationDescription(RespectImageOrientation)); return frameSize.width() * frameSize.height() * 4; }
IntSize ImageSource::size(ImageOrientationDescription description) const { return frameSizeAtIndex(0, 0, description); }
IntSize ImageSource::size(RespectImageOrientationEnum shouldRespectOrientation) const { return frameSizeAtIndex(0, shouldRespectOrientation); }
size_t ImageDecoder::frameBytesAtIndex(size_t index) const { if (index >= m_frameBufferCache.size() || m_frameBufferCache[index].status() == ImageFrame::FrameEmpty) return 0; return frameSizeAtIndex(index).area() * sizeof(ImageFrame::PixelData); }
unsigned ImageSource::frameBytesAtIndex(size_t index) const { IntSize frameSize = frameSizeAtIndex(index, RespectImageOrientation); return frameSize.width() * frameSize.height() * 4; }