| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |