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

Side by Side Diff: third_party/WebKit/Source/core/frame/ImageBitmap.cpp

Issue 2182583002: Change implementation of resize ImageBitmap to meet specs (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 4 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 unified diff | Download patch
« no previous file with comments | « third_party/WebKit/LayoutTests/fast/canvas/canvas-createImageBitmap-resize.html ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "core/frame/ImageBitmap.h" 5 #include "core/frame/ImageBitmap.h"
6 6
7 #include "core/html/HTMLCanvasElement.h" 7 #include "core/html/HTMLCanvasElement.h"
8 #include "core/html/HTMLVideoElement.h" 8 #include "core/html/HTMLVideoElement.h"
9 #include "core/html/ImageData.h" 9 #include "core/html/ImageData.h"
10 #include "platform/graphics/skia/SkiaUtils.h" 10 #include "platform/graphics/skia/SkiaUtils.h"
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
58 } 58 }
59 if (options.premultiplyAlpha() == imageBitmapOptionNone) { 59 if (options.premultiplyAlpha() == imageBitmapOptionNone) {
60 parsedOptions.premultiplyAlpha = false; 60 parsedOptions.premultiplyAlpha = false;
61 } else { 61 } else {
62 parsedOptions.premultiplyAlpha = true; 62 parsedOptions.premultiplyAlpha = true;
63 DCHECK(options.premultiplyAlpha() == "default" || options.premultiplyAlp ha() == "premultiply"); 63 DCHECK(options.premultiplyAlpha() == "default" || options.premultiplyAlp ha() == "premultiply");
64 } 64 }
65 65
66 int sourceWidth = sourceSize.width(); 66 int sourceWidth = sourceSize.width();
67 int sourceHeight = sourceSize.height(); 67 int sourceHeight = sourceSize.height();
68 if (!cropRect) {
69 parsedOptions.cropRect = IntRect(0, 0, sourceWidth, sourceHeight);
70 } else {
71 parsedOptions.cropRect = normalizeRect(*cropRect);
72 }
68 if (!options.hasResizeWidth() && !options.hasResizeHeight()) { 73 if (!options.hasResizeWidth() && !options.hasResizeHeight()) {
69 parsedOptions.resizeWidth = sourceWidth; 74 parsedOptions.resizeWidth = parsedOptions.cropRect.width();
70 parsedOptions.resizeHeight = sourceHeight; 75 parsedOptions.resizeHeight = parsedOptions.cropRect.height();
71 } else if (options.hasResizeWidth() && options.hasResizeHeight()) { 76 } else if (options.hasResizeWidth() && options.hasResizeHeight()) {
72 parsedOptions.resizeWidth = options.resizeWidth(); 77 parsedOptions.resizeWidth = options.resizeWidth();
73 parsedOptions.resizeHeight = options.resizeHeight(); 78 parsedOptions.resizeHeight = options.resizeHeight();
74 } else if (options.hasResizeWidth() && !options.hasResizeHeight()) { 79 } else if (options.hasResizeWidth() && !options.hasResizeHeight()) {
75 parsedOptions.resizeWidth = options.resizeWidth(); 80 parsedOptions.resizeWidth = options.resizeWidth();
76 parsedOptions.resizeHeight = ceil(static_cast<float>(options.resizeWidth ()) / sourceWidth * sourceHeight); 81 parsedOptions.resizeHeight = ceil(static_cast<float>(options.resizeWidth ()) / parsedOptions.cropRect.width() * parsedOptions.cropRect.height());
77 } else { 82 } else {
78 parsedOptions.resizeHeight = options.resizeHeight(); 83 parsedOptions.resizeHeight = options.resizeHeight();
79 parsedOptions.resizeWidth = ceil(static_cast<float>(options.resizeHeight ()) / sourceHeight * sourceWidth); 84 parsedOptions.resizeWidth = ceil(static_cast<float>(options.resizeHeight ()) / parsedOptions.cropRect.height() * parsedOptions.cropRect.width());
80 } 85 }
81 if (!cropRect) { 86 if (static_cast<int>(parsedOptions.resizeWidth) == parsedOptions.cropRect.wi dth() && static_cast<int>(parsedOptions.resizeHeight) == parsedOptions.cropRect. height()) {
82 parsedOptions.cropRect = IntRect(0, 0, parsedOptions.resizeWidth, parsed Options.resizeHeight);
83 } else {
84 parsedOptions.cropRect = normalizeRect(*cropRect);
85 }
86 if (static_cast<int>(parsedOptions.resizeWidth) == sourceWidth && static_cas t<int>(parsedOptions.resizeHeight) == sourceHeight) {
87 parsedOptions.shouldScaleInput = false; 87 parsedOptions.shouldScaleInput = false;
88 return parsedOptions; 88 return parsedOptions;
89 } 89 }
90 parsedOptions.shouldScaleInput = true; 90 parsedOptions.shouldScaleInput = true;
91 91
92 if (options.resizeQuality() == "high") 92 if (options.resizeQuality() == "high")
93 parsedOptions.resizeQuality = kHigh_SkFilterQuality; 93 parsedOptions.resizeQuality = kHigh_SkFilterQuality;
94 else if (options.resizeQuality() == "medium") 94 else if (options.resizeQuality() == "medium")
95 parsedOptions.resizeQuality = kMedium_SkFilterQuality; 95 parsedOptions.resizeQuality = kMedium_SkFilterQuality;
96 else if (options.resizeQuality() == "pixelated") 96 else if (options.resizeQuality() == "pixelated")
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
205 static PassRefPtr<StaticBitmapImage> cropImage(Image* image, const ParsedOptions & parsedOptions, AlphaDisposition imageFormat = PremultiplyAlpha, ImageDecoder:: GammaAndColorProfileOption colorSpaceOp = ImageDecoder::GammaAndColorProfileAppl ied) 205 static PassRefPtr<StaticBitmapImage> cropImage(Image* image, const ParsedOptions & parsedOptions, AlphaDisposition imageFormat = PremultiplyAlpha, ImageDecoder:: GammaAndColorProfileOption colorSpaceOp = ImageDecoder::GammaAndColorProfileAppl ied)
206 { 206 {
207 ASSERT(image); 207 ASSERT(image);
208 208
209 IntRect imgRect(IntPoint(), IntSize(image->width(), image->height())); 209 IntRect imgRect(IntPoint(), IntSize(image->width(), image->height()));
210 const IntRect srcRect = intersection(imgRect, parsedOptions.cropRect); 210 const IntRect srcRect = intersection(imgRect, parsedOptions.cropRect);
211 211
212 // In the case when cropRect doesn't intersect the source image and it requi res a umpremul image 212 // In the case when cropRect doesn't intersect the source image and it requi res a umpremul image
213 // We immediately return a transparent black image with cropRect.size() 213 // We immediately return a transparent black image with cropRect.size()
214 if (srcRect.isEmpty() && !parsedOptions.premultiplyAlpha) { 214 if (srcRect.isEmpty() && !parsedOptions.premultiplyAlpha) {
215 SkImageInfo info = SkImageInfo::Make(parsedOptions.cropRect.width(), par sedOptions.cropRect.height(), kN32_SkColorType, kUnpremul_SkAlphaType); 215 SkImageInfo info = SkImageInfo::Make(parsedOptions.shouldScaleInput ? pa rsedOptions.resizeWidth : parsedOptions.cropRect.width(),
Justin Novosad 2016/07/25 18:03:10 This ternary operation is not necessary. Reason:
xidachen 2016/07/25 19:02:01 Good catch, changes are made. Thanks.
216 std::unique_ptr<uint8_t[]> dstPixels = wrapArrayUnique(new uint8_t[parse dOptions.cropRect.width() * parsedOptions.cropRect.height() * info.bytesPerPixel ()]()); 216 parsedOptions.shouldScaleInput ? parsedOptions.resizeHeight : parsed Options.cropRect.height(), kN32_SkColorType, kUnpremul_SkAlphaType);
Justin Novosad 2016/07/25 18:03:10 same here.
xidachen 2016/07/25 19:02:01 Done.
217 return StaticBitmapImage::create(newSkImageFromRaster(info, std::move(ds tPixels), parsedOptions.cropRect.width() * info.bytesPerPixel())); 217 std::unique_ptr<uint8_t[]> dstPixels = wrapArrayUnique(new uint8_t[info. width() * info.height() * info.bytesPerPixel()]());
218 return StaticBitmapImage::create(newSkImageFromRaster(info, std::move(ds tPixels), info.width() * info.bytesPerPixel()));
218 } 219 }
219 220
220 RefPtr<SkImage> skiaImage = image->imageForCurrentFrame(); 221 RefPtr<SkImage> skiaImage = image->imageForCurrentFrame();
221 // Attempt to get raw unpremultiplied image data, executed only when skiaIma ge is premultiplied. 222 // Attempt to get raw unpremultiplied image data, executed only when skiaIma ge is premultiplied.
222 if ((((!parsedOptions.premultiplyAlpha && !skiaImage->isOpaque()) || !skiaIm age) && image->data() && imageFormat == PremultiplyAlpha) || colorSpaceOp == Ima geDecoder::GammaAndColorProfileIgnored) { 223 if ((((!parsedOptions.premultiplyAlpha && !skiaImage->isOpaque()) || !skiaIm age) && image->data() && imageFormat == PremultiplyAlpha) || colorSpaceOp == Ima geDecoder::GammaAndColorProfileIgnored) {
223 std::unique_ptr<ImageDecoder> decoder(ImageDecoder::create(*(image->data ()), 224 std::unique_ptr<ImageDecoder> decoder(ImageDecoder::create(*(image->data ()),
224 parsedOptions.premultiplyAlpha ? ImageDecoder::AlphaPremultiplied : ImageDecoder::AlphaNotPremultiplied, 225 parsedOptions.premultiplyAlpha ? ImageDecoder::AlphaPremultiplied : ImageDecoder::AlphaNotPremultiplied,
225 colorSpaceOp)); 226 colorSpaceOp));
226 if (!decoder) 227 if (!decoder)
227 return nullptr; 228 return nullptr;
228 decoder->setData(image->data(), true); 229 decoder->setData(image->data(), true);
229 skiaImage = ImageBitmap::getSkImageFromDecoder(std::move(decoder)); 230 skiaImage = ImageBitmap::getSkImageFromDecoder(std::move(decoder));
230 if (!skiaImage) 231 if (!skiaImage)
231 return nullptr; 232 return nullptr;
232 } 233 }
233 234
234 if (parsedOptions.cropRect == srcRect) { 235 if (parsedOptions.cropRect == srcRect && !parsedOptions.shouldScaleInput) {
235 RefPtr<SkImage> croppedSkImage = fromSkSp(skiaImage->makeSubset(srcRect) ); 236 RefPtr<SkImage> croppedSkImage = fromSkSp(skiaImage->makeSubset(srcRect) );
236 if (parsedOptions.flipY) 237 if (parsedOptions.flipY)
237 return StaticBitmapImage::create(flipSkImageVertically(croppedSkImag e.get(), parsedOptions.premultiplyAlpha ? PremultiplyAlpha : DontPremultiplyAlph a)); 238 return StaticBitmapImage::create(flipSkImageVertically(croppedSkImag e.get(), parsedOptions.premultiplyAlpha ? PremultiplyAlpha : DontPremultiplyAlph a));
238 // Special case: The first parameter image is unpremul but we need to tu rn it into premul. 239 // Special case: The first parameter image is unpremul but we need to tu rn it into premul.
239 if (parsedOptions.premultiplyAlpha && imageFormat == DontPremultiplyAlph a) 240 if (parsedOptions.premultiplyAlpha && imageFormat == DontPremultiplyAlph a)
240 return StaticBitmapImage::create(unPremulSkImageToPremul(croppedSkIm age.get())); 241 return StaticBitmapImage::create(unPremulSkImageToPremul(croppedSkIm age.get()));
241 // Call preroll to trigger image decoding. 242 // Call preroll to trigger image decoding.
242 croppedSkImage->preroll(); 243 croppedSkImage->preroll();
243 return StaticBitmapImage::create(croppedSkImage.release()); 244 return StaticBitmapImage::create(croppedSkImage.release());
244 } 245 }
245 246
246 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(parsedOptions.crop Rect.width(), parsedOptions.cropRect.height()); 247 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(parsedOptions.shou ldScaleInput ? parsedOptions.resizeWidth : parsedOptions.cropRect.width(),
Justin Novosad 2016/07/25 18:03:10 same here.
xidachen 2016/07/25 19:02:01 Done.
248 parsedOptions.shouldScaleInput ? parsedOptions.resizeHeight : parsedOpti ons.cropRect.height());
Justin Novosad 2016/07/25 18:03:10 same here.
xidachen 2016/07/25 19:02:02 Done.
247 if (!surface) 249 if (!surface)
248 return nullptr; 250 return nullptr;
249 if (srcRect.isEmpty()) 251 if (srcRect.isEmpty())
250 return StaticBitmapImage::create(fromSkSp(surface->makeImageSnapshot())) ; 252 return StaticBitmapImage::create(fromSkSp(surface->makeImageSnapshot())) ;
251 253
252 SkScalar dstLeft = std::min(0, -parsedOptions.cropRect.x()); 254 SkScalar dstLeft = std::min(0, -parsedOptions.cropRect.x());
253 SkScalar dstTop = std::min(0, -parsedOptions.cropRect.y()); 255 SkScalar dstTop = std::min(0, -parsedOptions.cropRect.y());
254 if (parsedOptions.cropRect.x() < 0) 256 if (parsedOptions.cropRect.x() < 0)
255 dstLeft = -parsedOptions.cropRect.x(); 257 dstLeft = -parsedOptions.cropRect.x();
256 if (parsedOptions.cropRect.y() < 0) 258 if (parsedOptions.cropRect.y() < 0)
257 dstTop = -parsedOptions.cropRect.y(); 259 dstTop = -parsedOptions.cropRect.y();
258 if (parsedOptions.flipY) { 260 if (parsedOptions.flipY) {
259 surface->getCanvas()->translate(0, surface->height()); 261 surface->getCanvas()->translate(0, surface->height());
260 surface->getCanvas()->scale(1, -1); 262 surface->getCanvas()->scale(1, -1);
261 } 263 }
262 if (parsedOptions.shouldScaleInput) { 264 if (parsedOptions.shouldScaleInput) {
263 SkRect drawDstRect = SkRect::MakeXYWH(dstLeft, dstTop, parsedOptions.res izeWidth, parsedOptions.resizeHeight); 265 SkRect drawSrcRect = SkRect::MakeXYWH(parsedOptions.cropRect.x(), parsed Options.cropRect.y(), parsedOptions.cropRect.width(), parsedOptions.cropRect.hei ght());
266 SkRect drawDstRect = SkRect::MakeXYWH(0, 0, parsedOptions.resizeWidth, p arsedOptions.resizeHeight);
264 SkPaint paint; 267 SkPaint paint;
265 paint.setFilterQuality(parsedOptions.resizeQuality); 268 paint.setFilterQuality(parsedOptions.resizeQuality);
266 surface->getCanvas()->drawImageRect(skiaImage.get(), drawDstRect, &paint ); 269 surface->getCanvas()->drawImageRect(skiaImage.get(), drawSrcRect, drawDs tRect, &paint);
267 } else { 270 } else {
268 surface->getCanvas()->drawImage(skiaImage.get(), dstLeft, dstTop); 271 surface->getCanvas()->drawImage(skiaImage.get(), dstLeft, dstTop);
269 } 272 }
270 skiaImage = fromSkSp(surface->makeImageSnapshot()); 273 skiaImage = fromSkSp(surface->makeImageSnapshot());
271 274
272 if (parsedOptions.premultiplyAlpha) { 275 if (parsedOptions.premultiplyAlpha) {
273 if (imageFormat == PremultiplyAlpha) 276 if (imageFormat == PremultiplyAlpha)
274 return StaticBitmapImage::create(unPremulSkImageToPremul(skiaImage.g et())); 277 return StaticBitmapImage::create(unPremulSkImageToPremul(skiaImage.g et()));
275 return StaticBitmapImage::create(skiaImage.release()); 278 return StaticBitmapImage::create(skiaImage.release());
276 } 279 }
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after
605 FloatSize ImageBitmap::elementSize(const FloatSize&) const 608 FloatSize ImageBitmap::elementSize(const FloatSize&) const
606 { 609 {
607 return FloatSize(width(), height()); 610 return FloatSize(width(), height());
608 } 611 }
609 612
610 DEFINE_TRACE(ImageBitmap) 613 DEFINE_TRACE(ImageBitmap)
611 { 614 {
612 } 615 }
613 616
614 } // namespace blink 617 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/LayoutTests/fast/canvas/canvas-createImageBitmap-resize.html ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698