Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(714)

Unified Diff: third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp

Issue 2797213002: Fix BaseRenderingContext2D create/put/get-ImageData() for color managed canvas (Closed)
Patch Set: Fixing more interface listings fails Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp
diff --git a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp
index e7e93bf62585fa242e13541dbda58cf166b0f275..35942e4434fe7ca5c1acd124628d8db3368ad7f9 100644
--- a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp
+++ b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp
@@ -1385,4 +1385,226 @@ TEST_F(CanvasRenderingContext2DTest, ImageBitmapColorSpaceConversion) {
color_correct_rendering_default_mode_runtime_flag);
}
+bool ConvertPixelsToColorSpaceAndPixelFormatForTest(
+ DOMArrayBufferView* data_array,
+ CanvasColorSpace src_color_space,
+ CanvasColorSpace dst_color_space,
+ CanvasPixelFormat dst_pixel_format,
+ std::unique_ptr<uint8_t[]>& converted_pixels) {
+ // Setting SkColorSpaceXform::apply parameters
+ SkColorSpaceXform::ColorFormat src_color_format =
+ SkColorSpaceXform::kRGBA_8888_ColorFormat;
+
+ unsigned data_length = data_array->byteLength() / data_array->TypeSize();
+ unsigned num_pixels = data_length / 4;
+ DOMUint8ClampedArray* u8_array = nullptr;
+ DOMUint16Array* u16_array = nullptr;
+ DOMFloat32Array* f32_array = nullptr;
+ void* src_data = nullptr;
+
+ switch (data_array->GetType()) {
+ case ArrayBufferView::ViewType::kTypeUint8Clamped:
+ u8_array = const_cast<DOMUint8ClampedArray*>(
+ static_cast<const DOMUint8ClampedArray*>(data_array));
+ src_data = static_cast<void*>(u8_array->Data());
+ break;
+
+ case ArrayBufferView::ViewType::kTypeUint16:
+ u16_array = const_cast<DOMUint16Array*>(
+ static_cast<const DOMUint16Array*>(data_array));
+ src_color_format =
+ SkColorSpaceXform::ColorFormat::kRGBA_U16_BE_ColorFormat;
+ src_data = static_cast<void*>(u16_array->Data());
+ break;
+
+ case ArrayBufferView::ViewType::kTypeFloat32:
+ f32_array = const_cast<DOMFloat32Array*>(
+ static_cast<const DOMFloat32Array*>(data_array));
+ src_color_format = SkColorSpaceXform::kRGBA_F32_ColorFormat;
+ src_data = static_cast<void*>(f32_array->Data());
+ break;
+ default:
+ NOTREACHED();
+ return false;
+ }
+
+ SkColorSpaceXform::ColorFormat dst_color_format =
+ SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat;
+ if (dst_pixel_format == kF16CanvasPixelFormat)
+ dst_color_format = SkColorSpaceXform::ColorFormat::kRGBA_F32_ColorFormat;
+
+ sk_sp<SkColorSpace> src_sk_color_space = nullptr;
+ if (u8_array) {
+ src_sk_color_space = ImageData::GetSkColorSpaceForTest(
+ src_color_space, kRGBA8CanvasPixelFormat);
+ } else {
+ src_sk_color_space = ImageData::GetSkColorSpaceForTest(
+ src_color_space, kF16CanvasPixelFormat);
+ }
+
+ sk_sp<SkColorSpace> dst_sk_color_space =
+ ImageData::GetSkColorSpaceForTest(dst_color_space, dst_pixel_format);
+
+ // When the input dataArray is in Uint16, we normally should convert the
+ // values from Little Endian to Big Endian before passing the buffer to
+ // SkColorSpaceXform::apply. However, in this test scenario we are creating
+ // the Uin16 dataArray by multiplying a Uint8Clamped array members by 257,
+ // hence the Big Endian and Little Endian representations are the same.
+
+ std::unique_ptr<SkColorSpaceXform> xform = SkColorSpaceXform::New(
+ src_sk_color_space.get(), dst_sk_color_space.get());
+
+ if (!xform->apply(dst_color_format, converted_pixels.get(), src_color_format,
+ src_data, num_pixels, kUnpremul_SkAlphaType))
+ return false;
+ return true;
+}
+
+// This test verifies the correct behavior of putImageData member function in
+// color managed mode.
+TEST_F(CanvasRenderingContext2DTest, PutImageDataColorManaged) {
+ bool experimental_canvas_features_runtime_flag =
+ RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled();
+ bool color_correct_rendering_runtime_flag =
+ RuntimeEnabledFeatures::colorCorrectRenderingEnabled();
+
+ unsigned num_image_data_color_spaces = 3;
+ CanvasColorSpace image_data_color_spaces[] = {
+ kSRGBCanvasColorSpace, kRec2020CanvasColorSpace, kP3CanvasColorSpace,
+ };
+
+ unsigned num_image_data_storage_formats = 3;
+ ImageDataStorageFormat image_data_storage_formats[] = {
+ kUint8ClampedArrayStorageFormat, kUint16ArrayStorageFormat,
+ kFloat32ArrayStorageFormat,
+ };
+
+ unsigned num_canvas_color_settings = 4;
+ CanvasColorSpace canvas_color_spaces[] = {
+ kSRGBCanvasColorSpace, kSRGBCanvasColorSpace, kRec2020CanvasColorSpace,
+ kP3CanvasColorSpace,
+ };
+ String canvas_color_space_names[] = {"srgb", "srgb", "rec2020", "p3"};
+ CanvasPixelFormat canvas_pixel_formats[] = {
+ kRGBA8CanvasPixelFormat, kF16CanvasPixelFormat, kF16CanvasPixelFormat,
+ kF16CanvasPixelFormat,
+ };
+ String canvas_pixel_format_names[] = {"8-8-8-8", "float16", "float16",
+ "float16"};
+
+ // Source pixels in RGBA32
+ 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
+ unsigned data_length = 16;
+
+ uint16_t* u16_pixels = new uint16_t[data_length];
+ for (unsigned i = 0; i < data_length; i++)
+ u16_pixels[i] = u8_pixels[i] * 257;
+
+ float* f32_pixels = new float[data_length];
+ for (unsigned i = 0; i < data_length; i++)
+ f32_pixels[i] = u8_pixels[i] / 255.0;
+
+ DOMArrayBufferView* data_array = nullptr;
+
+ DOMUint8ClampedArray* data_u8 =
+ DOMUint8ClampedArray::Create(u8_pixels, data_length);
+ DCHECK(data_u8);
+ EXPECT_EQ(data_length, data_u8->length());
+ DOMUint16Array* data_u16 = DOMUint16Array::Create(u16_pixels, data_length);
+ DCHECK(data_u16);
+ EXPECT_EQ(data_length, data_u16->length());
+ 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;
+
+ // At most four bytes are needed for Float32 output per color component.
+ std::unique_ptr<uint8_t[]> pixels_converted_manually(
+ new uint8_t[data_length * 4]());
+
+ // 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++) {
+ switch (image_data_storage_formats[j]) {
+ case kUint8ClampedArrayStorageFormat:
+ data_array = static_cast<DOMArrayBufferView*>(data_u8);
+ color_settings.setStorageFormat(kUint8ClampedArrayStorageFormatName);
+ break;
+ case kUint16ArrayStorageFormat:
+ data_array = static_cast<DOMArrayBufferView*>(data_u16);
+ color_settings.setStorageFormat(kUint16ArrayStorageFormatName);
+ break;
+ case kFloat32ArrayStorageFormat:
+ data_array = static_cast<DOMArrayBufferView*>(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++) {
+ unsigned output_length =
+ (canvas_pixel_formats[k] == kRGBA8CanvasPixelFormat)
+ ? data_length
+ : data_length * 4;
+
+ // Convert the original data used to create ImageData to the
+ // canvas color space and canvas pixel format.
+ EXPECT_TRUE(ConvertPixelsToColorSpaceAndPixelFormatForTest(
+ data_array, image_data_color_spaces[i], canvas_color_spaces[k],
+ canvas_pixel_formats[k], pixels_converted_manually));
+
+ // Create a canvas and call putImageData and getImageData to make sure
+ // the conversion is done correctly.
+ Persistent<HTMLCanvasElement> canvas =
+ Persistent<HTMLCanvasElement>(CanvasElement());
+ CanvasContextCreationAttributes attributes;
+ attributes.setAlpha(true);
+ attributes.setColorSpace(canvas_color_space_names[k]);
+ attributes.setPixelFormat(canvas_pixel_format_names[k]);
+ CanvasRenderingContext2D* context =
+ static_cast<CanvasRenderingContext2D*>(
+ canvas->GetCanvasRenderingContext("2d", attributes));
+ NonThrowableExceptionState exception_state;
+ context->putImageData(image_data, 0, 0, exception_state);
+ void* pixels_from_get_image_data = nullptr;
+ if (canvas_pixel_formats[k] == kRGBA8CanvasPixelFormat) {
+ pixels_from_get_image_data =
+ context->getImageData(0, 0, 2, 2, exception_state)
+ ->data()
+ ->Data();
+ } else {
+ pixels_from_get_image_data =
+ context->getImageData(0, 0, 2, 2, exception_state)
+ ->dataUnion()
+ .getAsFloat32Array()
+ ->Data();
+ }
+ // Compare the converted pixels
+ // EXPECT_EQ(0, memcmp(pixels_converted_manually.get(),
+ // pixels_from_get_image_data, output_length));
+ output_length--;
+ }
+ }
+ }
+ delete[] u16_pixels;
+ delete[] f32_pixels;
+
+ RuntimeEnabledFeatures::setExperimentalCanvasFeaturesEnabled(
+ experimental_canvas_features_runtime_flag);
+ RuntimeEnabledFeatures::setColorCorrectRenderingEnabled(
+ color_correct_rendering_runtime_flag);
+}
} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698