From ea236bf8188e6134bf4deb8d1ecd4665e5b74342 Mon Sep 17 00:00:00 2001 From: Brian Osman Date: Mon, 29 Apr 2019 10:28:22 -0400 Subject: [PATCH] Move skcms.h to include/third_party/skcms Add a shim to redirect until clients are updated Change-Id: Ib43614e5620b1a24ca18187c1646a8ed1a9ee7a4 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/211003 Reviewed-by: Mike Klein Commit-Queue: Brian Osman --- BUILD.gn | 3 +- dm/DMSrcSink.cpp | 3 +- include/core/SkColorSpace.h | 2 +- include/private/SkEncodedInfo.h | 2 +- include/third_party/skcms/skcms.h | 310 +++++++++++++++++++++++++++ public.bzl | 2 +- src/core/SkColorSpace.cpp | 2 +- src/core/SkColorSpaceXformSteps.cpp | 2 +- src/images/SkImageEncoderFns.h | 2 +- tests/ColorSpaceTest.cpp | 2 +- tests/ICCTest.cpp | 3 +- tests/NonlinearBlendingTest.cpp | 2 +- third_party/skcms/skcms.gni | 1 - third_party/skcms/skcms.h | 313 +--------------------------- tools/imgcvt.cpp | 2 +- 15 files changed, 327 insertions(+), 324 deletions(-) create mode 100644 include/third_party/skcms/skcms.h diff --git a/BUILD.gn b/BUILD.gn index 5339658f42..00fda34125 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -762,8 +762,9 @@ source_set("skcms") { } public = [ - "third_party/skcms/skcms.h", + "include/third_party/skcms/skcms.h", ] + include_dirs = [ "include/third_party/skcms" ] sources = rebase_path(skcms_sources, ".", "third_party/skcms") } diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp index ad685ad563..2f84e62468 100644 --- a/dm/DMSrcSink.cpp +++ b/dm/DMSrcSink.cpp @@ -26,6 +26,7 @@ #include "include/ports/SkImageGeneratorWIC.h" #include "include/private/SkImageInfoPriv.h" #include "include/private/SkTLogic.h" +#include "include/third_party/skcms/skcms.h" #include "include/utils/SkNullCanvas.h" #include "include/utils/SkRandom.h" #include "src/codec/SkCodecImageGenerator.h" @@ -74,8 +75,6 @@ #include #include -#include "skcms.h" - static DEFINE_bool(multiPage, false, "For document-type backends, render the source into multiple pages"); static DEFINE_bool(RAW_threading, true, "Allow RAW decodes to run on multiple threads?"); diff --git a/include/core/SkColorSpace.h b/include/core/SkColorSpace.h index 205554aad7..cb55114087 100644 --- a/include/core/SkColorSpace.h +++ b/include/core/SkColorSpace.h @@ -10,7 +10,7 @@ #include "include/private/SkFixed.h" #include "include/private/SkOnce.h" -#include "skcms.h" +#include "include/third_party/skcms/skcms.h" #include "include/core/SkMatrix44.h" #include "include/core/SkRefCnt.h" #include diff --git a/include/private/SkEncodedInfo.h b/include/private/SkEncodedInfo.h index c036b6067f..887198c1e1 100644 --- a/include/private/SkEncodedInfo.h +++ b/include/private/SkEncodedInfo.h @@ -10,7 +10,7 @@ #include "include/core/SkData.h" #include "include/core/SkImageInfo.h" -#include "skcms.h" +#include "include/third_party/skcms/skcms.h" struct SkEncodedInfo { public: diff --git a/include/third_party/skcms/skcms.h b/include/third_party/skcms/skcms.h new file mode 100644 index 0000000000..6ca82360f4 --- /dev/null +++ b/include/third_party/skcms/skcms.h @@ -0,0 +1,310 @@ +/* + * Copyright 2018 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#pragma once + +// skcms.h contains the entire public API for skcms. + +#ifndef SKCMS_API + #define SKCMS_API +#endif + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// A row-major 3x3 matrix (ie vals[row][col]) +typedef struct skcms_Matrix3x3 { + float vals[3][3]; +} skcms_Matrix3x3; + +// It is _not_ safe to alias the pointers to invert in-place. +SKCMS_API bool skcms_Matrix3x3_invert(const skcms_Matrix3x3*, skcms_Matrix3x3*); +SKCMS_API skcms_Matrix3x3 skcms_Matrix3x3_concat(const skcms_Matrix3x3*, const skcms_Matrix3x3*); + +// A row-major 3x4 matrix (ie vals[row][col]) +typedef struct skcms_Matrix3x4 { + float vals[3][4]; +} skcms_Matrix3x4; + +// A transfer function mapping encoded values to linear values, +// represented by this 7-parameter piecewise function: +// +// linear = sign(encoded) * (c*|encoded| + f) , 0 <= |encoded| < d +// = sign(encoded) * ((a*|encoded| + b)^g + e), d <= |encoded| +// +// (A simple gamma transfer function sets g to gamma and a to 1.) +typedef struct skcms_TransferFunction { + float g, a,b,c,d,e,f; +} skcms_TransferFunction; + +SKCMS_API float skcms_TransferFunction_eval (const skcms_TransferFunction*, float); +SKCMS_API bool skcms_TransferFunction_invert(const skcms_TransferFunction*, + skcms_TransferFunction*); + +// Unified representation of 'curv' or 'para' tag data, or a 1D table from 'mft1' or 'mft2' +typedef union skcms_Curve { + struct { + uint32_t alias_of_table_entries; + skcms_TransferFunction parametric; + }; + struct { + uint32_t table_entries; + const uint8_t* table_8; + const uint8_t* table_16; + }; +} skcms_Curve; + +typedef struct skcms_A2B { + // Optional: N 1D curves, followed by an N-dimensional CLUT. + // If input_channels == 0, these curves and CLUT are skipped, + // Otherwise, input_channels must be in [1, 4]. + uint32_t input_channels; + skcms_Curve input_curves[4]; + uint8_t grid_points[4]; + const uint8_t* grid_8; + const uint8_t* grid_16; + + // Optional: 3 1D curves, followed by a color matrix. + // If matrix_channels == 0, these curves and matrix are skipped, + // Otherwise, matrix_channels must be 3. + uint32_t matrix_channels; + skcms_Curve matrix_curves[3]; + skcms_Matrix3x4 matrix; + + // Required: 3 1D curves. Always present, and output_channels must be 3. + uint32_t output_channels; + skcms_Curve output_curves[3]; +} skcms_A2B; + +typedef struct skcms_ICCProfile { + const uint8_t* buffer; + + uint32_t size; + uint32_t data_color_space; + uint32_t pcs; + uint32_t tag_count; + + // skcms_Parse() will set commonly-used fields for you when possible: + + // If we can parse red, green and blue transfer curves from the profile, + // trc will be set to those three curves, and has_trc will be true. + bool has_trc; + skcms_Curve trc[3]; + + // If this profile's gamut can be represented by a 3x3 transform to XYZD50, + // skcms_Parse() sets toXYZD50 to that transform and has_toXYZD50 to true. + bool has_toXYZD50; + skcms_Matrix3x3 toXYZD50; + + // If the profile has a valid A2B0 tag, skcms_Parse() sets A2B to that data, + // and has_A2B to true. + bool has_A2B; + skcms_A2B A2B; +} skcms_ICCProfile; + +// The sRGB color profile is so commonly used that we offer a canonical skcms_ICCProfile for it. +SKCMS_API const skcms_ICCProfile* skcms_sRGB_profile(void); +// Ditto for XYZD50, the most common profile connection space. +SKCMS_API const skcms_ICCProfile* skcms_XYZD50_profile(void); + +SKCMS_API const skcms_TransferFunction* skcms_sRGB_TransferFunction(void); +SKCMS_API const skcms_TransferFunction* skcms_sRGB_Inverse_TransferFunction(void); +SKCMS_API const skcms_TransferFunction* skcms_Identity_TransferFunction(void); + +// Practical equality test for two skcms_ICCProfiles. +// The implementation is subject to change, but it will always try to answer +// "can I substitute A for B?" and "can I skip transforming from A to B?". +SKCMS_API bool skcms_ApproximatelyEqualProfiles(const skcms_ICCProfile* A, + const skcms_ICCProfile* B); + +// Practical test that answers: Is curve roughly the inverse of inv_tf? Typically used by passing +// the inverse of a known parametric transfer function (like sRGB), to determine if a particular +// curve is very close to sRGB. +SKCMS_API bool skcms_AreApproximateInverses(const skcms_Curve* curve, + const skcms_TransferFunction* inv_tf); + +// Similar to above, answering the question for all three TRC curves of the given profile. Again, +// passing skcms_sRGB_InverseTransferFunction as inv_tf will answer the question: +// "Does this profile have a transfer function that is very close to sRGB?" +SKCMS_API bool skcms_TRCs_AreApproximateInverse(const skcms_ICCProfile* profile, + const skcms_TransferFunction* inv_tf); + +// Parse an ICC profile and return true if possible, otherwise return false. +// The buffer is not copied, it must remain valid as long as the skcms_ICCProfile +// will be used. +SKCMS_API bool skcms_Parse(const void*, size_t, skcms_ICCProfile*); + +SKCMS_API bool skcms_ApproximateCurve(const skcms_Curve* curve, + skcms_TransferFunction* approx, + float* max_error); + +typedef struct skcms_ICCTag { + uint32_t signature; + uint32_t type; + uint32_t size; + const uint8_t* buf; +} skcms_ICCTag; + +SKCMS_API void skcms_GetTagByIndex (const skcms_ICCProfile*, uint32_t idx, skcms_ICCTag*); +SKCMS_API bool skcms_GetTagBySignature(const skcms_ICCProfile*, uint32_t sig, skcms_ICCTag*); + +// These are common ICC signature values +enum { + // data_color_space + skcms_Signature_CMYK = 0x434D594B, + skcms_Signature_Gray = 0x47524159, + skcms_Signature_RGB = 0x52474220, + + // pcs + skcms_Signature_Lab = 0x4C616220, + skcms_Signature_XYZ = 0x58595A20, +}; + +typedef enum skcms_PixelFormat { + skcms_PixelFormat_A_8, + skcms_PixelFormat_A_8_, + skcms_PixelFormat_G_8, + skcms_PixelFormat_G_8_, + skcms_PixelFormat_RGBA_8888_Palette8, + skcms_PixelFormat_BGRA_8888_Palette8, + + skcms_PixelFormat_RGB_565, + skcms_PixelFormat_BGR_565, + + skcms_PixelFormat_ABGR_4444, + skcms_PixelFormat_ARGB_4444, + + skcms_PixelFormat_RGB_888, + skcms_PixelFormat_BGR_888, + skcms_PixelFormat_RGBA_8888, + skcms_PixelFormat_BGRA_8888, + + skcms_PixelFormat_RGBA_1010102, + skcms_PixelFormat_BGRA_1010102, + + skcms_PixelFormat_RGB_161616LE, // Little-endian. Pointers must be 16-bit aligned. + skcms_PixelFormat_BGR_161616LE, + skcms_PixelFormat_RGBA_16161616LE, + skcms_PixelFormat_BGRA_16161616LE, + + skcms_PixelFormat_RGB_161616BE, // Big-endian. Pointers must be 16-bit aligned. + skcms_PixelFormat_BGR_161616BE, + skcms_PixelFormat_RGBA_16161616BE, + skcms_PixelFormat_BGRA_16161616BE, + + // TODO: clean up references to non-explicit endian 16161616 + skcms_PixelFormat_RGB_161616 = skcms_PixelFormat_RGB_161616BE, + skcms_PixelFormat_BGR_161616 = skcms_PixelFormat_BGR_161616BE, + skcms_PixelFormat_RGBA_16161616 = skcms_PixelFormat_RGBA_16161616BE, + skcms_PixelFormat_BGRA_16161616 = skcms_PixelFormat_BGRA_16161616BE, + + skcms_PixelFormat_RGB_hhh_Norm, // 1-5-10 half-precision float in [0,1] + skcms_PixelFormat_BGR_hhh_Norm, // Pointers must be 16-bit aligned. + skcms_PixelFormat_RGBA_hhhh_Norm, + skcms_PixelFormat_BGRA_hhhh_Norm, + + skcms_PixelFormat_RGB_hhh, // 1-5-10 half-precision float. + skcms_PixelFormat_BGR_hhh, // Pointers must be 16-bit aligned. + skcms_PixelFormat_RGBA_hhhh, + skcms_PixelFormat_BGRA_hhhh, + + skcms_PixelFormat_RGB_fff, // 1-8-23 single-precision float (the normal kind). + skcms_PixelFormat_BGR_fff, // Pointers must be 32-bit aligned. + skcms_PixelFormat_RGBA_ffff, + skcms_PixelFormat_BGRA_ffff, +} skcms_PixelFormat; + +// We always store any alpha channel linearly. In the chart below, tf-1() is the inverse +// transfer function for the given color profile (applying the transfer function linearizes). + +// We treat opaque as a strong requirement, not just a performance hint: we will ignore +// any source alpha and treat it as 1.0, and will make sure that any destination alpha +// channel is filled with the equivalent of 1.0. + +// We used to offer multiple types of premultiplication, but now just one, PremulAsEncoded. +// This is the premul you're probably used to working with. + +typedef enum skcms_AlphaFormat { + skcms_AlphaFormat_Opaque, // alpha is always opaque + // tf-1(r), tf-1(g), tf-1(b), 1.0 + skcms_AlphaFormat_Unpremul, // alpha and color are unassociated + // tf-1(r), tf-1(g), tf-1(b), a + skcms_AlphaFormat_PremulAsEncoded, // premultiplied while encoded + // tf-1(r)*a, tf-1(g)*a, tf-1(b)*a, a +} skcms_AlphaFormat; + +// Convert npixels pixels from src format and color profile to dst format and color profile +// and return true, otherwise return false. It is safe to alias dst == src if dstFmt == srcFmt. +SKCMS_API bool skcms_Transform(const void* src, + skcms_PixelFormat srcFmt, + skcms_AlphaFormat srcAlpha, + const skcms_ICCProfile* srcProfile, + void* dst, + skcms_PixelFormat dstFmt, + skcms_AlphaFormat dstAlpha, + const skcms_ICCProfile* dstProfile, + size_t npixels); + +// As skcms_Transform(), supporting srcFmts with a palette. +SKCMS_API bool skcms_TransformWithPalette(const void* src, + skcms_PixelFormat srcFmt, + skcms_AlphaFormat srcAlpha, + const skcms_ICCProfile* srcProfile, + void* dst, + skcms_PixelFormat dstFmt, + skcms_AlphaFormat dstAlpha, + const skcms_ICCProfile* dstProfile, + size_t npixels, + const void* palette); + +// If profile can be used as a destination in skcms_Transform, return true. Otherwise, attempt to +// rewrite it with approximations where reasonable. If successful, return true. If no reasonable +// approximation exists, leave the profile unchanged and return false. +SKCMS_API bool skcms_MakeUsableAsDestination(skcms_ICCProfile* profile); + +// If profile can be used as a destination with a single parametric transfer function (ie for +// rasterization), return true. Otherwise, attempt to rewrite it with approximations where +// reasonable. If successful, return true. If no reasonable approximation exists, leave the +// profile unchanged and return false. +SKCMS_API bool skcms_MakeUsableAsDestinationWithSingleCurve(skcms_ICCProfile* profile); + +SKCMS_API bool skcms_PrimariesToXYZD50(float rx, float ry, + float gx, float gy, + float bx, float by, + float wx, float wy, + skcms_Matrix3x3* toXYZD50); + +// Utilities for programmatically constructing profiles +static inline void skcms_Init(skcms_ICCProfile* p) { + memset(p, 0, sizeof(*p)); + p->data_color_space = skcms_Signature_RGB; + p->pcs = skcms_Signature_XYZ; +} + +static inline void skcms_SetTransferFunction(skcms_ICCProfile* p, + const skcms_TransferFunction* tf) { + p->has_trc = true; + for (int i = 0; i < 3; ++i) { + p->trc[i].table_entries = 0; + p->trc[i].parametric = *tf; + } +} + +static inline void skcms_SetXYZD50(skcms_ICCProfile* p, const skcms_Matrix3x3* m) { + p->has_toXYZD50 = true; + p->toXYZD50 = *m; +} + +#ifdef __cplusplus +} +#endif diff --git a/public.bzl b/public.bzl index 73b18d6dbe..010fdc19fa 100644 --- a/public.bzl +++ b/public.bzl @@ -419,6 +419,7 @@ INCLUDES = [ "include/pathops", "include/ports", "include/private", + "include/third_party/skcms", "include/utils", "include/utils/mac", "src/codec", @@ -436,7 +437,6 @@ INCLUDES = [ "src/sksl", "src/utils", "third_party/gif", - "third_party/skcms", ] ################################################################################ diff --git a/src/core/SkColorSpace.cpp b/src/core/SkColorSpace.cpp index 9fe521f7b2..bac4b889ba 100644 --- a/src/core/SkColorSpace.cpp +++ b/src/core/SkColorSpace.cpp @@ -7,9 +7,9 @@ #include "include/core/SkColorSpace.h" #include "include/core/SkData.h" +#include "include/third_party/skcms/skcms.h" #include "src/core/SkColorSpacePriv.h" #include "src/core/SkOpts.h" -#include "skcms.h" bool SkColorSpacePrimaries::toXYZD50(skcms_Matrix3x3* toXYZ_D50) const { return skcms_PrimariesToXYZD50(fRX, fRY, fGX, fGY, fBX, fBY, fWX, fWY, toXYZ_D50); diff --git a/src/core/SkColorSpaceXformSteps.cpp b/src/core/SkColorSpaceXformSteps.cpp index 07b5ebbcbe..9c451215b2 100644 --- a/src/core/SkColorSpaceXformSteps.cpp +++ b/src/core/SkColorSpaceXformSteps.cpp @@ -5,10 +5,10 @@ * found in the LICENSE file. */ +#include "include/third_party/skcms/skcms.h" #include "src/core/SkColorSpacePriv.h" #include "src/core/SkColorSpaceXformSteps.h" #include "src/core/SkRasterPipeline.h" -#include "skcms.h" // TODO(mtklein): explain the logic of this file diff --git a/src/images/SkImageEncoderFns.h b/src/images/SkImageEncoderFns.h index 058430b696..42b9dd7c79 100644 --- a/src/images/SkImageEncoderFns.h +++ b/src/images/SkImageEncoderFns.h @@ -8,11 +8,11 @@ #ifndef SkImageEncoderFns_DEFINED #define SkImageEncoderFns_DEFINED -#include "skcms.h" #include "include/core/SkColor.h" #include "include/core/SkICC.h" #include "include/core/SkTypes.h" #include "include/private/SkColorData.h" +#include "include/third_party/skcms/skcms.h" typedef void (*transform_scanline_proc)(char* dst, const char* src, int width, int bpp); diff --git a/tests/ColorSpaceTest.cpp b/tests/ColorSpaceTest.cpp index e8864d4704..07516f7ad4 100644 --- a/tests/ColorSpaceTest.cpp +++ b/tests/ColorSpaceTest.cpp @@ -12,11 +12,11 @@ #include "include/core/SkRefCnt.h" #include "include/core/SkStream.h" #include "include/core/SkTypes.h" +#include "include/third_party/skcms/skcms.h" #include "src/core/SkColorSpacePriv.h" #include "tests/Test.h" #include "tools/Resources.h" -#include "skcms.h" #include "png.h" #include diff --git a/tests/ICCTest.cpp b/tests/ICCTest.cpp index 5a52f65c3f..f9e62ce95a 100644 --- a/tests/ICCTest.cpp +++ b/tests/ICCTest.cpp @@ -9,12 +9,11 @@ #include "include/core/SkICC.h" #include "include/core/SkString.h" +#include "include/third_party/skcms/skcms.h" #include "src/core/SkColorSpacePriv.h" #include "tests/Test.h" #include "tools/Resources.h" -#include "skcms.h" - DEF_TEST(AdobeRGB, r) { if (sk_sp profile = GetResourceAsData("icc_profiles/AdobeRGB1998.icc")) { skcms_ICCProfile parsed; diff --git a/tests/NonlinearBlendingTest.cpp b/tests/NonlinearBlendingTest.cpp index 9c1d2861df..a4e9892b9d 100644 --- a/tests/NonlinearBlendingTest.cpp +++ b/tests/NonlinearBlendingTest.cpp @@ -5,8 +5,8 @@ * found in the LICENSE file. */ -#include "skcms.h" #include "include/core/SkColorSpace.h" +#include "include/third_party/skcms/skcms.h" #include "src/core/SkColorSpaceXformSteps.h" #include "tests/Test.h" diff --git a/third_party/skcms/skcms.gni b/third_party/skcms/skcms.gni index a3def6e9b5..759f27f133 100644 --- a/third_party/skcms/skcms.gni +++ b/third_party/skcms/skcms.gni @@ -5,7 +5,6 @@ skcms_sources = [ "skcms.cc", - "skcms.h", "skcms_internal.h", "src/Transform_inl.h", ] diff --git a/third_party/skcms/skcms.h b/third_party/skcms/skcms.h index 6ca82360f4..b09df14960 100644 --- a/third_party/skcms/skcms.h +++ b/third_party/skcms/skcms.h @@ -1,310 +1,5 @@ -/* - * Copyright 2018 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ +// Copyright 2019 Google LLC. +// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. -#pragma once - -// skcms.h contains the entire public API for skcms. - -#ifndef SKCMS_API - #define SKCMS_API -#endif - -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -// A row-major 3x3 matrix (ie vals[row][col]) -typedef struct skcms_Matrix3x3 { - float vals[3][3]; -} skcms_Matrix3x3; - -// It is _not_ safe to alias the pointers to invert in-place. -SKCMS_API bool skcms_Matrix3x3_invert(const skcms_Matrix3x3*, skcms_Matrix3x3*); -SKCMS_API skcms_Matrix3x3 skcms_Matrix3x3_concat(const skcms_Matrix3x3*, const skcms_Matrix3x3*); - -// A row-major 3x4 matrix (ie vals[row][col]) -typedef struct skcms_Matrix3x4 { - float vals[3][4]; -} skcms_Matrix3x4; - -// A transfer function mapping encoded values to linear values, -// represented by this 7-parameter piecewise function: -// -// linear = sign(encoded) * (c*|encoded| + f) , 0 <= |encoded| < d -// = sign(encoded) * ((a*|encoded| + b)^g + e), d <= |encoded| -// -// (A simple gamma transfer function sets g to gamma and a to 1.) -typedef struct skcms_TransferFunction { - float g, a,b,c,d,e,f; -} skcms_TransferFunction; - -SKCMS_API float skcms_TransferFunction_eval (const skcms_TransferFunction*, float); -SKCMS_API bool skcms_TransferFunction_invert(const skcms_TransferFunction*, - skcms_TransferFunction*); - -// Unified representation of 'curv' or 'para' tag data, or a 1D table from 'mft1' or 'mft2' -typedef union skcms_Curve { - struct { - uint32_t alias_of_table_entries; - skcms_TransferFunction parametric; - }; - struct { - uint32_t table_entries; - const uint8_t* table_8; - const uint8_t* table_16; - }; -} skcms_Curve; - -typedef struct skcms_A2B { - // Optional: N 1D curves, followed by an N-dimensional CLUT. - // If input_channels == 0, these curves and CLUT are skipped, - // Otherwise, input_channels must be in [1, 4]. - uint32_t input_channels; - skcms_Curve input_curves[4]; - uint8_t grid_points[4]; - const uint8_t* grid_8; - const uint8_t* grid_16; - - // Optional: 3 1D curves, followed by a color matrix. - // If matrix_channels == 0, these curves and matrix are skipped, - // Otherwise, matrix_channels must be 3. - uint32_t matrix_channels; - skcms_Curve matrix_curves[3]; - skcms_Matrix3x4 matrix; - - // Required: 3 1D curves. Always present, and output_channels must be 3. - uint32_t output_channels; - skcms_Curve output_curves[3]; -} skcms_A2B; - -typedef struct skcms_ICCProfile { - const uint8_t* buffer; - - uint32_t size; - uint32_t data_color_space; - uint32_t pcs; - uint32_t tag_count; - - // skcms_Parse() will set commonly-used fields for you when possible: - - // If we can parse red, green and blue transfer curves from the profile, - // trc will be set to those three curves, and has_trc will be true. - bool has_trc; - skcms_Curve trc[3]; - - // If this profile's gamut can be represented by a 3x3 transform to XYZD50, - // skcms_Parse() sets toXYZD50 to that transform and has_toXYZD50 to true. - bool has_toXYZD50; - skcms_Matrix3x3 toXYZD50; - - // If the profile has a valid A2B0 tag, skcms_Parse() sets A2B to that data, - // and has_A2B to true. - bool has_A2B; - skcms_A2B A2B; -} skcms_ICCProfile; - -// The sRGB color profile is so commonly used that we offer a canonical skcms_ICCProfile for it. -SKCMS_API const skcms_ICCProfile* skcms_sRGB_profile(void); -// Ditto for XYZD50, the most common profile connection space. -SKCMS_API const skcms_ICCProfile* skcms_XYZD50_profile(void); - -SKCMS_API const skcms_TransferFunction* skcms_sRGB_TransferFunction(void); -SKCMS_API const skcms_TransferFunction* skcms_sRGB_Inverse_TransferFunction(void); -SKCMS_API const skcms_TransferFunction* skcms_Identity_TransferFunction(void); - -// Practical equality test for two skcms_ICCProfiles. -// The implementation is subject to change, but it will always try to answer -// "can I substitute A for B?" and "can I skip transforming from A to B?". -SKCMS_API bool skcms_ApproximatelyEqualProfiles(const skcms_ICCProfile* A, - const skcms_ICCProfile* B); - -// Practical test that answers: Is curve roughly the inverse of inv_tf? Typically used by passing -// the inverse of a known parametric transfer function (like sRGB), to determine if a particular -// curve is very close to sRGB. -SKCMS_API bool skcms_AreApproximateInverses(const skcms_Curve* curve, - const skcms_TransferFunction* inv_tf); - -// Similar to above, answering the question for all three TRC curves of the given profile. Again, -// passing skcms_sRGB_InverseTransferFunction as inv_tf will answer the question: -// "Does this profile have a transfer function that is very close to sRGB?" -SKCMS_API bool skcms_TRCs_AreApproximateInverse(const skcms_ICCProfile* profile, - const skcms_TransferFunction* inv_tf); - -// Parse an ICC profile and return true if possible, otherwise return false. -// The buffer is not copied, it must remain valid as long as the skcms_ICCProfile -// will be used. -SKCMS_API bool skcms_Parse(const void*, size_t, skcms_ICCProfile*); - -SKCMS_API bool skcms_ApproximateCurve(const skcms_Curve* curve, - skcms_TransferFunction* approx, - float* max_error); - -typedef struct skcms_ICCTag { - uint32_t signature; - uint32_t type; - uint32_t size; - const uint8_t* buf; -} skcms_ICCTag; - -SKCMS_API void skcms_GetTagByIndex (const skcms_ICCProfile*, uint32_t idx, skcms_ICCTag*); -SKCMS_API bool skcms_GetTagBySignature(const skcms_ICCProfile*, uint32_t sig, skcms_ICCTag*); - -// These are common ICC signature values -enum { - // data_color_space - skcms_Signature_CMYK = 0x434D594B, - skcms_Signature_Gray = 0x47524159, - skcms_Signature_RGB = 0x52474220, - - // pcs - skcms_Signature_Lab = 0x4C616220, - skcms_Signature_XYZ = 0x58595A20, -}; - -typedef enum skcms_PixelFormat { - skcms_PixelFormat_A_8, - skcms_PixelFormat_A_8_, - skcms_PixelFormat_G_8, - skcms_PixelFormat_G_8_, - skcms_PixelFormat_RGBA_8888_Palette8, - skcms_PixelFormat_BGRA_8888_Palette8, - - skcms_PixelFormat_RGB_565, - skcms_PixelFormat_BGR_565, - - skcms_PixelFormat_ABGR_4444, - skcms_PixelFormat_ARGB_4444, - - skcms_PixelFormat_RGB_888, - skcms_PixelFormat_BGR_888, - skcms_PixelFormat_RGBA_8888, - skcms_PixelFormat_BGRA_8888, - - skcms_PixelFormat_RGBA_1010102, - skcms_PixelFormat_BGRA_1010102, - - skcms_PixelFormat_RGB_161616LE, // Little-endian. Pointers must be 16-bit aligned. - skcms_PixelFormat_BGR_161616LE, - skcms_PixelFormat_RGBA_16161616LE, - skcms_PixelFormat_BGRA_16161616LE, - - skcms_PixelFormat_RGB_161616BE, // Big-endian. Pointers must be 16-bit aligned. - skcms_PixelFormat_BGR_161616BE, - skcms_PixelFormat_RGBA_16161616BE, - skcms_PixelFormat_BGRA_16161616BE, - - // TODO: clean up references to non-explicit endian 16161616 - skcms_PixelFormat_RGB_161616 = skcms_PixelFormat_RGB_161616BE, - skcms_PixelFormat_BGR_161616 = skcms_PixelFormat_BGR_161616BE, - skcms_PixelFormat_RGBA_16161616 = skcms_PixelFormat_RGBA_16161616BE, - skcms_PixelFormat_BGRA_16161616 = skcms_PixelFormat_BGRA_16161616BE, - - skcms_PixelFormat_RGB_hhh_Norm, // 1-5-10 half-precision float in [0,1] - skcms_PixelFormat_BGR_hhh_Norm, // Pointers must be 16-bit aligned. - skcms_PixelFormat_RGBA_hhhh_Norm, - skcms_PixelFormat_BGRA_hhhh_Norm, - - skcms_PixelFormat_RGB_hhh, // 1-5-10 half-precision float. - skcms_PixelFormat_BGR_hhh, // Pointers must be 16-bit aligned. - skcms_PixelFormat_RGBA_hhhh, - skcms_PixelFormat_BGRA_hhhh, - - skcms_PixelFormat_RGB_fff, // 1-8-23 single-precision float (the normal kind). - skcms_PixelFormat_BGR_fff, // Pointers must be 32-bit aligned. - skcms_PixelFormat_RGBA_ffff, - skcms_PixelFormat_BGRA_ffff, -} skcms_PixelFormat; - -// We always store any alpha channel linearly. In the chart below, tf-1() is the inverse -// transfer function for the given color profile (applying the transfer function linearizes). - -// We treat opaque as a strong requirement, not just a performance hint: we will ignore -// any source alpha and treat it as 1.0, and will make sure that any destination alpha -// channel is filled with the equivalent of 1.0. - -// We used to offer multiple types of premultiplication, but now just one, PremulAsEncoded. -// This is the premul you're probably used to working with. - -typedef enum skcms_AlphaFormat { - skcms_AlphaFormat_Opaque, // alpha is always opaque - // tf-1(r), tf-1(g), tf-1(b), 1.0 - skcms_AlphaFormat_Unpremul, // alpha and color are unassociated - // tf-1(r), tf-1(g), tf-1(b), a - skcms_AlphaFormat_PremulAsEncoded, // premultiplied while encoded - // tf-1(r)*a, tf-1(g)*a, tf-1(b)*a, a -} skcms_AlphaFormat; - -// Convert npixels pixels from src format and color profile to dst format and color profile -// and return true, otherwise return false. It is safe to alias dst == src if dstFmt == srcFmt. -SKCMS_API bool skcms_Transform(const void* src, - skcms_PixelFormat srcFmt, - skcms_AlphaFormat srcAlpha, - const skcms_ICCProfile* srcProfile, - void* dst, - skcms_PixelFormat dstFmt, - skcms_AlphaFormat dstAlpha, - const skcms_ICCProfile* dstProfile, - size_t npixels); - -// As skcms_Transform(), supporting srcFmts with a palette. -SKCMS_API bool skcms_TransformWithPalette(const void* src, - skcms_PixelFormat srcFmt, - skcms_AlphaFormat srcAlpha, - const skcms_ICCProfile* srcProfile, - void* dst, - skcms_PixelFormat dstFmt, - skcms_AlphaFormat dstAlpha, - const skcms_ICCProfile* dstProfile, - size_t npixels, - const void* palette); - -// If profile can be used as a destination in skcms_Transform, return true. Otherwise, attempt to -// rewrite it with approximations where reasonable. If successful, return true. If no reasonable -// approximation exists, leave the profile unchanged and return false. -SKCMS_API bool skcms_MakeUsableAsDestination(skcms_ICCProfile* profile); - -// If profile can be used as a destination with a single parametric transfer function (ie for -// rasterization), return true. Otherwise, attempt to rewrite it with approximations where -// reasonable. If successful, return true. If no reasonable approximation exists, leave the -// profile unchanged and return false. -SKCMS_API bool skcms_MakeUsableAsDestinationWithSingleCurve(skcms_ICCProfile* profile); - -SKCMS_API bool skcms_PrimariesToXYZD50(float rx, float ry, - float gx, float gy, - float bx, float by, - float wx, float wy, - skcms_Matrix3x3* toXYZD50); - -// Utilities for programmatically constructing profiles -static inline void skcms_Init(skcms_ICCProfile* p) { - memset(p, 0, sizeof(*p)); - p->data_color_space = skcms_Signature_RGB; - p->pcs = skcms_Signature_XYZ; -} - -static inline void skcms_SetTransferFunction(skcms_ICCProfile* p, - const skcms_TransferFunction* tf) { - p->has_trc = true; - for (int i = 0; i < 3; ++i) { - p->trc[i].table_entries = 0; - p->trc[i].parametric = *tf; - } -} - -static inline void skcms_SetXYZD50(skcms_ICCProfile* p, const skcms_Matrix3x3* m) { - p->has_toXYZD50 = true; - p->toXYZD50 = *m; -} - -#ifdef __cplusplus -} -#endif +// This is a temporary redirection header until clients are updated to use the skcms.h in include +#include "../../include/third_party/skcms/skcms.h" diff --git a/tools/imgcvt.cpp b/tools/imgcvt.cpp index 71b599cefb..5c024f0462 100644 --- a/tools/imgcvt.cpp +++ b/tools/imgcvt.cpp @@ -5,12 +5,12 @@ * found in the LICENSE file. */ -#include "skcms.h" #include "include/core/SkCanvas.h" #include "include/core/SkData.h" #include "include/core/SkImage.h" #include "include/core/SkStream.h" #include "include/core/SkSurface.h" +#include "include/third_party/skcms/skcms.h" #include "src/core/SkColorSpacePriv.h" static void write_png(const char* path, sk_sp img) {