Commit 267cb8af authored by Reza.Zakerinasab's avatar Reza.Zakerinasab Committed by Commit Bot

Remove SkColorSpaceXform usage from Canvas code

This is the last CL to remove SkColorSpaceXform call sites from
third_party/blink. This change also does some refactoring in
ImageBitmap unit tests, etc.

TBR=fserb@chromium.org

Bug: 774520
Cq-Include-Trybots: luci.chromium.try:linux_layout_tests_slimming_paint_v2;luci.chromium.try:win_optional_gpu_tests_rel;master.tryserver.blink:linux_trusty_blink_rel
Change-Id: I8279f1687ef096ae9aa2179c74d5d6cf2364ce9b
Reviewed-on: https://chromium-review.googlesource.com/1237140Reviewed-by: default avatarMohammad Reza Zakerinasab <zakerinasab@chromium.org>
Reviewed-by: default avatarMike Klein <mtklein@chromium.org>
Commit-Queue: Mohammad Reza Zakerinasab <zakerinasab@chromium.org>
Cr-Commit-Position: refs/heads/master@{#593674}
parent 1147ea0f
......@@ -23,7 +23,6 @@
#include "third_party/blink/renderer/platform/web_task_runner.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/blink/renderer/platform/wtf/time.h"
#include "third_party/skia/include/core/SkColorSpaceXform.h"
#include "third_party/skia/include/core/SkSurface.h"
namespace blink {
......@@ -234,42 +233,36 @@ CanvasAsyncBlobCreator::CanvasAsyncBlobCreator(
skia_image = SkImage::MakeFromRaster(src_data_, nullptr, nullptr);
}
DCHECK(skia_image->colorSpace());
skia_image = skia_image->makeColorSpace(blob_color_space);
image_ = StaticBitmapImage::Create(skia_image);
image_ = image_->ConvertToColorSpace(blob_color_space,
skia_image->colorType());
skia_image = image_->PaintImageForCurrentFrame().GetSkImage();
}
if (skia_image->peekPixels(&src_data_))
if (skia_image->peekPixels(&src_data_)) {
static_bitmap_image_loaded_ = true;
// If the source image is 8 bit per channel but the blob is requested in
// 16 bpc PNG, we need to ensure the color type of the pixmap is
// kRGBA_F16_SkColorType to kick in 16 bit encoding in SkPngEncoder. Since
// SkPixmap only holds a pointer to data, we need a helper data member here.
if (mime_type_ == kMimeTypePng &&
encode_options_.pixelFormat() == kRGBA16ImagePixelFormatName &&
src_data_.colorType() == kN32_SkColorType) {
size_t data_length = src_data_.width() * src_data_.height() *
SkColorTypeBytesPerPixel(kRGBA_F16_SkColorType);
png_16bit_data_helper_ = SkData::MakeUninitialized(data_length);
SkColorSpaceXform::ColorFormat src_format =
SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat;
if (kN32_SkColorType == kBGRA_8888_SkColorType)
src_format = SkColorSpaceXform::ColorFormat::kBGRA_8888_ColorFormat;
if (SkColorSpaceXform::Apply(
src_data_.colorSpace(),
SkColorSpaceXform::ColorFormat::kRGBA_F16_ColorFormat,
png_16bit_data_helper_->writable_data(), src_data_.colorSpace(),
src_format, src_data_.addr(),
src_data_.width() * src_data_.height(),
SkColorSpaceXform::AlphaOp::kPreserve_AlphaOp)) {
// If the source image is 8 bit per channel but the blob is requested in
// 16 bpc PNG, we need to ensure the color type of the pixmap is
// kRGBA_F16_SkColorType to kick in 16 bit encoding in SkPngEncoder. Since
// SkPixmap only holds a pointer to data, we need a helper data member
// here.
if (mime_type_ == kMimeTypePng &&
encode_options_.pixelFormat() == kRGBA16ImagePixelFormatName &&
src_data_.colorType() == kN32_SkColorType) {
size_t data_length = src_data_.width() * src_data_.height() *
SkColorTypeBytesPerPixel(kRGBA_F16_SkColorType);
png_16bit_data_helper_ = SkData::MakeUninitialized(data_length);
SkImageInfo info = SkImageInfo::Make(
src_data_.width(), src_data_.height(), kRGBA_F16_SkColorType,
src_data_.alphaType(), src_data_.info().refColorSpace());
src_data_.reset(info, png_16bit_data_helper_->data(),
info.minRowBytes());
SkPixmap src_data_f16(info, png_16bit_data_helper_->data(),
info.minRowBytes());
src_data_.readPixels(src_data_f16);
src_data_ = src_data_f16;
skia_image = SkImage::MakeFromRaster(src_data_, nullptr, nullptr);
image_ = StaticBitmapImage::Create(skia_image);
}
skia_image = SkImage::MakeFromRaster(src_data_, nullptr, nullptr);
image_ = StaticBitmapImage::Create(skia_image);
}
}
......
......@@ -265,8 +265,6 @@ TEST_F(CanvasAsyncBlobCreatorTest, ColorManagedConvertToBlob) {
// The maximum difference locally observed is 3.
const unsigned uint8_color_tolerance = 5;
const float f16_color_tolerance = 0.01;
// The maximum difference locally observed has the order of e^-6.
const float xyz_d50_color_space_component_tolerance = 0.001;
for (auto color_space_param : color_space_params) {
for (auto blob_mime_type : blob_mime_types) {
......@@ -306,8 +304,7 @@ TEST_F(CanvasAsyncBlobCreatorTest, ColorManagedConvertToBlob) {
bool compare_alpha = (blob_mime_type != "image/jpeg");
ASSERT_TRUE(ColorCorrectionTestUtils::MatchSkImages(
ref_image, decoded_img, uint8_color_tolerance,
f16_color_tolerance, xyz_d50_color_space_component_tolerance,
compare_alpha));
f16_color_tolerance, compare_alpha));
}
}
}
......
......@@ -312,47 +312,6 @@ TEST_F(ImageBitmapTest, AvoidGPUReadback) {
}
}
enum class ColorSpaceConversion : uint8_t {
NONE = 0,
DEFAULT_COLOR_CORRECTED = 1,
PRESERVE = 2,
SRGB = 3,
LINEAR_RGB = 4,
P3 = 5,
REC2020 = 6,
LAST = REC2020
};
static ImageBitmapOptions PrepareBitmapOptions(
const ColorSpaceConversion& color_space_conversion) {
// Set the color space conversion in ImageBitmapOptions
ImageBitmapOptions options;
static const Vector<String> kConversions = {
"none", "default", "preserve", "srgb", "linear-rgb", "p3", "rec2020"};
options.setColorSpaceConversion(
kConversions[static_cast<uint8_t>(color_space_conversion)]);
return options;
}
static sk_sp<SkColorSpace> GetColorSpaceForColorSpaceConversion(
ColorSpaceConversion conversion) {
sk_sp<SkColorSpace> color_space = nullptr;
if (conversion == ColorSpaceConversion::DEFAULT_COLOR_CORRECTED ||
conversion == ColorSpaceConversion::SRGB) {
color_space = SkColorSpace::MakeSRGB();
} else if (conversion == ColorSpaceConversion::LINEAR_RGB) {
color_space = SkColorSpace::MakeSRGBLinear();
} else if (conversion == ColorSpaceConversion::P3) {
color_space = SkColorSpace::MakeRGB(SkColorSpace::kLinear_RenderTargetGamma,
SkColorSpace::kDCIP3_D65_Gamut);
} else if (conversion == ColorSpaceConversion::REC2020) {
color_space = SkColorSpace::MakeRGB(SkColorSpace::kLinear_RenderTargetGamma,
SkColorSpace::kRec2020_Gamut);
}
return color_space;
}
TEST_F(ImageBitmapTest, ImageBitmapColorSpaceConversionHTMLImageElement) {
HTMLImageElement* image_element =
HTMLImageElement::Create(*Document::CreateForTest());
......@@ -377,13 +336,13 @@ TEST_F(ImageBitmapTest, ImageBitmapColorSpaceConversionHTMLImageElement) {
base::Optional<IntRect> crop_rect =
IntRect(0, 0, source_image->width(), source_image->height());
for (uint8_t i =
static_cast<uint8_t>(ColorSpaceConversion::DEFAULT_COLOR_CORRECTED);
i <= static_cast<uint8_t>(ColorSpaceConversion::LAST); i++) {
ColorSpaceConversion color_space_conversion =
static_cast<ColorSpaceConversion>(i);
ImageBitmapOptions options =
PrepareBitmapOptions(color_space_conversion);
for (int conversion_iterator = ColorSpaceConversion::kDefault;
conversion_iterator <= ColorSpaceConversion::kLast;
conversion_iterator++) {
ImageBitmapOptions options;
options.setColorSpaceConversion(
ColorCorrectionTestUtils::ColorSpaceConversionToString(
static_cast<ColorSpaceConversion>(conversion_iterator)));
ImageBitmap* image_bitmap = ImageBitmap::Create(
image_element, crop_rect, &(image_element->GetDocument()), options);
ASSERT_TRUE(image_bitmap);
......@@ -393,7 +352,7 @@ TEST_F(ImageBitmapTest, ImageBitmapColorSpaceConversionHTMLImageElement) {
converted_image->peekPixels(&converted_pixmap);
unsigned num_pixels = source_image->width() * source_image->height();
if (color_space_conversion == ColorSpaceConversion::PRESERVE) {
if (conversion_iterator == ColorSpaceConversion::kPreserve) {
EXPECT_TRUE(
SkColorSpace::Equals(colorspin.get(), converted_image->colorSpace()));
ColorCorrectionTestUtils::CompareColorCorrectedPixels(
......@@ -401,7 +360,8 @@ TEST_F(ImageBitmapTest, ImageBitmapColorSpaceConversionHTMLImageElement) {
kPixelFormat_8888, kAlphaMultiplied, kUnpremulRoundTripTolerance);
} else {
sk_sp<SkColorSpace> color_space =
GetColorSpaceForColorSpaceConversion(color_space_conversion);
ColorCorrectionTestUtils::ColorSpaceConversionToSkColorSpace(
static_cast<ColorSpaceConversion>(conversion_iterator));
EXPECT_TRUE(SkColorSpace::Equals(color_space.get(),
converted_image->colorSpace()));
......@@ -412,8 +372,7 @@ TEST_F(ImageBitmapTest, ImageBitmapColorSpaceConversionHTMLImageElement) {
expected_image_info.makeColorType(kRGBA_F16_SkColorType);
}
SkBitmap expected_bitmap;
EXPECT_TRUE(expected_bitmap.tryAllocPixels(
expected_image_info, expected_image_info.minRowBytes()));
EXPECT_TRUE(expected_bitmap.tryAllocPixels(expected_image_info));
source_image->readPixels(expected_bitmap.pixmap(), 0, 0);
ColorCorrectionTestUtils::CompareColorCorrectedPixels(
......@@ -439,18 +398,20 @@ TEST_F(ImageBitmapTest, ImageBitmapColorSpaceConversionImageBitmap) {
base::Optional<IntRect> crop_rect =
IntRect(0, 0, source_image->width(), source_image->height());
ImageBitmapOptions options =
PrepareBitmapOptions(ColorSpaceConversion::PRESERVE);
ImageBitmapOptions options;
options.setColorSpaceConversion(
ColorCorrectionTestUtils::ColorSpaceConversionToString(
ColorSpaceConversion::kPreserve));
ImageBitmap* source_image_bitmap = ImageBitmap::Create(
StaticBitmapImage::Create(source_image), crop_rect, options);
ASSERT_TRUE(source_image_bitmap);
for (uint8_t i =
static_cast<uint8_t>(ColorSpaceConversion::DEFAULT_COLOR_CORRECTED);
i <= static_cast<uint8_t>(ColorSpaceConversion::LAST); i++) {
ColorSpaceConversion color_space_conversion =
static_cast<ColorSpaceConversion>(i);
options = PrepareBitmapOptions(color_space_conversion);
for (int conversion_iterator = ColorSpaceConversion::kDefault;
conversion_iterator <= ColorSpaceConversion::kLast;
conversion_iterator++) {
options.setColorSpaceConversion(
ColorCorrectionTestUtils::ColorSpaceConversionToString(
static_cast<ColorSpaceConversion>(conversion_iterator)));
ImageBitmap* image_bitmap =
ImageBitmap::Create(source_image_bitmap, crop_rect, options);
ASSERT_TRUE(image_bitmap);
......@@ -460,7 +421,7 @@ TEST_F(ImageBitmapTest, ImageBitmapColorSpaceConversionImageBitmap) {
converted_image->peekPixels(&converted_pixmap);
unsigned num_pixels = source_image->width() * source_image->height();
if (color_space_conversion == ColorSpaceConversion::PRESERVE) {
if (conversion_iterator == ColorSpaceConversion::kPreserve) {
EXPECT_TRUE(
SkColorSpace::Equals(colorspin.get(), converted_image->colorSpace()));
ColorCorrectionTestUtils::CompareColorCorrectedPixels(
......@@ -468,7 +429,8 @@ TEST_F(ImageBitmapTest, ImageBitmapColorSpaceConversionImageBitmap) {
kPixelFormat_8888, kAlphaMultiplied, kUnpremulRoundTripTolerance);
} else {
sk_sp<SkColorSpace> color_space =
GetColorSpaceForColorSpaceConversion(color_space_conversion);
ColorCorrectionTestUtils::ColorSpaceConversionToSkColorSpace(
static_cast<ColorSpaceConversion>(conversion_iterator));
EXPECT_TRUE(SkColorSpace::Equals(color_space.get(),
converted_image->colorSpace()));
......@@ -479,8 +441,7 @@ TEST_F(ImageBitmapTest, ImageBitmapColorSpaceConversionImageBitmap) {
expected_image_info.makeColorType(kRGBA_F16_SkColorType);
}
SkBitmap expected_bitmap;
EXPECT_TRUE(expected_bitmap.tryAllocPixels(
expected_image_info, expected_image_info.minRowBytes()));
EXPECT_TRUE(expected_bitmap.tryAllocPixels(expected_image_info));
source_image->readPixels(expected_bitmap.pixmap(), 0, 0);
ColorCorrectionTestUtils::CompareColorCorrectedPixels(
......@@ -507,13 +468,13 @@ TEST_F(ImageBitmapTest, ImageBitmapColorSpaceConversionStaticBitmapImage) {
base::Optional<IntRect> crop_rect =
IntRect(0, 0, source_image->width(), source_image->height());
for (uint8_t i =
static_cast<uint8_t>(ColorSpaceConversion::DEFAULT_COLOR_CORRECTED);
i <= static_cast<uint8_t>(ColorSpaceConversion::LAST); i++) {
ColorSpaceConversion color_space_conversion =
static_cast<ColorSpaceConversion>(i);
ImageBitmapOptions options =
PrepareBitmapOptions(color_space_conversion);
for (int conversion_iterator = ColorSpaceConversion::kDefault;
conversion_iterator <= ColorSpaceConversion::kLast;
conversion_iterator++) {
ImageBitmapOptions options;
options.setColorSpaceConversion(
ColorCorrectionTestUtils::ColorSpaceConversionToString(
static_cast<ColorSpaceConversion>(conversion_iterator)));
ImageBitmap* image_bitmap = ImageBitmap::Create(
StaticBitmapImage::Create(source_image), crop_rect, options);
ASSERT_TRUE(image_bitmap);
......@@ -523,7 +484,7 @@ TEST_F(ImageBitmapTest, ImageBitmapColorSpaceConversionStaticBitmapImage) {
converted_image->peekPixels(&converted_pixmap);
unsigned num_pixels = source_image->width() * source_image->height();
if (color_space_conversion == ColorSpaceConversion::PRESERVE) {
if (conversion_iterator == ColorSpaceConversion::kPreserve) {
EXPECT_TRUE(
SkColorSpace::Equals(colorspin.get(), converted_image->colorSpace()));
ColorCorrectionTestUtils::CompareColorCorrectedPixels(
......@@ -531,7 +492,8 @@ TEST_F(ImageBitmapTest, ImageBitmapColorSpaceConversionStaticBitmapImage) {
kPixelFormat_8888, kAlphaMultiplied, kUnpremulRoundTripTolerance);
} else {
sk_sp<SkColorSpace> color_space =
GetColorSpaceForColorSpaceConversion(color_space_conversion);
ColorCorrectionTestUtils::ColorSpaceConversionToSkColorSpace(
static_cast<ColorSpaceConversion>(conversion_iterator));
EXPECT_TRUE(SkColorSpace::Equals(color_space.get(),
converted_image->colorSpace()));
......@@ -542,8 +504,7 @@ TEST_F(ImageBitmapTest, ImageBitmapColorSpaceConversionStaticBitmapImage) {
expected_image_info.makeColorType(kRGBA_F16_SkColorType);
}
SkBitmap expected_bitmap;
EXPECT_TRUE(expected_bitmap.tryAllocPixels(
expected_image_info, expected_image_info.minRowBytes()));
EXPECT_TRUE(expected_bitmap.tryAllocPixels(expected_image_info));
source_image->readPixels(expected_bitmap.pixmap(), 0, 0);
ColorCorrectionTestUtils::CompareColorCorrectedPixels(
......@@ -565,21 +526,20 @@ TEST_F(ImageBitmapTest, ImageBitmapColorSpaceConversionImageData) {
SkImageInfo::Make(1, 1, kRGBA_8888_SkColorType, kUnpremul_SkAlphaType,
SkColorSpace::MakeSRGB());
SkBitmap source_bitmap;
EXPECT_TRUE(
source_bitmap.tryAllocPixels(image_info, image_info.minRowBytes()));
EXPECT_TRUE(source_bitmap.tryAllocPixels(image_info));
SkPixmap source_pixmap;
source_pixmap = source_bitmap.pixmap();
memcpy(source_pixmap.writable_addr(), image_data->BufferBase()->Data(), 4);
base::Optional<IntRect> crop_rect = IntRect(0, 0, 1, 1);
for (uint8_t i =
static_cast<uint8_t>(ColorSpaceConversion::DEFAULT_COLOR_CORRECTED);
i <= static_cast<uint8_t>(ColorSpaceConversion::LAST); i++) {
ColorSpaceConversion color_space_conversion =
static_cast<ColorSpaceConversion>(i);
ImageBitmapOptions options =
PrepareBitmapOptions(color_space_conversion);
for (int conversion_iterator = ColorSpaceConversion::kDefault;
conversion_iterator <= ColorSpaceConversion::kLast;
conversion_iterator++) {
ImageBitmapOptions options;
options.setColorSpaceConversion(
ColorCorrectionTestUtils::ColorSpaceConversionToString(
static_cast<ColorSpaceConversion>(conversion_iterator)));
ImageBitmap* image_bitmap =
ImageBitmap::Create(image_data, crop_rect, options);
ASSERT_TRUE(image_bitmap);
......@@ -589,13 +549,12 @@ TEST_F(ImageBitmapTest, ImageBitmapColorSpaceConversionImageData) {
converted_image->peekPixels(&converted_pixmap);
unsigned num_pixels = converted_image->width() * converted_image->height();
if (color_space_conversion == ColorSpaceConversion::PRESERVE) {
if (conversion_iterator == ColorSpaceConversion::kPreserve) {
// crbug.com/886999
// EXPECT_TRUE(SkColorSpace::Equals(SkColorSpace::MakeSRGB().get(),
// converted_image->colorSpace()));
SkBitmap expected_bitmap;
EXPECT_TRUE(expected_bitmap.tryAllocPixels(
converted_pixmap.info(), converted_pixmap.info().minRowBytes()));
EXPECT_TRUE(expected_bitmap.tryAllocPixels(converted_pixmap.info()));
source_pixmap.readPixels(expected_bitmap.pixmap(), 0, 0);
ColorCorrectionTestUtils::CompareColorCorrectedPixels(
......@@ -603,13 +562,13 @@ TEST_F(ImageBitmapTest, ImageBitmapColorSpaceConversionImageData) {
kPixelFormat_8888, kAlphaMultiplied, kUnpremulRoundTripTolerance);
} else {
sk_sp<SkColorSpace> color_space =
GetColorSpaceForColorSpaceConversion(color_space_conversion);
ColorCorrectionTestUtils::ColorSpaceConversionToSkColorSpace(
static_cast<ColorSpaceConversion>(conversion_iterator));
// crbug.com/886999
// EXPECT_TRUE(SkColorSpace::Equals(color_space.get(),
// converted_image->colorSpace()));
SkBitmap expected_bitmap;
EXPECT_TRUE(expected_bitmap.tryAllocPixels(
converted_pixmap.info(), converted_pixmap.info().minRowBytes()));
EXPECT_TRUE(expected_bitmap.tryAllocPixels(converted_pixmap.info()));
source_pixmap.readPixels(expected_bitmap.pixmap(), 0, 0);
ColorCorrectionTestUtils::CompareColorCorrectedPixels(
......@@ -699,12 +658,13 @@ TEST_F(ImageBitmapTest,
ImageData* image_data =
ImageData::CreateForTest(IntSize(v8::TypedArray::kMaxLength / 16, 1));
DCHECK(image_data);
ImageBitmapOptions options =
PrepareBitmapOptions(ColorSpaceConversion::DEFAULT_COLOR_CORRECTED);
ImageBitmapOptions options;
options.setColorSpaceConversion(
ColorCorrectionTestUtils::ColorSpaceConversionToString(
ColorSpaceConversion::kDefault));
ImageBitmap* image_bitmap = ImageBitmap::Create(
image_data, IntRect(IntPoint(0, 0), image_data->Size()), options);
DCHECK(image_bitmap);
}
#undef MAYBE_ImageBitmapColorSpaceConversionHTMLImageElement
} // namespace blink
......@@ -35,10 +35,8 @@
#include "third_party/blink/renderer/platform/graphics/test/fake_web_graphics_context_3d_provider.h"
#include "third_party/blink/renderer/platform/loader/fetch/memory_cache.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
#include "third_party/skia/include/core/SkColorSpaceXform.h"
#include "third_party/skia/include/core/SkImage.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/core/SkSwizzle.h"
using testing::_;
using testing::InSequence;
......@@ -811,29 +809,6 @@ TEST_F(CanvasRenderingContext2DTest,
Mock::VerifyAndClearExpectations(surface_ptr);
}
enum class ColorSpaceConversion : uint8_t {
NONE = 0,
DEFAULT_COLOR_CORRECTED = 1,
SRGB = 2,
LINEAR_RGB = 3,
P3 = 4,
REC2020 = 5,
LAST = REC2020
};
static ImageBitmapOptions PrepareBitmapOptionsAndSetRuntimeFlags(
const ColorSpaceConversion& color_space_conversion) {
// Set the color space conversion in ImageBitmapOptions
ImageBitmapOptions options;
static const Vector<String> kConversions = {
"none", "default", "srgb", "linear-rgb", "p3", "rec2020"};
options.setColorSpaceConversion(
kConversions[static_cast<uint8_t>(color_space_conversion)]);
return options;
}
TEST_F(CanvasRenderingContext2DTest, ImageBitmapColorSpaceConversion) {
Persistent<HTMLCanvasElement> canvas =
Persistent<HTMLCanvasElement>(CanvasElement());
......@@ -845,89 +820,62 @@ TEST_F(CanvasRenderingContext2DTest, ImageBitmapColorSpaceConversion) {
StringOrCanvasGradientOrCanvasPattern fill_style;
fill_style.SetString("#FFC08040"); // 255,192,128,64
context->setFillStyle(fill_style);
context->fillRect(0, 0, 4, 4);
NonThrowableExceptionState exception_state;
uint8_t* src_pixel =
context->getImageData(2, 2, 1, 1, exception_state)->data()->Data();
context->fillRect(0, 0, 1, 1);
scoped_refptr<StaticBitmapImage> snapshot =
canvas->Snapshot(kFrontBuffer, kPreferNoAcceleration);
ASSERT_TRUE(snapshot);
sk_sp<SkImage> source_image =
snapshot->PaintImageForCurrentFrame().GetSkImage();
SkPixmap source_pixmap;
source_image->peekPixels(&source_pixmap);
// Create and test the ImageBitmap objects.
base::Optional<IntRect> crop_rect = IntRect(0, 0, 4, 4);
sk_sp<SkColorSpace> color_space = nullptr;
SkColorType color_type = SkColorType::kRGBA_8888_SkColorType;
SkColorSpaceXform::ColorFormat color_format32 =
SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat;
SkColorSpaceXform::ColorFormat color_format = color_format32;
sk_sp<SkColorSpace> src_rgb_color_space = SkColorSpace::MakeSRGB();
for (uint8_t i =
static_cast<uint8_t>(ColorSpaceConversion::DEFAULT_COLOR_CORRECTED);
i <= static_cast<uint8_t>(ColorSpaceConversion::LAST); i++) {
ColorSpaceConversion color_space_conversion =
static_cast<ColorSpaceConversion>(i);
switch (color_space_conversion) {
case ColorSpaceConversion::NONE:
NOTREACHED();
break;
case ColorSpaceConversion::DEFAULT_COLOR_CORRECTED:
case ColorSpaceConversion::SRGB:
color_space = SkColorSpace::MakeSRGB();
color_format = color_format32;
break;
case ColorSpaceConversion::LINEAR_RGB:
color_space = SkColorSpace::MakeSRGBLinear();
color_type = SkColorType::kRGBA_F16_SkColorType;
color_format = SkColorSpaceXform::ColorFormat::kRGBA_F16_ColorFormat;
break;
case ColorSpaceConversion::P3:
color_space =
SkColorSpace::MakeRGB(SkColorSpace::kLinear_RenderTargetGamma,
SkColorSpace::kDCIP3_D65_Gamut);
color_type = SkColorType::kRGBA_F16_SkColorType;
color_format = SkColorSpaceXform::ColorFormat::kRGBA_F16_ColorFormat;
break;
case ColorSpaceConversion::REC2020:
color_space =
SkColorSpace::MakeRGB(SkColorSpace::kLinear_RenderTargetGamma,
SkColorSpace::kRec2020_Gamut);
color_type = SkColorType::kRGBA_F16_SkColorType;
color_format = SkColorSpaceXform::ColorFormat::kRGBA_F16_ColorFormat;
break;
default:
NOTREACHED();
}
base::Optional<IntRect> crop_rect = IntRect(0, 0, 1, 1);
for (int conversion_iterator = ColorSpaceConversion::kDefault;
conversion_iterator <= ColorSpaceConversion::kLast;
conversion_iterator++) {
// Color convert using ImageBitmap
ImageBitmapOptions options =
PrepareBitmapOptionsAndSetRuntimeFlags(color_space_conversion);
ImageBitmapOptions options;
options.setColorSpaceConversion(
ColorCorrectionTestUtils::ColorSpaceConversionToString(
static_cast<ColorSpaceConversion>(conversion_iterator)));
ImageBitmap* image_bitmap = ImageBitmap::Create(canvas, crop_rect, options);
ASSERT_TRUE(image_bitmap);
sk_sp<SkImage> converted_image =
image_bitmap->BitmapImage()->PaintImageForCurrentFrame().GetSkImage();
ASSERT_TRUE(converted_image);
SkImageInfo image_info =
SkImageInfo::Make(1, 1, color_type, SkAlphaType::kUnpremul_SkAlphaType,
converted_image->refColorSpace());
std::unique_ptr<uint8_t[]> converted_pixel(
new uint8_t[image_info.bytesPerPixel()]());
EXPECT_TRUE(converted_image->readPixels(image_info, converted_pixel.get(),
image_info.minRowBytes(), 2, 2));
// Transform the source pixel and check if the image bitmap color conversion
// is done correctly.
std::unique_ptr<SkColorSpaceXform> color_space_xform =
SkColorSpaceXform::New(src_rgb_color_space.get(), color_space.get());
std::unique_ptr<uint8_t[]> transformed_pixel(
new uint8_t[image_info.bytesPerPixel()]());
EXPECT_TRUE(color_space_xform->apply(color_format, transformed_pixel.get(),
color_format32, src_pixel, 1,
SkAlphaType::kUnpremul_SkAlphaType));
SkPixmap converted_pixmap;
converted_image->peekPixels(&converted_pixmap);
// Manual color convert for testing
sk_sp<SkColorSpace> color_space =
ColorCorrectionTestUtils::ColorSpaceConversionToSkColorSpace(
static_cast<ColorSpaceConversion>(conversion_iterator));
if (conversion_iterator == ColorSpaceConversion::kPreserve)
color_space = SkColorSpace::MakeSRGB();
// TODO: crbug.com/768855: Remove if statement when CanvasResourceProvider
// does not use SkColorSpaceXformCanvas (which rips off sRGB from
// ImageBitmap).
if (!color_space->isSRGB()) {
EXPECT_TRUE(SkColorSpace::Equals(color_space.get(),
converted_image->colorSpace()));
}
SkColorType color_type = SkColorType::kN32_SkColorType;
if (color_space && color_space->gammaIsLinear())
color_type = kRGBA_F16_SkColorType;
SkImageInfo image_info = SkImageInfo::Make(
1, 1, color_type, SkAlphaType::kPremul_SkAlphaType, color_space);
SkBitmap manual_converted_bitmap;
EXPECT_TRUE(manual_converted_bitmap.tryAllocPixels(image_info));
source_pixmap.readPixels(manual_converted_bitmap.pixmap(), 0, 0);
ColorCorrectionTestUtils::CompareColorCorrectedPixels(
converted_pixel.get(), transformed_pixel.get(), 1,
(color_type == kRGBA_8888_SkColorType) ? kPixelFormat_8888
: kPixelFormat_hhhh,
kAlphaUnmultiplied, kUnpremulRoundTripTolerance);
converted_pixmap.addr(), manual_converted_bitmap.pixmap().addr(), 1,
(color_type == kN32_SkColorType) ? kPixelFormat_8888
: kPixelFormat_hhhh,
kAlphaMultiplied, kNoUnpremulRoundTripTolerance);
}
}
......
......@@ -7,7 +7,6 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/graphics/color_correction_test_utils.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
#include "third_party/skia/include/core/SkColorSpaceXform.h"
#include "ui/gfx/color_space.h"
namespace blink {
......@@ -17,56 +16,20 @@ namespace blink {
// to the canvas, the target gfx::ColorSpace is returned by CanvasColorParams::
// GetStorageGfxColorSpace(). This test verifies that the two different color
// spaces are approximately the same for different CanvasColorParam objects.
// This test does not use SkColorSpace::Equals() since it is sensitive to
// rounding issues (floats don't round-trip perfectly through ICC fixed point).
// Instead, it color converts a pixel and compares the result. Furthermore, this
// test does not include sRGB as target color space since we use
// SkColorSpaceXformCanvas for sRGB targets and GetSkColorSpaceForSkSurfaces()
// returns nullptr for the surface.
TEST(CanvasColorParamsTest, MatchSkColorSpaceWithGfxColorSpace) {
sk_sp<SkColorSpace> src_rgb_color_space = SkColorSpace::MakeSRGB();
std::unique_ptr<uint8_t[]> src_pixel(new uint8_t[4]{32, 96, 160, 255});
CanvasColorSpace canvas_color_spaces[] = {
kSRGBCanvasColorSpace, kRec2020CanvasColorSpace, kP3CanvasColorSpace,
};
for (int iter_color_space = 0; iter_color_space < 3; iter_color_space++) {
CanvasColorParams color_params(canvas_color_spaces[iter_color_space],
kF16CanvasPixelFormat, kNonOpaque);
std::unique_ptr<SkColorSpaceXform> color_space_xform_canvas =
SkColorSpaceXform::New(src_rgb_color_space.get(),
color_params.GetSkColorSpace().get());
std::unique_ptr<SkColorSpaceXform> color_space_xform_media =
SkColorSpaceXform::New(
src_rgb_color_space.get(),
color_params.GetStorageGfxColorSpace().ToSkColorSpace().get());
std::unique_ptr<uint8_t[]> transformed_pixel_canvas(
new uint8_t[color_params.BytesPerPixel()]());
std::unique_ptr<uint8_t[]> transformed_pixel_media(
new uint8_t[color_params.BytesPerPixel()]());
SkColorSpaceXform::ColorFormat transformed_color_format =
color_params.BytesPerPixel() == 4
? SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat
: SkColorSpaceXform::ColorFormat::kRGBA_F16_ColorFormat;
EXPECT_TRUE(color_space_xform_canvas->apply(
transformed_color_format, transformed_pixel_canvas.get(),
SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat, src_pixel.get(),
1, SkAlphaType::kPremul_SkAlphaType));
EXPECT_TRUE(color_space_xform_media->apply(
transformed_color_format, transformed_pixel_media.get(),
SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat, src_pixel.get(),
1, SkAlphaType::kPremul_SkAlphaType));
ColorCorrectionTestUtils::CompareColorCorrectedPixels(
transformed_pixel_canvas.get(), transformed_pixel_media.get(), 1,
kPixelFormat_hhhh, kAlphaMultiplied, kUnpremulRoundTripTolerance);
}
sk_sp<SkColorSpace> canvas_drawing_color_space =
color_params.GetSkColorSpace();
sk_sp<SkColorSpace> canvas_media_color_space =
color_params.GetStorageGfxColorSpace().ToSkColorSpace();
ASSERT_TRUE(ColorCorrectionTestUtils::MatchColorSpace(
canvas_drawing_color_space, canvas_media_color_space));
}
}
} // namespace blink
......@@ -6,6 +6,7 @@
#include "base/sys_byteorder.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/third_party/skcms/skcms.h"
namespace blink {
......@@ -66,6 +67,32 @@ sk_sp<SkColorSpace> ColorCorrectionTestUtils::ColorSpinSkColorSpace() {
return SkColorSpace::Make(colorspin_profile);
}
sk_sp<SkColorSpace>
ColorCorrectionTestUtils::ColorSpaceConversionToSkColorSpace(
ColorSpaceConversion conversion) {
if (conversion == kDefault || conversion == kSRGB) {
return SkColorSpace::MakeSRGB();
}
if (conversion == kLinearRGB)
return SkColorSpace::MakeSRGBLinear();
if (conversion == kP3) {
return SkColorSpace::MakeRGB(SkColorSpace::kLinear_RenderTargetGamma,
SkColorSpace::kDCIP3_D65_Gamut);
}
if (conversion == kRec2020) {
return SkColorSpace::MakeRGB(SkColorSpace::kLinear_RenderTargetGamma,
SkColorSpace::kRec2020_Gamut);
}
return nullptr;
}
String ColorCorrectionTestUtils::ColorSpaceConversionToString(
ColorSpaceConversion color_space_conversion) {
static const Vector<String> kConversions = {
"none", "default", "preserve", "srgb", "linear-rgb", "p3", "rec2020"};
return kConversions[static_cast<uint8_t>(color_space_conversion)];
}
void ColorCorrectionTestUtils::CompareColorCorrectedPixels(
const void* actual_pixels,
const void* expected_pixels,
......@@ -227,32 +254,23 @@ bool ColorCorrectionTestUtils::ConvertPixelsToColorSpaceAndPixelFormatForTest(
}
bool ColorCorrectionTestUtils::MatchColorSpace(
SkColorSpace* src_color_space,
SkColorSpace* dst_color_space,
float xyz_d50_component_tolerance) {
sk_sp<SkColorSpace> src_color_space,
sk_sp<SkColorSpace> dst_color_space) {
if ((!src_color_space && dst_color_space) ||
(src_color_space && !dst_color_space))
return false;
if (src_color_space) {
const SkMatrix44* src_matrix = src_color_space->toXYZD50();
const SkMatrix44* dst_matrix = dst_color_space->toXYZD50();
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (fabs(src_matrix->get(i, j) - dst_matrix->get(i, j)) >
xyz_d50_component_tolerance) {
return false;
}
}
}
}
return true;
if (!src_color_space && !dst_color_space)
return true;
skcms_ICCProfile src_profile, dst_profile;
src_color_space->toProfile(&src_profile);
dst_color_space->toProfile(&dst_profile);
return skcms_ApproximatelyEqualProfiles(&src_profile, &dst_profile);
}
bool ColorCorrectionTestUtils::MatchSkImages(sk_sp<SkImage> src_image,
sk_sp<SkImage> dst_image,
unsigned uint8_tolerance,
float f16_tolerance,
float xyz_d50_component_tolerance,
bool compare_alpha) {
if ((!src_image && dst_image) || (src_image && !dst_image))
return false;
......@@ -265,8 +283,10 @@ bool ColorCorrectionTestUtils::MatchSkImages(sk_sp<SkImage> src_image,
if (compare_alpha && src_image->alphaType() != dst_image->alphaType())
return false;
if (!MatchColorSpace(src_image->colorSpace(), dst_image->colorSpace(),
xyz_d50_component_tolerance)) {
// Color type is not checked since the decoded image does not have a specific
// color type, unless it is drawn onto a surface or readPixels() is called.
if (!MatchColorSpace(src_image->refColorSpace(),
dst_image->refColorSpace())) {
return false;
}
......
......@@ -9,8 +9,8 @@
#include "third_party/blink/renderer/platform/graphics/graphics_types.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "third_party/skia/include/core/SkImage.h"
#include "third_party/skia/third_party/skcms/skcms.h"
namespace blink {
......@@ -31,9 +31,25 @@ enum UnpremulRoundTripTolerance {
kUnpremulRoundTripTolerance,
};
enum ColorSpaceConversion {
kNone,
kDefault,
kPreserve,
kSRGB,
kLinearRGB,
kP3,
kRec2020,
kLast = kRec2020,
};
class ColorCorrectionTestUtils {
public:
// ImageBitmap color space conversion test utils
static sk_sp<SkColorSpace> ColorSpinSkColorSpace();
static sk_sp<SkColorSpace> ColorSpaceConversionToSkColorSpace(
ColorSpaceConversion conversion);
static String ColorSpaceConversionToString(
ColorSpaceConversion color_space_conversion);
static void CompareColorCorrectedPixels(
const void* actual_pixels,
......@@ -53,15 +69,13 @@ class ColorCorrectionTestUtils {
std::unique_ptr<uint8_t[]>& converted_pixels,
PixelFormat pixel_format_for_f16_canvas);
static bool MatchColorSpace(SkColorSpace* src_color_space,
SkColorSpace* dst_color_space,
float xyz_d50_component_tolerance);
static bool MatchColorSpace(sk_sp<SkColorSpace> src_color_space,
sk_sp<SkColorSpace> dst_color_space);
static bool MatchSkImages(sk_sp<SkImage> src_image,
sk_sp<SkImage> dst_image,
unsigned uint8_tolerance,
float f16_tolerance,
float xyz_d50_component_tolerance,
bool compare_alpha);
private:
......
......@@ -57,7 +57,7 @@
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer_contents.h"
#include "third_party/skia/include/core/SkColorSpaceXform.h"
#include "third_party/skia/include/core/SkPixmap.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/gpu/GrContext.h"
#include "third_party/skia/include/gpu/gl/GrGLTypes.h"
......@@ -1367,15 +1367,15 @@ void DrawingBuffer::ReadBackFramebuffer(unsigned char* pixels,
}
if (op == WebGLImageConversion::kAlphaDoPremultiply) {
std::unique_ptr<SkColorSpaceXform> xform =
SkColorSpaceXform::New(SkColorSpace::MakeSRGBLinear().get(),
SkColorSpace::MakeSRGBLinear().get());
SkColorSpaceXform::ColorFormat color_format =
SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat;
auto color_type = kRGBA_8888_SkColorType;
if (data_type != GL_UNSIGNED_BYTE)
color_format = SkColorSpaceXform::ColorFormat::kRGBA_F16_ColorFormat;
xform->apply(color_format, pixels, color_format, pixels, width * height,
kPremul_SkAlphaType);
color_type = kRGBA_F16_SkColorType;
const auto src =
SkImageInfo::Make(width, height, color_type, kUnpremul_SkAlphaType);
const auto dst =
SkImageInfo::Make(width, height, color_type, kPremul_SkAlphaType);
SkPixmap{src, pixels, src.minRowBytes()}.readPixels(
SkPixmap{dst, pixels, dst.minRowBytes()});
} else if (op != WebGLImageConversion::kAlphaDoNothing) {
NOTREACHED();
}
......
......@@ -5,7 +5,7 @@
#include "third_party/blink/renderer/platform/image-decoders/image_frame.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkColorSpaceXform.h"
#include "third_party/skia/third_party/skcms/skcms.h"
namespace blink {
namespace {
......@@ -26,20 +26,16 @@ class ImageFrameTest : public testing::Test {
src_8888 = SkPackARGB32(src_8888_a, src_8888_r, src_8888_g, src_8888_b);
dst_8888 = SkPackARGB32(0xA0, 0x60, 0x70, 0x80);
typedef SkColorSpaceXform::ColorFormat ColorFormat;
color_format_8888 = ColorFormat::kBGRA_8888_ColorFormat;
pixel_format_n32 = skcms_PixelFormat_RGBA_8888;
if (kN32_SkColorType == kRGBA_8888_SkColorType)
color_format_8888 = ColorFormat::kRGBA_8888_ColorFormat;
color_format_f16 = ColorFormat::kRGBA_F16_ColorFormat;
color_format_f32 = ColorFormat::kRGBA_F32_ColorFormat;
sk_sp<SkColorSpace> srgb_linear = SkColorSpace::MakeSRGBLinear();
SkColorSpaceXform::Apply(srgb_linear.get(), color_format_f16, &src_f16,
srgb_linear.get(), color_format_8888, &src_8888, 1,
SkColorSpaceXform::AlphaOp::kPreserve_AlphaOp);
SkColorSpaceXform::Apply(srgb_linear.get(), color_format_f16, &dst_f16,
srgb_linear.get(), color_format_8888, &dst_8888, 1,
SkColorSpaceXform::AlphaOp::kPreserve_AlphaOp);
pixel_format_n32 = skcms_PixelFormat_BGRA_8888;
skcms_Transform(&src_8888, pixel_format_n32, skcms_AlphaFormat_Unpremul,
nullptr, &src_f16, skcms_PixelFormat_RGBA_hhhh,
skcms_AlphaFormat_Unpremul, nullptr, 1);
skcms_Transform(&dst_8888, pixel_format_n32, skcms_AlphaFormat_Unpremul,
nullptr, &dst_f16, skcms_PixelFormat_RGBA_hhhh,
skcms_AlphaFormat_Unpremul, nullptr, 1);
}
protected:
......@@ -47,21 +43,19 @@ class ImageFrameTest : public testing::Test {
unsigned src_8888_a, src_8888_r, src_8888_g, src_8888_b;
ImageFrame::PixelData src_8888, dst_8888;
ImageFrame::PixelDataF16 src_f16, dst_f16;
SkColorSpaceXform::ColorFormat color_format_8888, color_format_f16,
color_format_f32;
skcms_PixelFormat pixel_format_n32;
void ConvertN32ToF32(float* dst, ImageFrame::PixelData src) {
sk_sp<SkColorSpace> srgb_linear = SkColorSpace::MakeSRGBLinear();
SkColorSpaceXform::Apply(srgb_linear.get(), color_format_f32, dst,
srgb_linear.get(), color_format_8888, &src, 1,
SkColorSpaceXform::AlphaOp::kPreserve_AlphaOp);
skcms_Transform(&src, pixel_format_n32, skcms_AlphaFormat_Unpremul, nullptr,
dst, skcms_PixelFormat_RGBA_ffff,
skcms_AlphaFormat_Unpremul, nullptr, 1);
}
void ConvertF16ToF32(float* dst, ImageFrame::PixelDataF16 src) {
sk_sp<SkColorSpace> srgb_linear = SkColorSpace::MakeSRGBLinear();
SkColorSpaceXform::Apply(srgb_linear.get(), color_format_f32, dst,
srgb_linear.get(), color_format_f16, &src, 1,
SkColorSpaceXform::AlphaOp::kPreserve_AlphaOp);
skcms_Transform(&src, skcms_PixelFormat_RGBA_hhhh,
skcms_AlphaFormat_Unpremul, nullptr, dst,
skcms_PixelFormat_RGBA_ffff, skcms_AlphaFormat_Unpremul,
nullptr, 1);
}
};
......
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