String ImageBuffer::toDataURL(const String& mimeType, const double* quality) const { ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); RetainPtr<CGImageRef> image(AdoptCF, copyNativeImage(CopyBackingStore)); if (!image) return "data:,"; return CGImageToDataURL(image.get(), mimeType, quality); }
void ImageBuffer::clip(GraphicsContext* contextToClip, const FloatRect& rect) const { CGContextRef platformContextToClip = contextToClip->platformContext(); // FIXME: This image needs to be grayscale to be used as an alpha mask here. RetainPtr<CGImageRef> image(AdoptCF, copyNativeImage(DontCopyBackingStore)); CGContextTranslateCTM(platformContextToClip, rect.x(), rect.y() + rect.height()); CGContextScaleCTM(platformContextToClip, 1, -1); CGContextClipToMask(platformContextToClip, FloatRect(FloatPoint(), rect.size()), image.get()); CGContextScaleCTM(platformContextToClip, 1, -1); CGContextTranslateCTM(platformContextToClip, -rect.x(), -rect.y() - rect.height()); }
RefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyBehavior, ScaleBehavior scaleBehavior) const { RetainPtr<CGImageRef> image; if (m_resolutionScale == 1 || scaleBehavior == Unscaled) { image = copyNativeImage(copyBehavior); image = createCroppedImageIfNecessary(image.get(), internalSize()); } else { image = copyNativeImage(DontCopyBackingStore); RetainPtr<CGContextRef> context = adoptCF(CGBitmapContextCreate(0, logicalSize().width(), logicalSize().height(), 8, 4 * logicalSize().width(), deviceRGBColorSpaceRef(), kCGImageAlphaPremultipliedLast)); CGContextSetBlendMode(context.get(), kCGBlendModeCopy); CGContextClipToRect(context.get(), FloatRect(FloatPoint::zero(), logicalSize())); FloatSize imageSizeInUserSpace = scaleSizeToUserSpace(logicalSize(), m_data.backingStoreSize, internalSize()); CGContextDrawImage(context.get(), FloatRect(FloatPoint::zero(), imageSizeInUserSpace), image.get()); image = adoptCF(CGBitmapContextCreateImage(context.get())); } if (!image) return nullptr; return BitmapImage::create(image.get()); }
String ImageBuffer::toDataURL(const String& mimeType, const double* quality, CoordinateSystem) const { ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); RetainPtr<CFStringRef> uti = utiFromMIMEType(mimeType); ASSERT(uti); RefPtr<Uint8ClampedArray> premultipliedData; RetainPtr<CGImageRef> image; if (CFEqual(uti.get(), jpegUTI())) { // JPEGs don't have an alpha channel, so we have to manually composite on top of black. premultipliedData = getPremultipliedImageData(IntRect(IntPoint(0, 0), logicalSize())); if (!premultipliedData) return "data:,"; RetainPtr<CGDataProviderRef> dataProvider; dataProvider.adoptCF(CGDataProviderCreateWithData(0, premultipliedData->data(), 4 * logicalSize().width() * logicalSize().height(), 0)); if (!dataProvider) return "data:,"; image.adoptCF(CGImageCreate(logicalSize().width(), logicalSize().height(), 8, 32, 4 * logicalSize().width(), deviceRGBColorSpaceRef(), kCGBitmapByteOrderDefault | kCGImageAlphaNoneSkipLast, dataProvider.get(), 0, false, kCGRenderingIntentDefault)); } else if (m_resolutionScale == 1) image.adoptCF(copyNativeImage(CopyBackingStore)); else { image.adoptCF(copyNativeImage(DontCopyBackingStore)); RetainPtr<CGContextRef> context(AdoptCF, CGBitmapContextCreate(0, logicalSize().width(), logicalSize().height(), 8, 4 * logicalSize().width(), deviceRGBColorSpaceRef(), kCGImageAlphaPremultipliedLast)); CGContextSetBlendMode(context.get(), kCGBlendModeCopy); CGContextDrawImage(context.get(), CGRectMake(0, 0, logicalSize().width(), logicalSize().height()), image.get()); image.adoptCF(CGBitmapContextCreateImage(context.get())); } return CGImageToDataURL(image.get(), mimeType, quality); }
void ImageBuffer::clip(GraphicsContext& contextToClip, const FloatRect& rect) const { FloatSize backingStoreSizeInUserSpace = scaleSizeToUserSpace(rect.size(), m_data.backingStoreSize, internalSize()); RetainPtr<CGImageRef> image = copyNativeImage(DontCopyBackingStore); contextToClip.clipToNativeImage(image.get(), rect, backingStoreSizeInUserSpace); }