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

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

Issue 2035113002: Implement ImageBitmapOptions resize (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 4 years, 6 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 7c0de1e9e10b593f496e058d70579b981bd201f8..1816ee097e17f4920226df3f1ee2caca6871a17b 100644
--- a/third_party/WebKit/Source/core/frame/ImageBitmap.cpp
+++ b/third_party/WebKit/Source/core/frame/ImageBitmap.cpp
@@ -117,7 +117,7 @@ PassRefPtr<SkImage> ImageBitmap::getSkImageFromDecoder(std::unique_ptr<ImageDeco
// imageFormat = PremultiplyAlpha means the image is in premuliplied format
// For example, if the image is already in unpremultiplied format and we want the created ImageBitmap
// in the same format, then we don't need to use the ImageDecoder to decode the image.
-static PassRefPtr<StaticBitmapImage> cropImage(Image* image, const IntRect& cropRect, bool flipY, bool premultiplyAlpha, AlphaDisposition imageFormat = PremultiplyAlpha, ImageDecoder::GammaAndColorProfileOption colorSpaceOp = ImageDecoder::GammaAndColorProfileApplied)
+static PassRefPtr<StaticBitmapImage> cropImage(Image* image, IntRect& cropRect, bool flipY, bool premultiplyAlpha, AlphaDisposition imageFormat = PremultiplyAlpha, ImageDecoder::GammaAndColorProfileOption colorSpaceOp = ImageDecoder::GammaAndColorProfileApplied)
{
ASSERT(image);
@@ -183,16 +183,49 @@ static PassRefPtr<StaticBitmapImage> cropImage(Image* image, const IntRect& crop
return StaticBitmapImage::create(premulSkImageToUnPremul(skiaImage.get()));
}
-ImageBitmap::ImageBitmap(HTMLImageElement* image, const IntRect& cropRect, Document* document, const ImageBitmapOptions& options)
+static PassRefPtr<Image> scaleInput(Image* input, unsigned resizeWidth, unsigned resizeHeight, SkFilterQuality resizeQuality)
+{
+ RefPtr<SkImage> skiaImage = input->imageForCurrentFrame();
+ SkImageInfo scaledInfo = SkImageInfo::MakeN32Premul(resizeWidth, resizeHeight);
+ std::unique_ptr<uint8_t[]> scaledPixels = wrapArrayUnique(new uint8_t[resizeWidth * resizeHeight * scaledInfo.bytesPerPixel()]);
+ SkPixmap scaledPixmap(scaledInfo, scaledPixels.release(), scaledInfo.minRowBytes());
+ if (!skiaImage->scalePixels(scaledPixmap, resizeQuality))
+ return nullptr;
+ RefPtr<SkImage> scaledImage = fromSkSp(SkImage::MakeFromRaster(scaledPixmap, [](const void* pixels, void*)
jbroman 2016/06/29 21:14:41 Doing a special pixmap allocation here seems sligh
xidachen 2016/06/30 15:23:11 Done.
+ {
+ delete[] static_cast<const uint8_t*>(pixels);
+ }, nullptr));
+ return StaticBitmapImage::create(scaledImage);
+}
+
+static void scaleCropRect(IntRect& cropRect, int width, int height, unsigned resizeWidth, unsigned resizeHeight)
+{
+ if (cropRect.x() == 0 && cropRect.y() == 0 && cropRect.width() == width && cropRect.height() == height) {
+ cropRect.setWidth(resizeWidth);
+ cropRect.setHeight(resizeHeight);
+ }
+}
+
+ImageBitmap::ImageBitmap(HTMLImageElement* image, IntRect& cropRect, Document* document, const ImageBitmapOptions& options)
{
bool flipY;
bool premultiplyAlpha;
- parseOptions(options, flipY, premultiplyAlpha);
+ unsigned resizeWidth = 0;
+ unsigned resizeHeight = 0;
+ SkFilterQuality resizeQuality = kLow_SkFilterQuality;
+ parseOptions(options, flipY, premultiplyAlpha, resizeWidth, resizeHeight, resizeQuality);
+
+ RefPtr<Image> input = image->cachedImage()->getImage();
+ if (options.hasResizeWidth() && options.hasResizeHeight()
+ && (static_cast<int>(resizeWidth) != input->width() || static_cast<int>(resizeHeight) != input->height())) {
+ scaleCropRect(cropRect, input->width(), input->height(), resizeWidth, resizeHeight);
+ input = scaleInput(input.get(), resizeWidth, resizeHeight, resizeQuality);
+ }
if (options.colorSpaceConversion() == "none")
- m_image = cropImage(image->cachedImage()->getImage(), cropRect, flipY, premultiplyAlpha, PremultiplyAlpha, ImageDecoder::GammaAndColorProfileIgnored);
+ m_image = cropImage(input.get(), cropRect, flipY, premultiplyAlpha, PremultiplyAlpha, ImageDecoder::GammaAndColorProfileIgnored);
else
- m_image = cropImage(image->cachedImage()->getImage(), cropRect, flipY, premultiplyAlpha, PremultiplyAlpha, ImageDecoder::GammaAndColorProfileApplied);
+ m_image = cropImage(input.get(), cropRect, flipY, premultiplyAlpha, PremultiplyAlpha, ImageDecoder::GammaAndColorProfileApplied);
if (!m_image)
return;
// In the case where the source image is lazy-decoded, m_image may not be in
@@ -208,7 +241,7 @@ ImageBitmap::ImageBitmap(HTMLImageElement* image, const IntRect& cropRect, Docum
m_image->setPremultiplied(premultiplyAlpha);
}
-ImageBitmap::ImageBitmap(HTMLVideoElement* video, const IntRect& cropRect, Document* document, const ImageBitmapOptions& options)
+ImageBitmap::ImageBitmap(HTMLVideoElement* video, IntRect& cropRect, Document* document, const ImageBitmapOptions& options)
{
IntSize playerSize;
if (video->webMediaPlayer())
@@ -225,7 +258,10 @@ ImageBitmap::ImageBitmap(HTMLVideoElement* video, const IntRect& cropRect, Docum
bool flipY;
bool premultiplyAlpha;
- parseOptions(options, flipY, premultiplyAlpha);
+ unsigned resizeWidth = 0;
+ unsigned resizeHeight = 0;
+ SkFilterQuality resizeQuality = kLow_SkFilterQuality;
+ parseOptions(options, flipY, premultiplyAlpha, resizeWidth, resizeHeight, resizeQuality);
if (flipY || !premultiplyAlpha) {
RefPtr<SkImage> skiaImage = buffer->newSkImageSnapshot(PreferNoAcceleration, SnapshotReasonUnknown);
@@ -241,15 +277,25 @@ ImageBitmap::ImageBitmap(HTMLVideoElement* video, const IntRect& cropRect, Docum
m_image->setPremultiplied(premultiplyAlpha);
}
-ImageBitmap::ImageBitmap(HTMLCanvasElement* canvas, const IntRect& cropRect, const ImageBitmapOptions& options)
+ImageBitmap::ImageBitmap(HTMLCanvasElement* canvas, IntRect& cropRect, const ImageBitmapOptions& options)
{
ASSERT(canvas->isPaintable());
bool flipY;
bool premultiplyAlpha;
- parseOptions(options, flipY, premultiplyAlpha);
+ unsigned resizeWidth = 0;
+ unsigned resizeHeight = 0;
+ SkFilterQuality resizeQuality = kLow_SkFilterQuality;
+ parseOptions(options, flipY, premultiplyAlpha, resizeWidth, resizeHeight, resizeQuality);
+
+ RefPtr<Image> input = canvas->copiedImage(BackBuffer, PreferAcceleration);
+ if (options.hasResizeWidth() && options.hasResizeHeight()
+ && (static_cast<int>(resizeWidth) != input->width() || static_cast<int>(resizeHeight) != input->height())) {
+ scaleCropRect(cropRect, input->width(), input->height(), resizeWidth, resizeHeight);
+ input = scaleInput(input.get(), resizeWidth, resizeHeight, resizeQuality);
+ }
// canvas is always premultiplied, so set the last parameter to true and convert to un-premul later
- m_image = cropImage(canvas->copiedImage(BackBuffer, PreferAcceleration).get(), cropRect, flipY, true);
+ m_image = cropImage(input.get(), cropRect, flipY, true);
if (!m_image)
return;
if (!premultiplyAlpha)
@@ -259,11 +305,14 @@ ImageBitmap::ImageBitmap(HTMLCanvasElement* canvas, const IntRect& cropRect, con
}
// The last two parameters are used for structure-cloning.
-ImageBitmap::ImageBitmap(ImageData* data, const IntRect& cropRect, const ImageBitmapOptions& options, const bool& isImageDataPremultiplied, const bool& isImageDataOriginClean)
+ImageBitmap::ImageBitmap(ImageData* data, IntRect& cropRect, const ImageBitmapOptions& options, const bool& isImageDataPremultiplied, const bool& isImageDataOriginClean)
{
bool flipY;
bool premultiplyAlpha;
- parseOptions(options, flipY, premultiplyAlpha);
+ unsigned resizeWidth = 0;
+ unsigned resizeHeight = 0;
+ SkFilterQuality resizeQuality = kLow_SkFilterQuality;
+ parseOptions(options, flipY, premultiplyAlpha, resizeWidth, resizeHeight, resizeQuality);
IntRect srcRect = intersection(cropRect, IntRect(IntPoint(), data->size()));
// treat non-premultiplyAlpha as a special case
@@ -342,27 +391,50 @@ ImageBitmap::ImageBitmap(ImageData* data, const IntRect& cropRect, const ImageBi
m_image = StaticBitmapImage::create(buffer->newSkImageSnapshot(PreferNoAcceleration, SnapshotReasonUnknown));
}
-ImageBitmap::ImageBitmap(ImageBitmap* bitmap, const IntRect& cropRect, const ImageBitmapOptions& options)
+ImageBitmap::ImageBitmap(ImageBitmap* bitmap, IntRect& cropRect, const ImageBitmapOptions& options)
{
bool flipY;
bool premultiplyAlpha;
- parseOptions(options, flipY, premultiplyAlpha);
- m_image = cropImage(bitmap->bitmapImage(), cropRect, flipY, premultiplyAlpha, bitmap->isPremultiplied() ? PremultiplyAlpha : DontPremultiplyAlpha);
+ unsigned resizeWidth = 0;
+ unsigned resizeHeight = 0;
+ SkFilterQuality resizeQuality = kLow_SkFilterQuality;
+ parseOptions(options, flipY, premultiplyAlpha, resizeWidth, resizeHeight, resizeQuality);
+
+ RefPtr<Image> input = bitmap->bitmapImage();
+ if (options.hasResizeWidth() && options.hasResizeHeight()
+ && (static_cast<int>(resizeWidth) != input->width() || static_cast<int>(resizeHeight) != input->height())) {
+ scaleCropRect(cropRect, input->width(), input->height(), resizeWidth, resizeHeight);
+ input = scaleInput(input.get(), resizeWidth, resizeHeight, resizeQuality);
+ }
+
+ m_image = cropImage(input.get(), cropRect, flipY, premultiplyAlpha, bitmap->isPremultiplied() ? PremultiplyAlpha : DontPremultiplyAlpha);
if (!m_image)
return;
m_image->setOriginClean(bitmap->originClean());
m_image->setPremultiplied(premultiplyAlpha);
}
-ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image, const IntRect& cropRect, const ImageBitmapOptions& options)
+ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image, IntRect& cropRect, const ImageBitmapOptions& options)
{
bool flipY;
bool premultiplyAlpha;
- parseOptions(options, flipY, premultiplyAlpha);
- m_image = cropImage(image.get(), cropRect, flipY, premultiplyAlpha, DontPremultiplyAlpha);
+ unsigned resizeWidth = 0;
+ unsigned resizeHeight = 0;
+ SkFilterQuality resizeQuality = kLow_SkFilterQuality;
+ parseOptions(options, flipY, premultiplyAlpha, resizeWidth, resizeHeight, resizeQuality);
jbroman 2016/06/29 21:14:42 This is getting to be quite a few options; have yo
xidachen 2016/06/30 15:23:12 Done.
+
+ bool originClean = image->originClean();
+ RefPtr<Image> input = image;
+ if (options.hasResizeWidth() && options.hasResizeHeight()
jbroman 2016/06/29 21:14:41 nit: It seems a little odd to duplicate the "shoul
xidachen 2016/06/30 15:23:11 Done.
+ && (static_cast<int>(resizeWidth) != input->width() || static_cast<int>(resizeHeight) != input->height())) {
+ scaleCropRect(cropRect, input->width(), input->height(), resizeWidth, resizeHeight);
jbroman 2016/06/29 21:14:41 A lot of this logic is duplicated with the above f
xidachen 2016/06/30 15:23:11 Done.
+ input = scaleInput(input.get(), resizeWidth, resizeHeight, resizeQuality);
+ }
+
+ m_image = cropImage(input.get(), cropRect, flipY, premultiplyAlpha, DontPremultiplyAlpha);
if (!m_image)
return;
- m_image->setOriginClean(image->originClean());
+ m_image->setOriginClean(originClean);
m_image->setPremultiplied(premultiplyAlpha);
}
@@ -492,7 +564,7 @@ ScriptPromise ImageBitmap::createImageBitmap(ScriptState* scriptState, EventTarg
return ImageBitmapSource::fulfillImageBitmap(scriptState, create(this, IntRect(sx, sy, sw, sh), options));
}
-void ImageBitmap::parseOptions(const ImageBitmapOptions& options, bool& flipY, bool& premultiplyAlpha)
+void ImageBitmap::parseOptions(const ImageBitmapOptions& options, bool& flipY, bool& premultiplyAlpha, unsigned& resizeWidth, unsigned& resizeHeight, SkFilterQuality& resizeQuality)
{
if (options.imageOrientation() == imageOrientationFlipY) {
flipY = true;
@@ -506,6 +578,18 @@ void ImageBitmap::parseOptions(const ImageBitmapOptions& options, bool& flipY, b
premultiplyAlpha = true;
ASSERT(options.premultiplyAlpha() == "default" || options.premultiplyAlpha() == "premultiply");
}
+ if (options.hasResizeWidth() && options.hasResizeHeight()) {
jbroman 2016/06/29 21:14:41 What if one is provided but not the other? Your sp
xidachen 2016/06/30 15:23:11 Changed to scale proportionally, will have a pull
+ resizeWidth = options.resizeWidth();
+ resizeHeight = options.resizeHeight();
+ if (options.resizeQuality() == "high")
+ resizeQuality = kHigh_SkFilterQuality;
+ else if (options.resizeQuality() == "medium")
+ resizeQuality = kMedium_SkFilterQuality;
+ else if (options.resizeQuality() == "pixelated")
+ resizeQuality = kNone_SkFilterQuality;
+ else
+ DCHECK_EQ(options.resizeQuality(), "low");
+ }
}
PassRefPtr<Image> ImageBitmap::getSourceImageForCanvas(SourceImageStatus* status, AccelerationHint, SnapshotReason, const FloatSize&) const

Powered by Google App Engine
This is Rietveld 408576698