| 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/image-decoders/ImageDecoder.h" | 10 #include "platform/image-decoders/ImageDecoder.h" |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 159 else | 159 else |
| 160 skiaImage = adoptRef(surface->newImageSnapshot()); | 160 skiaImage = adoptRef(surface->newImageSnapshot()); |
| 161 if (premultiplyAlpha) | 161 if (premultiplyAlpha) |
| 162 return StaticBitmapImage::create(skiaImage.release()); | 162 return StaticBitmapImage::create(skiaImage.release()); |
| 163 return StaticBitmapImage::create(premulSkImageToUnPremul(skiaImage.get())); | 163 return StaticBitmapImage::create(premulSkImageToUnPremul(skiaImage.get())); |
| 164 } | 164 } |
| 165 | 165 |
| 166 ImageBitmap::ImageBitmap(HTMLImageElement* image, const IntRect& cropRect, Docum
ent* document, const ImageBitmapOptions& options) | 166 ImageBitmap::ImageBitmap(HTMLImageElement* image, const IntRect& cropRect, Docum
ent* document, const ImageBitmapOptions& options) |
| 167 { | 167 { |
| 168 bool flipY; | 168 bool flipY; |
| 169 parseOptions(options, flipY); | 169 bool premultiplyAlpha; |
| 170 parseOptions(options, flipY, premultiplyAlpha); |
| 170 | 171 |
| 171 m_image = cropImage(image->cachedImage()->getImage(), cropRect, flipY, m_isP
remultiplied); | 172 m_image = cropImage(image->cachedImage()->getImage(), cropRect, flipY, premu
ltiplyAlpha); |
| 172 if (!m_image) | 173 if (!m_image) |
| 173 return; | 174 return; |
| 174 m_image->setOriginClean(!image->wouldTaintOrigin(document->getSecurityOrigin
())); | 175 m_image->setOriginClean(!image->wouldTaintOrigin(document->getSecurityOrigin
())); |
| 176 m_image->setPremultiplied(premultiplyAlpha); |
| 175 } | 177 } |
| 176 | 178 |
| 177 ImageBitmap::ImageBitmap(HTMLVideoElement* video, const IntRect& cropRect, Docum
ent* document, const ImageBitmapOptions& options) | 179 ImageBitmap::ImageBitmap(HTMLVideoElement* video, const IntRect& cropRect, Docum
ent* document, const ImageBitmapOptions& options) |
| 178 { | 180 { |
| 179 IntSize playerSize; | 181 IntSize playerSize; |
| 180 if (video->webMediaPlayer()) | 182 if (video->webMediaPlayer()) |
| 181 playerSize = video->webMediaPlayer()->naturalSize(); | 183 playerSize = video->webMediaPlayer()->naturalSize(); |
| 182 | 184 |
| 183 IntRect videoRect = IntRect(IntPoint(), playerSize); | 185 IntRect videoRect = IntRect(IntPoint(), playerSize); |
| 184 IntRect srcRect = intersection(cropRect, videoRect); | 186 IntRect srcRect = intersection(cropRect, videoRect); |
| 185 OwnPtr<ImageBuffer> buffer = ImageBuffer::create(cropRect.size(), NonOpaque,
DoNotInitializeImagePixels); | 187 OwnPtr<ImageBuffer> buffer = ImageBuffer::create(cropRect.size(), NonOpaque,
DoNotInitializeImagePixels); |
| 186 if (!buffer) | 188 if (!buffer) |
| 187 return; | 189 return; |
| 188 | 190 |
| 189 IntPoint dstPoint = IntPoint(std::max(0, -cropRect.x()), std::max(0, -cropRe
ct.y())); | 191 IntPoint dstPoint = IntPoint(std::max(0, -cropRect.x()), std::max(0, -cropRe
ct.y())); |
| 190 video->paintCurrentFrame(buffer->canvas(), IntRect(dstPoint, srcRect.size())
, nullptr); | 192 video->paintCurrentFrame(buffer->canvas(), IntRect(dstPoint, srcRect.size())
, nullptr); |
| 191 | 193 |
| 192 bool flipY; | 194 bool flipY; |
| 193 parseOptions(options, flipY); | 195 bool premultiplyAlpha; |
| 196 parseOptions(options, flipY, premultiplyAlpha); |
| 194 | 197 |
| 195 if (flipY || !m_isPremultiplied) { | 198 if (flipY || !premultiplyAlpha) { |
| 196 RefPtr<SkImage> skiaImage = buffer->newSkImageSnapshot(PreferNoAccelerat
ion, SnapshotReasonUnknown); | 199 RefPtr<SkImage> skiaImage = buffer->newSkImageSnapshot(PreferNoAccelerat
ion, SnapshotReasonUnknown); |
| 197 if (flipY) | 200 if (flipY) |
| 198 skiaImage = flipSkImageVertically(skiaImage.get(), PremultiplyAlpha)
; | 201 skiaImage = flipSkImageVertically(skiaImage.get(), PremultiplyAlpha)
; |
| 199 if (!m_isPremultiplied) | 202 if (!premultiplyAlpha) |
| 200 skiaImage = premulSkImageToUnPremul(skiaImage.get()); | 203 skiaImage = premulSkImageToUnPremul(skiaImage.get()); |
| 201 m_image = StaticBitmapImage::create(skiaImage.release()); | 204 m_image = StaticBitmapImage::create(skiaImage.release()); |
| 202 } else { | 205 } else { |
| 203 m_image = StaticBitmapImage::create(buffer->newSkImageSnapshot(PreferNoA
cceleration, SnapshotReasonUnknown)); | 206 m_image = StaticBitmapImage::create(buffer->newSkImageSnapshot(PreferNoA
cceleration, SnapshotReasonUnknown)); |
| 204 } | 207 } |
| 205 m_image->setOriginClean(!video->wouldTaintOrigin(document->getSecurityOrigin
())); | 208 m_image->setOriginClean(!video->wouldTaintOrigin(document->getSecurityOrigin
())); |
| 209 m_image->setPremultiplied(premultiplyAlpha); |
| 206 } | 210 } |
| 207 | 211 |
| 208 ImageBitmap::ImageBitmap(HTMLCanvasElement* canvas, const IntRect& cropRect, con
st ImageBitmapOptions& options) | 212 ImageBitmap::ImageBitmap(HTMLCanvasElement* canvas, const IntRect& cropRect, con
st ImageBitmapOptions& options) |
| 209 { | 213 { |
| 210 ASSERT(canvas->isPaintable()); | 214 ASSERT(canvas->isPaintable()); |
| 211 bool flipY; | 215 bool flipY; |
| 212 parseOptions(options, flipY); | 216 bool premultiplyAlpha; |
| 217 parseOptions(options, flipY, premultiplyAlpha); |
| 213 | 218 |
| 214 // canvas is always premultiplied, so set the last parameter to true and con
vert to un-premul later | 219 // canvas is always premultiplied, so set the last parameter to true and con
vert to un-premul later |
| 215 m_image = cropImage(canvas->copiedImage(BackBuffer, PreferAcceleration).get(
), cropRect, flipY, true); | 220 m_image = cropImage(canvas->copiedImage(BackBuffer, PreferAcceleration).get(
), cropRect, flipY, true); |
| 216 if (!m_image) | 221 if (!m_image) |
| 217 return; | 222 return; |
| 218 if (!m_isPremultiplied) | 223 if (!premultiplyAlpha) |
| 219 m_image = StaticBitmapImage::create(premulSkImageToUnPremul(m_image->ima
geForCurrentFrame().get())); | 224 m_image = StaticBitmapImage::create(premulSkImageToUnPremul(m_image->ima
geForCurrentFrame().get())); |
| 220 m_image->setOriginClean(canvas->originClean()); | 225 m_image->setOriginClean(canvas->originClean()); |
| 226 m_image->setPremultiplied(premultiplyAlpha); |
| 221 } | 227 } |
| 222 | 228 |
| 223 ImageBitmap::ImageBitmap(ImageData* data, const IntRect& cropRect, const ImageBi
tmapOptions& options) | 229 ImageBitmap::ImageBitmap(ImageData* data, const IntRect& cropRect, const ImageBi
tmapOptions& options) |
| 224 { | 230 { |
| 225 bool flipY; | 231 bool flipY; |
| 226 parseOptions(options, flipY); | 232 bool premultiplyAlpha; |
| 233 parseOptions(options, flipY, premultiplyAlpha); |
| 227 IntRect srcRect = intersection(cropRect, IntRect(IntPoint(), data->size())); | 234 IntRect srcRect = intersection(cropRect, IntRect(IntPoint(), data->size())); |
| 228 | 235 |
| 229 // treat non-premultiplyAlpha as a special case | 236 // treat non-premultiplyAlpha as a special case |
| 230 if (!m_isPremultiplied) { | 237 if (!premultiplyAlpha) { |
| 231 unsigned char* srcAddr = data->data()->data(); | 238 unsigned char* srcAddr = data->data()->data(); |
| 232 int srcHeight = data->size().height(); | 239 int srcHeight = data->size().height(); |
| 233 int dstHeight = cropRect.height(); | 240 int dstHeight = cropRect.height(); |
| 234 // TODO (xidachen): skia doesn't support SkImage::NewRasterCopy from a k
RGBA color type. | 241 // TODO (xidachen): skia doesn't support SkImage::NewRasterCopy from a k
RGBA color type. |
| 235 // For now, we swap R and B channel and uses kBGRA color type. | 242 // For now, we swap R and B channel and uses kBGRA color type. |
| 236 SkImageInfo info = SkImageInfo::Make(cropRect.width(), dstHeight, kBGRA_
8888_SkColorType, kUnpremul_SkAlphaType); | 243 SkImageInfo info = SkImageInfo::Make(cropRect.width(), dstHeight, kBGRA_
8888_SkColorType, kUnpremul_SkAlphaType); |
| 237 int srcPixelBytesPerRow = info.bytesPerPixel() * data->size().width(); | 244 int srcPixelBytesPerRow = info.bytesPerPixel() * data->size().width(); |
| 238 int dstPixelBytesPerRow = info.bytesPerPixel() * cropRect.width(); | 245 int dstPixelBytesPerRow = info.bytesPerPixel() * cropRect.width(); |
| 239 if (cropRect == IntRect(IntPoint(), data->size())) { | 246 if (cropRect == IntRect(IntPoint(), data->size())) { |
| 240 swizzleImageData(srcAddr, srcHeight, srcPixelBytesPerRow, flipY); | 247 swizzleImageData(srcAddr, srcHeight, srcPixelBytesPerRow, flipY); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 265 copiedDataBuffer[dstStartCopyPosition + j] = srcAddr
[srcStartCopyPosition + j + 2]; | 272 copiedDataBuffer[dstStartCopyPosition + j] = srcAddr
[srcStartCopyPosition + j + 2]; |
| 266 else if (j % 4 == 2) | 273 else if (j % 4 == 2) |
| 267 copiedDataBuffer[dstStartCopyPosition + j] = srcAddr
[srcStartCopyPosition + j - 2]; | 274 copiedDataBuffer[dstStartCopyPosition + j] = srcAddr
[srcStartCopyPosition + j - 2]; |
| 268 else | 275 else |
| 269 copiedDataBuffer[dstStartCopyPosition + j] = srcAddr
[srcStartCopyPosition + j]; | 276 copiedDataBuffer[dstStartCopyPosition + j] = srcAddr
[srcStartCopyPosition + j]; |
| 270 } | 277 } |
| 271 } | 278 } |
| 272 } | 279 } |
| 273 m_image = StaticBitmapImage::create(newSkImageFromRaster(info, copie
dDataBuffer.release(), dstPixelBytesPerRow)); | 280 m_image = StaticBitmapImage::create(newSkImageFromRaster(info, copie
dDataBuffer.release(), dstPixelBytesPerRow)); |
| 274 } | 281 } |
| 282 m_image->setPremultiplied(premultiplyAlpha); |
| 275 return; | 283 return; |
| 276 } | 284 } |
| 277 | 285 |
| 278 OwnPtr<ImageBuffer> buffer = ImageBuffer::create(cropRect.size(), NonOpaque,
DoNotInitializeImagePixels); | 286 OwnPtr<ImageBuffer> buffer = ImageBuffer::create(cropRect.size(), NonOpaque,
DoNotInitializeImagePixels); |
| 279 if (!buffer) | 287 if (!buffer) |
| 280 return; | 288 return; |
| 281 | 289 |
| 282 if (srcRect.isEmpty()) { | 290 if (srcRect.isEmpty()) { |
| 283 m_image = StaticBitmapImage::create(buffer->newSkImageSnapshot(PreferNoA
cceleration, SnapshotReasonUnknown)); | 291 m_image = StaticBitmapImage::create(buffer->newSkImageSnapshot(PreferNoA
cceleration, SnapshotReasonUnknown)); |
| 284 return; | 292 return; |
| 285 } | 293 } |
| 286 | 294 |
| 287 IntPoint dstPoint = IntPoint(std::min(0, -cropRect.x()), std::min(0, -cropRe
ct.y())); | 295 IntPoint dstPoint = IntPoint(std::min(0, -cropRect.x()), std::min(0, -cropRe
ct.y())); |
| 288 if (cropRect.x() < 0) | 296 if (cropRect.x() < 0) |
| 289 dstPoint.setX(-cropRect.x()); | 297 dstPoint.setX(-cropRect.x()); |
| 290 if (cropRect.y() < 0) | 298 if (cropRect.y() < 0) |
| 291 dstPoint.setY(-cropRect.y()); | 299 dstPoint.setY(-cropRect.y()); |
| 292 buffer->putByteArray(Unmultiplied, data->data()->data(), data->size(), srcRe
ct, dstPoint); | 300 buffer->putByteArray(Unmultiplied, data->data()->data(), data->size(), srcRe
ct, dstPoint); |
| 293 if (flipY) | 301 if (flipY) |
| 294 m_image = StaticBitmapImage::create(flipSkImageVertically(buffer->newSkI
mageSnapshot(PreferNoAcceleration, SnapshotReasonUnknown).get(), PremultiplyAlph
a)); | 302 m_image = StaticBitmapImage::create(flipSkImageVertically(buffer->newSkI
mageSnapshot(PreferNoAcceleration, SnapshotReasonUnknown).get(), PremultiplyAlph
a)); |
| 295 else | 303 else |
| 296 m_image = StaticBitmapImage::create(buffer->newSkImageSnapshot(PreferNoA
cceleration, SnapshotReasonUnknown)); | 304 m_image = StaticBitmapImage::create(buffer->newSkImageSnapshot(PreferNoA
cceleration, SnapshotReasonUnknown)); |
| 297 } | 305 } |
| 298 | 306 |
| 299 ImageBitmap::ImageBitmap(ImageBitmap* bitmap, const IntRect& cropRect, const Ima
geBitmapOptions& options) | 307 ImageBitmap::ImageBitmap(ImageBitmap* bitmap, const IntRect& cropRect, const Ima
geBitmapOptions& options) |
| 300 { | 308 { |
| 301 bool flipY; | 309 bool flipY; |
| 302 parseOptions(options, flipY); | 310 bool premultiplyAlpha; |
| 303 m_image = cropImage(bitmap->bitmapImage(), cropRect, flipY, m_isPremultiplie
d, bitmap->isPremultiplied() ? DontPremultiplyAlpha : PremultiplyAlpha); | 311 parseOptions(options, flipY, premultiplyAlpha); |
| 312 m_image = cropImage(bitmap->bitmapImage(), cropRect, flipY, premultiplyAlpha
, bitmap->isPremultiplied() ? DontPremultiplyAlpha : PremultiplyAlpha); |
| 304 if (!m_image) | 313 if (!m_image) |
| 305 return; | 314 return; |
| 306 m_image->setOriginClean(bitmap->originClean()); | 315 m_image->setOriginClean(bitmap->originClean()); |
| 316 m_image->setPremultiplied(premultiplyAlpha); |
| 307 } | 317 } |
| 308 | 318 |
| 309 ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image, const IntRect& cro
pRect, const ImageBitmapOptions& options) | 319 ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image, const IntRect& cro
pRect, const ImageBitmapOptions& options) |
| 310 { | 320 { |
| 311 bool flipY; | 321 bool flipY; |
| 312 parseOptions(options, flipY); | 322 bool premultiplyAlpha; |
| 313 m_image = cropImage(image.get(), cropRect, flipY, m_isPremultiplied, Premult
iplyAlpha); | 323 parseOptions(options, flipY, premultiplyAlpha); |
| 324 m_image = cropImage(image.get(), cropRect, flipY, premultiplyAlpha, Premulti
plyAlpha); |
| 314 if (!m_image) | 325 if (!m_image) |
| 315 return; | 326 return; |
| 316 m_image->setOriginClean(image->originClean()); | 327 m_image->setOriginClean(image->originClean()); |
| 328 m_image->setPremultiplied(premultiplyAlpha); |
| 317 } | 329 } |
| 318 | 330 |
| 319 ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image) | 331 ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image) |
| 320 { | 332 { |
| 321 m_image = image; | 333 m_image = image; |
| 322 } | 334 } |
| 323 | 335 |
| 324 PassRefPtr<StaticBitmapImage> ImageBitmap::transfer() | 336 PassRefPtr<StaticBitmapImage> ImageBitmap::transfer() |
| 325 { | 337 { |
| 326 ASSERT(!isNeutered()); | 338 ASSERT(!isNeutered()); |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 414 | 426 |
| 415 ScriptPromise ImageBitmap::createImageBitmap(ScriptState* scriptState, EventTarg
et& eventTarget, int sx, int sy, int sw, int sh, const ImageBitmapOptions& optio
ns, ExceptionState& exceptionState) | 427 ScriptPromise ImageBitmap::createImageBitmap(ScriptState* scriptState, EventTarg
et& eventTarget, int sx, int sy, int sw, int sh, const ImageBitmapOptions& optio
ns, ExceptionState& exceptionState) |
| 416 { | 428 { |
| 417 if (!sw || !sh) { | 429 if (!sw || !sh) { |
| 418 exceptionState.throwDOMException(IndexSizeError, String::format("The sou
rce %s provided is 0.", sw ? "height" : "width")); | 430 exceptionState.throwDOMException(IndexSizeError, String::format("The sou
rce %s provided is 0.", sw ? "height" : "width")); |
| 419 return ScriptPromise(); | 431 return ScriptPromise(); |
| 420 } | 432 } |
| 421 return ImageBitmapSource::fulfillImageBitmap(scriptState, create(this, IntRe
ct(sx, sy, sw, sh), options)); | 433 return ImageBitmapSource::fulfillImageBitmap(scriptState, create(this, IntRe
ct(sx, sy, sw, sh), options)); |
| 422 } | 434 } |
| 423 | 435 |
| 424 void ImageBitmap::parseOptions(const ImageBitmapOptions& options, bool& flipY) | 436 void ImageBitmap::parseOptions(const ImageBitmapOptions& options, bool& flipY, b
ool& premultiplyAlpha) |
| 425 { | 437 { |
| 426 if (options.imageOrientation() == imageOrientationFlipY) { | 438 if (options.imageOrientation() == imageOrientationFlipY) { |
| 427 flipY = true; | 439 flipY = true; |
| 428 } else { | 440 } else { |
| 429 flipY = false; | 441 flipY = false; |
| 430 ASSERT(options.imageOrientation() == imageBitmapOptionNone); | 442 ASSERT(options.imageOrientation() == imageBitmapOptionNone); |
| 431 } | 443 } |
| 432 if (options.premultiplyAlpha() == imageBitmapOptionNone) { | 444 if (options.premultiplyAlpha() == imageBitmapOptionNone) { |
| 433 m_isPremultiplied = false; | 445 premultiplyAlpha = false; |
| 434 } else { | 446 } else { |
| 447 premultiplyAlpha = true; |
| 435 ASSERT(options.premultiplyAlpha() == "default" || options.premultiplyAlp
ha() == "premultiply"); | 448 ASSERT(options.premultiplyAlpha() == "default" || options.premultiplyAlp
ha() == "premultiply"); |
| 436 } | 449 } |
| 437 } | 450 } |
| 438 | 451 |
| 439 PassRefPtr<Image> ImageBitmap::getSourceImageForCanvas(SourceImageStatus* status
, AccelerationHint, SnapshotReason, const FloatSize&) const | 452 PassRefPtr<Image> ImageBitmap::getSourceImageForCanvas(SourceImageStatus* status
, AccelerationHint, SnapshotReason, const FloatSize&) const |
| 440 { | 453 { |
| 441 *status = NormalSourceImageStatus; | 454 *status = NormalSourceImageStatus; |
| 442 return m_image ? m_image : nullptr; | 455 return m_image ? m_image : nullptr; |
| 443 } | 456 } |
| 444 | 457 |
| 445 void ImageBitmap::adjustDrawRects(FloatRect* srcRect, FloatRect* dstRect) const | 458 void ImageBitmap::adjustDrawRects(FloatRect* srcRect, FloatRect* dstRect) const |
| 446 { | 459 { |
| 447 } | 460 } |
| 448 | 461 |
| 449 FloatSize ImageBitmap::elementSize(const FloatSize&) const | 462 FloatSize ImageBitmap::elementSize(const FloatSize&) const |
| 450 { | 463 { |
| 451 return FloatSize(width(), height()); | 464 return FloatSize(width(), height()); |
| 452 } | 465 } |
| 453 | 466 |
| 454 DEFINE_TRACE(ImageBitmap) | 467 DEFINE_TRACE(ImageBitmap) |
| 455 { | 468 { |
| 456 } | 469 } |
| 457 | 470 |
| 458 } // namespace blink | 471 } // namespace blink |
| OLD | NEW |