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 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 |