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

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: address comments 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..af6167cc5bfd5b45de81747bd093d5e499bb481c 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,34 @@ 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> scaleInputAndCropRect(Image* input, IntRect& cropRect, unsigned resizeWidth, unsigned resizeHeight, SkFilterQuality resizeQuality)
{
- bool flipY;
- bool premultiplyAlpha;
- parseOptions(options, flipY, premultiplyAlpha);
+ if (cropRect.x() == 0 && cropRect.y() == 0 && cropRect.width() == input->width() && cropRect.height() == input->height()) {
+ cropRect.setWidth(resizeWidth);
jbroman 2016/06/30 18:52:34 Hmm. It seems you're setting parameters to use for
xidachen 2016/07/07 13:48:47 Done. The scale && crop are in cropImage(), and it
+ cropRect.setHeight(resizeHeight);
+ }
+
+ RefPtr<SkImage> skiaImage = input->imageForCurrentFrame();
+ sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(resizeWidth, resizeHeight);
+ SkRect srcRect = SkRect::MakeIWH(input->width(), input->height());
+ SkRect dstRect = SkRect::MakeIWH(resizeWidth, resizeHeight);
+ SkPaint paint;
+ paint.setFilterQuality(resizeQuality);
+ surface->getCanvas()->drawImageRect(skiaImage.get(), srcRect, dstRect, &paint);
jbroman 2016/06/30 18:52:34 You should also clear the canvas to transparent be
xidachen 2016/07/07 13:48:47 This is not needed as SkSurface::MakeRaster() does
+ return StaticBitmapImage::create(fromSkSp(surface->makeImageSnapshot()));
+}
+
+ImageBitmap::ImageBitmap(HTMLImageElement* image, IntRect& cropRect, Document* document, const ImageBitmapOptions& options)
+{
+ RefPtr<Image> input = image->cachedImage()->getImage();
+ ParsedOptions parsedOptions = parseOptions(options, input->width(), input->height());
+ if (parsedOptions.shouldScaleInput)
+ input = scaleInputAndCropRect(input.get(), cropRect, parsedOptions.resizeWidth, parsedOptions.resizeHeight, parsedOptions.resizeQuality);
if (options.colorSpaceConversion() == "none")
- m_image = cropImage(image->cachedImage()->getImage(), cropRect, flipY, premultiplyAlpha, PremultiplyAlpha, ImageDecoder::GammaAndColorProfileIgnored);
+ m_image = cropImage(input.get(), cropRect, parsedOptions.flipY, parsedOptions.premultiplyAlpha, PremultiplyAlpha, ImageDecoder::GammaAndColorProfileIgnored);
else
- m_image = cropImage(image->cachedImage()->getImage(), cropRect, flipY, premultiplyAlpha, PremultiplyAlpha, ImageDecoder::GammaAndColorProfileApplied);
+ m_image = cropImage(input.get(), cropRect, parsedOptions.flipY, parsedOptions.premultiplyAlpha, PremultiplyAlpha, ImageDecoder::GammaAndColorProfileApplied);
if (!m_image)
return;
// In the case where the source image is lazy-decoded, m_image may not be in
@@ -205,10 +223,10 @@ ImageBitmap::ImageBitmap(HTMLImageElement* image, const IntRect& cropRect, Docum
m_image = StaticBitmapImage::create(fromSkSp(surface->makeImageSnapshot()));
}
m_image->setOriginClean(!image->wouldTaintOrigin(document->getSecurityOrigin()));
- m_image->setPremultiplied(premultiplyAlpha);
+ m_image->setPremultiplied(parsedOptions.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())
@@ -223,51 +241,50 @@ 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);
- bool flipY;
- bool premultiplyAlpha;
- parseOptions(options, flipY, premultiplyAlpha);
+ // TODO(xidachen); implement the resize option.
+ ParsedOptions parsedOptions = parseOptions(options, playerSize.width(), playerSize.height());
- if (flipY || !premultiplyAlpha) {
+ if (parsedOptions.flipY || !parsedOptions.premultiplyAlpha) {
RefPtr<SkImage> skiaImage = buffer->newSkImageSnapshot(PreferNoAcceleration, SnapshotReasonUnknown);
- if (flipY)
+ if (parsedOptions.flipY)
skiaImage = flipSkImageVertically(skiaImage.get(), PremultiplyAlpha);
- if (!premultiplyAlpha)
+ if (!parsedOptions.premultiplyAlpha)
skiaImage = premulSkImageToUnPremul(skiaImage.get());
m_image = StaticBitmapImage::create(skiaImage.release());
} else {
m_image = StaticBitmapImage::create(buffer->newSkImageSnapshot(PreferNoAcceleration, SnapshotReasonUnknown));
}
m_image->setOriginClean(!video->wouldTaintOrigin(document->getSecurityOrigin()));
- m_image->setPremultiplied(premultiplyAlpha);
+ m_image->setPremultiplied(parsedOptions.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);
+ RefPtr<Image> input = canvas->copiedImage(BackBuffer, PreferAcceleration);
+ ParsedOptions parsedOptions = parseOptions(options, input->width(), input->height());
+ if (parsedOptions.shouldScaleInput)
+ input = scaleInputAndCropRect(input.get(), cropRect, parsedOptions.resizeWidth, parsedOptions.resizeHeight, parsedOptions.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, parsedOptions.flipY, true);
if (!m_image)
return;
- if (!premultiplyAlpha)
+ if (!parsedOptions.premultiplyAlpha)
m_image = StaticBitmapImage::create(premulSkImageToUnPremul(m_image->imageForCurrentFrame().get()));
m_image->setOriginClean(canvas->originClean());
- m_image->setPremultiplied(premultiplyAlpha);
+ m_image->setPremultiplied(parsedOptions.premultiplyAlpha);
}
// 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);
+ // TODO(xidachen): implement the resize option
+ ParsedOptions parsedOptions = parseOptions(options, data->width(), data->height());
IntRect srcRect = intersection(cropRect, IntRect(IntPoint(), data->size()));
// treat non-premultiplyAlpha as a special case
- if (!premultiplyAlpha) {
+ if (!parsedOptions.premultiplyAlpha) {
unsigned char* srcAddr = data->data()->data();
int srcHeight = data->size().height();
int dstHeight = cropRect.height();
@@ -281,10 +298,10 @@ ImageBitmap::ImageBitmap(ImageData* data, const IntRect& cropRect, const ImageBi
int srcPixelBytesPerRow = info.bytesPerPixel() * data->size().width();
int dstPixelBytesPerRow = info.bytesPerPixel() * cropRect.width();
if (cropRect == IntRect(IntPoint(), data->size())) {
- swizzleImageData(srcAddr, srcHeight, srcPixelBytesPerRow, flipY);
+ swizzleImageData(srcAddr, srcHeight, srcPixelBytesPerRow, parsedOptions.flipY);
m_image = StaticBitmapImage::create(fromSkSp(SkImage::MakeRasterCopy(SkPixmap(info, srcAddr, dstPixelBytesPerRow))));
// restore the original ImageData
- swizzleImageData(srcAddr, srcHeight, srcPixelBytesPerRow, flipY);
+ swizzleImageData(srcAddr, srcHeight, srcPixelBytesPerRow, parsedOptions.flipY);
} else {
std::unique_ptr<uint8_t[]> copiedDataBuffer = wrapArrayUnique(new uint8_t[dstHeight * dstPixelBytesPerRow]());
if (!srcRect.isEmpty()) {
@@ -300,7 +317,7 @@ ImageBitmap::ImageBitmap(ImageData* data, const IntRect& cropRect, const ImageBi
int srcStartCopyPosition = (i + srcPoint.y()) * srcPixelBytesPerRow + srcPoint.x() * info.bytesPerPixel();
int srcEndCopyPosition = srcStartCopyPosition + copyWidth * info.bytesPerPixel();
int dstStartCopyPosition;
- if (flipY)
+ if (parsedOptions.flipY)
dstStartCopyPosition = (dstHeight -1 - dstPoint.y() - i) * dstPixelBytesPerRow + dstPoint.x() * info.bytesPerPixel();
else
dstStartCopyPosition = (dstPoint.y() + i) * dstPixelBytesPerRow + dstPoint.x() * info.bytesPerPixel();
@@ -316,7 +333,7 @@ ImageBitmap::ImageBitmap(ImageData* data, const IntRect& cropRect, const ImageBi
}
m_image = StaticBitmapImage::create(newSkImageFromRaster(info, std::move(copiedDataBuffer), dstPixelBytesPerRow));
}
- m_image->setPremultiplied(premultiplyAlpha);
+ m_image->setPremultiplied(parsedOptions.premultiplyAlpha);
m_image->setOriginClean(isImageDataOriginClean);
return;
}
@@ -336,34 +353,39 @@ ImageBitmap::ImageBitmap(ImageData* data, const IntRect& cropRect, const ImageBi
if (cropRect.y() < 0)
dstPoint.setY(-cropRect.y());
buffer->putByteArray(Unmultiplied, data->data()->data(), data->size(), srcRect, dstPoint);
- if (flipY)
+ if (parsedOptions.flipY)
m_image = StaticBitmapImage::create(flipSkImageVertically(buffer->newSkImageSnapshot(PreferNoAcceleration, SnapshotReasonUnknown).get(), PremultiplyAlpha));
else
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);
+ RefPtr<Image> input = bitmap->bitmapImage();
+ ParsedOptions parsedOptions = parseOptions(options, input->width(), input->height());
+ if (parsedOptions.shouldScaleInput)
jbroman 2016/06/30 18:52:34 Could the next few lines be bundles into function
xidachen 2016/07/07 13:48:47 Done.
+ input = scaleInputAndCropRect(input.get(), cropRect, parsedOptions.resizeWidth, parsedOptions.resizeHeight, parsedOptions.resizeQuality);
+
+ m_image = cropImage(input.get(), cropRect, parsedOptions.flipY, parsedOptions.premultiplyAlpha, bitmap->isPremultiplied() ? PremultiplyAlpha : DontPremultiplyAlpha);
if (!m_image)
return;
m_image->setOriginClean(bitmap->originClean());
- m_image->setPremultiplied(premultiplyAlpha);
+ m_image->setPremultiplied(parsedOptions.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);
+ bool originClean = image->originClean();
+ RefPtr<Image> input = image;
+ ParsedOptions parsedOptions = parseOptions(options, input->width(), input->height());
+ if (parsedOptions.shouldScaleInput)
+ input = scaleInputAndCropRect(input.get(), cropRect, parsedOptions.resizeWidth, parsedOptions.resizeHeight, parsedOptions.resizeQuality);
+
+ m_image = cropImage(input.get(), cropRect, parsedOptions.flipY, parsedOptions.premultiplyAlpha, DontPremultiplyAlpha);
if (!m_image)
return;
- m_image->setOriginClean(image->originClean());
- m_image->setPremultiplied(premultiplyAlpha);
+ m_image->setOriginClean(originClean);
+ m_image->setPremultiplied(parsedOptions.premultiplyAlpha);
}
ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image)
@@ -492,20 +514,49 @@ 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)
+ParsedOptions ImageBitmap::parseOptions(const ImageBitmapOptions& options, const int width, const int height)
{
+ ParsedOptions parsedOptions;
if (options.imageOrientation() == imageOrientationFlipY) {
- flipY = true;
+ parsedOptions.flipY = true;
} else {
- flipY = false;
+ parsedOptions.flipY = false;
ASSERT(options.imageOrientation() == imageBitmapOptionNone);
}
if (options.premultiplyAlpha() == imageBitmapOptionNone) {
- premultiplyAlpha = false;
+ parsedOptions.premultiplyAlpha = false;
} else {
- premultiplyAlpha = true;
+ parsedOptions.premultiplyAlpha = true;
ASSERT(options.premultiplyAlpha() == "default" || options.premultiplyAlpha() == "premultiply");
}
+
+ parsedOptions.shouldScaleInput = false;
+ if (!options.hasResizeWidth() && !options.hasResizeHeight())
+ return parsedOptions;
+ if (options.hasResizeWidth() && options.hasResizeHeight()) {
+ parsedOptions.resizeWidth = options.resizeWidth();
jbroman 2016/06/30 18:52:34 What happens if one or both of these is specified,
xidachen 2016/07/07 13:48:47 Spec has been changed, now an exception is thrown
+ parsedOptions.resizeHeight = options.resizeHeight();
+ } else if (options.hasResizeWidth() && !options.hasResizeHeight()) {
+ parsedOptions.resizeWidth = options.resizeWidth();
+ parsedOptions.resizeHeight = static_cast<unsigned>(static_cast<float>(options.resizeWidth()) / width * height);
jbroman 2016/06/30 18:52:34 What should be happening when the computed size ba
xidachen 2016/07/07 13:48:47 Spec has been changed, so we round up to its neare
+ } else {
+ parsedOptions.resizeHeight = options.resizeHeight();
+ parsedOptions.resizeWidth = static_cast<unsigned>(static_cast<float>(options.resizeHeight()) / height * width);
+ }
+ if (static_cast<int>(parsedOptions.resizeWidth) != width || static_cast<int>(parsedOptions.resizeHeight) != height)
+ parsedOptions.shouldScaleInput = true;
+ else
+ return parsedOptions;
+
+ if (options.resizeQuality() == "high")
+ parsedOptions.resizeQuality = kHigh_SkFilterQuality;
+ else if (options.resizeQuality() == "medium")
+ parsedOptions.resizeQuality = kMedium_SkFilterQuality;
+ else if (options.resizeQuality() == "pixelated")
+ parsedOptions.resizeQuality = kNone_SkFilterQuality;
+ else
+ parsedOptions.resizeQuality = kLow_SkFilterQuality;
+ return parsedOptions;
}
PassRefPtr<Image> ImageBitmap::getSourceImageForCanvas(SourceImageStatus* status, AccelerationHint, SnapshotReason, const FloatSize&) const

Powered by Google App Engine
This is Rietveld 408576698