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

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: address comments 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.resizeWidth, parsedOp tions.resizeHeight, kN32_SkColorType, kUnpremul_SkAlphaType);
216 std::unique_ptr<uint8_t[]> dstPixels = wrapArrayUnique(new uint8_t[parse dOptions.cropRect.width() * parsedOptions.cropRect.height() * info.bytesPerPixel ()]()); 216 std::unique_ptr<uint8_t[]> dstPixels = wrapArrayUnique(new uint8_t[info. width() * info.height() * info.bytesPerPixel()]());
217 return StaticBitmapImage::create(newSkImageFromRaster(info, std::move(ds tPixels), parsedOptions.cropRect.width() * info.bytesPerPixel())); 217 return StaticBitmapImage::create(newSkImageFromRaster(info, std::move(ds tPixels), info.width() * info.bytesPerPixel()));
218 } 218 }
219 219
220 RefPtr<SkImage> skiaImage = image->imageForCurrentFrame(); 220 RefPtr<SkImage> skiaImage = image->imageForCurrentFrame();
221 // Attempt to get raw unpremultiplied image data, executed only when skiaIma ge is premultiplied. 221 // 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) { 222 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 ()), 223 std::unique_ptr<ImageDecoder> decoder(ImageDecoder::create(*(image->data ()),
224 parsedOptions.premultiplyAlpha ? ImageDecoder::AlphaPremultiplied : ImageDecoder::AlphaNotPremultiplied, 224 parsedOptions.premultiplyAlpha ? ImageDecoder::AlphaPremultiplied : ImageDecoder::AlphaNotPremultiplied,
225 colorSpaceOp)); 225 colorSpaceOp));
226 if (!decoder) 226 if (!decoder)
227 return nullptr; 227 return nullptr;
228 decoder->setData(image->data(), true); 228 decoder->setData(image->data(), true);
229 skiaImage = ImageBitmap::getSkImageFromDecoder(std::move(decoder)); 229 skiaImage = ImageBitmap::getSkImageFromDecoder(std::move(decoder));
230 if (!skiaImage) 230 if (!skiaImage)
231 return nullptr; 231 return nullptr;
232 } 232 }
233 233
234 if (parsedOptions.cropRect == srcRect) { 234 if (parsedOptions.cropRect == srcRect && !parsedOptions.shouldScaleInput) {
235 RefPtr<SkImage> croppedSkImage = fromSkSp(skiaImage->makeSubset(srcRect) ); 235 RefPtr<SkImage> croppedSkImage = fromSkSp(skiaImage->makeSubset(srcRect) );
236 if (parsedOptions.flipY) 236 if (parsedOptions.flipY)
237 return StaticBitmapImage::create(flipSkImageVertically(croppedSkImag e.get(), parsedOptions.premultiplyAlpha ? PremultiplyAlpha : DontPremultiplyAlph a)); 237 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. 238 // Special case: The first parameter image is unpremul but we need to tu rn it into premul.
239 if (parsedOptions.premultiplyAlpha && imageFormat == DontPremultiplyAlph a) 239 if (parsedOptions.premultiplyAlpha && imageFormat == DontPremultiplyAlph a)
240 return StaticBitmapImage::create(unPremulSkImageToPremul(croppedSkIm age.get())); 240 return StaticBitmapImage::create(unPremulSkImageToPremul(croppedSkIm age.get()));
241 // Call preroll to trigger image decoding. 241 // Call preroll to trigger image decoding.
242 croppedSkImage->preroll(); 242 croppedSkImage->preroll();
243 return StaticBitmapImage::create(croppedSkImage.release()); 243 return StaticBitmapImage::create(croppedSkImage.release());
244 } 244 }
245 245
246 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(parsedOptions.crop Rect.width(), parsedOptions.cropRect.height()); 246 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(parsedOptions.resi zeWidth, parsedOptions.resizeHeight);
247 if (!surface) 247 if (!surface)
248 return nullptr; 248 return nullptr;
249 if (srcRect.isEmpty()) 249 if (srcRect.isEmpty())
250 return StaticBitmapImage::create(fromSkSp(surface->makeImageSnapshot())) ; 250 return StaticBitmapImage::create(fromSkSp(surface->makeImageSnapshot())) ;
251 251
252 SkScalar dstLeft = std::min(0, -parsedOptions.cropRect.x()); 252 SkScalar dstLeft = std::min(0, -parsedOptions.cropRect.x());
253 SkScalar dstTop = std::min(0, -parsedOptions.cropRect.y()); 253 SkScalar dstTop = std::min(0, -parsedOptions.cropRect.y());
254 if (parsedOptions.cropRect.x() < 0) 254 if (parsedOptions.cropRect.x() < 0)
255 dstLeft = -parsedOptions.cropRect.x(); 255 dstLeft = -parsedOptions.cropRect.x();
256 if (parsedOptions.cropRect.y() < 0) 256 if (parsedOptions.cropRect.y() < 0)
257 dstTop = -parsedOptions.cropRect.y(); 257 dstTop = -parsedOptions.cropRect.y();
258 if (parsedOptions.flipY) { 258 if (parsedOptions.flipY) {
259 surface->getCanvas()->translate(0, surface->height()); 259 surface->getCanvas()->translate(0, surface->height());
260 surface->getCanvas()->scale(1, -1); 260 surface->getCanvas()->scale(1, -1);
261 } 261 }
262 if (parsedOptions.shouldScaleInput) { 262 if (parsedOptions.shouldScaleInput) {
263 SkRect drawDstRect = SkRect::MakeXYWH(dstLeft, dstTop, parsedOptions.res izeWidth, parsedOptions.resizeHeight); 263 SkRect drawSrcRect = SkRect::MakeXYWH(parsedOptions.cropRect.x(), parsed Options.cropRect.y(), parsedOptions.cropRect.width(), parsedOptions.cropRect.hei ght());
264 SkRect drawDstRect = SkRect::MakeXYWH(0, 0, parsedOptions.resizeWidth, p arsedOptions.resizeHeight);
264 SkPaint paint; 265 SkPaint paint;
265 paint.setFilterQuality(parsedOptions.resizeQuality); 266 paint.setFilterQuality(parsedOptions.resizeQuality);
266 surface->getCanvas()->drawImageRect(skiaImage.get(), drawDstRect, &paint ); 267 surface->getCanvas()->drawImageRect(skiaImage.get(), drawSrcRect, drawDs tRect, &paint);
267 } else { 268 } else {
268 surface->getCanvas()->drawImage(skiaImage.get(), dstLeft, dstTop); 269 surface->getCanvas()->drawImage(skiaImage.get(), dstLeft, dstTop);
269 } 270 }
270 skiaImage = fromSkSp(surface->makeImageSnapshot()); 271 skiaImage = fromSkSp(surface->makeImageSnapshot());
271 272
272 if (parsedOptions.premultiplyAlpha) { 273 if (parsedOptions.premultiplyAlpha) {
273 if (imageFormat == PremultiplyAlpha) 274 if (imageFormat == PremultiplyAlpha)
274 return StaticBitmapImage::create(unPremulSkImageToPremul(skiaImage.g et())); 275 return StaticBitmapImage::create(unPremulSkImageToPremul(skiaImage.g et()));
275 return StaticBitmapImage::create(skiaImage.release()); 276 return StaticBitmapImage::create(skiaImage.release());
276 } 277 }
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after
605 FloatSize ImageBitmap::elementSize(const FloatSize&) const 606 FloatSize ImageBitmap::elementSize(const FloatSize&) const
606 { 607 {
607 return FloatSize(width(), height()); 608 return FloatSize(width(), height());
608 } 609 }
609 610
610 DEFINE_TRACE(ImageBitmap) 611 DEFINE_TRACE(ImageBitmap)
611 { 612 {
612 } 613 }
613 614
614 } // namespace blink 615 } // 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