Commit 00e1cd5e authored by Christopher Cameron's avatar Christopher Cameron Committed by Chromium LUCI CQ

ImageData: Remove CanvasColorParams accessors

CanvasColorParams is a poor match for ImageData. It has the same
CanvasColorSpace names, but different pixel format support, and
unused an unused opacity parameter. Remove the accessor
ImageData::GetCanvasColorParams because of this mismatch.

Clean up serialization of CanvasColorParams to not use these
accessors.

Remove ImageData::Create that takes a StaticBitmapImage, since this
is not used and is the last place where CanvasColorParams are used.

Remove the now-unused helper functions from ImageData
ImageDataInCanvasColorSettings and
ConvertPixelsFromCanvasPixelFormatToImageDataStorageFormat.

Bug: 1150969
Change-Id: Icf8697685ed4d0bfbcee07a47196a2fe4772a2ce
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2548773Reviewed-by: default avatarJeremy Roman <jbroman@chromium.org>
Commit-Queue: ccameron <ccameron@chromium.org>
Cr-Commit-Position: refs/heads/master@{#832000}
parent 7b6916c2
...@@ -8,25 +8,11 @@ ...@@ -8,25 +8,11 @@
namespace blink { namespace blink {
SerializedColorParams::SerializedColorParams() SerializedColorParams::SerializedColorParams() = default;
: color_space_(SerializedColorSpace::kSRGB),
pixel_format_(SerializedPixelFormat::kRGBA8),
opacity_mode_(SerializedOpacityMode::kNonOpaque),
storage_format_(SerializedImageDataStorageFormat::kUint8Clamped) {}
SerializedColorParams::SerializedColorParams(CanvasColorParams color_params) {
switch (color_params.ColorSpace()) {
case CanvasColorSpace::kSRGB:
color_space_ = SerializedColorSpace::kSRGB;
break;
case CanvasColorSpace::kRec2020:
color_space_ = SerializedColorSpace::kRec2020;
break;
case CanvasColorSpace::kP3:
color_space_ = SerializedColorSpace::kP3;
break;
}
SerializedColorParams::SerializedColorParams(CanvasColorParams color_params)
: SerializedColorParams(color_params.ColorSpace(),
kUint8ClampedArrayStorageFormat) {
switch (color_params.PixelFormat()) { switch (color_params.PixelFormat()) {
case CanvasPixelFormat::kRGBA8: case CanvasPixelFormat::kRGBA8:
pixel_format_ = SerializedPixelFormat::kRGBA8; pixel_format_ = SerializedPixelFormat::kRGBA8;
...@@ -42,13 +28,22 @@ SerializedColorParams::SerializedColorParams(CanvasColorParams color_params) { ...@@ -42,13 +28,22 @@ SerializedColorParams::SerializedColorParams(CanvasColorParams color_params) {
opacity_mode_ = SerializedOpacityMode::kNonOpaque; opacity_mode_ = SerializedOpacityMode::kNonOpaque;
if (color_params.GetOpacityMode() == blink::kOpaque) if (color_params.GetOpacityMode() == blink::kOpaque)
opacity_mode_ = SerializedOpacityMode::kOpaque; opacity_mode_ = SerializedOpacityMode::kOpaque;
storage_format_ = SerializedImageDataStorageFormat::kUint8Clamped;
} }
SerializedColorParams::SerializedColorParams( SerializedColorParams::SerializedColorParams(
CanvasColorParams color_params, CanvasColorSpace color_space,
ImageDataStorageFormat storage_format) ImageDataStorageFormat storage_format) {
: SerializedColorParams(color_params) { switch (color_space) {
case CanvasColorSpace::kSRGB:
color_space_ = SerializedColorSpace::kSRGB;
break;
case CanvasColorSpace::kRec2020:
color_space_ = SerializedColorSpace::kRec2020;
break;
case CanvasColorSpace::kP3:
color_space_ = SerializedColorSpace::kP3;
break;
}
switch (storage_format) { switch (storage_format) {
case kUint8ClampedArrayStorageFormat: case kUint8ClampedArrayStorageFormat:
storage_format_ = SerializedImageDataStorageFormat::kUint8Clamped; storage_format_ = SerializedImageDataStorageFormat::kUint8Clamped;
...@@ -66,12 +61,11 @@ SerializedColorParams::SerializedColorParams( ...@@ -66,12 +61,11 @@ SerializedColorParams::SerializedColorParams(
SerializedColorSpace color_space, SerializedColorSpace color_space,
SerializedPixelFormat pixel_format, SerializedPixelFormat pixel_format,
SerializedOpacityMode opacity_mode, SerializedOpacityMode opacity_mode,
SerializedImageDataStorageFormat storage_format) { SerializedImageDataStorageFormat storage_format)
SetSerializedColorSpace(color_space); : color_space_(color_space),
SetSerializedPixelFormat(pixel_format); pixel_format_(pixel_format),
SetSerializedOpacityMode(opacity_mode); opacity_mode_(opacity_mode),
SetSerializedImageDataStorageFormat(storage_format); storage_format_(storage_format) {}
}
CanvasColorParams SerializedColorParams::GetCanvasColorParams() const { CanvasColorParams SerializedColorParams::GetCanvasColorParams() const {
CanvasColorSpace color_space = CanvasColorSpace::kSRGB; CanvasColorSpace color_space = CanvasColorSpace::kSRGB;
...@@ -132,41 +126,4 @@ ImageDataStorageFormat SerializedColorParams::GetStorageFormat() const { ...@@ -132,41 +126,4 @@ ImageDataStorageFormat SerializedColorParams::GetStorageFormat() const {
return kUint8ClampedArrayStorageFormat; return kUint8ClampedArrayStorageFormat;
} }
void SerializedColorParams::SetSerializedColorSpace(
SerializedColorSpace color_space) {
color_space_ = color_space;
}
void SerializedColorParams::SetSerializedPixelFormat(
SerializedPixelFormat pixel_format) {
pixel_format_ = pixel_format;
}
void SerializedColorParams::SetSerializedOpacityMode(
SerializedOpacityMode opacity_mode) {
opacity_mode_ = opacity_mode;
}
void SerializedColorParams::SetSerializedImageDataStorageFormat(
SerializedImageDataStorageFormat storage_format) {
storage_format_ = storage_format;
}
SerializedColorSpace SerializedColorParams::GetSerializedColorSpace() const {
return color_space_;
}
SerializedPixelFormat SerializedColorParams::GetSerializedPixelFormat() const {
return pixel_format_;
}
SerializedOpacityMode SerializedColorParams::GetSerializedOpacityMode() const {
return opacity_mode_;
}
SerializedImageDataStorageFormat
SerializedColorParams::GetSerializedImageDataStorageFormat() const {
return storage_format_;
}
} // namespace blink } // namespace blink
...@@ -74,8 +74,8 @@ enum class SerializedOpacityMode : uint32_t { ...@@ -74,8 +74,8 @@ enum class SerializedOpacityMode : uint32_t {
class SerializedColorParams { class SerializedColorParams {
public: public:
SerializedColorParams(); SerializedColorParams();
SerializedColorParams(CanvasColorParams); explicit SerializedColorParams(CanvasColorParams);
SerializedColorParams(CanvasColorParams, ImageDataStorageFormat); SerializedColorParams(CanvasColorSpace, ImageDataStorageFormat);
SerializedColorParams(SerializedColorSpace, SerializedColorParams(SerializedColorSpace,
SerializedPixelFormat, SerializedPixelFormat,
SerializedOpacityMode, SerializedOpacityMode,
...@@ -85,21 +85,23 @@ class SerializedColorParams { ...@@ -85,21 +85,23 @@ class SerializedColorParams {
CanvasColorSpace GetColorSpace() const; CanvasColorSpace GetColorSpace() const;
ImageDataStorageFormat GetStorageFormat() const; ImageDataStorageFormat GetStorageFormat() const;
void SetSerializedColorSpace(SerializedColorSpace); SerializedColorSpace GetSerializedColorSpace() const { return color_space_; }
void SetSerializedPixelFormat(SerializedPixelFormat); SerializedPixelFormat GetSerializedPixelFormat() const {
void SetSerializedOpacityMode(SerializedOpacityMode); return pixel_format_;
void SetSerializedImageDataStorageFormat(SerializedImageDataStorageFormat); }
SerializedImageDataStorageFormat GetSerializedImageDataStorageFormat() const {
SerializedColorSpace GetSerializedColorSpace() const; return storage_format_;
SerializedPixelFormat GetSerializedPixelFormat() const; }
SerializedImageDataStorageFormat GetSerializedImageDataStorageFormat() const; SerializedOpacityMode GetSerializedOpacityMode() const {
SerializedOpacityMode GetSerializedOpacityMode() const; return opacity_mode_;
}
private: private:
SerializedColorSpace color_space_; SerializedColorSpace color_space_ = SerializedColorSpace::kSRGB;
SerializedPixelFormat pixel_format_; SerializedPixelFormat pixel_format_ = SerializedPixelFormat::kRGBA8;
SerializedOpacityMode opacity_mode_; SerializedOpacityMode opacity_mode_ = SerializedOpacityMode::kNonOpaque;
SerializedImageDataStorageFormat storage_format_; SerializedImageDataStorageFormat storage_format_ =
SerializedImageDataStorageFormat::kUint8Clamped;
}; };
} // namespace blink } // namespace blink
......
...@@ -334,7 +334,7 @@ bool V8ScriptValueSerializer::WriteDOMObject(ScriptWrappable* wrappable, ...@@ -334,7 +334,7 @@ bool V8ScriptValueSerializer::WriteDOMObject(ScriptWrappable* wrappable,
if (wrapper_type_info == V8ImageData::GetWrapperTypeInfo()) { if (wrapper_type_info == V8ImageData::GetWrapperTypeInfo()) {
ImageData* image_data = wrappable->ToImpl<ImageData>(); ImageData* image_data = wrappable->ToImpl<ImageData>();
WriteTag(kImageDataTag); WriteTag(kImageDataTag);
SerializedColorParams color_params(image_data->GetCanvasColorParams(), SerializedColorParams color_params(image_data->GetCanvasColorSpace(),
image_data->GetImageDataStorageFormat()); image_data->GetImageDataStorageFormat());
WriteUint32Enum(ImageSerializationTag::kCanvasColorSpaceTag); WriteUint32Enum(ImageSerializationTag::kCanvasColorSpaceTag);
WriteUint32Enum(color_params.GetSerializedColorSpace()); WriteUint32Enum(color_params.GetSerializedColorSpace());
......
...@@ -34,7 +34,6 @@ ...@@ -34,7 +34,6 @@
#include "third_party/blink/renderer/core/dom/dom_exception.h" #include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h" #include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h"
#include "third_party/blink/renderer/platform/graphics/color_behavior.h" #include "third_party/blink/renderer/platform/graphics/color_behavior.h"
#include "third_party/skia/include/third_party/skcms/skcms.h"
#include "v8/include/v8.h" #include "v8/include/v8.h"
namespace blink { namespace blink {
...@@ -251,26 +250,6 @@ ImageData* ImageData::Create(const IntSize& size, ...@@ -251,26 +250,6 @@ ImageData* ImageData::Create(const IntSize& size,
: nullptr; : nullptr;
} }
ImageDataColorSettings* CanvasColorParamsToImageDataColorSettings(
const CanvasColorParams& color_params) {
ImageDataColorSettings* color_settings = ImageDataColorSettings::Create();
switch (color_params.ColorSpace()) {
case CanvasColorSpace::kSRGB:
color_settings->setColorSpace(kSRGBCanvasColorSpaceName);
break;
case CanvasColorSpace::kRec2020:
color_settings->setColorSpace(kRec2020CanvasColorSpaceName);
break;
case CanvasColorSpace::kP3:
color_settings->setColorSpace(kP3CanvasColorSpaceName);
break;
}
color_settings->setStorageFormat(kUint8ClampedArrayStorageFormatName);
if (color_params.PixelFormat() == CanvasPixelFormat::kF16)
color_settings->setStorageFormat(kFloat32ArrayStorageFormatName);
return color_settings;
}
ImageData* ImageData::Create(const IntSize& size, ImageData* ImageData::Create(const IntSize& size,
CanvasColorSpace color_space, CanvasColorSpace color_space,
ImageDataStorageFormat storage_format) { ImageDataStorageFormat storage_format) {
...@@ -311,50 +290,6 @@ ImageData* ImageData::Create(const IntSize& size, ...@@ -311,50 +290,6 @@ ImageData* ImageData::Create(const IntSize& size,
return MakeGarbageCollected<ImageData>(size, data_array, color_settings); return MakeGarbageCollected<ImageData>(size, data_array, color_settings);
} }
ImageData* ImageData::Create(scoped_refptr<StaticBitmapImage> image,
AlphaDisposition alpha_disposition) {
PaintImage paint_image = image->PaintImageForCurrentFrame();
DCHECK(paint_image);
SkImageInfo image_info = image->PaintImageForCurrentFrame().GetSkImageInfo();
CanvasColorParams color_params(image_info);
if (image_info.alphaType() != kOpaque_SkAlphaType) {
if (alpha_disposition == kPremultiplyAlpha) {
image_info = image_info.makeAlphaType(kPremul_SkAlphaType);
} else if (alpha_disposition == kUnpremultiplyAlpha) {
image_info = image_info.makeAlphaType(kUnpremul_SkAlphaType);
}
}
ImageData* image_data = Create(
image->Size(), CanvasColorParamsToImageDataColorSettings(color_params));
if (!image_data)
return nullptr;
ImageDataArray data = image_data->data();
SkColorType color_type = image_info.colorType();
bool create_f32_image_data = (color_type == kRGBA_1010102_SkColorType ||
color_type == kRGB_101010x_SkColorType ||
color_type == kRGBA_F16_SkColorType ||
color_type == kRGBA_F32_SkColorType);
if (!create_f32_image_data) {
if (color_type == kR16G16B16A16_unorm_SkColorType) {
image_info = image_info.makeColorType(kR16G16B16A16_unorm_SkColorType);
paint_image.readPixels(image_info, data.GetAsUint16Array()->Data(),
image_info.minRowBytes(), 0, 0);
} else {
image_info = image_info.makeColorType(kRGBA_8888_SkColorType);
paint_image.readPixels(image_info, data.GetAsUint8ClampedArray()->Data(),
image_info.minRowBytes(), 0, 0);
}
} else {
image_info = image_info.makeColorType(kRGBA_F32_SkColorType);
paint_image.readPixels(image_info, data.GetAsFloat32Array()->Data(),
image_info.minRowBytes(), 0, 0);
}
return image_data;
}
ImageData* ImageData::Create(unsigned width, ImageData* ImageData::Create(unsigned width,
unsigned height, unsigned height,
ExceptionState& exception_state) { ExceptionState& exception_state) {
...@@ -701,64 +636,6 @@ unsigned ImageData::StorageFormatBytesPerPixel( ...@@ -701,64 +636,6 @@ unsigned ImageData::StorageFormatBytesPerPixel(
return 1; return 1;
} }
NotShared<DOMArrayBufferView>
ImageData::ConvertPixelsFromCanvasPixelFormatToImageDataStorageFormat(
ArrayBufferContents& content,
CanvasPixelFormat pixel_format,
ImageDataStorageFormat storage_format) {
if (!content.DataLength())
return NotShared<DOMArrayBufferView>();
if (pixel_format == CanvasColorParams::GetNativeCanvasPixelFormat() &&
storage_format == kUint8ClampedArrayStorageFormat) {
DOMArrayBuffer* array_buffer = DOMArrayBuffer::Create(content);
return NotShared<DOMArrayBufferView>(DOMUint8ClampedArray::Create(
array_buffer, 0, array_buffer->ByteLength()));
}
skcms_PixelFormat src_format = skcms_PixelFormat_RGBA_8888;
unsigned num_pixels = content.DataLength() / 4;
if (pixel_format == CanvasPixelFormat::kF16) {
src_format = skcms_PixelFormat_RGBA_hhhh;
num_pixels /= 2;
}
skcms_AlphaFormat alpha_format = skcms_AlphaFormat_Unpremul;
if (storage_format == kUint8ClampedArrayStorageFormat) {
NotShared<DOMUint8ClampedArray> u8_array =
AllocateAndValidateUint8ClampedArray(num_pixels * 4);
if (!u8_array)
return NotShared<DOMArrayBufferView>();
bool data_transform_successful = skcms_Transform(
content.Data(), src_format, alpha_format, nullptr, u8_array->Data(),
skcms_PixelFormat_RGBA_8888, alpha_format, nullptr, num_pixels);
DCHECK(data_transform_successful);
return u8_array;
}
if (storage_format == kUint16ArrayStorageFormat) {
NotShared<DOMUint16Array> u16_array =
AllocateAndValidateUint16Array(num_pixels * 4);
if (!u16_array)
return NotShared<DOMArrayBufferView>();
bool data_transform_successful = skcms_Transform(
content.Data(), src_format, alpha_format, nullptr, u16_array->Data(),
skcms_PixelFormat_RGBA_16161616LE, alpha_format, nullptr, num_pixels);
DCHECK(data_transform_successful);
return u16_array;
}
NotShared<DOMFloat32Array> f32_array =
AllocateAndValidateFloat32Array(num_pixels * 4);
if (!f32_array)
return NotShared<DOMArrayBufferView>();
bool data_transform_successful = skcms_Transform(
content.Data(), src_format, alpha_format, nullptr, f32_array->Data(),
skcms_PixelFormat_RGBA_ffff, alpha_format, nullptr, num_pixels);
DCHECK(data_transform_successful);
return f32_array;
}
DOMArrayBufferBase* ImageData::BufferBase() const { DOMArrayBufferBase* ImageData::BufferBase() const {
if (data_.IsUint8ClampedArray()) if (data_.IsUint8ClampedArray())
return data_.GetAsUint8ClampedArray()->BufferBase(); return data_.GetAsUint8ClampedArray()->BufferBase();
...@@ -769,19 +646,6 @@ DOMArrayBufferBase* ImageData::BufferBase() const { ...@@ -769,19 +646,6 @@ DOMArrayBufferBase* ImageData::BufferBase() const {
return nullptr; return nullptr;
} }
CanvasColorParams ImageData::GetCanvasColorParams() {
if (!RuntimeEnabledFeatures::CanvasColorManagementEnabled())
return CanvasColorParams();
CanvasColorSpace color_space =
CanvasColorSpaceFromName(color_settings_->colorSpace());
return CanvasColorParams(
color_space,
color_settings_->storageFormat() != kUint8ClampedArrayStorageFormatName
? CanvasPixelFormat::kF16
: CanvasColorParams::GetNativeCanvasPixelFormat(),
kNonOpaque);
}
SkPixmap ImageData::GetSkPixmap() const { SkPixmap ImageData::GetSkPixmap() const {
SkColorType color_type = kRGBA_8888_SkColorType; SkColorType color_type = kRGBA_8888_SkColorType;
if (data_u16_) { if (data_u16_) {
...@@ -795,99 +659,6 @@ SkPixmap ImageData::GetSkPixmap() const { ...@@ -795,99 +659,6 @@ SkPixmap ImageData::GetSkPixmap() const {
return SkPixmap(info, BufferBase()->Data(), info.minRowBytes()); return SkPixmap(info, BufferBase()->Data(), info.minRowBytes());
} }
bool ImageData::ImageDataInCanvasColorSettings(
CanvasColorSpace canvas_color_space,
CanvasPixelFormat canvas_pixel_format,
unsigned char* converted_pixels,
DataU8ColorType u8_color_type,
const IntRect* src_rect,
const AlphaDisposition alpha_disposition) {
if (data_.IsNull())
return false;
CanvasColorParams canvas_color_params =
CanvasColorParams(canvas_color_space, canvas_pixel_format, kNonOpaque);
unsigned char* src_data = static_cast<unsigned char*>(BufferBase()->Data());
ImageDataStorageFormat storage_format = GetImageDataStorageFormat();
skcms_PixelFormat src_pixel_format = skcms_PixelFormat_RGBA_8888;
if (data_u16_)
src_pixel_format = skcms_PixelFormat_RGBA_16161616LE;
else if (data_f32_)
src_pixel_format = skcms_PixelFormat_RGBA_ffff;
skcms_PixelFormat dst_pixel_format = skcms_PixelFormat_RGBA_8888;
if (canvas_pixel_format == CanvasPixelFormat::kF16) {
dst_pixel_format = skcms_PixelFormat_RGBA_hhhh;
}
#if SK_PMCOLOR_BYTE_ORDER(B, G, R, A)
else if (canvas_pixel_format ==
CanvasColorParams::GetNativeCanvasPixelFormat() &&
u8_color_type == kN32ColorType) {
dst_pixel_format = skcms_PixelFormat_BGRA_8888;
}
#endif
skcms_AlphaFormat src_alpha_format = skcms_AlphaFormat_Unpremul;
skcms_AlphaFormat dst_alpha_format = skcms_AlphaFormat_Unpremul;
if (alpha_disposition == kPremultiplyAlpha)
dst_alpha_format = skcms_AlphaFormat_PremulAsEncoded;
skcms_ICCProfile* src_profile_ptr = nullptr;
skcms_ICCProfile* dst_profile_ptr = nullptr;
skcms_ICCProfile src_profile, dst_profile;
CanvasColorSpaceToSkColorSpace(GetCanvasColorSpace())
->toProfile(&src_profile);
canvas_color_params.GetSkColorSpace()->toProfile(&dst_profile);
// If the profiles are similar, we better leave them as nullptr, since
// skcms_Transform() only checks for profile pointer equality for the fast
// path.
if (!skcms_ApproximatelyEqualProfiles(&src_profile, &dst_profile)) {
src_profile_ptr = &src_profile;
dst_profile_ptr = &dst_profile;
}
const IntRect* crop_rect = nullptr;
if (src_rect && *src_rect != IntRect(IntPoint(), Size()))
crop_rect = src_rect;
// If only a portion of ImageData is required for canvas, we run the transform
// for every line.
if (crop_rect) {
unsigned bytes_per_pixel =
ImageData::StorageFormatBytesPerPixel(storage_format);
unsigned src_index =
(crop_rect->X() + crop_rect->Y() * width()) * bytes_per_pixel;
unsigned dst_index = 0;
unsigned src_row_stride = width() * bytes_per_pixel;
unsigned dst_row_stride =
crop_rect->Width() * canvas_color_params.BytesPerPixel();
bool data_transform_successful = true;
for (int i = 0; data_transform_successful && i < crop_rect->Height(); i++) {
data_transform_successful = skcms_Transform(
src_data + src_index, src_pixel_format, src_alpha_format,
src_profile_ptr, converted_pixels + dst_index, dst_pixel_format,
dst_alpha_format, dst_profile_ptr, crop_rect->Width());
DCHECK(data_transform_successful);
src_index += src_row_stride;
dst_index += dst_row_stride;
}
return data_transform_successful;
}
base::CheckedNumeric<uint32_t> area = size_.Area();
if (!area.IsValid())
return false;
bool data_transform_successful =
skcms_Transform(src_data, src_pixel_format, src_alpha_format,
src_profile_ptr, converted_pixels, dst_pixel_format,
dst_alpha_format, dst_profile_ptr, area.ValueOrDie());
return data_transform_successful;
}
void ImageData::Trace(Visitor* visitor) const { void ImageData::Trace(Visitor* visitor) const {
visitor->Trace(color_settings_); visitor->Trace(color_settings_);
visitor->Trace(data_); visitor->Trace(data_);
......
...@@ -77,8 +77,6 @@ class CORE_EXPORT ImageData final : public ScriptWrappable, ...@@ -77,8 +77,6 @@ class CORE_EXPORT ImageData final : public ScriptWrappable,
static ImageData* Create(const IntSize&, static ImageData* Create(const IntSize&,
NotShared<DOMArrayBufferView>, NotShared<DOMArrayBufferView>,
const ImageDataColorSettings* = nullptr); const ImageDataColorSettings* = nullptr);
static ImageData* Create(scoped_refptr<StaticBitmapImage>,
AlphaDisposition = kDontChangeAlpha);
static ImageData* Create(unsigned width, unsigned height, ExceptionState&); static ImageData* Create(unsigned width, unsigned height, ExceptionState&);
static ImageData* Create(NotShared<DOMUint8ClampedArray>, static ImageData* Create(NotShared<DOMUint8ClampedArray>,
...@@ -130,11 +128,6 @@ class CORE_EXPORT ImageData final : public ScriptWrappable, ...@@ -130,11 +128,6 @@ class CORE_EXPORT ImageData final : public ScriptWrappable,
static ImageDataStorageFormat GetImageDataStorageFormat(const String&); static ImageDataStorageFormat GetImageDataStorageFormat(const String&);
static unsigned StorageFormatBytesPerPixel(const String&); static unsigned StorageFormatBytesPerPixel(const String&);
static unsigned StorageFormatBytesPerPixel(ImageDataStorageFormat); static unsigned StorageFormatBytesPerPixel(ImageDataStorageFormat);
static NotShared<DOMArrayBufferView>
ConvertPixelsFromCanvasPixelFormatToImageDataStorageFormat(
ArrayBufferContents&,
CanvasPixelFormat,
ImageDataStorageFormat);
IntSize Size() const { return size_; } IntSize Size() const { return size_; }
int width() const { return size_.Width(); } int width() const { return size_.Width(); }
...@@ -145,26 +138,12 @@ class CORE_EXPORT ImageData final : public ScriptWrappable, ...@@ -145,26 +138,12 @@ class CORE_EXPORT ImageData final : public ScriptWrappable,
void data(ImageDataArray& result) { result = data_; } void data(ImageDataArray& result) { result = data_; }
DOMArrayBufferBase* BufferBase() const; DOMArrayBufferBase* BufferBase() const;
CanvasColorParams GetCanvasColorParams();
CanvasColorSpace GetCanvasColorSpace() const; CanvasColorSpace GetCanvasColorSpace() const;
ImageDataStorageFormat GetImageDataStorageFormat() const; ImageDataStorageFormat GetImageDataStorageFormat() const;
// Return an SkPixmap that references this data directly. // Return an SkPixmap that references this data directly.
SkPixmap GetSkPixmap() const; SkPixmap GetSkPixmap() const;
// DataU8ColorType param specifies if the converted pixels in uint8 pixel
// format should respect the "native" 32bit ARGB format of Skia's blitters.
// For example, if ImageDataInCanvasColorSettings() is called to fill an
// ImageBuffer, kRGBAColorType should be used. If the converted pixels are
// used to create an ImageBitmap, kN32ColorType should be used.
bool ImageDataInCanvasColorSettings(
CanvasColorSpace,
CanvasPixelFormat,
unsigned char* converted_pixels,
DataU8ColorType,
const IntRect* = nullptr,
const AlphaDisposition = kUnpremultiplyAlpha);
// ImageBitmapSource implementation // ImageBitmapSource implementation
IntSize BitmapSourceSize() const override { return size_; } IntSize BitmapSourceSize() const override { return size_; }
ScriptPromise CreateImageBitmap(ScriptState*, ScriptPromise CreateImageBitmap(ScriptState*,
......
...@@ -27,358 +27,6 @@ TEST_F(ImageDataTest, CreateImageDataTooBig) { ...@@ -27,358 +27,6 @@ TEST_F(ImageDataTest, CreateImageDataTooBig) {
} }
} }
// This test verifies the correct behavior of ImageData member function used
// to convert pixels data from canvas pixel format to image data storage
// format. This function is used in BaseRenderingContext2D::getImageData.
TEST_F(ImageDataTest,
TestConvertPixelsFromCanvasPixelFormatToImageDataStorageFormat) {
// Source pixels in RGBA32
unsigned char rgba32_pixels[] = {255, 0, 0, 255, // Red
0, 0, 0, 0, // Transparent
255, 192, 128, 64, // Decreasing values
93, 117, 205, 11}; // Random values
const unsigned kNumColorComponents = 16;
float f32_pixels[kNumColorComponents];
for (unsigned i = 0; i < kNumColorComponents; i++)
f32_pixels[i] = rgba32_pixels[i] / 255.0;
const unsigned kNumPixels = kNumColorComponents / 4;
// Source pixels in F16
unsigned char f16_pixels[kNumColorComponents * 2];
EXPECT_TRUE(skcms_Transform(f32_pixels, skcms_PixelFormat_RGBA_ffff,
skcms_AlphaFormat_Unpremul, nullptr, f16_pixels,
skcms_PixelFormat_RGBA_hhhh,
skcms_AlphaFormat_Unpremul, nullptr, 4));
// Source pixels in U16
uint16_t u16_pixels[kNumColorComponents];
for (unsigned i = 0; i < kNumColorComponents; i++)
u16_pixels[i] = f32_pixels[i] * 65535.0;
// Creating ArrayBufferContents objects. We need two buffers for RGBA32 data
// because
// CanvasPixelFormat::kRGBA8->kUint8ClampedArrayStorageFormat
// consumes the input data parameter.
ArrayBufferContents contents_rgba32(kNumColorComponents, 1,
ArrayBufferContents::kNotShared,
ArrayBufferContents::kDontInitialize);
std::memcpy(contents_rgba32.Data(), rgba32_pixels, kNumColorComponents);
ArrayBufferContents contents_rgba32_2;
contents_rgba32.CopyTo(contents_rgba32_2);
ArrayBufferContents contents_f16(kNumColorComponents * 2, 1,
ArrayBufferContents::kNotShared,
ArrayBufferContents::kDontInitialize);
std::memcpy(contents_f16.Data(), f16_pixels, kNumColorComponents * 2);
// Testing CanvasPixelFormat::kRGBA8->
// kUint8ClampedArrayStorageFormat
NotShared<DOMArrayBufferView> data(
ImageData::ConvertPixelsFromCanvasPixelFormatToImageDataStorageFormat(
contents_rgba32, CanvasPixelFormat::kRGBA8,
kUint8ClampedArrayStorageFormat));
DCHECK(data->GetType() == DOMArrayBufferView::ViewType::kTypeUint8Clamped);
ColorCorrectionTestUtils::CompareColorCorrectedPixels(
data->BaseAddress(), rgba32_pixels, kNumPixels, kPixelFormat_8888,
kAlphaUnmultiplied, kNoUnpremulRoundTripTolerance);
// Testing CanvasPixelFormat::kRGBA8->
// kUint16ArrayStorageFormat
data = ImageData::ConvertPixelsFromCanvasPixelFormatToImageDataStorageFormat(
contents_rgba32_2, CanvasPixelFormat::kRGBA8, kUint16ArrayStorageFormat);
DCHECK(data->GetType() == DOMArrayBufferView::ViewType::kTypeUint16);
ColorCorrectionTestUtils::CompareColorCorrectedPixels(
data->BaseAddress(), u16_pixels, kNumPixels, kPixelFormat_16161616,
kAlphaUnmultiplied, kUnpremulRoundTripTolerance);
// Testing CanvasPixelFormat::kRGBA8 ->
// kFloat32ArrayStorageFormat
data = ImageData::ConvertPixelsFromCanvasPixelFormatToImageDataStorageFormat(
contents_rgba32_2, CanvasPixelFormat::kRGBA8, kFloat32ArrayStorageFormat);
DCHECK(data->GetType() == DOMArrayBufferView::ViewType::kTypeFloat32);
ColorCorrectionTestUtils::CompareColorCorrectedPixels(
data->BaseAddress(), f32_pixels, kNumPixels, kPixelFormat_ffff,
kAlphaUnmultiplied, kUnpremulRoundTripTolerance);
// Testing CanvasPixelFormat::kF16 -> kUint8ClampedArrayStorageFormat
data = ImageData::ConvertPixelsFromCanvasPixelFormatToImageDataStorageFormat(
contents_f16, CanvasPixelFormat::kF16, kUint8ClampedArrayStorageFormat);
DCHECK(data->GetType() == DOMArrayBufferView::ViewType::kTypeUint8Clamped);
ColorCorrectionTestUtils::CompareColorCorrectedPixels(
data->BaseAddress(), rgba32_pixels, kNumPixels, kPixelFormat_8888,
kAlphaUnmultiplied, kNoUnpremulRoundTripTolerance);
// Testing CanvasPixelFormat::kF16 -> kUint16ArrayStorageFormat
data = ImageData::ConvertPixelsFromCanvasPixelFormatToImageDataStorageFormat(
contents_f16, CanvasPixelFormat::kF16, kUint16ArrayStorageFormat);
DCHECK(data->GetType() == DOMArrayBufferView::ViewType::kTypeUint16);
ColorCorrectionTestUtils::CompareColorCorrectedPixels(
data->BaseAddress(), u16_pixels, kNumPixels, kPixelFormat_16161616,
kAlphaUnmultiplied, kUnpremulRoundTripTolerance);
// Testing CanvasPixelFormat::kF16 -> kFloat32ArrayStorageFormat
data = ImageData::ConvertPixelsFromCanvasPixelFormatToImageDataStorageFormat(
contents_f16, CanvasPixelFormat::kF16, kFloat32ArrayStorageFormat);
DCHECK(data->GetType() == DOMArrayBufferView::ViewType::kTypeFloat32);
ColorCorrectionTestUtils::CompareColorCorrectedPixels(
data->BaseAddress(), f32_pixels, kNumPixels, kPixelFormat_ffff,
kAlphaUnmultiplied, kUnpremulRoundTripTolerance);
}
// This test verifies the correct behavior of ImageData member function used
// to convert image data from image data storage format to canvas pixel format.
// This function is used in BaseRenderingContext2D::putImageData.
TEST_F(ImageDataTest, TestGetImageDataInCanvasColorSettings) {
unsigned num_image_data_color_spaces = 3;
CanvasColorSpace image_data_color_spaces[] = {
CanvasColorSpace::kSRGB,
CanvasColorSpace::kRec2020,
CanvasColorSpace::kP3,
};
unsigned num_image_data_storage_formats = 3;
ImageDataStorageFormat image_data_storage_formats[] = {
kUint8ClampedArrayStorageFormat, kUint16ArrayStorageFormat,
kFloat32ArrayStorageFormat,
};
unsigned num_canvas_color_settings = 3;
CanvasColorSpace canvas_color_spaces[] = {
CanvasColorSpace::kSRGB,
CanvasColorSpace::kSRGB,
CanvasColorSpace::kRec2020,
CanvasColorSpace::kP3,
};
CanvasPixelFormat canvas_pixel_formats[] = {
CanvasPixelFormat::kRGBA8, CanvasPixelFormat::kF16,
CanvasPixelFormat::kF16, CanvasPixelFormat::kF16,
};
// As cross checking the output of Skia color space covnersion API is not in
// the scope of this unit test, we do turn-around tests here. To do so, we
// create an ImageData with the selected color space and storage format,
// convert it to the target canvas color space and pixel format by calling
// ImageData::imageDataInCanvasColorSettings(), and then convert it back
// to the source image data color space and Float32 storage format by calling
// ImageData::convertPixelsFromCanvasPixelFormatToImageDataStorageFormat().
// We expect to get the same image data as we started with.
// Source pixels in RGBA32, unpremul
uint8_t u8_pixels[] = {255, 0, 0, 255, // Red
0, 0, 0, 0, // Transparent
255, 192, 128, 64, // Decreasing values
93, 117, 205, 11}; // Random values
size_t data_length = 16;
uint16_t* u16_pixels = new uint16_t[data_length];
for (size_t i = 0; i < data_length; i++)
u16_pixels[i] = u8_pixels[i] * 257;
float* f32_pixels = new float[data_length];
for (size_t i = 0; i < data_length; i++)
f32_pixels[i] = u8_pixels[i] / 255.0;
NotShared<DOMUint8ClampedArray> data_u8(
DOMUint8ClampedArray::Create(u8_pixels, data_length));
DCHECK(data_u8);
EXPECT_EQ(data_length, data_u8->length());
NotShared<DOMUint16Array> data_u16(
DOMUint16Array::Create(u16_pixels, data_length));
DCHECK(data_u16);
EXPECT_EQ(data_length, data_u16->length());
NotShared<DOMFloat32Array> data_f32(
DOMFloat32Array::Create(f32_pixels, data_length));
DCHECK(data_f32);
EXPECT_EQ(data_length, data_f32->length());
ImageData* image_data = nullptr;
ImageDataColorSettings* color_settings = ImageDataColorSettings::Create();
// At most two bytes are needed for output per color component.
std::unique_ptr<uint8_t[]> pixels_converted_manually(
new uint8_t[data_length * 2]());
std::unique_ptr<uint8_t[]> pixels_converted_in_image_data(
new uint8_t[data_length * 2]());
// Loop through different possible combinations of image data color space and
// storage formats and create the respective test image data objects.
for (unsigned i = 0; i < num_image_data_color_spaces; i++) {
color_settings->setColorSpace(
ImageData::CanvasColorSpaceName(image_data_color_spaces[i]));
for (unsigned j = 0; j < num_image_data_storage_formats; j++) {
NotShared<DOMArrayBufferView> data_array;
switch (image_data_storage_formats[j]) {
case kUint8ClampedArrayStorageFormat:
data_array = data_u8;
color_settings->setStorageFormat(kUint8ClampedArrayStorageFormatName);
break;
case kUint16ArrayStorageFormat:
data_array = data_u16;
color_settings->setStorageFormat(kUint16ArrayStorageFormatName);
break;
case kFloat32ArrayStorageFormat:
data_array = data_f32;
color_settings->setStorageFormat(kFloat32ArrayStorageFormatName);
break;
default:
NOTREACHED();
}
image_data =
ImageData::CreateForTest(IntSize(2, 2), data_array, color_settings);
for (unsigned k = 0; k < num_canvas_color_settings; k++) {
// Convert the original data used to create ImageData to the
// canvas color space and canvas pixel format.
EXPECT_TRUE(
ColorCorrectionTestUtils::
ConvertPixelsToColorSpaceAndPixelFormatForTest(
data_array->BaseAddress(), data_length,
image_data_color_spaces[i], image_data_storage_formats[j],
canvas_color_spaces[k], canvas_pixel_formats[k],
pixels_converted_manually, kPixelFormat_hhhh));
// Convert the image data to the color settings of the canvas.
EXPECT_TRUE(image_data->ImageDataInCanvasColorSettings(
canvas_color_spaces[k], canvas_pixel_formats[k],
pixels_converted_in_image_data.get(), kRGBAColorType));
// Compare the converted pixels
ColorCorrectionTestUtils::CompareColorCorrectedPixels(
pixels_converted_manually.get(),
pixels_converted_in_image_data.get(),
static_cast<int>(image_data->Size().Area()),
(canvas_pixel_formats[k] == CanvasPixelFormat::kRGBA8)
? kPixelFormat_8888
: kPixelFormat_hhhh,
kAlphaUnmultiplied, kUnpremulRoundTripTolerance);
}
}
}
delete[] u16_pixels;
delete[] f32_pixels;
}
// This test examines ImageData::Create(StaticBitmapImage)
TEST_F(ImageDataTest, TestCreateImageDataFromStaticBitmapImage) {
const unsigned kNumColorComponents = 16;
const unsigned kNumPixels = kNumColorComponents / 4;
const unsigned kWidth = 2;
const unsigned kHeight = 2;
// Preparing source pixels
uint8_t expected_u8_pixels_unpremul[] = {
255, 0, 0, 255, // Red
0, 0, 0, 0, // Transparent
255, 192, 128, 64, // Decreasing values
93, 117, 205, 41}; // Random values
uint8_t expected_u8_pixels_premul[kNumColorComponents];
uint16_t expected_f16_pixels_unpremul[kNumColorComponents];
uint16_t expected_f16_pixels_premul[kNumColorComponents];
float expected_f32_pixels_unpremul[kNumColorComponents];
float expected_f32_pixels_premul[kNumColorComponents];
auto prepareSourcePixels = [&expected_u8_pixels_unpremul, &kNumPixels](
auto buffer, bool is_premul,
auto pixel_format) {
EXPECT_TRUE(skcms_Transform(
expected_u8_pixels_unpremul, skcms_PixelFormat_RGBA_8888,
skcms_AlphaFormat_Unpremul, nullptr, buffer, pixel_format,
is_premul ? skcms_AlphaFormat_PremulAsEncoded
: skcms_AlphaFormat_Unpremul,
nullptr, kNumPixels));
};
prepareSourcePixels(expected_u8_pixels_premul, true,
skcms_PixelFormat_RGBA_8888);
prepareSourcePixels(expected_f16_pixels_unpremul, false,
skcms_PixelFormat_RGBA_hhhh);
prepareSourcePixels(expected_f16_pixels_premul, true,
skcms_PixelFormat_RGBA_hhhh);
prepareSourcePixels(expected_f32_pixels_unpremul, false,
skcms_PixelFormat_RGBA_ffff);
prepareSourcePixels(expected_f32_pixels_premul, true,
skcms_PixelFormat_RGBA_ffff);
auto contents_u8_premul =
SkData::MakeWithoutCopy(expected_u8_pixels_premul, kNumColorComponents);
auto contents_u8_unpremul =
SkData::MakeWithoutCopy(expected_u8_pixels_unpremul, kNumColorComponents);
auto contents_f16_premul = SkData::MakeWithoutCopy(expected_f16_pixels_premul,
kNumColorComponents * 2);
auto contents_f16_unpremul = SkData::MakeWithoutCopy(
expected_f16_pixels_unpremul, kNumColorComponents * 2);
// Preparing StaticBitmapImage objects
auto info_u8_premul = SkImageInfo::Make(
kWidth, kHeight, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
auto info_u8_unpremul = info_u8_premul.makeAlphaType(kUnpremul_SkAlphaType);
auto info_f16_premul = info_u8_premul.makeColorType(kRGBA_F16_SkColorType)
.makeColorSpace(SkColorSpace::MakeSRGBLinear());
auto info_f16_unpremul = info_f16_premul.makeAlphaType(kUnpremul_SkAlphaType);
auto image_u8_premul =
StaticBitmapImage::Create(contents_u8_premul, info_u8_premul);
auto image_u8_unpremul =
StaticBitmapImage::Create(contents_u8_unpremul, info_u8_unpremul);
auto image_f16_premul =
StaticBitmapImage::Create(contents_f16_premul, info_f16_premul);
auto image_f16_unpremul =
StaticBitmapImage::Create(contents_f16_unpremul, info_f16_unpremul);
// Creating ImageData objects
ImageData* actual_image_data_u8[4];
ImageData* actual_image_data_f32[4];
// u8 premul
actual_image_data_u8[0] = ImageData::Create(image_u8_premul);
actual_image_data_u8[1] =
ImageData::Create(image_u8_unpremul, kPremultiplyAlpha);
// u8 unpremul
actual_image_data_u8[2] = ImageData::Create(image_u8_unpremul);
actual_image_data_u8[3] =
ImageData::Create(image_u8_premul, kUnpremultiplyAlpha);
// ImageData does not support half float storage. Therefore, ImageData
// objects that are created from half-float backed StaticBitmapImage objects
// will contain float 32 data items.
// f32 premul
actual_image_data_f32[0] = ImageData::Create(image_f16_premul);
actual_image_data_f32[1] =
ImageData::Create(image_f16_unpremul, kPremultiplyAlpha);
// f32 unpremul
actual_image_data_f32[2] = ImageData::Create(image_f16_unpremul);
actual_image_data_f32[3] =
ImageData::Create(image_f16_premul, kUnpremultiplyAlpha);
// Associating expected color component arrays
uint8_t* expected_pixel_arrays_u8[4] = {
expected_u8_pixels_premul, expected_u8_pixels_premul,
expected_u8_pixels_unpremul, expected_u8_pixels_unpremul};
float* expected_pixel_arrays_f32[4] = {
expected_f32_pixels_premul, expected_f32_pixels_premul,
expected_f32_pixels_unpremul, expected_f32_pixels_unpremul};
// Comparing ImageData with the source StaticBitmapImage
for (unsigned i = 0; i < 4; i++) {
ColorCorrectionTestUtils::CompareColorCorrectedPixels(
expected_pixel_arrays_u8[i],
actual_image_data_u8[i]->BufferBase()->Data(), kNumPixels,
kPixelFormat_8888, kAlphaUnmultiplied, kUnpremulRoundTripTolerance);
}
for (unsigned i = 0; i < 4; i++) {
ColorCorrectionTestUtils::CompareColorCorrectedPixels(
expected_pixel_arrays_f32[i],
actual_image_data_f32[i]->BufferBase()->Data(), kNumPixels,
kPixelFormat_ffff, kAlphaUnmultiplied, kUnpremulRoundTripTolerance);
}
}
// This test examines ImageData::CropRect() // This test examines ImageData::CropRect()
TEST_F(ImageDataTest, TestCropRect) { TEST_F(ImageDataTest, TestCropRect) {
const int num_image_data_storage_formats = 3; const int num_image_data_storage_formats = 3;
......
...@@ -1917,7 +1917,12 @@ void BaseRenderingContext2D::putImageData(ImageData* data, ...@@ -1917,7 +1917,12 @@ void BaseRenderingContext2D::putImageData(ImageData* data,
// order for both ImageData and CanvasResourceProvider, therefore no // order for both ImageData and CanvasResourceProvider, therefore no
// additional swizzling is needed. // additional swizzling is needed.
SkPixmap data_pixmap = data->GetSkPixmap(); SkPixmap data_pixmap = data->GetSkPixmap();
CanvasColorParams data_color_params = data->GetCanvasColorParams(); CanvasColorParams data_color_params(
data->GetCanvasColorSpace(),
data->GetImageDataStorageFormat() != kUint8ClampedArrayStorageFormat
? CanvasPixelFormat::kF16
: CanvasColorParams::GetNativeCanvasPixelFormat(),
kNonOpaque);
CanvasColorParams context_color_params = CanvasColorParams( CanvasColorParams context_color_params = CanvasColorParams(
GetCanvas2DColorParams().ColorSpace(), PixelFormat(), kNonOpaque); GetCanvas2DColorParams().ColorSpace(), PixelFormat(), kNonOpaque);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment