Commit 050fee06 authored by Christopher Cameron's avatar Christopher Cameron Committed by Chromium LUCI CQ

ImageBitmap: Use SkImageInfo in serialization

Serialization code for ImageBitmap goes through CanvasColorParams.
This constrains unrelated canvas code, and isn't a good fit. This
changes serialization to use SkImageInfo instead of CanvasColorParams.
The serialization code still uses the CanvasColorSpace enums, though
that should eventually be made more flexible.

Bug: 1121448, 1150969
Change-Id: I33189ac40ae923e921473cfea41c2b6dcb9aa3cf
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2569211
Commit-Queue: ccameron <ccameron@chromium.org>
Reviewed-by: default avatarJeremy Roman <jbroman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#835579}
parent be48a068
......@@ -8,45 +8,45 @@
namespace blink {
SerializedColorParams::SerializedColorParams() = default;
namespace {
SerializedColorParams::SerializedColorParams(CanvasColorParams color_params)
: SerializedColorParams(color_params.ColorSpace(),
kUint8ClampedArrayStorageFormat) {
switch (color_params.PixelFormat()) {
case CanvasPixelFormat::kF16:
pixel_format_ = SerializedPixelFormat::kF16;
break;
case CanvasPixelFormat::kRGBA8:
pixel_format_ = SerializedPixelFormat::kRGBA8;
break;
case CanvasPixelFormat::kBGRA8:
pixel_format_ = SerializedPixelFormat::kBGRA8;
break;
case CanvasPixelFormat::kRGBX8:
pixel_format_ = SerializedPixelFormat::kRGBX8;
break;
}
opacity_mode_ = SerializedOpacityMode::kNonOpaque;
if (color_params.GetOpacityMode() == blink::kOpaque)
opacity_mode_ = SerializedOpacityMode::kOpaque;
}
SerializedColorParams::SerializedColorParams(
CanvasColorSpace color_space,
ImageDataStorageFormat storage_format) {
SerializedColorSpace SerializeColorSpace(CanvasColorSpace color_space) {
switch (color_space) {
case CanvasColorSpace::kSRGB:
color_space_ = SerializedColorSpace::kSRGB;
break;
return SerializedColorSpace::kSRGB;
case CanvasColorSpace::kRec2020:
color_space_ = SerializedColorSpace::kRec2020;
break;
return SerializedColorSpace::kRec2020;
case CanvasColorSpace::kP3:
color_space_ = SerializedColorSpace::kP3;
break;
return SerializedColorSpace::kP3;
}
NOTREACHED();
return SerializedColorSpace::kSRGB;
}
CanvasColorSpace DeserializeColorSpace(
SerializedColorSpace serialized_color_space) {
switch (serialized_color_space) {
case SerializedColorSpace::kLegacyObsolete:
case SerializedColorSpace::kSRGB:
return CanvasColorSpace::kSRGB;
case SerializedColorSpace::kRec2020:
return CanvasColorSpace::kRec2020;
case SerializedColorSpace::kP3:
return CanvasColorSpace::kP3;
}
NOTREACHED();
return CanvasColorSpace::kSRGB;
}
} // namespace
////////////////////////////////////////////////////////////////////////////////
// SerializedImageDataSettings
SerializedImageDataSettings::SerializedImageDataSettings(
CanvasColorSpace color_space,
ImageDataStorageFormat storage_format)
: color_space_(SerializeColorSpace(color_space)) {
switch (storage_format) {
case kUint8ClampedArrayStorageFormat:
storage_format_ = SerializedImageDataStorageFormat::kUint8Clamped;
......@@ -60,76 +60,120 @@ SerializedColorParams::SerializedColorParams(
}
}
SerializedColorParams::SerializedColorParams(
SerializedImageDataSettings::SerializedImageDataSettings(
SerializedColorSpace color_space,
SerializedPixelFormat pixel_format,
SerializedOpacityMode opacity_mode,
SerializedImageDataStorageFormat storage_format)
: color_space_(color_space),
pixel_format_(pixel_format),
opacity_mode_(opacity_mode),
storage_format_(storage_format) {}
: color_space_(color_space), storage_format_(storage_format) {}
CanvasColorParams SerializedColorParams::GetCanvasColorParams() const {
CanvasColorSpace color_space = CanvasColorSpace::kSRGB;
switch (color_space_) {
case SerializedColorSpace::kLegacyObsolete:
case SerializedColorSpace::kSRGB:
color_space = CanvasColorSpace::kSRGB;
CanvasColorSpace SerializedImageDataSettings::GetColorSpace() const {
return DeserializeColorSpace(color_space_);
}
ImageDataStorageFormat SerializedImageDataSettings::GetStorageFormat() const {
switch (storage_format_) {
case SerializedImageDataStorageFormat::kUint8Clamped:
return kUint8ClampedArrayStorageFormat;
case SerializedImageDataStorageFormat::kUint16:
return kUint16ArrayStorageFormat;
case SerializedImageDataStorageFormat::kFloat32:
return kFloat32ArrayStorageFormat;
}
NOTREACHED();
return kUint8ClampedArrayStorageFormat;
}
////////////////////////////////////////////////////////////////////////////////
// SerializedImageBitmapSettings
SerializedImageBitmapSettings::SerializedImageBitmapSettings() = default;
SerializedImageBitmapSettings::SerializedImageBitmapSettings(SkImageInfo info) {
color_space_ =
SerializeColorSpace(CanvasColorSpaceFromSkColorSpace(info.colorSpace()));
switch (info.colorType()) {
default:
case kRGBA_8888_SkColorType:
pixel_format_ = SerializedPixelFormat::kRGBA8;
break;
case SerializedColorSpace::kRec2020:
color_space = CanvasColorSpace::kRec2020;
case kBGRA_8888_SkColorType:
pixel_format_ = SerializedPixelFormat::kBGRA8;
break;
case SerializedColorSpace::kP3:
color_space = CanvasColorSpace::kP3;
case kRGB_888x_SkColorType:
pixel_format_ = SerializedPixelFormat::kRGBX8;
break;
case kRGBA_F16_SkColorType:
pixel_format_ = SerializedPixelFormat::kF16;
break;
}
switch (info.alphaType()) {
case kUnknown_SkAlphaType:
case kPremul_SkAlphaType:
opacity_mode_ = SerializedOpacityMode::kNonOpaque;
is_premultiplied_ = true;
break;
case kUnpremul_SkAlphaType:
opacity_mode_ = SerializedOpacityMode::kNonOpaque;
is_premultiplied_ = false;
break;
case kOpaque_SkAlphaType:
opacity_mode_ = SerializedOpacityMode::kOpaque;
is_premultiplied_ = true;
break;
}
}
CanvasPixelFormat pixel_format = CanvasPixelFormat::kRGBA8;
SerializedImageBitmapSettings::SerializedImageBitmapSettings(
SerializedColorSpace color_space,
SerializedPixelFormat pixel_format,
SerializedOpacityMode opacity_mode,
uint32_t is_premultiplied)
: color_space_(color_space),
pixel_format_(pixel_format),
opacity_mode_(opacity_mode),
is_premultiplied_(is_premultiplied) {}
SkImageInfo SerializedImageBitmapSettings::GetSkImageInfo(
uint32_t width,
uint32_t height) const {
sk_sp<SkColorSpace> sk_color_space =
CanvasColorSpaceToSkColorSpace(DeserializeColorSpace(color_space_));
SkColorType sk_color_type = kRGBA_8888_SkColorType;
switch (pixel_format_) {
case SerializedPixelFormat::kNative8_LegacyObsolete:
#if defined(OS_ANDROID)
pixel_format = CanvasPixelFormat::kRGBA8;
#else
pixel_format = CanvasPixelFormat::kBGRA8;
#endif
break;
case SerializedPixelFormat::kF16:
pixel_format = CanvasPixelFormat::kF16;
sk_color_type = kN32_SkColorType;
break;
case SerializedPixelFormat::kRGBA8:
pixel_format = CanvasPixelFormat::kRGBA8;
sk_color_type = kRGBA_8888_SkColorType;
break;
case SerializedPixelFormat::kBGRA8:
pixel_format = CanvasPixelFormat::kBGRA8;
sk_color_type = kBGRA_8888_SkColorType;
break;
case SerializedPixelFormat::kRGBX8:
pixel_format = CanvasPixelFormat::kRGBX8;
sk_color_type = kRGB_888x_SkColorType;
break;
case SerializedPixelFormat::kF16:
sk_color_type = kRGBA_F16_SkColorType;
break;
}
SkAlphaType sk_alpha_type = kPremul_SkAlphaType;
if (opacity_mode_ == SerializedOpacityMode::kOpaque) {
sk_alpha_type = kOpaque_SkAlphaType;
} else if (is_premultiplied_) {
sk_alpha_type = kPremul_SkAlphaType;
} else {
sk_alpha_type = kUnpremul_SkAlphaType;
}
blink::OpacityMode opacity_mode = blink::kNonOpaque;
if (opacity_mode_ == SerializedOpacityMode::kOpaque)
opacity_mode = blink::kOpaque;
return CanvasColorParams(color_space, pixel_format, opacity_mode);
}
CanvasColorSpace SerializedColorParams::GetColorSpace() const {
return GetCanvasColorParams().ColorSpace();
}
ImageDataStorageFormat SerializedColorParams::GetStorageFormat() const {
switch (storage_format_) {
case SerializedImageDataStorageFormat::kUint8Clamped:
return kUint8ClampedArrayStorageFormat;
case SerializedImageDataStorageFormat::kUint16:
return kUint16ArrayStorageFormat;
case SerializedImageDataStorageFormat::kFloat32:
return kFloat32ArrayStorageFormat;
}
NOTREACHED();
return kUint8ClampedArrayStorageFormat;
return SkImageInfo::Make(width, height, sk_color_type, sk_alpha_type,
std::move(sk_color_space));
}
} // namespace blink
......@@ -72,37 +72,51 @@ enum class SerializedOpacityMode : uint32_t {
kLast = kOpaque,
};
class SerializedColorParams {
class SerializedImageDataSettings {
public:
SerializedColorParams();
explicit SerializedColorParams(CanvasColorParams);
SerializedColorParams(CanvasColorSpace, ImageDataStorageFormat);
SerializedColorParams(SerializedColorSpace,
SerializedPixelFormat,
SerializedOpacityMode,
SerializedImageDataStorageFormat);
CanvasColorParams GetCanvasColorParams() const;
SerializedImageDataSettings(CanvasColorSpace, ImageDataStorageFormat);
SerializedImageDataSettings(SerializedColorSpace,
SerializedImageDataStorageFormat);
CanvasColorSpace GetColorSpace() const;
ImageDataStorageFormat GetStorageFormat() const;
SerializedColorSpace GetSerializedColorSpace() const { return color_space_; }
SerializedPixelFormat GetSerializedPixelFormat() const {
return pixel_format_;
}
SerializedImageDataStorageFormat GetSerializedImageDataStorageFormat() const {
return storage_format_;
}
private:
SerializedColorSpace color_space_ = SerializedColorSpace::kSRGB;
SerializedImageDataStorageFormat storage_format_ =
SerializedImageDataStorageFormat::kUint8Clamped;
};
class SerializedImageBitmapSettings {
public:
SerializedImageBitmapSettings();
explicit SerializedImageBitmapSettings(SkImageInfo);
SerializedImageBitmapSettings(SerializedColorSpace,
SerializedPixelFormat,
SerializedOpacityMode,
uint32_t is_premultiplied);
SkImageInfo GetSkImageInfo(uint32_t width, uint32_t height) const;
SerializedColorSpace GetSerializedColorSpace() const { return color_space_; }
SerializedPixelFormat GetSerializedPixelFormat() const {
return pixel_format_;
}
SerializedOpacityMode GetSerializedOpacityMode() const {
return opacity_mode_;
}
uint32_t IsPremultiplied() const { return is_premultiplied_; }
private:
SerializedColorSpace color_space_ = SerializedColorSpace::kSRGB;
SerializedPixelFormat pixel_format_ = SerializedPixelFormat::kRGBA8;
SerializedOpacityMode opacity_mode_ = SerializedOpacityMode::kNonOpaque;
SerializedImageDataStorageFormat storage_format_ =
SerializedImageDataStorageFormat::kUint8Clamped;
bool is_premultiplied_ = true;
};
} // namespace blink
......
......@@ -358,14 +358,12 @@ ScriptWrappable* V8ScriptValueDeserializer::ReadDOMObject(
if (!ReadUint32(&width) || !ReadUint32(&height) ||
!ReadUint32(&byte_length) || !ReadRawBytes(byte_length, &pixels))
return nullptr;
CanvasColorParams color_params =
SerializedColorParams(canvas_color_space, canvas_pixel_format,
canvas_opacity_mode,
SerializedImageDataStorageFormat::kUint8Clamped)
.GetCanvasColorParams();
base::CheckedNumeric<uint32_t> computed_byte_length = width;
computed_byte_length *= height;
computed_byte_length *= color_params.BytesPerPixel();
SkImageInfo info =
SerializedImageBitmapSettings(canvas_color_space, canvas_pixel_format,
canvas_opacity_mode, is_premultiplied)
.GetSkImageInfo(width, height);
base::CheckedNumeric<uint32_t> computed_byte_length =
info.computeMinByteSize();
if (!computed_byte_length.IsValid() ||
computed_byte_length.ValueOrDie() != byte_length)
return nullptr;
......@@ -374,10 +372,6 @@ ScriptWrappable* V8ScriptValueDeserializer::ReadDOMObject(
// been deprecated.
return nullptr;
}
SkImageInfo info = SkImageInfo::Make(
width, height, color_params.GetSkColorType(),
is_premultiplied ? kPremul_SkAlphaType : kUnpremul_SkAlphaType,
color_params.GetSkColorSpace());
SkPixmap pixmap(info, pixels, info.minRowBytes());
return MakeGarbageCollected<ImageBitmap>(pixmap, origin_clean);
}
......@@ -434,10 +428,9 @@ ScriptWrappable* V8ScriptValueDeserializer::ReadDOMObject(
return nullptr;
}
SerializedColorParams color_params(
canvas_color_space, SerializedPixelFormat::kNative8_LegacyObsolete,
SerializedOpacityMode::kNonOpaque, image_data_storage_format);
ImageDataStorageFormat storage_format = color_params.GetStorageFormat();
SerializedImageDataSettings settings(canvas_color_space,
image_data_storage_format);
ImageDataStorageFormat storage_format = settings.GetStorageFormat();
base::CheckedNumeric<size_t> computed_byte_length = width;
computed_byte_length *= height;
computed_byte_length *=
......@@ -446,7 +439,7 @@ ScriptWrappable* V8ScriptValueDeserializer::ReadDOMObject(
computed_byte_length.ValueOrDie() != byte_length)
return nullptr;
ImageData* image_data = ImageData::Create(
IntSize(width, height), color_params.GetColorSpace(), storage_format);
IntSize(width, height), settings.GetColorSpace(), storage_format);
if (!image_data)
return nullptr;
DOMArrayBufferBase* pixel_buffer = image_data->BufferBase();
......
......@@ -305,7 +305,7 @@ bool V8ScriptValueSerializer::WriteDOMObject(ScriptWrappable* wrappable,
}
WriteTag(kImageBitmapTag);
SkImageInfo info = image_bitmap->GetBitmapSkImageInfo();
SerializedColorParams color_params((CanvasColorParams(info)));
SerializedImageBitmapSettings color_params(info);
WriteUint32Enum(ImageSerializationTag::kCanvasColorSpaceTag);
WriteUint32Enum(color_params.GetSerializedColorSpace());
WriteUint32Enum(ImageSerializationTag::kCanvasPixelFormatTag);
......@@ -315,7 +315,7 @@ bool V8ScriptValueSerializer::WriteDOMObject(ScriptWrappable* wrappable,
WriteUint32Enum(ImageSerializationTag::kOriginCleanTag);
WriteUint32(image_bitmap->OriginClean());
WriteUint32Enum(ImageSerializationTag::kIsPremultipliedTag);
WriteUint32(image_bitmap->IsPremultiplied());
WriteUint32(color_params.IsPremultiplied());
WriteUint32Enum(ImageSerializationTag::kEndTag);
WriteUint32(image_bitmap->width());
WriteUint32(image_bitmap->height());
......@@ -335,12 +335,13 @@ bool V8ScriptValueSerializer::WriteDOMObject(ScriptWrappable* wrappable,
if (wrapper_type_info == V8ImageData::GetWrapperTypeInfo()) {
ImageData* image_data = wrappable->ToImpl<ImageData>();
WriteTag(kImageDataTag);
SerializedColorParams color_params(image_data->GetCanvasColorSpace(),
image_data->GetImageDataStorageFormat());
SerializedImageDataSettings settings(
image_data->GetCanvasColorSpace(),
image_data->GetImageDataStorageFormat());
WriteUint32Enum(ImageSerializationTag::kCanvasColorSpaceTag);
WriteUint32Enum(color_params.GetSerializedColorSpace());
WriteUint32Enum(settings.GetSerializedColorSpace());
WriteUint32Enum(ImageSerializationTag::kImageDataStorageFormatTag);
WriteUint32Enum(color_params.GetSerializedImageDataStorageFormat());
WriteUint32Enum(settings.GetSerializedImageDataStorageFormat());
WriteUint32Enum(ImageSerializationTag::kEndTag);
WriteUint32(image_data->width());
WriteUint32(image_data->height());
......
......@@ -43,6 +43,27 @@ sk_sp<SkColorSpace> CanvasColorSpaceToSkColorSpace(
return CanvasColorSpaceToGfxColorSpace(color_space).ToSkColorSpace();
}
CanvasColorSpace CanvasColorSpaceFromSkColorSpace(
const SkColorSpace* sk_color_space) {
// TODO(https://crbug.com/1121448): This function returns sRGB if
// |sk_color_space| does not exactly match one of the named color spaces. It
// should find the best named match.
CanvasColorSpace color_spaces[] = {
CanvasColorSpace::kSRGB,
CanvasColorSpace::kRec2020,
CanvasColorSpace::kP3,
};
for (const auto& color_space : color_spaces) {
if (SkColorSpace::Equals(sk_color_space,
CanvasColorSpaceToGfxColorSpace(color_space)
.ToSkColorSpace()
.get())) {
return color_space;
}
}
return CanvasColorSpace::kSRGB;
}
CanvasColorSpace CanvasColorSpaceFromName(const String& color_space_name) {
if (color_space_name == kRec2020CanvasColorSpaceName)
return CanvasColorSpace::kRec2020;
......@@ -184,24 +205,9 @@ viz::ResourceFormat CanvasColorParams::TransferableResourceFormat() const {
CanvasColorParams::CanvasColorParams(const sk_sp<SkColorSpace> sk_color_space,
SkColorType sk_color_type) {
color_space_ = CanvasColorSpace::kSRGB;
color_space_ = CanvasColorSpaceFromSkColorSpace(sk_color_space.get());
pixel_format_ = GetNativeCanvasPixelFormat();
CanvasColorSpace color_spaces[] = {
CanvasColorSpace::kSRGB,
CanvasColorSpace::kRec2020,
CanvasColorSpace::kP3,
};
for (const auto& color_space : color_spaces) {
if (SkColorSpace::Equals(sk_color_space.get(),
CanvasColorSpaceToGfxColorSpace(color_space)
.ToSkColorSpace()
.get())) {
color_space_ = color_space;
break;
}
}
if (sk_color_type == kRGBA_F16_SkColorType)
pixel_format_ = CanvasPixelFormat::kF16;
else if (sk_color_type == kRGBA_8888_SkColorType)
......
......@@ -50,6 +50,10 @@ CanvasColorSpaceFromName(const String& color_space_name);
sk_sp<SkColorSpace> PLATFORM_EXPORT
CanvasColorSpaceToSkColorSpace(CanvasColorSpace color_space);
// Return the named CanvasColorSpace that best matches |sk_color_space|.
CanvasColorSpace PLATFORM_EXPORT
CanvasColorSpaceFromSkColorSpace(const SkColorSpace* sk_color_space);
class PLATFORM_EXPORT CanvasColorParams {
DISALLOW_NEW();
......
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