blob: 29f75f4b716b4623a42321c7c3dd8a7a8a4df456 [file] [log] [blame]
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "include/core/SkColorSpace.h"
#include "include/core/SkData.h"
#include "include/core/SkICC.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkTypes.h"
#include "modules/skcms/skcms.h"
#include "tests/Test.h"
#include "tools/Resources.h"
#include <cmath>
#include <cstdint>
#include <cstdlib>
DEF_TEST(AdobeRGB, r) {
if (sk_sp<SkData> profile = GetResourceAsData("icc_profiles/AdobeRGB1998.icc")) {
skcms_ICCProfile parsed;
REPORTER_ASSERT(r, skcms_Parse(profile->data(), profile->size(), &parsed));
REPORTER_ASSERT(r, !parsed.has_CICP);
auto got = SkColorSpace::Make(parsed);
auto want = SkColorSpace::MakeRGB(SkNamedTransferFn::k2Dot2, SkNamedGamut::kAdobeRGB);
REPORTER_ASSERT(r, SkColorSpace::Equals(got.get(), want.get()));
}
}
DEF_TEST(HDR_ICC, r) {
constexpr size_t kTestCount = 3;
SK_API sk_sp<SkData> profile[kTestCount] = {
SkWriteICCProfile(SkNamedTransferFn::kPQ, SkNamedGamut::kRec2020),
SkWriteICCProfile(SkNamedTransferFn::kHLG, SkNamedGamut::kDisplayP3),
SkWriteICCProfile(SkNamedTransferFn::kSRGB, SkNamedGamut::kSRGB),
};
SK_API sk_sp<SkData> dst_profile[kTestCount] = {
SkWriteICCProfile(SkNamedTransferFn::kLinear, SkNamedGamut::kRec2020),
SkWriteICCProfile(SkNamedTransferFn::kLinear, SkNamedGamut::kDisplayP3),
SkWriteICCProfile(SkNamedTransferFn::kLinear, SkNamedGamut::kSRGB),
};
constexpr size_t kPixelCount = 6;
// clang-format off
float pixels[kPixelCount][3] = {
{ 0.0f, 0.0f, 0.0f, },
{ 0.5f, 0.5f, 0.5f, },
{ 0.5f, 0.0f, 0.0f, },
{ 0.0f, 0.5f, 0.0f, },
{ 0.0f, 0.0f, 0.5f, },
{ 1.0f, 1.0f, 1.0f, },
};
float dst_pixels_expected[kTestCount][kPixelCount][3] = {
{
{ 0.f, 0.f, 0.f, },
{ 0.3126f, 0.3125f, 0.3125f, },
{ 0.4061f, 0.f, 0.f, },
{ 0.f, 0.3475f, 0.f, },
{ 0.f, 0.f, 0.4426f, },
{ 1.f, 1.f, 1.f, },
},
{
{ 0.f, 0.f, 0.f, },
{ 0.1044f, 0.1044f, 0.1044f, },
{ 0.1044f, 0.f, 0.f, },
{ 0.f, 0.1044f, 0.f, },
{ 0.f, 0.f, 0.1044f, },
{ 1.f, 1.f, 1.f, },
},
{
{ 0.f, 0.0f, 0.0f, },
{ 0.2140f, 0.2140f, 0.2140f, },
{ 0.2140f, 0.0f, 0.0f, },
{ 0.0f, 0.2140f, 0.0f, },
{ 0.0f, 0.0f, 0.2140f, },
{ 1.0f, 1.0f, 1.0f, },
},
};
// clang-format on
bool cicp_expected[kTestCount] = {true, true, false};
bool a2b_expected[kTestCount] = {true, false, false};
uint32_t cicp_primaries_expected[kTestCount] = {9, 12, 0};
uint32_t cicp_trfn_expected[kTestCount] = {16, 18, 0};
for (size_t test = 0; test < kTestCount; ++test) {
skcms_ICCProfile parsed;
REPORTER_ASSERT(r, skcms_Parse(profile[test]->data(), profile[test]->size(), &parsed));
REPORTER_ASSERT(r, parsed.has_A2B == a2b_expected[test]);
REPORTER_ASSERT(r, parsed.has_CICP == cicp_expected[test]);
if (cicp_expected[test]) {
REPORTER_ASSERT(r, parsed.CICP.color_primaries == cicp_primaries_expected[test]);
REPORTER_ASSERT(r, parsed.CICP.transfer_characteristics == cicp_trfn_expected[test]);
REPORTER_ASSERT(r, parsed.CICP.matrix_coefficients == 0);
REPORTER_ASSERT(r, parsed.CICP.video_full_range_flag == 1);
}
skcms_ICCProfile dst_parsed;
REPORTER_ASSERT(
r, skcms_Parse(dst_profile[test]->data(), dst_profile[test]->size(), &dst_parsed));
for (size_t pixel = 0; pixel < kPixelCount; ++pixel) {
float dst_pixel_actual[3]{0.f, 0.f, 0.f};
bool xform_result = skcms_Transform(pixels[pixel],
skcms_PixelFormat_RGB_fff,
skcms_AlphaFormat_Opaque,
&parsed,
dst_pixel_actual,
skcms_PixelFormat_RGB_fff,
skcms_AlphaFormat_Opaque,
&dst_parsed,
1);
REPORTER_ASSERT(r, xform_result);
auto approx_equal = [=](float x, float y) { return std::abs(x - y) < 1e-3f; };
for (size_t i = 0; i < 3; ++i) {
REPORTER_ASSERT(
r, approx_equal(dst_pixel_actual[i], dst_pixels_expected[test][pixel][i]));
}
}
}
}