Make skcms mandatory

Change-Id: I6b08cd586d313e3bc41c0da90698fc26ae1a8bb8
Reviewed-on: https://skia-review.googlesource.com/130822
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Mike Klein <mtklein@google.com>
This commit is contained in:
Brian Osman 2018-05-30 12:57:45 -04:00 committed by Skia Commit-Bot
parent 588f879677
commit 8dc68c67f8
8 changed files with 182 additions and 242 deletions

View File

@ -30,7 +30,6 @@ declare_args() {
skia_use_zlib = true skia_use_zlib = true
skia_use_metal = false skia_use_metal = false
skia_use_libheif = is_skia_dev_build skia_use_libheif = is_skia_dev_build
skia_use_skcms = true
skia_android_serial = "" skia_android_serial = ""
skia_enable_discrete_gpu = true skia_enable_discrete_gpu = true
@ -724,12 +723,7 @@ optional("raw") {
} }
import("third_party/skcms/skcms.gni") import("third_party/skcms/skcms.gni")
config("third_party_skcms_public") { source_set("skcms") {
include_dirs = [ "third_party/skcms" ]
}
source_set("third_party_skcms") {
public_configs = [ ":third_party_skcms_public" ]
cflags = [] cflags = []
if (!is_win || is_clang) { if (!is_win || is_clang) {
cflags += [ cflags += [
@ -744,18 +738,6 @@ source_set("third_party_skcms") {
sources = rebase_path(skcms_sources, ".", "third_party/skcms") sources = rebase_path(skcms_sources, ".", "third_party/skcms")
} }
optional("skcms") {
enabled = skia_use_skcms
public_defines = [ "SK_USE_SKCMS" ]
deps = [
":third_party_skcms",
]
sources = [
"src/core/SkColorSpaceXform_skcms.cpp",
]
}
optional("typeface_freetype") { optional("typeface_freetype") {
enabled = skia_use_freetype enabled = skia_use_freetype
@ -1406,7 +1388,6 @@ if (skia_enable_tools) {
":experimental_svg_model", ":experimental_svg_model",
":flags", ":flags",
":skia", ":skia",
":third_party_skcms",
":tool_utils", ":tool_utils",
"modules/sksg:tests", "modules/sksg:tests",
"//third_party/libpng", "//third_party/libpng",
@ -1578,7 +1559,6 @@ if (skia_enable_tools) {
":gpu_tool_utils", ":gpu_tool_utils",
":skia", ":skia",
":tests", ":tests",
":third_party_skcms",
":tool_utils", ":tool_utils",
"modules/skottie", "modules/skottie",
"modules/sksg", "modules/sksg",

View File

@ -73,9 +73,7 @@
#include "SkXMLWriter.h" #include "SkXMLWriter.h"
#endif #endif
#if defined(SK_USE_SKCMS) #include "../third_party/skcms/skcms.h"
#include "skcms.h"
#endif
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
#include "GrBackendSurface.h" #include "GrBackendSurface.h"
@ -1090,14 +1088,10 @@ Error ColorCodecSrc::draw(SkCanvas* canvas) const {
if (kDst_sRGB_Mode == fMode) { if (kDst_sRGB_Mode == fMode) {
dstSpace = SkColorSpace::MakeSRGB(); dstSpace = SkColorSpace::MakeSRGB();
} else if (kDst_HPZR30w_Mode == fMode) { } else if (kDst_HPZR30w_Mode == fMode) {
#if defined(SK_USE_SKCMS)
skcms_ICCProfile profile; skcms_ICCProfile profile;
SkAssertResult(skcms_Parse(dstData->data(), dstData->size(), &profile)); SkAssertResult(skcms_Parse(dstData->data(), dstData->size(), &profile));
dstSpace = SkColorSpace::Make(profile); dstSpace = SkColorSpace::Make(profile);
SkASSERT(dstSpace); SkASSERT(dstSpace);
#else
return "Cannot use ICC profile without skcms support.";
#endif
} }
SkImageInfo decodeInfo = codec->getInfo().makeColorType(fColorType).makeColorSpace(dstSpace); SkImageInfo decodeInfo = codec->getInfo().makeColorType(fColorType).makeColorSpace(dstSpace);

View File

@ -247,7 +247,6 @@ gn_to_bp_utils.GrabDependentValues(js, '//:nanobench', 'sources',
nanobench_srcs, 'skia') nanobench_srcs, 'skia')
# skcms is a little special, kind of a second-party library. # skcms is a little special, kind of a second-party library.
srcs .add("third_party/skcms/skcms.c")
local_includes.add("third_party/skcms") local_includes.add("third_party/skcms")
dm_includes .add("third_party/skcms") dm_includes .add("third_party/skcms")

View File

@ -7,23 +7,14 @@
#include "SkColorSpaceXform.h" #include "SkColorSpaceXform.h"
#include "SkColorSpaceXformPriv.h" #include "SkColorSpaceXformPriv.h"
#include "SkData.h"
#include "SkMakeUnique.h"
#include "../../third_party/skcms/skcms.h"
std::unique_ptr<SkColorSpaceXform> SkColorSpaceXform::New(SkColorSpace* src, SkColorSpace* dst) { std::unique_ptr<SkColorSpaceXform> SkColorSpaceXform::New(SkColorSpace* src, SkColorSpace* dst) {
return SkMakeColorSpaceXform(src, dst, SkTransferFunctionBehavior::kRespect); return SkMakeColorSpaceXform(src, dst, SkTransferFunctionBehavior::kRespect);
} }
std::unique_ptr<SkColorSpaceXform> SkMakeColorSpaceXform(
SkColorSpace* src,
SkColorSpace* dst,
SkTransferFunctionBehavior premulBehavior) {
#if defined(SK_USE_SKCMS)
if (src && dst && dst->toXYZD50()) {
return SkMakeColorSpaceXform_skcms(src, dst, premulBehavior);
}
#endif
return nullptr;
}
bool SkColorSpaceXform::Apply(SkColorSpace* dstCS, ColorFormat dstFormat, void* dst, bool SkColorSpaceXform::Apply(SkColorSpace* dstCS, ColorFormat dstFormat, void* dst,
SkColorSpace* srcCS, ColorFormat srcFormat, const void* src, SkColorSpace* srcCS, ColorFormat srcFormat, const void* src,
int len, AlphaOp op) { int len, AlphaOp op) {
@ -35,3 +26,127 @@ bool SkColorSpaceXform::Apply(SkColorSpace* dstCS, ColorFormat dstFormat, void*
} }
return SkColorSpaceXform::New(srcCS, dstCS)->apply(dstFormat, dst, srcFormat, src, len, at); return SkColorSpaceXform::New(srcCS, dstCS)->apply(dstFormat, dst, srcFormat, src, len, at);
} }
class SkColorSpaceXform_skcms : public SkColorSpaceXform {
public:
SkColorSpaceXform_skcms(const skcms_ICCProfile& srcProfile,
const skcms_ICCProfile& dstProfile,
skcms_AlphaFormat premulFormat)
: fSrcProfile(srcProfile)
, fDstProfile(dstProfile)
, fPremulFormat(premulFormat) {
}
bool apply(ColorFormat, void*, ColorFormat, const void*, int, SkAlphaType) const override;
private:
skcms_ICCProfile fSrcProfile;
skcms_ICCProfile fDstProfile;
skcms_AlphaFormat fPremulFormat;
};
static skcms_PixelFormat get_skcms_format(SkColorSpaceXform::ColorFormat fmt) {
switch (fmt) {
case SkColorSpaceXform::kRGBA_8888_ColorFormat:
return skcms_PixelFormat_RGBA_8888;
case SkColorSpaceXform::kBGRA_8888_ColorFormat:
return skcms_PixelFormat_BGRA_8888;
case SkColorSpaceXform::kRGB_U16_BE_ColorFormat:
return skcms_PixelFormat_RGB_161616;
case SkColorSpaceXform::kRGBA_U16_BE_ColorFormat:
return skcms_PixelFormat_RGBA_16161616;
case SkColorSpaceXform::kRGBA_F16_ColorFormat:
return skcms_PixelFormat_RGBA_hhhh;
case SkColorSpaceXform::kRGBA_F32_ColorFormat:
return skcms_PixelFormat_RGBA_ffff;
case SkColorSpaceXform::kBGR_565_ColorFormat:
return skcms_PixelFormat_BGR_565;
default:
SkDEBUGFAIL("Invalid ColorFormat");
return skcms_PixelFormat_RGBA_8888;
}
}
bool SkColorSpaceXform_skcms::apply(ColorFormat dstFormat, void* dst,
ColorFormat srcFormat, const void* src,
int count, SkAlphaType alphaType) const {
skcms_AlphaFormat srcAlpha = skcms_AlphaFormat_Unpremul;
skcms_AlphaFormat dstAlpha = kPremul_SkAlphaType == alphaType ? fPremulFormat
: skcms_AlphaFormat_Unpremul;
return skcms_Transform(src, get_skcms_format(srcFormat), srcAlpha, &fSrcProfile,
dst, get_skcms_format(dstFormat), dstAlpha, &fDstProfile, count);
}
void SkColorSpace::toProfile(skcms_ICCProfile* profile) const {
if (auto blob = this->onProfileData()) {
SkAssertResult(skcms_Parse(blob->data(), blob->size(), profile));
} else {
SkMatrix44 toXYZ(SkMatrix44::kUninitialized_Constructor);
SkColorSpaceTransferFn tf;
SkAssertResult(this->toXYZD50(&toXYZ) && this->isNumericalTransferFn(&tf));
skcms_Matrix3x3 m = { {
{ toXYZ.get(0, 0), toXYZ.get(0, 1), toXYZ.get(0, 2) },
{ toXYZ.get(1, 0), toXYZ.get(1, 1), toXYZ.get(1, 2) },
{ toXYZ.get(2, 0), toXYZ.get(2, 1), toXYZ.get(2, 2) },
} };
skcms_Init(profile);
skcms_SetTransferFunction(profile, (const skcms_TransferFunction*)&tf);
skcms_SetXYZD50(profile, &m);
}
}
std::unique_ptr<SkColorSpaceXform> SkMakeColorSpaceXform(SkColorSpace* src, SkColorSpace* dst,
SkTransferFunctionBehavior premul) {
if (src && dst && dst->toXYZD50()) {
// Construct skcms_ICCProfiles from each color space. For now, support A2B and XYZ.
// Eventually, only need to support XYZ. Map premul to one of the two premul formats
// in skcms.
skcms_ICCProfile srcProfile, dstProfile;
src->toProfile(&srcProfile);
dst->toProfile(&dstProfile);
if (!skcms_MakeUsableAsDestination(&dstProfile)) {
return nullptr;
}
skcms_AlphaFormat premulFormat = SkTransferFunctionBehavior::kRespect == premul
? skcms_AlphaFormat_PremulLinear
: skcms_AlphaFormat_PremulAsEncoded;
return skstd::make_unique<SkColorSpaceXform_skcms>(srcProfile, dstProfile, premulFormat);
}
return nullptr;
}
sk_sp<SkColorSpace> SkColorSpace::Make(const skcms_ICCProfile& profile) {
if (!profile.has_toXYZD50 || !profile.has_trc) {
return nullptr;
}
if (skcms_ApproximatelyEqualProfiles(&profile, skcms_sRGB_profile())) {
return SkColorSpace::MakeSRGB();
}
SkMatrix44 toXYZD50(SkMatrix44::kUninitialized_Constructor);
toXYZD50.set3x3RowMajorf(&profile.toXYZD50.vals[0][0]);
if (!toXYZD50.invert(nullptr)) {
return nullptr;
}
const skcms_Curve* trc = profile.trc;
if (trc[0].table_entries ||
trc[1].table_entries ||
trc[2].table_entries ||
memcmp(&trc[0].parametric, &trc[1].parametric, sizeof(trc[0].parametric)) ||
memcmp(&trc[0].parametric, &trc[2].parametric, sizeof(trc[0].parametric))) {
return nullptr;
}
SkColorSpaceTransferFn skia_tf;
memcpy(&skia_tf, &profile.trc[0].parametric, sizeof(skia_tf));
return SkColorSpace::MakeRGB(skia_tf, toXYZD50);
}

View File

@ -6,132 +6,5 @@
*/ */
#include "SkColorSpaceXform.h" #include "SkColorSpaceXform.h"
#include "SkData.h"
#include "SkMakeUnique.h"
#include "skcms.h"
class SkColorSpaceXform_skcms : public SkColorSpaceXform { // Leaving this file around temporarily until client build files no longer refer to it
public:
SkColorSpaceXform_skcms(const skcms_ICCProfile& srcProfile,
const skcms_ICCProfile& dstProfile,
skcms_AlphaFormat premulFormat)
: fSrcProfile(srcProfile)
, fDstProfile(dstProfile)
, fPremulFormat(premulFormat) {}
bool apply(ColorFormat, void*, ColorFormat, const void*, int, SkAlphaType) const override;
private:
skcms_ICCProfile fSrcProfile;
skcms_ICCProfile fDstProfile;
skcms_AlphaFormat fPremulFormat;
};
static skcms_PixelFormat get_skcms_format(SkColorSpaceXform::ColorFormat fmt) {
switch (fmt) {
case SkColorSpaceXform::kRGBA_8888_ColorFormat:
return skcms_PixelFormat_RGBA_8888;
case SkColorSpaceXform::kBGRA_8888_ColorFormat:
return skcms_PixelFormat_BGRA_8888;
case SkColorSpaceXform::kRGB_U16_BE_ColorFormat:
return skcms_PixelFormat_RGB_161616;
case SkColorSpaceXform::kRGBA_U16_BE_ColorFormat:
return skcms_PixelFormat_RGBA_16161616;
case SkColorSpaceXform::kRGBA_F16_ColorFormat:
return skcms_PixelFormat_RGBA_hhhh;
case SkColorSpaceXform::kRGBA_F32_ColorFormat:
return skcms_PixelFormat_RGBA_ffff;
case SkColorSpaceXform::kBGR_565_ColorFormat:
return skcms_PixelFormat_BGR_565;
default:
SkDEBUGFAIL("Invalid ColorFormat");
return skcms_PixelFormat_RGBA_8888;
}
}
bool SkColorSpaceXform_skcms::apply(ColorFormat dstFormat, void* dst,
ColorFormat srcFormat, const void* src,
int count, SkAlphaType alphaType) const {
skcms_AlphaFormat srcAlpha = skcms_AlphaFormat_Unpremul;
skcms_AlphaFormat dstAlpha = kPremul_SkAlphaType == alphaType ? fPremulFormat
: skcms_AlphaFormat_Unpremul;
return skcms_Transform(src, get_skcms_format(srcFormat), srcAlpha, &fSrcProfile,
dst, get_skcms_format(dstFormat), dstAlpha, &fDstProfile, count);
}
void SkColorSpace::toProfile(skcms_ICCProfile* profile) const {
if (auto blob = this->onProfileData()) {
SkAssertResult(skcms_Parse(blob->data(), blob->size(), profile));
} else {
SkMatrix44 toXYZ(SkMatrix44::kUninitialized_Constructor);
SkColorSpaceTransferFn tf;
SkAssertResult(this->toXYZD50(&toXYZ) && this->isNumericalTransferFn(&tf));
skcms_Matrix3x3 m = {{
{ toXYZ.get(0, 0), toXYZ.get(0, 1), toXYZ.get(0, 2) },
{ toXYZ.get(1, 0), toXYZ.get(1, 1), toXYZ.get(1, 2) },
{ toXYZ.get(2, 0), toXYZ.get(2, 1), toXYZ.get(2, 2) },
}};
skcms_Init(profile);
skcms_SetTransferFunction(profile, (const skcms_TransferFunction*)&tf);
skcms_SetXYZD50(profile, &m);
}
}
std::unique_ptr<SkColorSpaceXform> SkMakeColorSpaceXform_skcms(SkColorSpace* src,
SkColorSpace* dst,
SkTransferFunctionBehavior premul) {
// Construct skcms_ICCProfiles from each color space. For now, support A2B and XYZ.
// Eventually, only need to support XYZ. Map premul to one of the two premul formats
// in skcms.
skcms_ICCProfile srcProfile, dstProfile;
src->toProfile(&srcProfile);
dst->toProfile(&dstProfile);
if (!skcms_MakeUsableAsDestination(&dstProfile)) {
return nullptr;
}
skcms_AlphaFormat premulFormat = SkTransferFunctionBehavior::kRespect == premul
? skcms_AlphaFormat_PremulLinear
: skcms_AlphaFormat_PremulAsEncoded;
return skstd::make_unique<SkColorSpaceXform_skcms>(srcProfile, dstProfile, premulFormat);
}
sk_sp<SkColorSpace> SkColorSpace::Make(const skcms_ICCProfile& profile) {
if (!profile.has_toXYZD50 || !profile.has_trc) {
return nullptr;
}
if (skcms_ApproximatelyEqualProfiles(&profile, skcms_sRGB_profile())) {
return SkColorSpace::MakeSRGB();
}
SkMatrix44 toXYZD50(SkMatrix44::kUninitialized_Constructor);
toXYZD50.set3x3RowMajorf(&profile.toXYZD50.vals[0][0]);
if (!toXYZD50.invert(nullptr)) {
return nullptr;
}
const skcms_Curve* trc = profile.trc;
if (trc[0].table_entries ||
trc[1].table_entries ||
trc[2].table_entries ||
memcmp(&trc[0].parametric, &trc[1].parametric, sizeof(trc[0].parametric)) ||
memcmp(&trc[0].parametric, &trc[2].parametric, sizeof(trc[0].parametric))) {
return nullptr;
}
SkColorSpaceTransferFn skia_tf;
memcpy(&skia_tf, &profile.trc[0].parametric, sizeof(skia_tf));
return SkColorSpace::MakeRGB(skia_tf, toXYZD50);
}
bool skcms_can_parse(const void* buf, size_t len) {
skcms_ICCProfile p;
return skcms_Parse(buf, len, &p);
}

View File

@ -14,12 +14,7 @@
#include "SkFixed.h" #include "SkFixed.h"
#include "SkICCPriv.h" #include "SkICCPriv.h"
#include "SkTemplates.h" #include "SkTemplates.h"
#include "../../third_party/skcms/skcms.h"
#if defined(SK_USE_SKCMS)
bool skcms_can_parse(const void*, size_t);
#else
static bool skcms_can_parse(const void*, size_t) { return true; }
#endif
#define return_if_false(pred, msg) \ #define return_if_false(pred, msg) \
do { \ do { \
@ -1489,7 +1484,8 @@ sk_sp<SkColorSpace> SkColorSpace::MakeICC(const void* input, size_t len) {
} }
// Make sure we're at least as strict as skcms_Parse(). // Make sure we're at least as strict as skcms_Parse().
if (!skcms_can_parse(input, len)) { skcms_ICCProfile p;
if (!skcms_Parse(input, len, &p)) {
return nullptr; return nullptr;
} }

View File

@ -18,10 +18,7 @@
#include "SkTypes.h" #include "SkTypes.h"
#include "Test.h" #include "Test.h"
#include "png.h" #include "png.h"
#include "../third_party/skcms/skcms.h"
#if defined(SK_USE_SKCMS)
#include "skcms.h"
#endif
#include <memory> #include <memory>
#include <utility> #include <utility>
@ -208,7 +205,6 @@ DEF_TEST(ColorSpace_Serialize, r) {
test_serialize(r, SkColorSpace::MakeSRGB(), true); test_serialize(r, SkColorSpace::MakeSRGB(), true);
test_serialize(r, SkColorSpace::MakeSRGBLinear(), true); test_serialize(r, SkColorSpace::MakeSRGBLinear(), true);
#if defined(SK_USE_SKCMS)
auto test = [&](const char* path) { auto test = [&](const char* path) {
sk_sp<SkData> data = GetResourceAsData(path); sk_sp<SkData> data = GetResourceAsData(path);
@ -222,7 +218,6 @@ DEF_TEST(ColorSpace_Serialize, r) {
}; };
test("icc_profiles/HP_ZR30w.icc"); test("icc_profiles/HP_ZR30w.icc");
test("icc_profiles/HP_Z32x.icc"); test("icc_profiles/HP_Z32x.icc");
#endif
SkColorSpaceTransferFn fn; SkColorSpaceTransferFn fn;
fn.fA = 1.0f; fn.fA = 1.0f;
@ -239,7 +234,6 @@ DEF_TEST(ColorSpace_Serialize, r) {
DEF_TEST(ColorSpace_Equals, r) { DEF_TEST(ColorSpace_Equals, r) {
sk_sp<SkColorSpace> srgb = SkColorSpace::MakeSRGB(); sk_sp<SkColorSpace> srgb = SkColorSpace::MakeSRGB();
#if defined(SK_USE_SKCMS)
auto parse = [&](const char* path) { auto parse = [&](const char* path) {
sk_sp<SkData> data = GetResourceAsData(path); sk_sp<SkData> data = GetResourceAsData(path);
@ -253,7 +247,6 @@ DEF_TEST(ColorSpace_Equals, r) {
}; };
sk_sp<SkColorSpace> z30 = parse("icc_profiles/HP_ZR30w.icc"); sk_sp<SkColorSpace> z30 = parse("icc_profiles/HP_ZR30w.icc");
sk_sp<SkColorSpace> z32 = parse("icc_profiles/HP_Z32x.icc"); sk_sp<SkColorSpace> z32 = parse("icc_profiles/HP_Z32x.icc");
#endif
SkColorSpaceTransferFn fn; SkColorSpaceTransferFn fn;
fn.fA = 1.0f; fn.fA = 1.0f;
@ -268,19 +261,15 @@ DEF_TEST(ColorSpace_Equals, r) {
REPORTER_ASSERT(r, SkColorSpace::Equals(nullptr, nullptr)); REPORTER_ASSERT(r, SkColorSpace::Equals(nullptr, nullptr));
REPORTER_ASSERT(r, SkColorSpace::Equals(srgb.get(), srgb.get())); REPORTER_ASSERT(r, SkColorSpace::Equals(srgb.get(), srgb.get()));
#if defined(SK_USE_SKCMS)
REPORTER_ASSERT(r, SkColorSpace::Equals(z30.get(), z30.get())); REPORTER_ASSERT(r, SkColorSpace::Equals(z30.get(), z30.get()));
REPORTER_ASSERT(r, SkColorSpace::Equals(z32.get(), z32.get())); REPORTER_ASSERT(r, SkColorSpace::Equals(z32.get(), z32.get()));
#endif
REPORTER_ASSERT(r, SkColorSpace::Equals(rgb4.get(), rgb4.get())); REPORTER_ASSERT(r, SkColorSpace::Equals(rgb4.get(), rgb4.get()));
REPORTER_ASSERT(r, !SkColorSpace::Equals(nullptr, srgb.get())); REPORTER_ASSERT(r, !SkColorSpace::Equals(nullptr, srgb.get()));
REPORTER_ASSERT(r, !SkColorSpace::Equals(srgb.get(), nullptr)); REPORTER_ASSERT(r, !SkColorSpace::Equals(srgb.get(), nullptr));
#if defined(SK_USE_SKCMS)
REPORTER_ASSERT(r, !SkColorSpace::Equals(z30.get(), srgb.get())); REPORTER_ASSERT(r, !SkColorSpace::Equals(z30.get(), srgb.get()));
REPORTER_ASSERT(r, !SkColorSpace::Equals(z32.get(), z30.get())); REPORTER_ASSERT(r, !SkColorSpace::Equals(z32.get(), z30.get()));
REPORTER_ASSERT(r, !SkColorSpace::Equals(z30.get(), rgb4.get())); REPORTER_ASSERT(r, !SkColorSpace::Equals(z30.get(), rgb4.get()));
#endif
REPORTER_ASSERT(r, !SkColorSpace::Equals(srgb.get(), rgb4.get())); REPORTER_ASSERT(r, !SkColorSpace::Equals(srgb.get(), rgb4.get()));
} }
@ -431,9 +420,7 @@ DEF_TEST(ColorSpace_IsSRGB, r) {
REPORTER_ASSERT(r, !twoDotTwo->isSRGB()); REPORTER_ASSERT(r, !twoDotTwo->isSRGB());
} }
#if defined(SK_USE_SKCMS)
DEF_TEST(ColorSpace_skcms_IsSRGB, r) { DEF_TEST(ColorSpace_skcms_IsSRGB, r) {
sk_sp<SkColorSpace> srgb = SkColorSpace::Make(*skcms_sRGB_profile()); sk_sp<SkColorSpace> srgb = SkColorSpace::Make(*skcms_sRGB_profile());
REPORTER_ASSERT(r, srgb->isSRGB()); REPORTER_ASSERT(r, srgb->isSRGB());
} }
#endif

View File

@ -7,67 +7,63 @@
#include "SkTypes.h" #include "SkTypes.h"
#if defined(SK_USE_SKCMS) #include "Resources.h"
#include "SkColorSpacePriv.h"
#include "SkICC.h"
#include "SkString.h"
#include "Test.h"
#include "../third_party/skcms/skcms.h"
#include "Resources.h" DEF_TEST(WriteICCProfile, r) {
#include "SkColorSpacePriv.h" auto adobeRGB = SkColorSpace::MakeRGB(g2Dot2_TransferFn, SkColorSpace::kAdobeRGB_Gamut);
#include "SkICC.h"
#include "SkString.h"
#include "Test.h"
#include "skcms.h"
DEF_TEST(WriteICCProfile, r) { struct {
auto adobeRGB = SkColorSpace::MakeRGB(g2Dot2_TransferFn, SkColorSpace::kAdobeRGB_Gamut); SkColorSpaceTransferFn fn;
const float* toXYZD50;
const char* desc;
sk_sp<SkColorSpace> want;
} tests[] = {
{g2Dot2_TransferFn, gAdobeRGB_toXYZD50, "AdobeRGB", adobeRGB},
{ gSRGB_TransferFn, gSRGB_toXYZD50, "sRGB", SkColorSpace::MakeSRGB()},
};
struct { for (auto test : tests) {
SkColorSpaceTransferFn fn; sk_sp<SkData> profile = SkWriteICCProfile(test.fn, test.toXYZD50);
const float* toXYZD50; REPORTER_ASSERT(r, profile);
const char* desc;
sk_sp<SkColorSpace> want;
} tests[] = {
{g2Dot2_TransferFn, gAdobeRGB_toXYZD50, "AdobeRGB", adobeRGB},
{ gSRGB_TransferFn, gSRGB_toXYZD50, "sRGB", SkColorSpace::MakeSRGB()},
};
for (auto test : tests) { skcms_ICCProfile parsed;
sk_sp<SkData> profile = SkWriteICCProfile(test.fn, test.toXYZD50); REPORTER_ASSERT(r, skcms_Parse(profile->data(), profile->size(), &parsed));
REPORTER_ASSERT(r, profile);
skcms_ICCProfile parsed; sk_sp<SkColorSpace> got = SkColorSpace::Make(parsed);
REPORTER_ASSERT(r, skcms_Parse(profile->data(), profile->size(), &parsed)); REPORTER_ASSERT(r, got);
REPORTER_ASSERT(r, SkColorSpace::Equals(got.get(), test.want.get()));
sk_sp<SkColorSpace> got = SkColorSpace::Make(parsed); skcms_ICCTag desc;
REPORTER_ASSERT(r, got); REPORTER_ASSERT(r, skcms_GetTagBySignature(&parsed,
REPORTER_ASSERT(r, SkColorSpace::Equals(got.get(), test.want.get())); SkSetFourByteTag('d','e','s','c'),
&desc));
skcms_ICCTag desc; // Rather than really carefully break down the 'desc' tag,
REPORTER_ASSERT(r, skcms_GetTagBySignature(&parsed, // just check our expected description is somewhere in there (as big-endian UTF-16).
SkSetFourByteTag('d','e','s','c'), uint8_t big_endian_utf16[16];
&desc)); for (size_t i = 0; i < strlen(test.desc); i++) {
big_endian_utf16[2*i+0] = 0;
// Rather than really carefully break down the 'desc' tag, big_endian_utf16[2*i+1] = test.desc[i];
// just check our expected description is somewhere in there (as big-endian UTF-16).
uint8_t big_endian_utf16[16];
for (size_t i = 0; i < strlen(test.desc); i++) {
big_endian_utf16[2*i+0] = 0;
big_endian_utf16[2*i+1] = test.desc[i];
}
SkString haystack((const char*)desc.buf, desc.size),
needle ((const char*)big_endian_utf16, 2*strlen(test.desc));
REPORTER_ASSERT(r, haystack.contains(needle.c_str()));
} }
SkString haystack((const char*)desc.buf, desc.size),
needle ((const char*)big_endian_utf16, 2*strlen(test.desc));
REPORTER_ASSERT(r, haystack.contains(needle.c_str()));
} }
}
DEF_TEST(AdobeRGB, r) { DEF_TEST(AdobeRGB, r) {
if (sk_sp<SkData> profile = GetResourceAsData("icc_profiles/AdobeRGB1998.icc")) { if (sk_sp<SkData> profile = GetResourceAsData("icc_profiles/AdobeRGB1998.icc")) {
skcms_ICCProfile parsed; skcms_ICCProfile parsed;
REPORTER_ASSERT(r, skcms_Parse(profile->data(), profile->size(), &parsed)); REPORTER_ASSERT(r, skcms_Parse(profile->data(), profile->size(), &parsed));
auto got = SkColorSpace::Make(parsed); auto got = SkColorSpace::Make(parsed);
auto want = SkColorSpace::MakeRGB(g2Dot2_TransferFn, SkColorSpace::kAdobeRGB_Gamut); auto want = SkColorSpace::MakeRGB(g2Dot2_TransferFn, SkColorSpace::kAdobeRGB_Gamut);
REPORTER_ASSERT(r, SkColorSpace::Equals(got.get(), want.get())); REPORTER_ASSERT(r, SkColorSpace::Equals(got.get(), want.get()));
}
} }
}
#endif