Chromium Code Reviews| Index: third_party/WebKit/Source/core/frame/ImageBitmap.cpp |
| diff --git a/third_party/WebKit/Source/core/frame/ImageBitmap.cpp b/third_party/WebKit/Source/core/frame/ImageBitmap.cpp |
| index 7f848ba80871b373d307b52d1cd811514cb4c380..29d6a7ce21a51ef707bc0b40214d242ec0a29f7a 100644 |
| --- a/third_party/WebKit/Source/core/frame/ImageBitmap.cpp |
| +++ b/third_party/WebKit/Source/core/frame/ImageBitmap.cpp |
| @@ -7,11 +7,13 @@ |
| #include "core/html/HTMLCanvasElement.h" |
| #include "core/html/HTMLVideoElement.h" |
| #include "core/html/ImageData.h" |
| +#include "platform/image-decoders/ImageDecoder.h" |
| #include "third_party/skia/include/core/SkSurface.h" |
| #include "wtf/RefPtr.h" |
| namespace blink { |
| +// The following two functions are helpers used in cropImage |
| static inline IntRect normalizeRect(const IntRect& rect) |
| { |
| return IntRect(std::min(rect.x(), rect.maxX()), |
| @@ -20,17 +22,52 @@ static inline IntRect normalizeRect(const IntRect& rect) |
| std::max(rect.height(), -rect.height())); |
| } |
| -static PassRefPtr<StaticBitmapImage> cropImage(Image* image, const IntRect& cropRect) |
| +static bool frameIsValid(const SkBitmap& frameBitmap) |
| +{ |
| + return !frameBitmap.isNull() |
| + && !frameBitmap.empty() |
| + && frameBitmap.isImmutable() |
| + && frameBitmap.colorType() == kN32_SkColorType; |
| +} |
| + |
| +static PassRefPtr<StaticBitmapImage> cropImage(Image* image, const IntRect& cropRect, const ImageBitmapOptions& options) |
| { |
| ASSERT(image); |
| IntRect imgRect(IntPoint(), IntSize(image->width(), image->height())); |
| const IntRect srcRect = intersection(imgRect, cropRect); |
| - if (cropRect == srcRect) |
| - return StaticBitmapImage::create(adoptRef(image->imageForCurrentFrame()->newSubset(srcRect))); |
| + RefPtr<SkImage> skiaImage = image->imageForCurrentFrame(); |
| + // Attempt to get raw unpremultiplied image data. |
| + if (((!options.premultiplyAlpha() && !skiaImage->isOpaque()) || !skiaImage) && image->data()) { |
| + OwnPtr<ImageDecoder> decoder(ImageDecoder::create( |
| + *(image->data()), ImageDecoder::AlphaNotPremultiplied, |
| + ImageDecoder::GammaAndColorProfileIgnored)); |
| + if (!decoder) |
| + return nullptr; |
| + decoder->setData(image->data(), true); |
| + if (!decoder->frameCount()) |
| + return nullptr; |
| + ImageFrame* frame = decoder->frameBufferAtIndex(0); |
| + if (!frame || frame->status() != ImageFrame::FrameComplete) |
| + return nullptr; |
| + SkBitmap bitmap = frame->bitmap(); |
| + if (!frameIsValid(bitmap)) |
| + return nullptr; |
| + ASSERT(bitmap.isImmutable()); |
| + skiaImage = adoptRef(SkImage::NewFromBitmap(bitmap)); |
| + } |
| - RefPtr<SkSurface> surface = adoptRef(SkSurface::NewRasterN32Premul(cropRect.width(), cropRect.height())); |
| + if (cropRect == srcRect) |
| + return StaticBitmapImage::create(adoptRef(skiaImage->newSubset(srcRect))); |
| + |
| + RefPtr<SkSurface> surface; |
| + if (options.premultiplyAlpha()) { |
| + surface = adoptRef(SkSurface::NewRasterN32Premul(cropRect.width(), cropRect.height())); |
| + } else { |
| + SkImageInfo info = SkImageInfo::MakeN32(cropRect.width(), cropRect.height(), kUnpremul_SkAlphaType); |
| + surface = adoptRef(SkSurface::NewRaster(info)); |
| + } |
| if (srcRect.isEmpty()) |
| return StaticBitmapImage::create(adoptRef(surface->newImageSnapshot())); |
| @@ -41,13 +78,14 @@ static PassRefPtr<StaticBitmapImage> cropImage(Image* image, const IntRect& crop |
| dstLeft = -cropRect.x(); |
| if (cropRect.y() < 0) |
| dstTop = -cropRect.y(); |
| - surface->getCanvas()->drawImage(image->imageForCurrentFrame().get(), dstLeft, dstTop); |
| + |
| + surface->getCanvas()->drawImage(skiaImage.get(), dstLeft, dstTop); |
|
xidachen
2016/01/20 02:29:07
This program could crash at this point. It is beca
|
| return StaticBitmapImage::create(adoptRef(surface->newImageSnapshot())); |
| } |
| ImageBitmap::ImageBitmap(HTMLImageElement* image, const IntRect& cropRect, Document* document, const ImageBitmapOptions& options) |
| { |
| - m_image = cropImage(image->cachedImage()->image(), cropRect); |
| + m_image = cropImage(image->cachedImage()->image(), cropRect, options); |
| m_image->setOriginClean(!image->wouldTaintOrigin(document->securityOrigin())); |
| } |
| @@ -65,14 +103,17 @@ ImageBitmap::ImageBitmap(HTMLVideoElement* video, const IntRect& cropRect, Docum |
| IntPoint dstPoint = IntPoint(std::max(0, -cropRect.x()), std::max(0, -cropRect.y())); |
| video->paintCurrentFrame(buffer->canvas(), IntRect(dstPoint, srcRect.size()), nullptr); |
| - m_image = StaticBitmapImage::create(buffer->newSkImageSnapshot(PreferNoAcceleration)); |
| + if (options.premultiplyAlpha()) |
| + m_image = StaticBitmapImage::create(buffer->newSkImageSnapshot(PreferNoAcceleration)); |
| + else |
| + m_image = cropImage(buffer->newImageSnapshot().get(), IntRect(IntPoint(0, 0), cropRect.size()), options); |
| m_image->setOriginClean(!video->wouldTaintOrigin(document->securityOrigin())); |
| } |
| ImageBitmap::ImageBitmap(HTMLCanvasElement* canvas, const IntRect& cropRect, const ImageBitmapOptions& options) |
| { |
| ASSERT(canvas->isPaintable()); |
| - m_image = cropImage(canvas->copiedImage(BackBuffer, PreferAcceleration).get(), cropRect); |
| + m_image = cropImage(canvas->copiedImage(BackBuffer, PreferAcceleration).get(), cropRect, options); |
| m_image->setOriginClean(canvas->originClean()); |
| } |
| @@ -100,13 +141,13 @@ ImageBitmap::ImageBitmap(ImageData* data, const IntRect& cropRect, const ImageBi |
| ImageBitmap::ImageBitmap(ImageBitmap* bitmap, const IntRect& cropRect, const ImageBitmapOptions& options) |
| { |
| - m_image = cropImage(bitmap->bitmapImage(), cropRect); |
| + m_image = cropImage(bitmap->bitmapImage(), cropRect, options); |
| m_image->setOriginClean(bitmap->originClean()); |
| } |
| ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image, const IntRect& cropRect, const ImageBitmapOptions& options) |
| { |
| - m_image = cropImage(image.get(), cropRect); |
| + m_image = cropImage(image.get(), cropRect, options); |
| m_image->setOriginClean(image->originClean()); |
| } |