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; |