Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(512)

Unified Diff: third_party/WebKit/Source/core/frame/ImageBitmap.cpp

Issue 1609763002: Implement ImageBitmap options premultiplyAlpha (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: change to enum instead of boolean Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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..a17d0fd4f834e9026f5f33a9afb5930b56af5c8d 100644
--- a/third_party/WebKit/Source/core/frame/ImageBitmap.cpp
+++ b/third_party/WebKit/Source/core/frame/ImageBitmap.cpp
@@ -7,13 +7,28 @@
#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;
Justin Novosad 2016/02/05 14:46:41 ASSERT(options.imageOrientation() == imageBitmapOp
xidachen 2016/02/05 16:47:36 Acknowledged.
+ if (options.premultiplyAlpha() == imageBitmapOptionNone)
+ premultiplyAlphaEnabledFlag = false;
+ else
+ premultiplyAlphaEnabledFlag = true;
Justin Novosad 2016/02/05 14:46:41 ASSERT(options.premultiplyAlpha() == premultiplyAl
xidachen 2016/02/05 16:47:36 Acknowledged.
+}
+
+// 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 +37,14 @@ 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)
+{
+ return !frameBitmap.isNull()
+ && !frameBitmap.empty()
+ && frameBitmap.isImmutable()
+ && frameBitmap.colorType() == kN32_SkColorType;
Justin Novosad 2016/02/05 14:46:41 Should some of these conditions be ASSERTs (i.e. t
xidachen 2016/02/05 16:47:36 Acknowledged.
+}
+
static SkImage* flipSkImageVertically(SkImage* input)
{
int width = input->width();
@@ -41,21 +63,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 +123,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 +167,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 +201,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());
}

Powered by Google App Engine
This is Rietveld 408576698