| Index: third_party/WebKit/Source/core/frame/ImageBitmap.cpp
|
| diff --git a/third_party/WebKit/Source/core/frame/ImageBitmap.cpp b/third_party/WebKit/Source/core/frame/ImageBitmap.cpp
|
| index 663540f6512bf5d998b12fc8914a6903285018b2..0874cedeed4dca843ee408011a8585811e0d46e2 100644
|
| --- a/third_party/WebKit/Source/core/frame/ImageBitmap.cpp
|
| +++ b/third_party/WebKit/Source/core/frame/ImageBitmap.cpp
|
| @@ -18,6 +18,7 @@
|
| #include "third_party/skia/include/core/SkCanvas.h"
|
| #include "third_party/skia/include/core/SkImageInfo.h"
|
| #include "third_party/skia/include/core/SkSurface.h"
|
| +#include "third_party/skia/include/core/SkSwizzle.h"
|
|
|
| namespace blink {
|
|
|
| @@ -152,6 +153,9 @@ ParsedOptions ParseOptions(const ImageBitmapOptions& options,
|
| return parsed_options;
|
| }
|
|
|
| +// The function dstBufferSizeHasOverflow() is being called at the beginning of
|
| +// each ImageBitmap() constructor, which makes sure that doing
|
| +// width * height * bytesPerPixel will never overflow unsigned.
|
| bool DstBufferSizeHasOverflow(const ParsedOptions& options) {
|
| CheckedNumeric<unsigned> total_bytes = options.crop_rect.Width();
|
| total_bytes *= options.crop_rect.Height();
|
| @@ -174,11 +178,28 @@ bool DstBufferSizeHasOverflow(const ParsedOptions& options) {
|
|
|
| } // namespace
|
|
|
| +static void PrintSkImage(sk_sp<SkImage> input) {
|
| + SkImageInfo info =
|
| + SkImageInfo::Make(input->width(), input->height(), kN32_SkColorType,
|
| + kPremul_SkAlphaType, input->refColorSpace());
|
| + LOG(ERROR) << "Printing SkImage:" << input->width() << "," << input->height();
|
| + std::stringstream str;
|
| + std::unique_ptr<uint8_t[]> read_pixels(
|
| + new uint8_t[input->width() * input->height() * 4]());
|
| + input->readPixels(info, read_pixels.get(), input->width() * 4, 0, 0);
|
| + for (int i = 0; i < input->width() * input->height(); i++) {
|
| + if (i % input->width() == 0)
|
| + str << "\n";
|
| + str << "[";
|
| + for (int j = 0; j < 4; j++)
|
| + str << (int)(read_pixels[i * 4 + j]) << ",";
|
| + str << "] ";
|
| + }
|
| + LOG(ERROR) << str.str();
|
| +}
|
| +
|
| static PassRefPtr<Uint8Array> CopySkImageData(SkImage* input,
|
| const SkImageInfo& info) {
|
| - // The function dstBufferSizeHasOverflow() is being called at the beginning of
|
| - // each ImageBitmap() constructor, which makes sure that doing
|
| - // width * height * bytesPerPixel will never overflow unsigned.
|
| unsigned width = static_cast<unsigned>(input->width());
|
| RefPtr<ArrayBuffer> dst_buffer =
|
| ArrayBuffer::CreateOrNull(width * input->height(), info.bytesPerPixel());
|
| @@ -202,38 +223,6 @@ static sk_sp<SkImage> NewSkImageFromRaster(const SkImageInfo& info,
|
| image_pixels.LeakRef());
|
| }
|
|
|
| -static void SwizzleImageData(unsigned char* src_addr,
|
| - unsigned height,
|
| - unsigned bytes_per_row,
|
| - bool flip_y) {
|
| - if (flip_y) {
|
| - for (unsigned i = 0; i < height / 2; i++) {
|
| - unsigned top_row_start_position = i * bytes_per_row;
|
| - unsigned bottom_row_start_position = (height - 1 - i) * bytes_per_row;
|
| - if (kN32_SkColorType == kBGRA_8888_SkColorType) { // needs to swizzle
|
| - for (unsigned j = 0; j < bytes_per_row; j += 4) {
|
| - std::swap(src_addr[top_row_start_position + j],
|
| - src_addr[bottom_row_start_position + j + 2]);
|
| - std::swap(src_addr[top_row_start_position + j + 1],
|
| - src_addr[bottom_row_start_position + j + 1]);
|
| - std::swap(src_addr[top_row_start_position + j + 2],
|
| - src_addr[bottom_row_start_position + j]);
|
| - std::swap(src_addr[top_row_start_position + j + 3],
|
| - src_addr[bottom_row_start_position + j + 3]);
|
| - }
|
| - } else {
|
| - std::swap_ranges(src_addr + top_row_start_position,
|
| - src_addr + top_row_start_position + bytes_per_row,
|
| - src_addr + bottom_row_start_position);
|
| - }
|
| - }
|
| - } else {
|
| - if (kN32_SkColorType == kBGRA_8888_SkColorType) // needs to swizzle
|
| - for (unsigned i = 0; i < height * bytes_per_row; i += 4)
|
| - std::swap(src_addr[i], src_addr[i + 2]);
|
| - }
|
| -}
|
| -
|
| enum AlphaPremultiplyEnforcement {
|
| kEnforceAlphaPremultiply,
|
| kDontEnforceAlphaPremultiply,
|
| @@ -275,9 +264,32 @@ static sk_sp<SkImage> PremulSkImageToUnPremul(
|
| const ParsedOptions& options = DefaultOptions()) {
|
| SkImageInfo info = SkImageInfo::Make(
|
| input->width(), input->height(), options.color_params.GetSkColorType(),
|
| - kUnpremul_SkAlphaType, input->refColorSpace());
|
| + kPremul_SkAlphaType, options.color_params.GetSkColorSpaceForSkSurfaces());
|
| +
|
| + LOG(ERROR) << "Premul:";
|
| + std::stringstream str;
|
| + std::unique_ptr<uint8_t[]> read_pixels(new uint8_t[64]());
|
| + input->readPixels(info, read_pixels.get(), input->width() * 4, 0, 0);
|
| + for (int i = 0; i < 16; i++) {
|
| + str << "[";
|
| + for (int j = 0; j < 4; j++)
|
| + str << (int)(read_pixels[i * 4 + j]) << ",";
|
| + str << "] ";
|
| + }
|
| + LOG(ERROR) << str.str();
|
|
|
| + info = info.makeAlphaType(kUnpremul_SkAlphaType);
|
| RefPtr<Uint8Array> dst_pixels = CopySkImageData(input, info);
|
| + LOG(ERROR) << "Unpremul:";
|
| + str.str("");
|
| + for (int i = 0; i < 16; i++) {
|
| + str << "[";
|
| + for (int j = 0; j < 4; j++)
|
| + str << (int)(dst_pixels->Data()[i * 4 + j]) << ",";
|
| + str << "] ";
|
| + }
|
| + LOG(ERROR) << str.str();
|
| +
|
| if (!dst_pixels)
|
| return nullptr;
|
| return NewSkImageFromRaster(
|
| @@ -305,10 +317,8 @@ static void ApplyColorSpaceConversion(sk_sp<SkImage>& image,
|
| if (!options.color_canvas_extensions_enabled)
|
| return;
|
|
|
| - sk_sp<SkColorSpace> dst_color_space = nullptr;
|
| - SkColorType dst_color_type = kN32_SkColorType;
|
| - dst_color_space = options.color_params.GetSkColorSpace();
|
| - dst_color_type = options.color_params.GetSkColorType();
|
| + SkColorType dst_color_type = options.color_params.GetSkColorType();
|
| + sk_sp<SkColorSpace> dst_color_space = options.color_params.GetSkColorSpace();
|
| if (SkColorSpace::Equals(image->colorSpace(), dst_color_space.get()))
|
| return;
|
|
|
| @@ -321,15 +331,16 @@ static void ApplyColorSpaceConversion(sk_sp<SkImage>& image,
|
| if (dst_data->size() != size)
|
| return;
|
| sk_sp<SkImage> colored_image = nullptr;
|
| + // The desired way to apply color space conversion on a SkImage is to use
|
| + // SkImage::readPixels.
|
| if (image->readPixels(dst_info, dst_data->writable_data(),
|
| image->width() * dst_info.bytesPerPixel(), 0, 0)) {
|
| colored_image = SkImage::MakeRasterData(
|
| dst_info, dst_data, image->width() * dst_info.bytesPerPixel());
|
| } else {
|
| - // The desired way to apply color space conversion on a SkImage is to use
|
| - // SkImage::readPixels. However, if the SkImage is GPU-backed, readPixels
|
| - // still might not work properly. In this case, we fall back to drawing
|
| - // the SkImage to a canvas and reading back the result.
|
| + // However, if the SkImage is GPU-backed, readPixels might not work
|
| + // properly. In this case, we fall back to drawing the SkImage to a
|
| + // canvas and reading back the result.
|
| // Skia does not support drawing to unpremul surfaces/canvases.
|
| sk_sp<SkImage> un_premul_image = nullptr;
|
| if (image->alphaType() == kUnpremul_SkAlphaType) {
|
| @@ -411,32 +422,32 @@ static PassRefPtr<StaticBitmapImage> CropImageAndApplyColorSpaceConversion(
|
| IntRect img_rect(IntPoint(), IntSize(image->width(), image->height()));
|
| const IntRect src_rect = Intersection(img_rect, parsed_options.crop_rect);
|
|
|
| - // In the case when cropRect doesn't intersect the source image and it
|
| - // requires a umpremul image We immediately return a transparent black image
|
| - // with cropRect.size()
|
| - if (src_rect.IsEmpty() && !parsed_options.premultiply_alpha) {
|
| + // In the case when cropRect doesn't intersect the source image, we
|
| + // return a transparent black image, respecting the color_params but
|
| + // ignoring premultiply_alpha.
|
| + if (src_rect.IsEmpty()) {
|
| SkImageInfo info = SkImageInfo::Make(
|
| - parsed_options.resize_width, parsed_options.resize_height,
|
| - kN32_SkColorType, kUnpremul_SkAlphaType);
|
| - RefPtr<ArrayBuffer> dst_buffer = ArrayBuffer::CreateOrNull(
|
| - static_cast<unsigned>(info.width()) * info.height(),
|
| - info.bytesPerPixel());
|
| - if (!dst_buffer)
|
| + parsed_options.crop_rect.Width(), parsed_options.crop_rect.Height(),
|
| + parsed_options.color_params.GetSkColorType(), kPremul_SkAlphaType,
|
| + parsed_options.color_params.GetSkColorSpace());
|
| + if (parsed_options.should_scale_input) {
|
| + info = info.makeWH(parsed_options.resize_width,
|
| + parsed_options.resize_height);
|
| + }
|
| + sk_sp<SkSurface> surface = SkSurface::MakeRaster(info);
|
| + if (!surface)
|
| return nullptr;
|
| - RefPtr<Uint8Array> dst_pixels =
|
| - Uint8Array::Create(dst_buffer, 0, dst_buffer->ByteLength());
|
| - return StaticBitmapImage::Create(NewSkImageFromRaster(
|
| - info, std::move(dst_pixels),
|
| - static_cast<unsigned>(info.width()) * info.bytesPerPixel()));
|
| + return StaticBitmapImage::Create(surface->makeImageSnapshot());
|
| }
|
|
|
| sk_sp<SkImage> skia_image = image->ImageForCurrentFrame();
|
| - // Attempt to get raw unpremultiplied image data, executed only when skiaImage
|
| - // is premultiplied.
|
| + // Attempt to get raw unpremultiplied image data, executed only when
|
| + // skia_image is premultiplied.
|
| if ((((!parsed_options.premultiply_alpha && !skia_image->isOpaque()) ||
|
| !skia_image) &&
|
| image->Data() && image_format == kPremultiplyAlpha) ||
|
| color_behavior.IsIgnore()) {
|
| + LOG(ERROR) << "HERE...";
|
| std::unique_ptr<ImageDecoder> decoder(ImageDecoder::Create(
|
| image->Data(), true,
|
| parsed_options.premultiply_alpha ? ImageDecoder::kAlphaPremultiplied
|
| @@ -454,8 +465,7 @@ static PassRefPtr<StaticBitmapImage> CropImageAndApplyColorSpaceConversion(
|
| return nullptr;
|
| }
|
|
|
| - if (parsed_options.crop_rect == src_rect &&
|
| - !parsed_options.should_scale_input) {
|
| + if (!parsed_options.should_scale_input) {
|
| sk_sp<SkImage> cropped_sk_image = skia_image->makeSubset(src_rect);
|
| ApplyColorSpaceConversion(cropped_sk_image, parsed_options);
|
| if (parsed_options.flip_y) {
|
| @@ -473,52 +483,52 @@ static PassRefPtr<StaticBitmapImage> CropImageAndApplyColorSpaceConversion(
|
| return StaticBitmapImage::Create(std::move(cropped_sk_image));
|
| }
|
|
|
| - sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(
|
| - parsed_options.resize_width, parsed_options.resize_height);
|
| + LOG(ERROR) << "HERE...";
|
| + SkImageInfo info = SkImageInfo::Make(
|
| + parsed_options.resize_width, parsed_options.resize_height,
|
| + parsed_options.color_params.GetSkColorType(),
|
| + parsed_options.premultiply_alpha ? kPremul_SkAlphaType
|
| + : kUnpremul_SkAlphaType,
|
| + parsed_options.color_params.GetSkColorSpace());
|
| + sk_sp<SkSurface> surface = SkSurface::MakeRaster(info);
|
| if (!surface)
|
| return nullptr;
|
| - if (src_rect.IsEmpty())
|
| - return StaticBitmapImage::Create(surface->makeImageSnapshot());
|
| -
|
| - SkScalar dst_left = std::min(0, -parsed_options.crop_rect.X());
|
| - SkScalar dst_top = std::min(0, -parsed_options.crop_rect.Y());
|
| - if (parsed_options.crop_rect.X() < 0)
|
| - dst_left = -parsed_options.crop_rect.X();
|
| - if (parsed_options.crop_rect.Y() < 0)
|
| - dst_top = -parsed_options.crop_rect.Y();
|
| if (parsed_options.flip_y) {
|
| surface->getCanvas()->translate(0, surface->height());
|
| surface->getCanvas()->scale(1, -1);
|
| }
|
| - if (parsed_options.should_scale_input) {
|
| - SkRect draw_src_rect = SkRect::MakeXYWH(
|
| - parsed_options.crop_rect.X(), parsed_options.crop_rect.Y(),
|
| - parsed_options.crop_rect.Width(), parsed_options.crop_rect.Height());
|
| - SkRect draw_dst_rect = SkRect::MakeXYWH(0, 0, parsed_options.resize_width,
|
| - parsed_options.resize_height);
|
| - SkPaint paint;
|
| - paint.setFilterQuality(parsed_options.resize_quality);
|
| - surface->getCanvas()->drawImageRect(skia_image, draw_src_rect,
|
| - draw_dst_rect, &paint);
|
| - } else {
|
| - surface->getCanvas()->drawImage(skia_image, dst_left, dst_top);
|
| - }
|
| +
|
| + SkRect draw_src_rect(parsed_options.crop_rect);
|
| + SkRect draw_dst_rect =
|
| + SkRect::MakeWH(parsed_options.resize_width, parsed_options.resize_height);
|
| + SkPaint paint;
|
| + paint.setFilterQuality(parsed_options.resize_quality);
|
| + surface->getCanvas()->drawImageRect(skia_image, draw_src_rect, draw_dst_rect,
|
| + &paint);
|
| +
|
| skia_image = surface->makeImageSnapshot();
|
| + PrintSkImage(skia_image);
|
| ApplyColorSpaceConversion(skia_image, parsed_options);
|
| + PrintSkImage(skia_image);
|
|
|
| if (parsed_options.premultiply_alpha) {
|
| + LOG(ERROR) << "HERE";
|
| if (image_format == kDontPremultiplyAlpha)
|
| return StaticBitmapImage::Create(
|
| UnPremulSkImageToPremul(skia_image.get()));
|
| return StaticBitmapImage::Create(std::move(skia_image));
|
| }
|
| - return StaticBitmapImage::Create(PremulSkImageToUnPremul(skia_image.get()));
|
| + LOG(ERROR) << "HERE";
|
| + return StaticBitmapImage::Create(std::move(skia_image));
|
| + // return StaticBitmapImage::Create(
|
| + // PremulSkImageToUnPremul(skia_image.get(), parsed_options));
|
| }
|
|
|
| ImageBitmap::ImageBitmap(ImageElementBase* image,
|
| Optional<IntRect> crop_rect,
|
| Document* document,
|
| const ImageBitmapOptions& options) {
|
| + LOG(ERROR) << "Entering...";
|
| RefPtr<Image> input = image->CachedImage()->GetImage();
|
| ParsedOptions parsed_options =
|
| ParseOptions(options, crop_rect, image->BitmapSourceSize());
|
| @@ -566,6 +576,7 @@ ImageBitmap::ImageBitmap(HTMLVideoElement* video,
|
| Optional<IntRect> crop_rect,
|
| Document* document,
|
| const ImageBitmapOptions& options) {
|
| + LOG(ERROR) << "Entering...";
|
| IntSize player_size;
|
| if (video->GetWebMediaPlayer())
|
| player_size = video->GetWebMediaPlayer()->NaturalSize();
|
| @@ -604,7 +615,7 @@ ImageBitmap::ImageBitmap(HTMLVideoElement* video,
|
| sk_sp<SkImage> skia_image =
|
| buffer->NewSkImageSnapshot(kPreferNoAcceleration, kSnapshotReasonUnknown);
|
| if (!parsed_options.premultiply_alpha)
|
| - skia_image = PremulSkImageToUnPremul(skia_image.get());
|
| + skia_image = PremulSkImageToUnPremul(skia_image.get(), parsed_options);
|
| if (!skia_image)
|
| return;
|
| image_ = StaticBitmapImage::Create(std::move(skia_image));
|
| @@ -616,6 +627,7 @@ ImageBitmap::ImageBitmap(HTMLVideoElement* video,
|
| ImageBitmap::ImageBitmap(HTMLCanvasElement* canvas,
|
| Optional<IntRect> crop_rect,
|
| const ImageBitmapOptions& options) {
|
| + LOG(ERROR) << "Entering...";
|
| DCHECK(canvas->IsPaintable());
|
| RefPtr<Image> input;
|
| if (canvas->PlaceholderFrame()) {
|
| @@ -641,8 +653,8 @@ ImageBitmap::ImageBitmap(HTMLCanvasElement* canvas,
|
| return;
|
| if (is_premultiply_alpha_reverted) {
|
| parsed_options.premultiply_alpha = false;
|
| - image_ = StaticBitmapImage::Create(
|
| - PremulSkImageToUnPremul(image_->ImageForCurrentFrame().get()));
|
| + image_ = StaticBitmapImage::Create(PremulSkImageToUnPremul(
|
| + image_->ImageForCurrentFrame().get(), parsed_options));
|
| }
|
| if (!image_)
|
| return;
|
| @@ -653,6 +665,7 @@ ImageBitmap::ImageBitmap(HTMLCanvasElement* canvas,
|
| ImageBitmap::ImageBitmap(OffscreenCanvas* offscreen_canvas,
|
| Optional<IntRect> crop_rect,
|
| const ImageBitmapOptions& options) {
|
| + LOG(ERROR) << "Entering...";
|
| SourceImageStatus status;
|
| RefPtr<Image> input = offscreen_canvas->GetSourceImageForCanvas(
|
| &status, kPreferNoAcceleration, kSnapshotReasonCreateImageBitmap,
|
| @@ -676,8 +689,8 @@ ImageBitmap::ImageBitmap(OffscreenCanvas* offscreen_canvas,
|
| return;
|
| if (is_premultiply_alpha_reverted) {
|
| parsed_options.premultiply_alpha = false;
|
| - image_ = StaticBitmapImage::Create(
|
| - PremulSkImageToUnPremul(image_->ImageForCurrentFrame().get()));
|
| + image_ = StaticBitmapImage::Create(PremulSkImageToUnPremul(
|
| + image_->ImageForCurrentFrame().get(), parsed_options));
|
| }
|
| if (!image_)
|
| return;
|
| @@ -690,6 +703,7 @@ ImageBitmap::ImageBitmap(const void* pixel_data,
|
| uint32_t height,
|
| bool is_image_bitmap_premultiplied,
|
| bool is_image_bitmap_origin_clean) {
|
| + LOG(ERROR) << "Entering...";
|
| SkImageInfo info = SkImageInfo::MakeN32(width, height,
|
| is_image_bitmap_premultiplied
|
| ? kPremul_SkAlphaType
|
| @@ -703,209 +717,156 @@ ImageBitmap::ImageBitmap(const void* pixel_data,
|
| }
|
|
|
| static sk_sp<SkImage> ScaleSkImage(sk_sp<SkImage> sk_image,
|
| + const SkImageInfo& sk_image_info,
|
| unsigned resize_width,
|
| unsigned resize_height,
|
| - SkFilterQuality resize_quality,
|
| - SkColorType color_type = kN32_SkColorType,
|
| - sk_sp<SkColorSpace> color_space = nullptr) {
|
| - SkImageInfo resized_info =
|
| - SkImageInfo::Make(resize_width, resize_height, color_type,
|
| - kUnpremul_SkAlphaType, color_space);
|
| + SkFilterQuality resize_quality) {
|
| + SkImageInfo resized_info = sk_image_info.makeWH(resize_width, resize_height);
|
| RefPtr<ArrayBuffer> dst_buffer = ArrayBuffer::CreateOrNull(
|
| resize_width * resize_height, resized_info.bytesPerPixel());
|
| if (!dst_buffer)
|
| return nullptr;
|
|
|
| - if (color_type == kN32_SkColorType) {
|
| - RefPtr<Uint8Array> resized_pixels =
|
| - Uint8Array::Create(dst_buffer, 0, dst_buffer->ByteLength());
|
| - SkPixmap pixmap(
|
| - resized_info, resized_pixels->Data(),
|
| - static_cast<unsigned>(resize_width) * resized_info.bytesPerPixel());
|
| - sk_image->scalePixels(pixmap, resize_quality);
|
| - return SkImage::MakeFromRaster(pixmap,
|
| - [](const void*, void* pixels) {
|
| - static_cast<Uint8Array*>(pixels)->Deref();
|
| - },
|
| - resized_pixels.LeakRef());
|
| - }
|
| -
|
| - RefPtr<Float32Array> resized_pixels =
|
| - Float32Array::Create(dst_buffer, 0, dst_buffer->ByteLength());
|
| + RefPtr<Uint8Array> resized_pixels =
|
| + Uint8Array::Create(dst_buffer, 0, dst_buffer->ByteLength());
|
| SkPixmap pixmap(
|
| resized_info, resized_pixels->Data(),
|
| static_cast<unsigned>(resize_width) * resized_info.bytesPerPixel());
|
| sk_image->scalePixels(pixmap, resize_quality);
|
| return SkImage::MakeFromRaster(pixmap,
|
| [](const void*, void* pixels) {
|
| - static_cast<Float32Array*>(pixels)->Deref();
|
| + static_cast<Uint8Array*>(pixels)->Deref();
|
| },
|
| resized_pixels.LeakRef());
|
| }
|
|
|
| +static void SwizzleImageData(ImageData* data, bool needs_swizzle) {
|
| + needs_swizzle = false;
|
| + if (data && needs_swizzle) {
|
| + SkSwapRB(reinterpret_cast<uint32_t*>(data->data()->Data()),
|
| + reinterpret_cast<uint32_t*>(data->data()->Data()),
|
| + data->Size().Height() * data->Size().Width());
|
| + }
|
| +}
|
| +
|
| ImageBitmap::ImageBitmap(ImageData* data,
|
| Optional<IntRect> crop_rect,
|
| const ImageBitmapOptions& options) {
|
| - // TODO(xidachen): implement the resize option
|
| - IntRect data_src_rect = IntRect(IntPoint(), data->Size());
|
| + LOG(ERROR) << "Entering...";
|
| ParsedOptions parsed_options =
|
| ParseOptions(options, crop_rect, data->BitmapSourceSize());
|
| if (DstBufferSizeHasOverflow(parsed_options))
|
| return;
|
| +
|
| + IntRect data_src_rect = IntRect(IntPoint(), data->Size());
|
| IntRect src_rect = crop_rect
|
| ? Intersection(parsed_options.crop_rect, data_src_rect)
|
| : data_src_rect;
|
| + SkImageInfo unpremul_info = SkImageInfo::Make(
|
| + src_rect.Width(), src_rect.Height(),
|
| + parsed_options.color_params.GetSkColorType(), kUnpremul_SkAlphaType,
|
| + parsed_options.color_params.GetSkColorSpaceForSkSurfaces());
|
| + // if src_rect is empty, create an empty image bitmap with the requested size
|
| + // and return
|
| + if (src_rect.IsEmpty()) {
|
| + SkImageInfo info = parsed_options.premultiply_alpha
|
| + ? unpremul_info.makeAlphaType(kPremul_SkAlphaType)
|
| + : unpremul_info;
|
| + if (parsed_options.should_scale_input) {
|
| + info = info.makeWH(parsed_options.resize_width,
|
| + parsed_options.resize_height);
|
| + } else if (crop_rect) {
|
| + info = info.makeWH(crop_rect->Width(), crop_rect->Height());
|
| + } else {
|
| + info = info.makeWH(data->Size().Width(), data->Size().Height());
|
| + }
|
| + unsigned bytes_per_row =
|
| + info.width() * parsed_options.color_params.BytesPerPixel();
|
| + std::unique_ptr<uint8_t[]> pixels(
|
| + new uint8_t[info.height() * bytes_per_row]);
|
| + memset(pixels.get(), 0, info.height() * bytes_per_row);
|
| + sk_sp<SkImage> sk_image =
|
| + SkImage::MakeRasterCopy(SkPixmap(info, pixels.get(), bytes_per_row));
|
| + image_ = StaticBitmapImage::Create(sk_image);
|
| + image_->SetPremultiplied(parsed_options.premultiply_alpha);
|
| + return;
|
| + }
|
| +
|
| + // crop/flip the input and swizzle if needed. we swizzle back later if the
|
| + // input ImageData is swizzled here.
|
| + bool crop_or_flip = (src_rect != data_src_rect) || parsed_options.flip_y;
|
| + bool needs_swizzle =
|
| + parsed_options.color_params.GetSkColorType() == kBGRA_8888_SkColorType;
|
| + ImageData* cropped_data = data;
|
| + if (crop_or_flip)
|
| + cropped_data = data->CropRect(src_rect, parsed_options.flip_y);
|
| + SwizzleImageData(cropped_data, needs_swizzle);
|
| + unsigned bytes_per_row =
|
| + src_rect.Size().Width() * parsed_options.color_params.BytesPerPixel();
|
| + unsigned data_size = src_rect.Size().Height() * bytes_per_row;
|
| + // color convert the pixels if needed
|
| + unsigned char* color_corrected_pixels = cropped_data->data()->Data();
|
| + std::unique_ptr<uint8_t[]>* converted_pixels = nullptr;
|
| + if (!SkColorSpace::Equals(
|
| + cropped_data->GetCanvasColorParams()
|
| + .GetSkColorSpaceForSkSurfaces()
|
| + .get(),
|
| + parsed_options.color_params.GetSkColorSpaceForSkSurfaces().get()) ||
|
| + cropped_data->GetCanvasColorParams().GetSkColorType() ==
|
| + kRGBA_F16_SkColorType) {
|
| + converted_pixels = new std::unique_ptr<uint8_t[]>(new uint8_t[data_size]);
|
| + cropped_data->ImageDataInCanvasColorSettings(parsed_options.color_params,
|
| + *converted_pixels);
|
| + color_corrected_pixels = converted_pixels->get();
|
| + }
|
|
|
| // treat non-premultiplyAlpha as a special case
|
| if (!parsed_options.premultiply_alpha) {
|
| - unsigned char* src_addr = data->data()->Data();
|
| + SkImageInfo info = unpremul_info.makeColorType(kRGBA_8888_SkColorType);
|
| + sk_sp<SkImage> sk_image = SkImage::MakeRasterCopy(
|
| + SkPixmap(info, color_corrected_pixels, bytes_per_row));
|
|
|
| - // Using kN32 type, swizzle input if necessary.
|
| - SkImageInfo info = SkImageInfo::Make(
|
| - parsed_options.crop_rect.Width(), parsed_options.crop_rect.Height(),
|
| - kN32_SkColorType, kUnpremul_SkAlphaType, data->GetSkColorSpace());
|
| - unsigned bytes_per_pixel = static_cast<unsigned>(info.bytesPerPixel());
|
| - unsigned src_pixel_bytes_per_row = bytes_per_pixel * data->Size().Width();
|
| - unsigned dst_pixel_bytes_per_row =
|
| - bytes_per_pixel * parsed_options.crop_rect.Width();
|
| - sk_sp<SkImage> sk_image;
|
| - if (parsed_options.crop_rect == IntRect(IntPoint(), data->Size())) {
|
| - SwizzleImageData(src_addr, data->Size().Height(), src_pixel_bytes_per_row,
|
| - parsed_options.flip_y);
|
| - sk_image = SkImage::MakeRasterCopy(
|
| - SkPixmap(info, src_addr, dst_pixel_bytes_per_row));
|
| - // restore the original ImageData
|
| - SwizzleImageData(src_addr, data->Size().Height(), src_pixel_bytes_per_row,
|
| - parsed_options.flip_y);
|
| - } else {
|
| - RefPtr<ArrayBuffer> dst_buffer = ArrayBuffer::CreateOrNull(
|
| - static_cast<unsigned>(parsed_options.crop_rect.Height()) *
|
| - parsed_options.crop_rect.Width(),
|
| - bytes_per_pixel);
|
| - if (!dst_buffer)
|
| - return;
|
| - RefPtr<Uint8Array> copied_data_buffer =
|
| - Uint8Array::Create(dst_buffer, 0, dst_buffer->ByteLength());
|
| - if (!src_rect.IsEmpty()) {
|
| - IntPoint src_point = IntPoint(
|
| - (parsed_options.crop_rect.X() > 0) ? parsed_options.crop_rect.X()
|
| - : 0,
|
| - (parsed_options.crop_rect.Y() > 0) ? parsed_options.crop_rect.Y()
|
| - : 0);
|
| - IntPoint dst_point = IntPoint((parsed_options.crop_rect.X() >= 0)
|
| - ? 0
|
| - : -parsed_options.crop_rect.X(),
|
| - (parsed_options.crop_rect.Y() >= 0)
|
| - ? 0
|
| - : -parsed_options.crop_rect.Y());
|
| - int copy_height = data->Size().Height() - src_point.Y();
|
| - if (parsed_options.crop_rect.Height() < copy_height)
|
| - copy_height = parsed_options.crop_rect.Height();
|
| - int copy_width = data->Size().Width() - src_point.X();
|
| - if (parsed_options.crop_rect.Width() < copy_width)
|
| - copy_width = parsed_options.crop_rect.Width();
|
| - for (int i = 0; i < copy_height; i++) {
|
| - unsigned src_start_copy_position =
|
| - (i + src_point.Y()) * src_pixel_bytes_per_row +
|
| - src_point.X() * bytes_per_pixel;
|
| - unsigned src_end_copy_position =
|
| - src_start_copy_position + copy_width * bytes_per_pixel;
|
| - unsigned dst_start_copy_position;
|
| - if (parsed_options.flip_y)
|
| - dst_start_copy_position =
|
| - (parsed_options.crop_rect.Height() - 1 - dst_point.Y() - i) *
|
| - dst_pixel_bytes_per_row +
|
| - dst_point.X() * bytes_per_pixel;
|
| - else
|
| - dst_start_copy_position =
|
| - (dst_point.Y() + i) * dst_pixel_bytes_per_row +
|
| - dst_point.X() * bytes_per_pixel;
|
| - for (unsigned j = 0;
|
| - j < src_end_copy_position - src_start_copy_position; j++) {
|
| - // swizzle when necessary
|
| - if (kN32_SkColorType == kBGRA_8888_SkColorType) {
|
| - if (j % 4 == 0)
|
| - copied_data_buffer->Data()[dst_start_copy_position + j] =
|
| - src_addr[src_start_copy_position + j + 2];
|
| - else if (j % 4 == 2)
|
| - copied_data_buffer->Data()[dst_start_copy_position + j] =
|
| - src_addr[src_start_copy_position + j - 2];
|
| - else
|
| - copied_data_buffer->Data()[dst_start_copy_position + j] =
|
| - src_addr[src_start_copy_position + j];
|
| - } else {
|
| - copied_data_buffer->Data()[dst_start_copy_position + j] =
|
| - src_addr[src_start_copy_position + j];
|
| - }
|
| - }
|
| - }
|
| - }
|
| - sk_image = NewSkImageFromRaster(info, std::move(copied_data_buffer),
|
| - dst_pixel_bytes_per_row);
|
| - }
|
| - if (!sk_image)
|
| - return;
|
| - ApplyColorSpaceConversion(sk_image, parsed_options);
|
| if (parsed_options.should_scale_input) {
|
| image_ = StaticBitmapImage::Create(ScaleSkImage(
|
| - sk_image, parsed_options.resize_width, parsed_options.resize_height,
|
| - parsed_options.resize_quality,
|
| - parsed_options.color_params.GetSkColorType(),
|
| - data->GetSkColorSpace()));
|
| + sk_image, info, parsed_options.resize_width,
|
| + parsed_options.resize_height, parsed_options.resize_quality));
|
| } else {
|
| image_ = StaticBitmapImage::Create(sk_image);
|
| }
|
| if (!image_)
|
| return;
|
| image_->SetPremultiplied(parsed_options.premultiply_alpha);
|
| + SwizzleImageData(cropped_data, needs_swizzle);
|
| return;
|
| }
|
|
|
| - CanvasColorParams canvas_color_params;
|
| - if (RuntimeEnabledFeatures::colorCanvasExtensionsEnabled()) {
|
| - ImageDataColorSettings color_settings;
|
| - data->getColorSettings(color_settings);
|
| - CanvasColorSpace canvas_color_space =
|
| - ImageData::GetCanvasColorSpace(color_settings.colorSpace());
|
| - CanvasPixelFormat canvas_pixel_format = kRGBA8CanvasPixelFormat;
|
| - if (ImageData::GetImageDataStorageFormat(color_settings.storageFormat()) !=
|
| - kUint8ClampedArrayStorageFormat) {
|
| - canvas_pixel_format = kF16CanvasPixelFormat;
|
| - }
|
| - canvas_color_params =
|
| - CanvasColorParams(canvas_color_space, canvas_pixel_format);
|
| - }
|
| + IntSize buffer_size =
|
| + src_rect.IsEmpty() ? parsed_options.crop_rect.Size() : src_rect.Size();
|
| std::unique_ptr<ImageBuffer> buffer =
|
| - ImageBuffer::Create(parsed_options.crop_rect.Size(), kNonOpaque,
|
| - kDoNotInitializeImagePixels, canvas_color_params);
|
| + ImageBuffer::Create(buffer_size, kNonOpaque, kDoNotInitializeImagePixels,
|
| + parsed_options.color_params);
|
| if (!buffer)
|
| return;
|
| -
|
| if (src_rect.IsEmpty()) {
|
| image_ = StaticBitmapImage::Create(buffer->NewSkImageSnapshot(
|
| kPreferNoAcceleration, kSnapshotReasonUnknown));
|
| return;
|
| }
|
|
|
| - IntPoint dst_point = IntPoint(std::min(0, -parsed_options.crop_rect.X()),
|
| - std::min(0, -parsed_options.crop_rect.Y()));
|
| - if (parsed_options.crop_rect.X() < 0)
|
| - dst_point.SetX(-parsed_options.crop_rect.X());
|
| - if (parsed_options.crop_rect.Y() < 0)
|
| - dst_point.SetY(-parsed_options.crop_rect.Y());
|
| + buffer->PutByteArray(kUnmultiplied, color_corrected_pixels,
|
| + cropped_data->Size(),
|
| + IntRect(IntPoint(), cropped_data->Size()), IntPoint());
|
|
|
| - buffer->PutByteArray(kUnmultiplied, data->data()->Data(), data->Size(),
|
| - src_rect, dst_point);
|
| + SwizzleImageData(cropped_data, needs_swizzle);
|
| sk_sp<SkImage> sk_image =
|
| buffer->NewSkImageSnapshot(kPreferNoAcceleration, kSnapshotReasonUnknown);
|
| - if (parsed_options.flip_y)
|
| - sk_image = FlipSkImageVertically(sk_image.get(), kEnforceAlphaPremultiply);
|
| if (!sk_image)
|
| return;
|
| +
|
| if (parsed_options.should_scale_input) {
|
| sk_sp<SkSurface> surface = SkSurface::MakeRaster(SkImageInfo::MakeN32Premul(
|
| parsed_options.resize_width, parsed_options.resize_height,
|
| - data->GetSkColorSpace()));
|
| + data->GetCanvasColorParams().GetSkColorSpaceForSkSurfaces()));
|
| if (!surface)
|
| return;
|
| SkPaint paint;
|
| @@ -915,13 +876,13 @@ ImageBitmap::ImageBitmap(ImageData* data,
|
| surface->getCanvas()->drawImageRect(sk_image, dst_draw_rect, &paint);
|
| sk_image = surface->makeImageSnapshot();
|
| }
|
| - ApplyColorSpaceConversion(sk_image, parsed_options);
|
| image_ = StaticBitmapImage::Create(std::move(sk_image));
|
| }
|
|
|
| ImageBitmap::ImageBitmap(ImageBitmap* bitmap,
|
| Optional<IntRect> crop_rect,
|
| const ImageBitmapOptions& options) {
|
| + LOG(ERROR) << "Entering...";
|
| RefPtr<Image> input = bitmap->BitmapImage();
|
| if (!input)
|
| return;
|
| @@ -943,23 +904,33 @@ ImageBitmap::ImageBitmap(ImageBitmap* bitmap,
|
| ImageBitmap::ImageBitmap(RefPtr<StaticBitmapImage> image,
|
| Optional<IntRect> crop_rect,
|
| const ImageBitmapOptions& options) {
|
| + LOG(ERROR) << "Entering... ";
|
| bool origin_clean = image->OriginClean();
|
| ParsedOptions parsed_options =
|
| ParseOptions(options, crop_rect, image->Size());
|
| if (DstBufferSizeHasOverflow(parsed_options))
|
| return;
|
|
|
| + LOG(ERROR) << "parsed_options.premultiply_alpha: "
|
| + << parsed_options.premultiply_alpha;
|
| + PrintSkImage(image.Get()->ImageForCurrentFrame());
|
| +
|
| image_ = CropImageAndApplyColorSpaceConversion(
|
| image.Get(), parsed_options, kPremultiplyAlpha,
|
| ColorBehavior::TransformToGlobalTarget());
|
| + LOG(ERROR) << "HERE";
|
| if (!image_)
|
| return;
|
| + LOG(ERROR) << "HERE";
|
| +
|
| + PrintSkImage(image_.Get()->ImageForCurrentFrame());
|
|
|
| image_->SetOriginClean(origin_clean);
|
| image_->SetPremultiplied(parsed_options.premultiply_alpha);
|
| }
|
|
|
| ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image) {
|
| + LOG(ERROR) << "Entering...";
|
| image_ = std::move(image);
|
| }
|
|
|
| @@ -1044,6 +1015,7 @@ ImageBitmap* ImageBitmap::Take(ScriptPromiseResolver*, sk_sp<SkImage> image) {
|
|
|
| PassRefPtr<Uint8Array> ImageBitmap::CopyBitmapData(AlphaDisposition alpha_op,
|
| DataColorFormat format) {
|
| + LOG(ERROR) << "Entering...";
|
| SkImageInfo info = SkImageInfo::Make(
|
| width(), height(),
|
| (format == kRGBAColorType) ? kRGBA_8888_SkColorType : kN32_SkColorType,
|
| @@ -1100,6 +1072,7 @@ PassRefPtr<Image> ImageBitmap::GetSourceImageForCanvas(
|
| AccelerationHint,
|
| SnapshotReason,
|
| const FloatSize&) {
|
| + LOG(ERROR) << "HERE too ...";
|
| *status = kNormalSourceImageStatus;
|
| if (!image_)
|
| return nullptr;
|
|
|