| 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 c7348a846eba46ffd10fd41e291155fc90e3dc5f..15bdbf8119dde59c7f860da88a941aab8c86f8e7 100644
|
| --- a/third_party/WebKit/Source/core/frame/ImageBitmap.cpp
|
| +++ b/third_party/WebKit/Source/core/frame/ImageBitmap.cpp
|
| @@ -7,13 +7,32 @@
|
| #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 {
|
|
|
| static const char* imageOrientationFlipY = "flipY";
|
| +static const char* imageBitmapOptionNone = "none";
|
|
|
| +static void parseOptions(const ImageBitmapOptions& options, bool& imageOrientationFlipYFlag, bool& premultiplyAlphaEnabledFlag)
|
| +{
|
| + if (options.imageOrientation() == imageOrientationFlipY) {
|
| + imageOrientationFlipYFlag = true;
|
| + } else {
|
| + imageOrientationFlipYFlag = false;
|
| + ASSERT(options.imageOrientation() == imageBitmapOptionNone);
|
| + }
|
| + if (options.premultiplyAlpha() == imageBitmapOptionNone) {
|
| + premultiplyAlphaEnabledFlag = false;
|
| + } else {
|
| + premultiplyAlphaEnabledFlag = true;
|
| + ASSERT(options.premultiplyAlpha() == "default");
|
| + }
|
| +}
|
| +
|
| +// The following two functions are helpers used in cropImage
|
| static inline IntRect normalizeRect(const IntRect& rect)
|
| {
|
| return IntRect(std::min(rect.x(), rect.maxX()),
|
| @@ -22,7 +41,13 @@ static inline IntRect normalizeRect(const IntRect& rect)
|
| std::max(rect.height(), -rect.height()));
|
| }
|
|
|
| -// TODO(xidachen): this function needs to be changed later on when implementing premultiplyAlpha option
|
| +static bool frameIsValid(const SkBitmap& frameBitmap)
|
| +{
|
| + ASSERT(!frameBitmap.isNull() && !frameBitmap.empty());
|
| + return frameBitmap.isImmutable()
|
| + && frameBitmap.colorType() == kN32_SkColorType;
|
| +}
|
| +
|
| static SkImage* flipSkImageVertically(SkImage* input)
|
| {
|
| int width = input->width();
|
| @@ -41,21 +66,57 @@ static SkImage* flipSkImageVertically(SkImage* input)
|
| return SkImage::NewRasterCopy(info, imagePixels.get(), imageRowBytes);
|
| }
|
|
|
| -static PassRefPtr<StaticBitmapImage> cropImage(Image* image, const IntRect& cropRect, bool flipYEnabled)
|
| +// TODO(xidachen): the part of read an SkImage to a OwnPtr<uint8_t[]> has been used in multiple places,
|
| +// we should write it as a utility function here.
|
| +static SkImage* premulSkImageToUnPremul(SkImage* input)
|
| +{
|
| + int width = input->width();
|
| + int height = input->height();
|
| + SkImageInfo info = SkImageInfo::Make(width, height, kN32_SkColorType, kUnpremul_SkAlphaType);
|
| + OwnPtr<uint8_t[]> dstPixels = adoptArrayPtr(new uint8_t[width * height * info.bytesPerPixel()]);
|
| + size_t dstRowBytes = info.bytesPerPixel() * width;
|
| + input->readPixels(info, dstPixels.get(), dstRowBytes, 0, 0);
|
| + return SkImage::NewRasterCopy(info, dstPixels.get(), dstRowBytes);
|
| +}
|
| +
|
| +static PassRefPtr<StaticBitmapImage> cropImage(Image* image, const IntRect& cropRect, bool flipYEnabled, bool premultiplyAlphaEnabled)
|
| {
|
| ASSERT(image);
|
|
|
| IntRect imgRect(IntPoint(), IntSize(image->width(), image->height()));
|
| const IntRect srcRect = intersection(imgRect, cropRect);
|
|
|
| + RefPtr<SkImage> skiaImage = image->imageForCurrentFrame();
|
| + // Attempt to get raw unpremultiplied image data.
|
| + if (((!premultiplyAlphaEnabled && !skiaImage->isOpaque()) || !skiaImage) && image->data()) {
|
| + // TODO(xidachen): GammaAndColorProfileApplied needs to be changed when working on color-space conversion
|
| + OwnPtr<ImageDecoder> decoder(ImageDecoder::create(
|
| + *(image->data()), ImageDecoder::AlphaNotPremultiplied,
|
| + ImageDecoder::GammaAndColorProfileApplied));
|
| + 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));
|
| + }
|
| +
|
| if (cropRect == srcRect) {
|
| if (flipYEnabled)
|
| - return StaticBitmapImage::create(adoptRef(flipSkImageVertically(image->imageForCurrentFrame()->newSubset(srcRect))));
|
| - return StaticBitmapImage::create(adoptRef(image->imageForCurrentFrame()->newSubset(srcRect)));
|
| + return StaticBitmapImage::create(adoptRef(flipSkImageVertically(skiaImage->newSubset(srcRect))));
|
| + return StaticBitmapImage::create(adoptRef(skiaImage->newSubset(srcRect)));
|
| }
|
|
|
| RefPtr<SkSurface> surface = adoptRef(SkSurface::NewRasterN32Premul(cropRect.width(), cropRect.height()));
|
| -
|
| + // In the case where cropRect doesn't intesect the source image, we return a premultiplied transparent black SkImage.
|
| + // If we decide we want to grab meta data from m_image, we have to change this.
|
| if (srcRect.isEmpty())
|
| return StaticBitmapImage::create(adoptRef(surface->newImageSnapshot()));
|
|
|
| @@ -65,18 +126,23 @@ 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);
|
| if (flipYEnabled)
|
| - return StaticBitmapImage::create(adoptRef(flipSkImageVertically(surface->newImageSnapshot())));
|
| - return StaticBitmapImage::create(adoptRef(surface->newImageSnapshot()));
|
| + skiaImage = adoptRef(flipSkImageVertically(surface->newImageSnapshot()));
|
| + else
|
| + skiaImage = adoptRef(surface->newImageSnapshot());
|
| + if (premultiplyAlphaEnabled)
|
| + return StaticBitmapImage::create(skiaImage);
|
| + return StaticBitmapImage::create(adoptRef(premulSkImageToUnPremul(skiaImage.get())));
|
| }
|
|
|
| ImageBitmap::ImageBitmap(HTMLImageElement* image, const IntRect& cropRect, Document* document, const ImageBitmapOptions& options)
|
| {
|
| - if (options.imageOrientation() == imageOrientationFlipY)
|
| - m_image = cropImage(image->cachedImage()->image(), cropRect, true);
|
| - else
|
| - m_image = cropImage(image->cachedImage()->image(), cropRect, false);
|
| + bool imageOrientationFlipYFlag;
|
| + bool premultiplyAlphaEnabledFlag;
|
| + parseOptions(options, imageOrientationFlipYFlag, premultiplyAlphaEnabledFlag);
|
| +
|
| + m_image = cropImage(image->cachedImage()->image(), cropRect, imageOrientationFlipYFlag, premultiplyAlphaEnabledFlag);
|
| m_image->setOriginClean(!image->wouldTaintOrigin(document->securityOrigin()));
|
| }
|
|
|
| @@ -104,10 +170,10 @@ ImageBitmap::ImageBitmap(HTMLVideoElement* video, const IntRect& cropRect, Docum
|
| ImageBitmap::ImageBitmap(HTMLCanvasElement* canvas, const IntRect& cropRect, const ImageBitmapOptions& options)
|
| {
|
| ASSERT(canvas->isPaintable());
|
| - if (options.imageOrientation() == imageOrientationFlipY)
|
| - m_image = cropImage(canvas->copiedImage(BackBuffer, PreferAcceleration).get(), cropRect, true);
|
| - else
|
| - m_image = cropImage(canvas->copiedImage(BackBuffer, PreferAcceleration).get(), cropRect, false);
|
| + bool imageOrientationFlipYFlag;
|
| + bool premultiplyAlphaEnabledFlag;
|
| + parseOptions(options, imageOrientationFlipYFlag, premultiplyAlphaEnabledFlag);
|
| + m_image = cropImage(canvas->copiedImage(BackBuffer, PreferAcceleration).get(), cropRect, imageOrientationFlipYFlag, premultiplyAlphaEnabledFlag);
|
| m_image->setOriginClean(canvas->originClean());
|
| }
|
|
|
| @@ -138,19 +204,19 @@ ImageBitmap::ImageBitmap(ImageData* data, const IntRect& cropRect, const ImageBi
|
|
|
| ImageBitmap::ImageBitmap(ImageBitmap* bitmap, const IntRect& cropRect, const ImageBitmapOptions& options)
|
| {
|
| - if (options.imageOrientation() == imageOrientationFlipY)
|
| - m_image = cropImage(bitmap->bitmapImage(), cropRect, true);
|
| - else
|
| - m_image = cropImage(bitmap->bitmapImage(), cropRect, false);
|
| + bool imageOrientationFlipYFlag;
|
| + bool premultiplyAlphaEnabledFlag;
|
| + parseOptions(options, imageOrientationFlipYFlag, premultiplyAlphaEnabledFlag);
|
| + m_image = cropImage(bitmap->bitmapImage(), cropRect, imageOrientationFlipYFlag, true);
|
| m_image->setOriginClean(bitmap->originClean());
|
| }
|
|
|
| ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image, const IntRect& cropRect, const ImageBitmapOptions& options)
|
| {
|
| - if (options.imageOrientation() == imageOrientationFlipY)
|
| - m_image = cropImage(image.get(), cropRect, true);
|
| - else
|
| - m_image = cropImage(image.get(), cropRect, false);
|
| + bool imageOrientationFlipYFlag;
|
| + bool premultiplyAlphaEnabledFlag;
|
| + parseOptions(options, imageOrientationFlipYFlag, premultiplyAlphaEnabledFlag);
|
| + m_image = cropImage(image.get(), cropRect, imageOrientationFlipYFlag, premultiplyAlphaEnabledFlag);
|
| m_image->setOriginClean(image->originClean());
|
| }
|
|
|
|
|