Chromium Code Reviews| 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 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 84 return newSkImageFromRaster(info, std::move(imagePixels), imageRowBytes); | 84 return newSkImageFromRaster(info, std::move(imagePixels), imageRowBytes); |
| 85 } | 85 } |
| 86 | 86 |
| 87 static PassRefPtr<SkImage> premulSkImageToUnPremul(SkImage* input) | 87 static PassRefPtr<SkImage> premulSkImageToUnPremul(SkImage* input) |
| 88 { | 88 { |
| 89 SkImageInfo info = SkImageInfo::Make(input->width(), input->height(), kN32_S kColorType, kUnpremul_SkAlphaType); | 89 SkImageInfo info = SkImageInfo::Make(input->width(), input->height(), kN32_S kColorType, kUnpremul_SkAlphaType); |
| 90 OwnPtr<uint8_t[]> dstPixels = copySkImageData(input, info); | 90 OwnPtr<uint8_t[]> dstPixels = copySkImageData(input, info); |
| 91 return newSkImageFromRaster(info, std::move(dstPixels), input->width() * inf o.bytesPerPixel()); | 91 return newSkImageFromRaster(info, std::move(dstPixels), input->width() * inf o.bytesPerPixel()); |
| 92 } | 92 } |
| 93 | 93 |
| 94 static PassRefPtr<SkImage> unPremulSkImageToPremul(SkImage* input) | |
| 95 { | |
| 96 SkImageInfo info = SkImageInfo::Make(input->width(), input->height(), kN32_S kColorType, kPremul_SkAlphaType); | |
| 97 OwnPtr<uint8_t[]> dstPixels = copySkImageData(input, info); | |
| 98 return newSkImageFromRaster(info, std::move(dstPixels), input->width() * inf o.bytesPerPixel()); | |
| 99 } | |
| 100 | |
| 94 PassRefPtr<SkImage> ImageBitmap::getSkImageFromDecoder(PassOwnPtr<ImageDecoder> decoder) | 101 PassRefPtr<SkImage> ImageBitmap::getSkImageFromDecoder(PassOwnPtr<ImageDecoder> decoder) |
| 95 { | 102 { |
| 96 if (!decoder->frameCount()) | 103 if (!decoder->frameCount()) |
| 97 return nullptr; | 104 return nullptr; |
| 98 ImageFrame* frame = decoder->frameBufferAtIndex(0); | 105 ImageFrame* frame = decoder->frameBufferAtIndex(0); |
| 99 if (!frame || frame->getStatus() != ImageFrame::FrameComplete) | 106 if (!frame || frame->getStatus() != ImageFrame::FrameComplete) |
| 100 return nullptr; | 107 return nullptr; |
| 101 SkBitmap bitmap = frame->bitmap(); | 108 SkBitmap bitmap = frame->bitmap(); |
| 102 if (!frameIsValid(bitmap)) | 109 if (!frameIsValid(bitmap)) |
| 103 return nullptr; | 110 return nullptr; |
| 104 return adoptRef(SkImage::NewFromBitmap(bitmap)); | 111 return adoptRef(SkImage::NewFromBitmap(bitmap)); |
| 105 } | 112 } |
| 106 | 113 |
| 107 // The parameter imageFormat indicates whether the first parameter "image" is un premultiplied or not. | 114 // The parameter imageFormat indicates whether the first parameter "image" is un premultiplied or not. |
| 115 // imageFormat = PremultiplyAlpha means the image is in premuliplied format | |
| 108 // For example, if the image is already in unpremultiplied format and we want th e created ImageBitmap | 116 // For example, if the image is already in unpremultiplied format and we want th e created ImageBitmap |
| 109 // in the same format, then we don't need to use the ImageDecoder to decode the image. | 117 // in the same format, then we don't need to use the ImageDecoder to decode the image. |
| 110 static PassRefPtr<StaticBitmapImage> cropImage(Image* image, const IntRect& crop Rect, bool flipY, bool premultiplyAlpha, AlphaDisposition imageFormat = DontPrem ultiplyAlpha, ImageDecoder::GammaAndColorProfileOption colorSpaceOp = ImageDecod er::GammaAndColorProfileApplied) | 118 static PassRefPtr<StaticBitmapImage> cropImage(Image* image, const IntRect& crop Rect, bool flipY, bool premultiplyAlpha, AlphaDisposition imageFormat = Premulti plyAlpha, ImageDecoder::GammaAndColorProfileOption colorSpaceOp = ImageDecoder:: GammaAndColorProfileApplied) |
| 111 { | 119 { |
| 112 ASSERT(image); | 120 ASSERT(image); |
| 113 | 121 |
| 114 IntRect imgRect(IntPoint(), IntSize(image->width(), image->height())); | 122 IntRect imgRect(IntPoint(), IntSize(image->width(), image->height())); |
| 115 const IntRect srcRect = intersection(imgRect, cropRect); | 123 const IntRect srcRect = intersection(imgRect, cropRect); |
| 116 | 124 |
| 117 // In the case when cropRect doesn't intersect the source image and it requi res a umpremul image | 125 // In the case when cropRect doesn't intersect the source image and it requi res a umpremul image |
| 118 // We immediately return a transparent black image with cropRect.size() | 126 // We immediately return a transparent black image with cropRect.size() |
| 119 if (srcRect.isEmpty() && !premultiplyAlpha) { | 127 if (srcRect.isEmpty() && !premultiplyAlpha) { |
| 120 SkImageInfo info = SkImageInfo::Make(cropRect.width(), cropRect.height() , kN32_SkColorType, kUnpremul_SkAlphaType); | 128 SkImageInfo info = SkImageInfo::Make(cropRect.width(), cropRect.height() , kN32_SkColorType, kUnpremul_SkAlphaType); |
| 121 OwnPtr<uint8_t[]> dstPixels = adoptArrayPtr(new uint8_t[cropRect.width() * cropRect.height() * info.bytesPerPixel()]()); | 129 OwnPtr<uint8_t[]> dstPixels = adoptArrayPtr(new uint8_t[cropRect.width() * cropRect.height() * info.bytesPerPixel()]()); |
| 122 return StaticBitmapImage::create(newSkImageFromRaster(info, std::move(ds tPixels), cropRect.width() * info.bytesPerPixel())); | 130 return StaticBitmapImage::create(newSkImageFromRaster(info, std::move(ds tPixels), cropRect.width() * info.bytesPerPixel())); |
| 123 } | 131 } |
| 124 | 132 |
| 125 RefPtr<SkImage> skiaImage = image->imageForCurrentFrame(); | 133 RefPtr<SkImage> skiaImage = image->imageForCurrentFrame(); |
| 126 // Attempt to get raw unpremultiplied image data, executed only when skiaIma ge is premultiplied. | 134 // Attempt to get raw unpremultiplied image data, executed only when skiaIma ge is premultiplied. |
| 127 if ((((!premultiplyAlpha && !skiaImage->isOpaque()) || !skiaImage) && image- >data() && imageFormat == DontPremultiplyAlpha) || colorSpaceOp == ImageDecoder: :GammaAndColorProfileIgnored) { | 135 if ((((!premultiplyAlpha && !skiaImage->isOpaque()) || !skiaImage) && image- >data() && imageFormat == PremultiplyAlpha) || colorSpaceOp == ImageDecoder::Gam maAndColorProfileIgnored) { |
| 128 OwnPtr<ImageDecoder> decoder(ImageDecoder::create(*(image->data()), | 136 OwnPtr<ImageDecoder> decoder(ImageDecoder::create(*(image->data()), |
| 129 premultiplyAlpha ? ImageDecoder::AlphaPremultiplied : ImageDecoder:: AlphaNotPremultiplied, | 137 premultiplyAlpha ? ImageDecoder::AlphaPremultiplied : ImageDecoder:: AlphaNotPremultiplied, |
| 130 colorSpaceOp)); | 138 colorSpaceOp)); |
| 131 if (!decoder) | 139 if (!decoder) |
| 132 return nullptr; | 140 return nullptr; |
| 133 decoder->setData(image->data(), true); | 141 decoder->setData(image->data(), true); |
| 134 skiaImage = ImageBitmap::getSkImageFromDecoder(std::move(decoder)); | 142 skiaImage = ImageBitmap::getSkImageFromDecoder(std::move(decoder)); |
| 135 if (!skiaImage) | 143 if (!skiaImage) |
| 136 return nullptr; | 144 return nullptr; |
| 137 } | 145 } |
| 138 | 146 |
| 139 if (cropRect == srcRect) { | 147 if (cropRect == srcRect) { |
| 140 if (flipY) | 148 if (flipY) |
| 141 return StaticBitmapImage::create(flipSkImageVertically(skiaImage->ne wSubset(srcRect), premultiplyAlpha ? PremultiplyAlpha : DontPremultiplyAlpha)); | 149 return StaticBitmapImage::create(flipSkImageVertically(skiaImage->ne wSubset(srcRect), premultiplyAlpha ? PremultiplyAlpha : DontPremultiplyAlpha)); |
| 142 SkImage* croppedSkImage = skiaImage->newSubset(srcRect); | 150 SkImage* croppedSkImage = skiaImage->newSubset(srcRect); |
| 151 // Special case: The first parameter image is unpremul but we need to tu rn it into premul. | |
| 152 if (premultiplyAlpha && imageFormat == DontPremultiplyAlpha) | |
| 153 return StaticBitmapImage::create(unPremulSkImageToPremul(croppedSkIm age)); | |
| 143 // Call preroll to trigger image decoding. | 154 // Call preroll to trigger image decoding. |
| 144 croppedSkImage->preroll(); | 155 croppedSkImage->preroll(); |
| 145 return StaticBitmapImage::create(adoptRef(croppedSkImage)); | 156 return StaticBitmapImage::create(adoptRef(croppedSkImage)); |
| 146 } | 157 } |
| 147 | 158 |
| 148 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(cropRect.width(), cropRect.height()); | 159 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(cropRect.width(), cropRect.height()); |
| 149 if (!surface) | 160 if (!surface) |
| 150 return nullptr; | 161 return nullptr; |
| 151 if (srcRect.isEmpty()) | 162 if (srcRect.isEmpty()) |
| 152 return StaticBitmapImage::create(adoptRef(surface->newImageSnapshot())); | 163 return StaticBitmapImage::create(adoptRef(surface->newImageSnapshot())); |
| 153 | 164 |
| 154 SkScalar dstLeft = std::min(0, -cropRect.x()); | 165 SkScalar dstLeft = std::min(0, -cropRect.x()); |
| 155 SkScalar dstTop = std::min(0, -cropRect.y()); | 166 SkScalar dstTop = std::min(0, -cropRect.y()); |
| 156 if (cropRect.x() < 0) | 167 if (cropRect.x() < 0) |
| 157 dstLeft = -cropRect.x(); | 168 dstLeft = -cropRect.x(); |
| 158 if (cropRect.y() < 0) | 169 if (cropRect.y() < 0) |
| 159 dstTop = -cropRect.y(); | 170 dstTop = -cropRect.y(); |
| 160 surface->getCanvas()->drawImage(skiaImage.get(), dstLeft, dstTop); | 171 surface->getCanvas()->drawImage(skiaImage.get(), dstLeft, dstTop); |
| 161 if (flipY) | 172 if (flipY) |
| 162 skiaImage = flipSkImageVertically(surface->newImageSnapshot(), Premultip lyAlpha); | 173 skiaImage = flipSkImageVertically(surface->newImageSnapshot(), Premultip lyAlpha); |
| 163 else | 174 else |
| 164 skiaImage = adoptRef(surface->newImageSnapshot()); | 175 skiaImage = adoptRef(surface->newImageSnapshot()); |
| 165 if (premultiplyAlpha) | 176 if (premultiplyAlpha) { |
| 177 if (imageFormat == PremultiplyAlpha) | |
| 178 return StaticBitmapImage::create(unPremulSkImageToPremul(skiaImage.g et())); | |
| 166 return StaticBitmapImage::create(skiaImage.release()); | 179 return StaticBitmapImage::create(skiaImage.release()); |
| 180 } | |
| 167 return StaticBitmapImage::create(premulSkImageToUnPremul(skiaImage.get())); | 181 return StaticBitmapImage::create(premulSkImageToUnPremul(skiaImage.get())); |
| 168 } | 182 } |
| 169 | 183 |
| 170 ImageBitmap::ImageBitmap(HTMLImageElement* image, const IntRect& cropRect, Docum ent* document, const ImageBitmapOptions& options) | 184 ImageBitmap::ImageBitmap(HTMLImageElement* image, const IntRect& cropRect, Docum ent* document, const ImageBitmapOptions& options) |
| 171 { | 185 { |
| 172 bool flipY; | 186 bool flipY; |
| 173 bool premultiplyAlpha; | 187 bool premultiplyAlpha; |
| 174 parseOptions(options, flipY, premultiplyAlpha); | 188 parseOptions(options, flipY, premultiplyAlpha); |
| 175 | 189 |
| 176 if (options.colorSpaceConversion() == "none") | 190 if (options.colorSpaceConversion() == "none") |
| 177 m_image = cropImage(image->cachedImage()->getImage(), cropRect, flipY, p remultiplyAlpha, DontPremultiplyAlpha, ImageDecoder::GammaAndColorProfileIgnored ); | 191 m_image = cropImage(image->cachedImage()->getImage(), cropRect, flipY, p remultiplyAlpha, PremultiplyAlpha, ImageDecoder::GammaAndColorProfileIgnored); |
| 178 else | 192 else |
| 179 m_image = cropImage(image->cachedImage()->getImage(), cropRect, flipY, p remultiplyAlpha, DontPremultiplyAlpha, ImageDecoder::GammaAndColorProfileApplied ); | 193 m_image = cropImage(image->cachedImage()->getImage(), cropRect, flipY, p remultiplyAlpha, PremultiplyAlpha, ImageDecoder::GammaAndColorProfileApplied); |
|
Ken Russell (switch to Gerrit)
2016/05/27 21:17:08
This change is concerning. It's important that PNG
xidachen
2016/05/28 00:51:11
Actually there is no change in here in terms of co
| |
| 180 if (!m_image) | 194 if (!m_image) |
| 181 return; | 195 return; |
| 196 // In the case where the source image is lazy-decoded, m_image may not be in | |
| 197 // a decoded state, we trigger it here. | |
| 198 RefPtr<SkImage> skImage = m_image->imageForCurrentFrame(); | |
| 199 SkPixmap pixmap; | |
| 200 if (!skImage->isTextureBacked() && !skImage->peekPixels(&pixmap)) { | |
| 201 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(skImage->width (), skImage->height()); | |
| 202 surface->getCanvas()->drawImage(skImage.get(), 0, 0); | |
|
Ken Russell (switch to Gerrit)
2016/05/27 21:17:08
This looks to me like it will always force the alp
xidachen
2016/05/28 00:51:11
I think the concern here is that this piece of cod
| |
| 203 m_image = StaticBitmapImage::create(adoptRef(surface->newImageSnapshot() )); | |
| 204 } | |
| 182 m_image->setOriginClean(!image->wouldTaintOrigin(document->getSecurityOrigin ())); | 205 m_image->setOriginClean(!image->wouldTaintOrigin(document->getSecurityOrigin ())); |
| 183 m_image->setPremultiplied(premultiplyAlpha); | 206 m_image->setPremultiplied(premultiplyAlpha); |
| 184 } | 207 } |
| 185 | 208 |
| 186 ImageBitmap::ImageBitmap(HTMLVideoElement* video, const IntRect& cropRect, Docum ent* document, const ImageBitmapOptions& options) | 209 ImageBitmap::ImageBitmap(HTMLVideoElement* video, const IntRect& cropRect, Docum ent* document, const ImageBitmapOptions& options) |
| 187 { | 210 { |
| 188 IntSize playerSize; | 211 IntSize playerSize; |
| 189 if (video->webMediaPlayer()) | 212 if (video->webMediaPlayer()) |
| 190 playerSize = video->webMediaPlayer()->naturalSize(); | 213 playerSize = video->webMediaPlayer()->naturalSize(); |
| 191 | 214 |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 313 m_image = StaticBitmapImage::create(flipSkImageVertically(buffer->newSkI mageSnapshot(PreferNoAcceleration, SnapshotReasonUnknown).get(), PremultiplyAlph a)); | 336 m_image = StaticBitmapImage::create(flipSkImageVertically(buffer->newSkI mageSnapshot(PreferNoAcceleration, SnapshotReasonUnknown).get(), PremultiplyAlph a)); |
| 314 else | 337 else |
| 315 m_image = StaticBitmapImage::create(buffer->newSkImageSnapshot(PreferNoA cceleration, SnapshotReasonUnknown)); | 338 m_image = StaticBitmapImage::create(buffer->newSkImageSnapshot(PreferNoA cceleration, SnapshotReasonUnknown)); |
| 316 } | 339 } |
| 317 | 340 |
| 318 ImageBitmap::ImageBitmap(ImageBitmap* bitmap, const IntRect& cropRect, const Ima geBitmapOptions& options) | 341 ImageBitmap::ImageBitmap(ImageBitmap* bitmap, const IntRect& cropRect, const Ima geBitmapOptions& options) |
| 319 { | 342 { |
| 320 bool flipY; | 343 bool flipY; |
| 321 bool premultiplyAlpha; | 344 bool premultiplyAlpha; |
| 322 parseOptions(options, flipY, premultiplyAlpha); | 345 parseOptions(options, flipY, premultiplyAlpha); |
| 323 m_image = cropImage(bitmap->bitmapImage(), cropRect, flipY, premultiplyAlpha , bitmap->isPremultiplied() ? DontPremultiplyAlpha : PremultiplyAlpha); | 346 m_image = cropImage(bitmap->bitmapImage(), cropRect, flipY, premultiplyAlpha , bitmap->isPremultiplied() ? PremultiplyAlpha : DontPremultiplyAlpha); |
| 324 if (!m_image) | 347 if (!m_image) |
| 325 return; | 348 return; |
| 326 m_image->setOriginClean(bitmap->originClean()); | 349 m_image->setOriginClean(bitmap->originClean()); |
| 327 m_image->setPremultiplied(premultiplyAlpha); | 350 m_image->setPremultiplied(premultiplyAlpha); |
| 328 } | 351 } |
| 329 | 352 |
| 330 ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image, const IntRect& cro pRect, const ImageBitmapOptions& options) | 353 ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image, const IntRect& cro pRect, const ImageBitmapOptions& options) |
| 331 { | 354 { |
| 332 bool flipY; | 355 bool flipY; |
| 333 bool premultiplyAlpha; | 356 bool premultiplyAlpha; |
| 334 parseOptions(options, flipY, premultiplyAlpha); | 357 parseOptions(options, flipY, premultiplyAlpha); |
| 335 m_image = cropImage(image.get(), cropRect, flipY, premultiplyAlpha, Premulti plyAlpha); | 358 m_image = cropImage(image.get(), cropRect, flipY, premultiplyAlpha, DontPrem ultiplyAlpha); |
| 336 if (!m_image) | 359 if (!m_image) |
| 337 return; | 360 return; |
| 338 m_image->setOriginClean(image->originClean()); | 361 m_image->setOriginClean(image->originClean()); |
| 339 m_image->setPremultiplied(premultiplyAlpha); | 362 m_image->setPremultiplied(premultiplyAlpha); |
| 340 } | 363 } |
| 341 | 364 |
| 342 ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image) | 365 ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image) |
| 343 { | 366 { |
| 344 m_image = image; | 367 m_image = image; |
| 345 } | 368 } |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 489 FloatSize ImageBitmap::elementSize(const FloatSize&) const | 512 FloatSize ImageBitmap::elementSize(const FloatSize&) const |
| 490 { | 513 { |
| 491 return FloatSize(width(), height()); | 514 return FloatSize(width(), height()); |
| 492 } | 515 } |
| 493 | 516 |
| 494 DEFINE_TRACE(ImageBitmap) | 517 DEFINE_TRACE(ImageBitmap) |
| 495 { | 518 { |
| 496 } | 519 } |
| 497 | 520 |
| 498 } // namespace blink | 521 } // namespace blink |
| OLD | NEW |