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 @@ ...@@ -23,7 +23,6 @@
#include "third_party/blink/renderer/platform/web_task_runner.h" #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/functional.h"
#include "third_party/blink/renderer/platform/wtf/time.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" #include "third_party/skia/include/core/SkSurface.h"
namespace blink { namespace blink {
...@@ -234,42 +233,36 @@ CanvasAsyncBlobCreator::CanvasAsyncBlobCreator( ...@@ -234,42 +233,36 @@ CanvasAsyncBlobCreator::CanvasAsyncBlobCreator(
skia_image = SkImage::MakeFromRaster(src_data_, nullptr, nullptr); skia_image = SkImage::MakeFromRaster(src_data_, nullptr, nullptr);
} }
DCHECK(skia_image->colorSpace()); DCHECK(skia_image->colorSpace());
skia_image = skia_image->makeColorSpace(blob_color_space);
image_ = StaticBitmapImage::Create(skia_image); 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; static_bitmap_image_loaded_ = true;
// If the source image is 8 bit per channel but the blob is requested in // 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 // 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 // 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. // SkPixmap only holds a pointer to data, we need a helper data member
if (mime_type_ == kMimeTypePng && // here.
encode_options_.pixelFormat() == kRGBA16ImagePixelFormatName && if (mime_type_ == kMimeTypePng &&
src_data_.colorType() == kN32_SkColorType) { encode_options_.pixelFormat() == kRGBA16ImagePixelFormatName &&
size_t data_length = src_data_.width() * src_data_.height() * src_data_.colorType() == kN32_SkColorType) {
SkColorTypeBytesPerPixel(kRGBA_F16_SkColorType); size_t data_length = src_data_.width() * src_data_.height() *
png_16bit_data_helper_ = SkData::MakeUninitialized(data_length); SkColorTypeBytesPerPixel(kRGBA_F16_SkColorType);
SkColorSpaceXform::ColorFormat src_format = png_16bit_data_helper_ = SkData::MakeUninitialized(data_length);
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)) {
SkImageInfo info = SkImageInfo::Make( SkImageInfo info = SkImageInfo::Make(
src_data_.width(), src_data_.height(), kRGBA_F16_SkColorType, src_data_.width(), src_data_.height(), kRGBA_F16_SkColorType,
src_data_.alphaType(), src_data_.info().refColorSpace()); src_data_.alphaType(), src_data_.info().refColorSpace());
src_data_.reset(info, png_16bit_data_helper_->data(), SkPixmap src_data_f16(info, png_16bit_data_helper_->data(),
info.minRowBytes()); 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) { ...@@ -265,8 +265,6 @@ TEST_F(CanvasAsyncBlobCreatorTest, ColorManagedConvertToBlob) {
// The maximum difference locally observed is 3. // The maximum difference locally observed is 3.
const unsigned uint8_color_tolerance = 5; const unsigned uint8_color_tolerance = 5;
const float f16_color_tolerance = 0.01; 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 color_space_param : color_space_params) {
for (auto blob_mime_type : blob_mime_types) { for (auto blob_mime_type : blob_mime_types) {
...@@ -306,8 +304,7 @@ TEST_F(CanvasAsyncBlobCreatorTest, ColorManagedConvertToBlob) { ...@@ -306,8 +304,7 @@ TEST_F(CanvasAsyncBlobCreatorTest, ColorManagedConvertToBlob) {
bool compare_alpha = (blob_mime_type != "image/jpeg"); bool compare_alpha = (blob_mime_type != "image/jpeg");
ASSERT_TRUE(ColorCorrectionTestUtils::MatchSkImages( ASSERT_TRUE(ColorCorrectionTestUtils::MatchSkImages(
ref_image, decoded_img, uint8_color_tolerance, ref_image, decoded_img, uint8_color_tolerance,
f16_color_tolerance, xyz_d50_color_space_component_tolerance, f16_color_tolerance, compare_alpha));
compare_alpha));
} }
} }
} }
......
...@@ -35,10 +35,8 @@ ...@@ -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/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/loader/fetch/memory_cache.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.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/SkImage.h"
#include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/core/SkSwizzle.h"
using testing::_; using testing::_;
using testing::InSequence; using testing::InSequence;
...@@ -811,29 +809,6 @@ TEST_F(CanvasRenderingContext2DTest, ...@@ -811,29 +809,6 @@ TEST_F(CanvasRenderingContext2DTest,
Mock::VerifyAndClearExpectations(surface_ptr); 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) { TEST_F(CanvasRenderingContext2DTest, ImageBitmapColorSpaceConversion) {
Persistent<HTMLCanvasElement> canvas = Persistent<HTMLCanvasElement> canvas =
Persistent<HTMLCanvasElement>(CanvasElement()); Persistent<HTMLCanvasElement>(CanvasElement());
...@@ -845,89 +820,62 @@ TEST_F(CanvasRenderingContext2DTest, ImageBitmapColorSpaceConversion) { ...@@ -845,89 +820,62 @@ TEST_F(CanvasRenderingContext2DTest, ImageBitmapColorSpaceConversion) {
StringOrCanvasGradientOrCanvasPattern fill_style; StringOrCanvasGradientOrCanvasPattern fill_style;
fill_style.SetString("#FFC08040"); // 255,192,128,64 fill_style.SetString("#FFC08040"); // 255,192,128,64
context->setFillStyle(fill_style); context->setFillStyle(fill_style);
context->fillRect(0, 0, 4, 4); context->fillRect(0, 0, 1, 1);
NonThrowableExceptionState exception_state; scoped_refptr<StaticBitmapImage> snapshot =
uint8_t* src_pixel = canvas->Snapshot(kFrontBuffer, kPreferNoAcceleration);
context->getImageData(2, 2, 1, 1, exception_state)->data()->Data(); 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. // Create and test the ImageBitmap objects.
base::Optional<IntRect> crop_rect = IntRect(0, 0, 4, 4); base::Optional<IntRect> crop_rect = IntRect(0, 0, 1, 1);
sk_sp<SkColorSpace> color_space = nullptr; for (int conversion_iterator = ColorSpaceConversion::kDefault;
SkColorType color_type = SkColorType::kRGBA_8888_SkColorType; conversion_iterator <= ColorSpaceConversion::kLast;
SkColorSpaceXform::ColorFormat color_format32 = conversion_iterator++) {
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();
}
// Color convert using ImageBitmap // Color convert using ImageBitmap
ImageBitmapOptions options = ImageBitmapOptions options;
PrepareBitmapOptionsAndSetRuntimeFlags(color_space_conversion); options.setColorSpaceConversion(
ColorCorrectionTestUtils::ColorSpaceConversionToString(
static_cast<ColorSpaceConversion>(conversion_iterator)));
ImageBitmap* image_bitmap = ImageBitmap::Create(canvas, crop_rect, options); ImageBitmap* image_bitmap = ImageBitmap::Create(canvas, crop_rect, options);
ASSERT_TRUE(image_bitmap); ASSERT_TRUE(image_bitmap);
sk_sp<SkImage> converted_image = sk_sp<SkImage> converted_image =
image_bitmap->BitmapImage()->PaintImageForCurrentFrame().GetSkImage(); image_bitmap->BitmapImage()->PaintImageForCurrentFrame().GetSkImage();
ASSERT_TRUE(converted_image); ASSERT_TRUE(converted_image);
SkImageInfo image_info = SkPixmap converted_pixmap;
SkImageInfo::Make(1, 1, color_type, SkAlphaType::kUnpremul_SkAlphaType, converted_image->peekPixels(&converted_pixmap);
converted_image->refColorSpace());
std::unique_ptr<uint8_t[]> converted_pixel( // Manual color convert for testing
new uint8_t[image_info.bytesPerPixel()]()); sk_sp<SkColorSpace> color_space =
EXPECT_TRUE(converted_image->readPixels(image_info, converted_pixel.get(), ColorCorrectionTestUtils::ColorSpaceConversionToSkColorSpace(
image_info.minRowBytes(), 2, 2)); static_cast<ColorSpaceConversion>(conversion_iterator));
if (conversion_iterator == ColorSpaceConversion::kPreserve)
// Transform the source pixel and check if the image bitmap color conversion color_space = SkColorSpace::MakeSRGB();
// is done correctly.
std::unique_ptr<SkColorSpaceXform> color_space_xform = // TODO: crbug.com/768855: Remove if statement when CanvasResourceProvider
SkColorSpaceXform::New(src_rgb_color_space.get(), color_space.get()); // does not use SkColorSpaceXformCanvas (which rips off sRGB from
std::unique_ptr<uint8_t[]> transformed_pixel( // ImageBitmap).
new uint8_t[image_info.bytesPerPixel()]()); if (!color_space->isSRGB()) {
EXPECT_TRUE(color_space_xform->apply(color_format, transformed_pixel.get(), EXPECT_TRUE(SkColorSpace::Equals(color_space.get(),
color_format32, src_pixel, 1, converted_image->colorSpace()));
SkAlphaType::kUnpremul_SkAlphaType)); }
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( ColorCorrectionTestUtils::CompareColorCorrectedPixels(
converted_pixel.get(), transformed_pixel.get(), 1, converted_pixmap.addr(), manual_converted_bitmap.pixmap().addr(), 1,
(color_type == kRGBA_8888_SkColorType) ? kPixelFormat_8888 (color_type == kN32_SkColorType) ? kPixelFormat_8888
: kPixelFormat_hhhh, : kPixelFormat_hhhh,
kAlphaUnmultiplied, kUnpremulRoundTripTolerance); kAlphaMultiplied, kNoUnpremulRoundTripTolerance);
} }
} }
......
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
#include "testing/gtest/include/gtest/gtest.h" #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/graphics/color_correction_test_utils.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.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" #include "ui/gfx/color_space.h"
namespace blink { namespace blink {
...@@ -17,56 +16,20 @@ namespace blink { ...@@ -17,56 +16,20 @@ namespace blink {
// to the canvas, the target gfx::ColorSpace is returned by CanvasColorParams:: // to the canvas, the target gfx::ColorSpace is returned by CanvasColorParams::
// GetStorageGfxColorSpace(). This test verifies that the two different color // GetStorageGfxColorSpace(). This test verifies that the two different color
// spaces are approximately the same for different CanvasColorParam objects. // 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) { 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[] = { CanvasColorSpace canvas_color_spaces[] = {
kSRGBCanvasColorSpace, kRec2020CanvasColorSpace, kP3CanvasColorSpace, kSRGBCanvasColorSpace, kRec2020CanvasColorSpace, kP3CanvasColorSpace,
}; };
for (int iter_color_space = 0; iter_color_space < 3; iter_color_space++) { for (int iter_color_space = 0; iter_color_space < 3; iter_color_space++) {
CanvasColorParams color_params(canvas_color_spaces[iter_color_space], CanvasColorParams color_params(canvas_color_spaces[iter_color_space],
kF16CanvasPixelFormat, kNonOpaque); kF16CanvasPixelFormat, kNonOpaque);
sk_sp<SkColorSpace> canvas_drawing_color_space =
std::unique_ptr<SkColorSpaceXform> color_space_xform_canvas = color_params.GetSkColorSpace();
SkColorSpaceXform::New(src_rgb_color_space.get(), sk_sp<SkColorSpace> canvas_media_color_space =
color_params.GetSkColorSpace().get()); color_params.GetStorageGfxColorSpace().ToSkColorSpace();
std::unique_ptr<SkColorSpaceXform> color_space_xform_media = ASSERT_TRUE(ColorCorrectionTestUtils::MatchColorSpace(
SkColorSpaceXform::New( canvas_drawing_color_space, canvas_media_color_space));
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);
}
} }
} // namespace blink } // namespace blink
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "base/sys_byteorder.h" #include "base/sys_byteorder.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/third_party/skcms/skcms.h"
namespace blink { namespace blink {
...@@ -66,6 +67,32 @@ sk_sp<SkColorSpace> ColorCorrectionTestUtils::ColorSpinSkColorSpace() { ...@@ -66,6 +67,32 @@ sk_sp<SkColorSpace> ColorCorrectionTestUtils::ColorSpinSkColorSpace() {
return SkColorSpace::Make(colorspin_profile); 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( void ColorCorrectionTestUtils::CompareColorCorrectedPixels(
const void* actual_pixels, const void* actual_pixels,
const void* expected_pixels, const void* expected_pixels,
...@@ -227,32 +254,23 @@ bool ColorCorrectionTestUtils::ConvertPixelsToColorSpaceAndPixelFormatForTest( ...@@ -227,32 +254,23 @@ bool ColorCorrectionTestUtils::ConvertPixelsToColorSpaceAndPixelFormatForTest(
} }
bool ColorCorrectionTestUtils::MatchColorSpace( bool ColorCorrectionTestUtils::MatchColorSpace(
SkColorSpace* src_color_space, sk_sp<SkColorSpace> src_color_space,
SkColorSpace* dst_color_space, sk_sp<SkColorSpace> dst_color_space) {
float xyz_d50_component_tolerance) {
if ((!src_color_space && dst_color_space) || if ((!src_color_space && dst_color_space) ||
(src_color_space && !dst_color_space)) (src_color_space && !dst_color_space))
return false; return false;
if (src_color_space) { if (!src_color_space && !dst_color_space)
const SkMatrix44* src_matrix = src_color_space->toXYZD50(); return true;
const SkMatrix44* dst_matrix = dst_color_space->toXYZD50(); skcms_ICCProfile src_profile, dst_profile;
for (int i = 0; i < 4; i++) { src_color_space->toProfile(&src_profile);
for (int j = 0; j < 4; j++) { dst_color_space->toProfile(&dst_profile);
if (fabs(src_matrix->get(i, j) - dst_matrix->get(i, j)) > return skcms_ApproximatelyEqualProfiles(&src_profile, &dst_profile);
xyz_d50_component_tolerance) {
return false;
}
}
}
}
return true;
} }
bool ColorCorrectionTestUtils::MatchSkImages(sk_sp<SkImage> src_image, bool ColorCorrectionTestUtils::MatchSkImages(sk_sp<SkImage> src_image,
sk_sp<SkImage> dst_image, sk_sp<SkImage> dst_image,
unsigned uint8_tolerance, unsigned uint8_tolerance,
float f16_tolerance, float f16_tolerance,
float xyz_d50_component_tolerance,
bool compare_alpha) { bool compare_alpha) {
if ((!src_image && dst_image) || (src_image && !dst_image)) if ((!src_image && dst_image) || (src_image && !dst_image))
return false; return false;
...@@ -265,8 +283,10 @@ bool ColorCorrectionTestUtils::MatchSkImages(sk_sp<SkImage> src_image, ...@@ -265,8 +283,10 @@ bool ColorCorrectionTestUtils::MatchSkImages(sk_sp<SkImage> src_image,
if (compare_alpha && src_image->alphaType() != dst_image->alphaType()) if (compare_alpha && src_image->alphaType() != dst_image->alphaType())
return false; return false;
if (!MatchColorSpace(src_image->colorSpace(), dst_image->colorSpace(), // Color type is not checked since the decoded image does not have a specific
xyz_d50_component_tolerance)) { // color type, unless it is drawn onto a surface or readPixels() is called.
if (!MatchColorSpace(src_image->refColorSpace(),
dst_image->refColorSpace())) {
return false; return false;
} }
......
...@@ -9,8 +9,8 @@ ...@@ -9,8 +9,8 @@
#include "third_party/blink/renderer/platform/graphics/graphics_types.h" #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/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/include/core/SkImage.h"
#include "third_party/skia/third_party/skcms/skcms.h"
namespace blink { namespace blink {
...@@ -31,9 +31,25 @@ enum UnpremulRoundTripTolerance { ...@@ -31,9 +31,25 @@ enum UnpremulRoundTripTolerance {
kUnpremulRoundTripTolerance, kUnpremulRoundTripTolerance,
}; };
enum ColorSpaceConversion {
kNone,
kDefault,
kPreserve,
kSRGB,
kLinearRGB,
kP3,
kRec2020,
kLast = kRec2020,
};
class ColorCorrectionTestUtils { class ColorCorrectionTestUtils {
public: public:
// ImageBitmap color space conversion test utils
static sk_sp<SkColorSpace> ColorSpinSkColorSpace(); static sk_sp<SkColorSpace> ColorSpinSkColorSpace();
static sk_sp<SkColorSpace> ColorSpaceConversionToSkColorSpace(
ColorSpaceConversion conversion);
static String ColorSpaceConversionToString(
ColorSpaceConversion color_space_conversion);
static void CompareColorCorrectedPixels( static void CompareColorCorrectedPixels(
const void* actual_pixels, const void* actual_pixels,
...@@ -53,15 +69,13 @@ class ColorCorrectionTestUtils { ...@@ -53,15 +69,13 @@ class ColorCorrectionTestUtils {
std::unique_ptr<uint8_t[]>& converted_pixels, std::unique_ptr<uint8_t[]>& converted_pixels,
PixelFormat pixel_format_for_f16_canvas); PixelFormat pixel_format_for_f16_canvas);
static bool MatchColorSpace(SkColorSpace* src_color_space, static bool MatchColorSpace(sk_sp<SkColorSpace> src_color_space,
SkColorSpace* dst_color_space, sk_sp<SkColorSpace> dst_color_space);
float xyz_d50_component_tolerance);
static bool MatchSkImages(sk_sp<SkImage> src_image, static bool MatchSkImages(sk_sp<SkImage> src_image,
sk_sp<SkImage> dst_image, sk_sp<SkImage> dst_image,
unsigned uint8_tolerance, unsigned uint8_tolerance,
float f16_tolerance, float f16_tolerance,
float xyz_d50_component_tolerance,
bool compare_alpha); bool compare_alpha);
private: private:
......
...@@ -57,7 +57,7 @@ ...@@ -57,7 +57,7 @@
#include "third_party/blink/renderer/platform/runtime_enabled_features.h" #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/functional.h"
#include "third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer_contents.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/core/SkSurface.h"
#include "third_party/skia/include/gpu/GrContext.h" #include "third_party/skia/include/gpu/GrContext.h"
#include "third_party/skia/include/gpu/gl/GrGLTypes.h" #include "third_party/skia/include/gpu/gl/GrGLTypes.h"
...@@ -1367,15 +1367,15 @@ void DrawingBuffer::ReadBackFramebuffer(unsigned char* pixels, ...@@ -1367,15 +1367,15 @@ void DrawingBuffer::ReadBackFramebuffer(unsigned char* pixels,
} }
if (op == WebGLImageConversion::kAlphaDoPremultiply) { if (op == WebGLImageConversion::kAlphaDoPremultiply) {
std::unique_ptr<SkColorSpaceXform> xform = auto color_type = kRGBA_8888_SkColorType;
SkColorSpaceXform::New(SkColorSpace::MakeSRGBLinear().get(),
SkColorSpace::MakeSRGBLinear().get());
SkColorSpaceXform::ColorFormat color_format =
SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat;
if (data_type != GL_UNSIGNED_BYTE) if (data_type != GL_UNSIGNED_BYTE)
color_format = SkColorSpaceXform::ColorFormat::kRGBA_F16_ColorFormat; color_type = kRGBA_F16_SkColorType;
xform->apply(color_format, pixels, color_format, pixels, width * height, const auto src =
kPremul_SkAlphaType); 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) { } else if (op != WebGLImageConversion::kAlphaDoNothing) {
NOTREACHED(); NOTREACHED();
} }
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
#include "third_party/blink/renderer/platform/image-decoders/image_frame.h" #include "third_party/blink/renderer/platform/image-decoders/image_frame.h"
#include "testing/gtest/include/gtest/gtest.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 blink {
namespace { namespace {
...@@ -26,20 +26,16 @@ class ImageFrameTest : public testing::Test { ...@@ -26,20 +26,16 @@ class ImageFrameTest : public testing::Test {
src_8888 = SkPackARGB32(src_8888_a, src_8888_r, src_8888_g, src_8888_b); src_8888 = SkPackARGB32(src_8888_a, src_8888_r, src_8888_g, src_8888_b);
dst_8888 = SkPackARGB32(0xA0, 0x60, 0x70, 0x80); dst_8888 = SkPackARGB32(0xA0, 0x60, 0x70, 0x80);
typedef SkColorSpaceXform::ColorFormat ColorFormat; pixel_format_n32 = skcms_PixelFormat_RGBA_8888;
color_format_8888 = ColorFormat::kBGRA_8888_ColorFormat;
if (kN32_SkColorType == kRGBA_8888_SkColorType) if (kN32_SkColorType == kRGBA_8888_SkColorType)
color_format_8888 = ColorFormat::kRGBA_8888_ColorFormat; pixel_format_n32 = skcms_PixelFormat_BGRA_8888;
color_format_f16 = ColorFormat::kRGBA_F16_ColorFormat;
color_format_f32 = ColorFormat::kRGBA_F32_ColorFormat; skcms_Transform(&src_8888, pixel_format_n32, skcms_AlphaFormat_Unpremul,
nullptr, &src_f16, skcms_PixelFormat_RGBA_hhhh,
sk_sp<SkColorSpace> srgb_linear = SkColorSpace::MakeSRGBLinear(); skcms_AlphaFormat_Unpremul, nullptr, 1);
SkColorSpaceXform::Apply(srgb_linear.get(), color_format_f16, &src_f16, skcms_Transform(&dst_8888, pixel_format_n32, skcms_AlphaFormat_Unpremul,
srgb_linear.get(), color_format_8888, &src_8888, 1, nullptr, &dst_f16, skcms_PixelFormat_RGBA_hhhh,
SkColorSpaceXform::AlphaOp::kPreserve_AlphaOp); skcms_AlphaFormat_Unpremul, nullptr, 1);
SkColorSpaceXform::Apply(srgb_linear.get(), color_format_f16, &dst_f16,
srgb_linear.get(), color_format_8888, &dst_8888, 1,
SkColorSpaceXform::AlphaOp::kPreserve_AlphaOp);
} }
protected: protected:
...@@ -47,21 +43,19 @@ class ImageFrameTest : public testing::Test { ...@@ -47,21 +43,19 @@ class ImageFrameTest : public testing::Test {
unsigned src_8888_a, src_8888_r, src_8888_g, src_8888_b; unsigned src_8888_a, src_8888_r, src_8888_g, src_8888_b;
ImageFrame::PixelData src_8888, dst_8888; ImageFrame::PixelData src_8888, dst_8888;
ImageFrame::PixelDataF16 src_f16, dst_f16; ImageFrame::PixelDataF16 src_f16, dst_f16;
SkColorSpaceXform::ColorFormat color_format_8888, color_format_f16, skcms_PixelFormat pixel_format_n32;
color_format_f32;
void ConvertN32ToF32(float* dst, ImageFrame::PixelData src) { void ConvertN32ToF32(float* dst, ImageFrame::PixelData src) {
sk_sp<SkColorSpace> srgb_linear = SkColorSpace::MakeSRGBLinear(); skcms_Transform(&src, pixel_format_n32, skcms_AlphaFormat_Unpremul, nullptr,
SkColorSpaceXform::Apply(srgb_linear.get(), color_format_f32, dst, dst, skcms_PixelFormat_RGBA_ffff,
srgb_linear.get(), color_format_8888, &src, 1, skcms_AlphaFormat_Unpremul, nullptr, 1);
SkColorSpaceXform::AlphaOp::kPreserve_AlphaOp);
} }
void ConvertF16ToF32(float* dst, ImageFrame::PixelDataF16 src) { void ConvertF16ToF32(float* dst, ImageFrame::PixelDataF16 src) {
sk_sp<SkColorSpace> srgb_linear = SkColorSpace::MakeSRGBLinear(); skcms_Transform(&src, skcms_PixelFormat_RGBA_hhhh,
SkColorSpaceXform::Apply(srgb_linear.get(), color_format_f32, dst, skcms_AlphaFormat_Unpremul, nullptr, dst,
srgb_linear.get(), color_format_f16, &src, 1, skcms_PixelFormat_RGBA_ffff, skcms_AlphaFormat_Unpremul,
SkColorSpaceXform::AlphaOp::kPreserve_AlphaOp); 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