Пример #1
0
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);
}
Пример #2
0
void BitmapImage::draw(GraphicsContext& context, const FloatRect& dst, const FloatRect& src, CompositeOperator op,
    BlendMode blendMode, ImageOrientationDescription description)
{
    if (!dst.width() || !dst.height() || !src.width() || !src.height())
        return;

    startAnimation();

    auto surface = frameImageAtIndex(m_currentFrame);
    if (!surface) // If it's too early we won't have an image yet.
        return;

    Color color = singlePixelSolidColor();
    if (color.isValid()) {
        fillWithSolidColor(context, dst, color, op);
        return;
    }

    context.save();

    // Set the compositing operation.
    if (op == CompositeSourceOver && blendMode == BlendModeNormal && !frameHasAlphaAtIndex(m_currentFrame))
        context.setCompositeOperation(CompositeCopy);
    else
        context.setCompositeOperation(op, blendMode);

#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
    IntSize scaledSize = cairoSurfaceSize(surface.get());
    FloatRect adjustedSrcRect = adjustSourceRectForDownSampling(src, scaledSize);
#else
    FloatRect adjustedSrcRect(src);
#endif

    ImageOrientation frameOrientation(description.imageOrientation());
    if (description.respectImageOrientation() == RespectImageOrientation)
        frameOrientation = frameOrientationAtIndex(m_currentFrame);

    FloatRect dstRect = dst;

    if (frameOrientation != DefaultImageOrientation) {
        // ImageOrientation expects the origin to be at (0, 0).
        context.translate(dstRect.x(), dstRect.y());
        dstRect.setLocation(FloatPoint());
        context.concatCTM(frameOrientation.transformFromDefault(dstRect.size()));
        if (frameOrientation.usesWidthAsHeight()) {
            // The destination rectangle will have it's width and height already reversed for the orientation of
            // the image, as it was needed for page layout, so we need to reverse it back here.
            dstRect = FloatRect(dstRect.x(), dstRect.y(), dstRect.height(), dstRect.width());
        }
    }

    context.platformContext()->drawSurfaceToContext(surface.get(), dstRect, adjustedSrcRect, context);

    context.restore();

    if (imageObserver())
        imageObserver()->didDraw(this);
}
Пример #3
0
void BitmapImage::updateSize(ImageOrientationDescription description) const
{
    if (!m_sizeAvailable || m_haveSize)
        return;

    m_size = m_source.size(description);
    m_sizeRespectingOrientation = m_source.size(ImageOrientationDescription(RespectImageOrientation, description.imageOrientation()));

    m_imageOrientation = static_cast<unsigned>(description.imageOrientation());
    m_shouldRespectImageOrientation = static_cast<unsigned>(description.respectImageOrientation());

    m_haveSize = true;

    determineMinimumSubsamplingLevel();
    didDecodeProperties();
}
Пример #4
0
void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& destRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator compositeOp, BlendMode blendMode, ImageOrientationDescription description)
{
#if PLATFORM(IOS)
    startAnimation(DoNotCatchUp);
#else
    startAnimation();
#endif

    RetainPtr<CGImageRef> image;
    // Never use subsampled images for drawing into PDF contexts.
    if (wkCGContextIsPDFContext(ctxt->platformContext()))
        image = adoptCF(copyUnscaledFrameAtIndex(m_currentFrame));
    else {
        CGRect transformedDestinationRect = CGRectApplyAffineTransform(destRect, CGContextGetCTM(ctxt->platformContext()));
        float subsamplingScale = std::min<float>(1, std::max(transformedDestinationRect.size.width / srcRect.width(), transformedDestinationRect.size.height / srcRect.height()));

        image = frameAtIndex(m_currentFrame, subsamplingScale);
    }

    if (!image) // If it's too early we won't have an image yet.
        return;
    
    if (mayFillWithSolidColor()) {
        fillWithSolidColor(ctxt, destRect, solidColor(), styleColorSpace, compositeOp);
        return;
    }

    // Subsampling may have given us an image that is smaller than size().
    IntSize imageSize(CGImageGetWidth(image.get()), CGImageGetHeight(image.get()));
    
    // srcRect is in the coordinates of the unsubsampled image, so we have to map it to the subsampled image.
    FloatRect scaledSrcRect = srcRect;
    if (imageSize != m_size) {
        FloatRect originalImageBounds(FloatPoint(), m_size);
        FloatRect subsampledImageBounds(FloatPoint(), imageSize);
        scaledSrcRect = mapRect(srcRect, originalImageBounds, subsampledImageBounds);
    }
    
    ImageOrientation orientation;
    if (description.respectImageOrientation() == RespectImageOrientation)
        orientation = frameOrientationAtIndex(m_currentFrame);

    ctxt->drawNativeImage(image.get(), imageSize, styleColorSpace, destRect, scaledSrcRect, compositeOp, blendMode, orientation);

    if (imageObserver())
        imageObserver()->didDraw(this);
}
Пример #5
0
void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& destRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator compositeOp, BlendMode blendMode, ImageOrientationDescription description)
{
    CGImageRef image;
#if !PLATFORM(IOS)
    startAnimation();

    image = frameAtIndex(m_currentFrame);
#else
    startAnimation(DoNotCatchUp);

    CGRect transformedDestinationRect = CGRectApplyAffineTransform(destRect, CGContextGetCTM(ctxt->platformContext()));
    RetainPtr<CGImageRef> imagePossiblyCopied;
    // Never use subsampled images for drawing into PDF contexts.
    if (CGContextGetType(ctxt->platformContext()) == kCGContextTypePDF)
        imagePossiblyCopied = adoptCF(copyUnscaledFrameAtIndex(m_currentFrame));
    else
        imagePossiblyCopied = frameAtIndex(m_currentFrame, std::min<float>(1.0f, std::max(transformedDestinationRect.size.width  / srcRect.width(), transformedDestinationRect.size.height / srcRect.height())));

    image = imagePossiblyCopied.get();
#endif
    if (!image) // If it's too early we won't have an image yet.
        return;

    if (mayFillWithSolidColor()) {
        fillWithSolidColor(ctxt, destRect, solidColor(), styleColorSpace, compositeOp);
        return;
    }

    float scale = 1;
#if PLATFORM(IOS)
    scale = m_frames[m_currentFrame].m_scale;
#endif
    FloatSize selfSize = currentFrameSize();
    ImageOrientation orientation;

    if (description.respectImageOrientation() == RespectImageOrientation)
        orientation = frameOrientationAtIndex(m_currentFrame);

    ctxt->drawNativeImage(image, selfSize, styleColorSpace, destRect, srcRect, scale, compositeOp, blendMode, orientation);

    if (imageObserver())
        imageObserver()->didDraw(this);
}
Пример #6
0
IntSize ImageSource::frameSizeAtIndex(size_t index, SubsamplingLevel subsamplingLevel, ImageOrientationDescription description) const
{
    RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyPropertiesAtIndex(m_decoder, index, imageSourceOptions(subsamplingLevel).get()));

    if (!properties)
        return IntSize();

    int width = 0;
    int height = 0;
    CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyPixelWidth);
    if (num)
        CFNumberGetValue(num, kCFNumberIntType, &width);
    num = (CFNumberRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyPixelHeight);
    if (num)
        CFNumberGetValue(num, kCFNumberIntType, &height);

    if ((description.respectImageOrientation() == RespectImageOrientation) && orientationFromProperties(properties.get()).usesWidthAsHeight())
        return IntSize(height, width);

    return IntSize(width, height);
}