| 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 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 268 } | 268 } |
| 269 | 269 |
| 270 // The parameter imageFormat indicates whether the first parameter "image" is | 270 // The parameter imageFormat indicates whether the first parameter "image" is |
| 271 // unpremultiplied or not. imageFormat = PremultiplyAlpha means the image is in | 271 // unpremultiplied or not. imageFormat = PremultiplyAlpha means the image is in |
| 272 // premuliplied format For example, if the image is already in unpremultiplied | 272 // premuliplied format For example, if the image is already in unpremultiplied |
| 273 // format and we want the created ImageBitmap in the same format, then we don't | 273 // format and we want the created ImageBitmap in the same format, then we don't |
| 274 // need to use the ImageDecoder to decode the image. | 274 // need to use the ImageDecoder to decode the image. |
| 275 static PassRefPtr<StaticBitmapImage> cropImage( | 275 static PassRefPtr<StaticBitmapImage> cropImage( |
| 276 Image* image, | 276 Image* image, |
| 277 const ParsedOptions& parsedOptions, | 277 const ParsedOptions& parsedOptions, |
| 278 AlphaDisposition imageFormat = PremultiplyAlpha, | 278 AlphaDisposition imageFormat, |
| 279 ImageDecoder::ColorSpaceOption colorSpaceOp = | 279 ColorBehavior colorBehavior) { |
| 280 ImageDecoder::ColorSpaceTransformed) { | |
| 281 ASSERT(image); | 280 ASSERT(image); |
| 282 IntRect imgRect(IntPoint(), IntSize(image->width(), image->height())); | 281 IntRect imgRect(IntPoint(), IntSize(image->width(), image->height())); |
| 283 const IntRect srcRect = intersection(imgRect, parsedOptions.cropRect); | 282 const IntRect srcRect = intersection(imgRect, parsedOptions.cropRect); |
| 284 | 283 |
| 285 // In the case when cropRect doesn't intersect the source image and it | 284 // In the case when cropRect doesn't intersect the source image and it |
| 286 // requires a umpremul image We immediately return a transparent black image | 285 // requires a umpremul image We immediately return a transparent black image |
| 287 // with cropRect.size() | 286 // with cropRect.size() |
| 288 if (srcRect.isEmpty() && !parsedOptions.premultiplyAlpha) { | 287 if (srcRect.isEmpty() && !parsedOptions.premultiplyAlpha) { |
| 289 SkImageInfo info = | 288 SkImageInfo info = |
| 290 SkImageInfo::Make(parsedOptions.resizeWidth, parsedOptions.resizeHeight, | 289 SkImageInfo::Make(parsedOptions.resizeWidth, parsedOptions.resizeHeight, |
| 291 kN32_SkColorType, kUnpremul_SkAlphaType); | 290 kN32_SkColorType, kUnpremul_SkAlphaType); |
| 292 RefPtr<ArrayBuffer> dstBuffer = ArrayBuffer::createOrNull( | 291 RefPtr<ArrayBuffer> dstBuffer = ArrayBuffer::createOrNull( |
| 293 static_cast<unsigned>(info.width()) * info.height(), | 292 static_cast<unsigned>(info.width()) * info.height(), |
| 294 info.bytesPerPixel()); | 293 info.bytesPerPixel()); |
| 295 if (!dstBuffer) | 294 if (!dstBuffer) |
| 296 return nullptr; | 295 return nullptr; |
| 297 RefPtr<Uint8Array> dstPixels = | 296 RefPtr<Uint8Array> dstPixels = |
| 298 Uint8Array::create(dstBuffer, 0, dstBuffer->byteLength()); | 297 Uint8Array::create(dstBuffer, 0, dstBuffer->byteLength()); |
| 299 return StaticBitmapImage::create(newSkImageFromRaster( | 298 return StaticBitmapImage::create(newSkImageFromRaster( |
| 300 info, std::move(dstPixels), | 299 info, std::move(dstPixels), |
| 301 static_cast<unsigned>(info.width()) * info.bytesPerPixel())); | 300 static_cast<unsigned>(info.width()) * info.bytesPerPixel())); |
| 302 } | 301 } |
| 303 | 302 |
| 304 sk_sp<SkImage> skiaImage = image->imageForCurrentFrame(); | 303 sk_sp<SkImage> skiaImage = image->imageForCurrentFrame(); |
| 305 // Attempt to get raw unpremultiplied image data, executed only when skiaImage | 304 // Attempt to get raw unpremultiplied image data, executed only when skiaImage |
| 306 // is premultiplied. | 305 // is premultiplied. |
| 307 if ((((!parsedOptions.premultiplyAlpha && !skiaImage->isOpaque()) || | 306 if ((((!parsedOptions.premultiplyAlpha && !skiaImage->isOpaque()) || |
| 308 !skiaImage) && | 307 !skiaImage) && |
| 309 image->data() && imageFormat == PremultiplyAlpha) || | 308 image->data() && imageFormat == PremultiplyAlpha) || |
| 310 colorSpaceOp == ImageDecoder::ColorSpaceIgnored) { | 309 colorBehavior.isIgnore()) { |
| 311 std::unique_ptr<ImageDecoder> decoder(ImageDecoder::create( | 310 std::unique_ptr<ImageDecoder> decoder(ImageDecoder::create( |
| 312 image->data(), true, | 311 image->data(), true, |
| 313 parsedOptions.premultiplyAlpha ? ImageDecoder::AlphaPremultiplied | 312 parsedOptions.premultiplyAlpha ? ImageDecoder::AlphaPremultiplied |
| 314 : ImageDecoder::AlphaNotPremultiplied, | 313 : ImageDecoder::AlphaNotPremultiplied, |
| 315 colorSpaceOp, colorSpaceOp == ImageDecoder::ColorSpaceTransformed | 314 colorBehavior)); |
| 316 ? ImageDecoder::globalTargetColorSpace() | |
| 317 : nullptr)); | |
| 318 if (!decoder) | 315 if (!decoder) |
| 319 return nullptr; | 316 return nullptr; |
| 320 skiaImage = ImageBitmap::getSkImageFromDecoder(std::move(decoder)); | 317 skiaImage = ImageBitmap::getSkImageFromDecoder(std::move(decoder)); |
| 321 if (!skiaImage) | 318 if (!skiaImage) |
| 322 return nullptr; | 319 return nullptr; |
| 323 } | 320 } |
| 324 | 321 |
| 325 if (parsedOptions.cropRect == srcRect && !parsedOptions.shouldScaleInput) { | 322 if (parsedOptions.cropRect == srcRect && !parsedOptions.shouldScaleInput) { |
| 326 sk_sp<SkImage> croppedSkImage = skiaImage->makeSubset(srcRect); | 323 sk_sp<SkImage> croppedSkImage = skiaImage->makeSubset(srcRect); |
| 327 if (parsedOptions.flipY) | 324 if (parsedOptions.flipY) |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 385 Document* document, | 382 Document* document, |
| 386 const ImageBitmapOptions& options) { | 383 const ImageBitmapOptions& options) { |
| 387 RefPtr<Image> input = image->cachedImage()->getImage(); | 384 RefPtr<Image> input = image->cachedImage()->getImage(); |
| 388 ParsedOptions parsedOptions = | 385 ParsedOptions parsedOptions = |
| 389 parseOptions(options, cropRect, image->bitmapSourceSize()); | 386 parseOptions(options, cropRect, image->bitmapSourceSize()); |
| 390 if (dstBufferSizeHasOverflow(parsedOptions)) | 387 if (dstBufferSizeHasOverflow(parsedOptions)) |
| 391 return; | 388 return; |
| 392 | 389 |
| 393 if (options.colorSpaceConversion() == "none") { | 390 if (options.colorSpaceConversion() == "none") { |
| 394 m_image = cropImage(input.get(), parsedOptions, PremultiplyAlpha, | 391 m_image = cropImage(input.get(), parsedOptions, PremultiplyAlpha, |
| 395 ImageDecoder::ColorSpaceIgnored); | 392 ColorBehavior::ignore()); |
| 396 } else { | 393 } else { |
| 397 m_image = cropImage(input.get(), parsedOptions, PremultiplyAlpha, | 394 m_image = cropImage(input.get(), parsedOptions, PremultiplyAlpha, |
| 398 ImageDecoder::ColorSpaceTransformed); | 395 ColorBehavior::transformToGlobalTarget()); |
| 399 } | 396 } |
| 400 if (!m_image) | 397 if (!m_image) |
| 401 return; | 398 return; |
| 402 // In the case where the source image is lazy-decoded, m_image may not be in | 399 // In the case where the source image is lazy-decoded, m_image may not be in |
| 403 // a decoded state, we trigger it here. | 400 // a decoded state, we trigger it here. |
| 404 sk_sp<SkImage> skImage = m_image->imageForCurrentFrame(); | 401 sk_sp<SkImage> skImage = m_image->imageForCurrentFrame(); |
| 405 SkPixmap pixmap; | 402 SkPixmap pixmap; |
| 406 if (!skImage->isTextureBacked() && !skImage->peekPixels(&pixmap)) { | 403 if (!skImage->isTextureBacked() && !skImage->peekPixels(&pixmap)) { |
| 407 sk_sp<SkSurface> surface = | 404 sk_sp<SkSurface> surface = |
| 408 SkSurface::MakeRasterN32Premul(skImage->width(), skImage->height()); | 405 SkSurface::MakeRasterN32Premul(skImage->width(), skImage->height()); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 479 ParsedOptions parsedOptions = | 476 ParsedOptions parsedOptions = |
| 480 parseOptions(options, cropRect, IntSize(input->width(), input->height())); | 477 parseOptions(options, cropRect, IntSize(input->width(), input->height())); |
| 481 if (dstBufferSizeHasOverflow(parsedOptions)) | 478 if (dstBufferSizeHasOverflow(parsedOptions)) |
| 482 return; | 479 return; |
| 483 | 480 |
| 484 bool isPremultiplyAlphaReverted = false; | 481 bool isPremultiplyAlphaReverted = false; |
| 485 if (!parsedOptions.premultiplyAlpha) { | 482 if (!parsedOptions.premultiplyAlpha) { |
| 486 parsedOptions.premultiplyAlpha = true; | 483 parsedOptions.premultiplyAlpha = true; |
| 487 isPremultiplyAlphaReverted = true; | 484 isPremultiplyAlphaReverted = true; |
| 488 } | 485 } |
| 489 m_image = cropImage(input.get(), parsedOptions); | 486 m_image = cropImage(input.get(), parsedOptions, PremultiplyAlpha, |
| 487 ColorBehavior::transformToGlobalTarget()); |
| 490 if (!m_image) | 488 if (!m_image) |
| 491 return; | 489 return; |
| 492 if (isPremultiplyAlphaReverted) { | 490 if (isPremultiplyAlphaReverted) { |
| 493 parsedOptions.premultiplyAlpha = false; | 491 parsedOptions.premultiplyAlpha = false; |
| 494 m_image = StaticBitmapImage::create( | 492 m_image = StaticBitmapImage::create( |
| 495 premulSkImageToUnPremul(m_image->imageForCurrentFrame().get())); | 493 premulSkImageToUnPremul(m_image->imageForCurrentFrame().get())); |
| 496 } | 494 } |
| 497 if (!m_image) | 495 if (!m_image) |
| 498 return; | 496 return; |
| 499 m_image->setOriginClean(canvas->originClean()); | 497 m_image->setOriginClean(canvas->originClean()); |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 690 ImageBitmap::ImageBitmap(ImageBitmap* bitmap, | 688 ImageBitmap::ImageBitmap(ImageBitmap* bitmap, |
| 691 Optional<IntRect> cropRect, | 689 Optional<IntRect> cropRect, |
| 692 const ImageBitmapOptions& options) { | 690 const ImageBitmapOptions& options) { |
| 693 RefPtr<Image> input = bitmap->bitmapImage(); | 691 RefPtr<Image> input = bitmap->bitmapImage(); |
| 694 if (!input) | 692 if (!input) |
| 695 return; | 693 return; |
| 696 ParsedOptions parsedOptions = parseOptions(options, cropRect, input->size()); | 694 ParsedOptions parsedOptions = parseOptions(options, cropRect, input->size()); |
| 697 if (dstBufferSizeHasOverflow(parsedOptions)) | 695 if (dstBufferSizeHasOverflow(parsedOptions)) |
| 698 return; | 696 return; |
| 699 | 697 |
| 700 m_image = cropImage(input.get(), parsedOptions, bitmap->isPremultiplied() | 698 m_image = cropImage( |
| 701 ? PremultiplyAlpha | 699 input.get(), parsedOptions, |
| 702 : DontPremultiplyAlpha); | 700 bitmap->isPremultiplied() ? PremultiplyAlpha : DontPremultiplyAlpha, |
| 701 ColorBehavior::transformToGlobalTarget()); |
| 703 if (!m_image) | 702 if (!m_image) |
| 704 return; | 703 return; |
| 705 m_image->setOriginClean(bitmap->originClean()); | 704 m_image->setOriginClean(bitmap->originClean()); |
| 706 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); | 705 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); |
| 707 } | 706 } |
| 708 | 707 |
| 709 ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image, | 708 ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image, |
| 710 Optional<IntRect> cropRect, | 709 Optional<IntRect> cropRect, |
| 711 const ImageBitmapOptions& options) { | 710 const ImageBitmapOptions& options) { |
| 712 bool originClean = image->originClean(); | 711 bool originClean = image->originClean(); |
| 713 RefPtr<Image> input = image; | 712 RefPtr<Image> input = image; |
| 714 ParsedOptions parsedOptions = parseOptions(options, cropRect, input->size()); | 713 ParsedOptions parsedOptions = parseOptions(options, cropRect, input->size()); |
| 715 if (dstBufferSizeHasOverflow(parsedOptions)) | 714 if (dstBufferSizeHasOverflow(parsedOptions)) |
| 716 return; | 715 return; |
| 717 | 716 |
| 718 m_image = cropImage(input.get(), parsedOptions); | 717 m_image = cropImage(input.get(), parsedOptions, PremultiplyAlpha, |
| 718 ColorBehavior::transformToGlobalTarget()); |
| 719 if (!m_image) | 719 if (!m_image) |
| 720 return; | 720 return; |
| 721 | 721 |
| 722 m_image->setOriginClean(originClean); | 722 m_image->setOriginClean(originClean); |
| 723 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); | 723 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); |
| 724 } | 724 } |
| 725 | 725 |
| 726 ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image) { | 726 ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image) { |
| 727 m_image = image; | 727 m_image = image; |
| 728 } | 728 } |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 864 void ImageBitmap::adjustDrawRects(FloatRect* srcRect, | 864 void ImageBitmap::adjustDrawRects(FloatRect* srcRect, |
| 865 FloatRect* dstRect) const {} | 865 FloatRect* dstRect) const {} |
| 866 | 866 |
| 867 FloatSize ImageBitmap::elementSize(const FloatSize&) const { | 867 FloatSize ImageBitmap::elementSize(const FloatSize&) const { |
| 868 return FloatSize(width(), height()); | 868 return FloatSize(width(), height()); |
| 869 } | 869 } |
| 870 | 870 |
| 871 DEFINE_TRACE(ImageBitmap) {} | 871 DEFINE_TRACE(ImageBitmap) {} |
| 872 | 872 |
| 873 } // namespace blink | 873 } // namespace blink |
| OLD | NEW |