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 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 356 } | 356 } |
| 357 | 357 |
| 358 ImageBitmap::ImageBitmap(std::unique_ptr<uint8_t[]> data, uint32_t width, uint32 _t height, bool isImageBitmapPremultiplied, bool isImageBitmapOriginClean) | 358 ImageBitmap::ImageBitmap(std::unique_ptr<uint8_t[]> data, uint32_t width, uint32 _t height, bool isImageBitmapPremultiplied, bool isImageBitmapOriginClean) |
| 359 { | 359 { |
| 360 SkImageInfo info = SkImageInfo::MakeN32(width, height, isImageBitmapPremulti plied ? kPremul_SkAlphaType : kUnpremul_SkAlphaType); | 360 SkImageInfo info = SkImageInfo::MakeN32(width, height, isImageBitmapPremulti plied ? kPremul_SkAlphaType : kUnpremul_SkAlphaType); |
| 361 m_image = StaticBitmapImage::create(fromSkSp(SkImage::MakeRasterCopy(SkPixma p(info, data.get(), info.bytesPerPixel() * width)))); | 361 m_image = StaticBitmapImage::create(fromSkSp(SkImage::MakeRasterCopy(SkPixma p(info, data.get(), info.bytesPerPixel() * width)))); |
| 362 m_image->setPremultiplied(isImageBitmapPremultiplied); | 362 m_image->setPremultiplied(isImageBitmapPremultiplied); |
| 363 m_image->setOriginClean(isImageBitmapOriginClean); | 363 m_image->setOriginClean(isImageBitmapOriginClean); |
| 364 } | 364 } |
| 365 | 365 |
| 366 static PassRefPtr<SkImage> scaleSkImage(PassRefPtr<SkImage> skImage, unsigned re sizeWidth, unsigned resizeHeight, SkFilterQuality resizeQuality) | |
| 367 { | |
| 368 SkImageInfo resizedInfo = SkImageInfo::Make(resizeWidth, resizeHeight, kBGRA _8888_SkColorType, kUnpremul_SkAlphaType); | |
|
Justin Novosad
2016/07/27 17:05:05
Why BGRA instead of N32 (the platform-specific def
xidachen
2016/07/28 13:21:16
Done, changed to N32. Swizzle is applied only when
| |
| 369 std::unique_ptr<uint8_t[]> resizedPixels = wrapArrayUnique(new uint8_t[resiz eWidth * resizeHeight * resizedInfo.bytesPerPixel()]); | |
| 370 SkPixmap pixmap(resizedInfo, resizedPixels.release(), resizeWidth * resizedI nfo.bytesPerPixel()); | |
| 371 skImage->scalePixels(pixmap, resizeQuality); | |
| 372 return fromSkSp(SkImage::MakeFromRaster(pixmap, [](const void* pixels, void* ) | |
| 373 { | |
| 374 delete[] static_cast<const uint8_t*>(pixels); | |
| 375 }, nullptr)); | |
| 376 } | |
| 377 | |
| 366 ImageBitmap::ImageBitmap(ImageData* data, Optional<IntRect> cropRect, const Imag eBitmapOptions& options) | 378 ImageBitmap::ImageBitmap(ImageData* data, Optional<IntRect> cropRect, const Imag eBitmapOptions& options) |
| 367 { | 379 { |
| 368 // TODO(xidachen): implement the resize option | 380 // TODO(xidachen): implement the resize option |
| 369 IntRect dataSrcRect = IntRect(IntPoint(), data->size()); | 381 IntRect dataSrcRect = IntRect(IntPoint(), data->size()); |
| 370 ParsedOptions parsedOptions = parseOptions(options, cropRect, data->bitmapSo urceSize()); | 382 ParsedOptions parsedOptions = parseOptions(options, cropRect, data->bitmapSo urceSize()); |
| 371 IntRect srcRect = cropRect ? intersection(parsedOptions.cropRect, dataSrcRec t) : dataSrcRect; | 383 IntRect srcRect = cropRect ? intersection(parsedOptions.cropRect, dataSrcRec t) : dataSrcRect; |
| 372 | 384 |
| 373 // treat non-premultiplyAlpha as a special case | 385 // treat non-premultiplyAlpha as a special case |
| 374 if (!parsedOptions.premultiplyAlpha) { | 386 if (!parsedOptions.premultiplyAlpha) { |
| 375 unsigned char* srcAddr = data->data()->data(); | 387 unsigned char* srcAddr = data->data()->data(); |
| 376 int srcHeight = data->size().height(); | 388 int srcHeight = data->size().height(); |
| 377 int dstHeight = parsedOptions.cropRect.height(); | 389 int dstHeight = parsedOptions.cropRect.height(); |
| 378 // TODO (xidachen): skia doesn't support SkImage::NewRasterCopy from a k RGBA color type. | 390 // TODO (xidachen): skia doesn't support SkImage::NewRasterCopy from a k RGBA color type. |
| 379 // For now, we swap R and B channel and uses kBGRA color type. | 391 // For now, we swap R and B channel and uses kBGRA color type. |
| 380 SkImageInfo info = SkImageInfo::Make(parsedOptions.cropRect.width(), dst Height, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType); | 392 SkImageInfo info = SkImageInfo::Make(parsedOptions.cropRect.width(), dst Height, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType); |
| 381 int srcPixelBytesPerRow = info.bytesPerPixel() * data->size().width(); | 393 int srcPixelBytesPerRow = info.bytesPerPixel() * data->size().width(); |
| 382 int dstPixelBytesPerRow = info.bytesPerPixel() * parsedOptions.cropRect. width(); | 394 int dstPixelBytesPerRow = info.bytesPerPixel() * parsedOptions.cropRect. width(); |
| 395 RefPtr<SkImage> skImage; | |
| 383 if (parsedOptions.cropRect == IntRect(IntPoint(), data->size())) { | 396 if (parsedOptions.cropRect == IntRect(IntPoint(), data->size())) { |
| 384 swizzleImageData(srcAddr, srcHeight, srcPixelBytesPerRow, parsedOpti ons.flipY); | 397 swizzleImageData(srcAddr, srcHeight, srcPixelBytesPerRow, parsedOpti ons.flipY); |
| 385 m_image = StaticBitmapImage::create(fromSkSp(SkImage::MakeRasterCopy (SkPixmap(info, srcAddr, dstPixelBytesPerRow)))); | 398 skImage = fromSkSp(SkImage::MakeRasterCopy(SkPixmap(info, srcAddr, d stPixelBytesPerRow))); |
|
Justin Novosad
2016/07/27 17:05:05
It's a shame to have to make an make a copy here t
xidachen
2016/07/28 13:21:16
Not easy. SkSurface doesn't support un-premultipli
| |
| 386 // restore the original ImageData | 399 // restore the original ImageData |
| 387 swizzleImageData(srcAddr, srcHeight, srcPixelBytesPerRow, parsedOpti ons.flipY); | 400 swizzleImageData(srcAddr, srcHeight, srcPixelBytesPerRow, parsedOpti ons.flipY); |
| 388 } else { | 401 } else { |
| 389 std::unique_ptr<uint8_t[]> copiedDataBuffer = wrapArrayUnique(new ui nt8_t[dstHeight * dstPixelBytesPerRow]()); | 402 std::unique_ptr<uint8_t[]> copiedDataBuffer = wrapArrayUnique(new ui nt8_t[dstHeight * dstPixelBytesPerRow]()); |
| 390 if (!srcRect.isEmpty()) { | 403 if (!srcRect.isEmpty()) { |
| 391 IntPoint srcPoint = IntPoint((parsedOptions.cropRect.x() > 0) ? parsedOptions.cropRect.x() : 0, (parsedOptions.cropRect.y() > 0) ? parsedOptions .cropRect.y() : 0); | 404 IntPoint srcPoint = IntPoint((parsedOptions.cropRect.x() > 0) ? parsedOptions.cropRect.x() : 0, (parsedOptions.cropRect.y() > 0) ? parsedOptions .cropRect.y() : 0); |
| 392 IntPoint dstPoint = IntPoint((parsedOptions.cropRect.x() >= 0) ? 0 : -parsedOptions.cropRect.x(), (parsedOptions.cropRect.y() >= 0) ? 0 : -parse dOptions.cropRect.y()); | 405 IntPoint dstPoint = IntPoint((parsedOptions.cropRect.x() >= 0) ? 0 : -parsedOptions.cropRect.x(), (parsedOptions.cropRect.y() >= 0) ? 0 : -parse dOptions.cropRect.y()); |
| 393 int copyHeight = srcHeight - srcPoint.y(); | 406 int copyHeight = srcHeight - srcPoint.y(); |
| 394 if (parsedOptions.cropRect.height() < copyHeight) | 407 if (parsedOptions.cropRect.height() < copyHeight) |
| 395 copyHeight = parsedOptions.cropRect.height(); | 408 copyHeight = parsedOptions.cropRect.height(); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 407 for (int j = 0; j < srcEndCopyPosition - srcStartCopyPositio n; j++) { | 420 for (int j = 0; j < srcEndCopyPosition - srcStartCopyPositio n; j++) { |
| 408 if (j % 4 == 0) | 421 if (j % 4 == 0) |
| 409 copiedDataBuffer[dstStartCopyPosition + j] = srcAddr [srcStartCopyPosition + j + 2]; | 422 copiedDataBuffer[dstStartCopyPosition + j] = srcAddr [srcStartCopyPosition + j + 2]; |
| 410 else if (j % 4 == 2) | 423 else if (j % 4 == 2) |
| 411 copiedDataBuffer[dstStartCopyPosition + j] = srcAddr [srcStartCopyPosition + j - 2]; | 424 copiedDataBuffer[dstStartCopyPosition + j] = srcAddr [srcStartCopyPosition + j - 2]; |
| 412 else | 425 else |
| 413 copiedDataBuffer[dstStartCopyPosition + j] = srcAddr [srcStartCopyPosition + j]; | 426 copiedDataBuffer[dstStartCopyPosition + j] = srcAddr [srcStartCopyPosition + j]; |
| 414 } | 427 } |
| 415 } | 428 } |
| 416 } | 429 } |
| 417 m_image = StaticBitmapImage::create(newSkImageFromRaster(info, std:: move(copiedDataBuffer), dstPixelBytesPerRow)); | 430 skImage = newSkImageFromRaster(info, std::move(copiedDataBuffer), ds tPixelBytesPerRow); |
| 418 } | 431 } |
| 432 if (parsedOptions.shouldScaleInput) | |
| 433 m_image = StaticBitmapImage::create(scaleSkImage(skImage, parsedOpti ons.resizeWidth, parsedOptions.resizeHeight, parsedOptions.resizeQuality)); | |
| 434 else | |
| 435 m_image = StaticBitmapImage::create(skImage); | |
| 419 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); | 436 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); |
| 420 return; | 437 return; |
| 421 } | 438 } |
| 422 | 439 |
| 423 std::unique_ptr<ImageBuffer> buffer = ImageBuffer::create(parsedOptions.crop Rect.size(), NonOpaque, DoNotInitializeImagePixels); | 440 std::unique_ptr<ImageBuffer> buffer = ImageBuffer::create(parsedOptions.crop Rect.size(), NonOpaque, DoNotInitializeImagePixels); |
| 424 if (!buffer) | 441 if (!buffer) |
| 425 return; | 442 return; |
| 426 | 443 |
| 427 if (srcRect.isEmpty()) { | 444 if (srcRect.isEmpty()) { |
| 428 m_image = StaticBitmapImage::create(buffer->newSkImageSnapshot(PreferNoA cceleration, SnapshotReasonUnknown)); | 445 m_image = StaticBitmapImage::create(buffer->newSkImageSnapshot(PreferNoA cceleration, SnapshotReasonUnknown)); |
| 429 return; | 446 return; |
| 430 } | 447 } |
| 431 | 448 |
| 432 IntPoint dstPoint = IntPoint(std::min(0, -parsedOptions.cropRect.x()), std:: min(0, -parsedOptions.cropRect.y())); | 449 IntPoint dstPoint = IntPoint(std::min(0, -parsedOptions.cropRect.x()), std:: min(0, -parsedOptions.cropRect.y())); |
| 433 if (parsedOptions.cropRect.x() < 0) | 450 if (parsedOptions.cropRect.x() < 0) |
| 434 dstPoint.setX(-parsedOptions.cropRect.x()); | 451 dstPoint.setX(-parsedOptions.cropRect.x()); |
| 435 if (parsedOptions.cropRect.y() < 0) | 452 if (parsedOptions.cropRect.y() < 0) |
| 436 dstPoint.setY(-parsedOptions.cropRect.y()); | 453 dstPoint.setY(-parsedOptions.cropRect.y()); |
| 437 buffer->putByteArray(Unmultiplied, data->data()->data(), data->size(), srcRe ct, dstPoint); | 454 buffer->putByteArray(Unmultiplied, data->data()->data(), data->size(), srcRe ct, dstPoint); |
| 455 RefPtr<SkImage> skImage = buffer->newSkImageSnapshot(PreferNoAcceleration, S napshotReasonUnknown); | |
| 438 if (parsedOptions.flipY) | 456 if (parsedOptions.flipY) |
| 439 m_image = StaticBitmapImage::create(flipSkImageVertically(buffer->newSkI mageSnapshot(PreferNoAcceleration, SnapshotReasonUnknown).get(), PremultiplyAlph a)); | 457 skImage = flipSkImageVertically(skImage.get(), PremultiplyAlpha); |
| 440 else | 458 if (parsedOptions.shouldScaleInput) { |
| 441 m_image = StaticBitmapImage::create(buffer->newSkImageSnapshot(PreferNoA cceleration, SnapshotReasonUnknown)); | 459 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(parsedOptions. resizeWidth, parsedOptions.resizeHeight); |
| 460 if (!surface) | |
| 461 return; | |
| 462 SkPaint paint; | |
| 463 paint.setFilterQuality(parsedOptions.resizeQuality); | |
| 464 SkRect dstDrawRect = SkRect::MakeWH(parsedOptions.resizeWidth, parsedOpt ions.resizeHeight); | |
| 465 surface->getCanvas()->drawImageRect(skImage.get(), dstDrawRect, &paint); | |
| 466 skImage = fromSkSp(surface->makeImageSnapshot()); | |
| 467 } | |
| 468 m_image = StaticBitmapImage::create(skImage); | |
| 442 } | 469 } |
| 443 | 470 |
| 444 ImageBitmap::ImageBitmap(ImageBitmap* bitmap, Optional<IntRect> cropRect, const ImageBitmapOptions& options) | 471 ImageBitmap::ImageBitmap(ImageBitmap* bitmap, Optional<IntRect> cropRect, const ImageBitmapOptions& options) |
| 445 { | 472 { |
| 446 RefPtr<Image> input = bitmap->bitmapImage(); | 473 RefPtr<Image> input = bitmap->bitmapImage(); |
| 447 if (!input) | 474 if (!input) |
| 448 return; | 475 return; |
| 449 ParsedOptions parsedOptions = parseOptions(options, cropRect, input->size()) ; | 476 ParsedOptions parsedOptions = parseOptions(options, cropRect, input->size()) ; |
| 450 | 477 |
| 451 m_image = cropImage(input.get(), parsedOptions, bitmap->isPremultiplied() ? PremultiplyAlpha : DontPremultiplyAlpha); | 478 m_image = cropImage(input.get(), parsedOptions, bitmap->isPremultiplied() ? PremultiplyAlpha : DontPremultiplyAlpha); |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 607 FloatSize ImageBitmap::elementSize(const FloatSize&) const | 634 FloatSize ImageBitmap::elementSize(const FloatSize&) const |
| 608 { | 635 { |
| 609 return FloatSize(width(), height()); | 636 return FloatSize(width(), height()); |
| 610 } | 637 } |
| 611 | 638 |
| 612 DEFINE_TRACE(ImageBitmap) | 639 DEFINE_TRACE(ImageBitmap) |
| 613 { | 640 { |
| 614 } | 641 } |
| 615 | 642 |
| 616 } // namespace blink | 643 } // namespace blink |
| OLD | NEW |