remove profile.tf, use profile.trc[0-2] instead
Change-Id: Ie12a02832a6e1ec105fa587af4b93c2e0bf8055f
Reviewed-on: https://skia-review.googlesource.com/112160
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Mike Klein <mtklein@chromium.org>
diff --git a/skcms.h b/skcms.h
index d233484..7fac666 100644
--- a/skcms.h
+++ b/skcms.h
@@ -107,12 +107,6 @@
// skcms_Parse() will set commonly-used fields for you when possible:
- // If the transfer functions for all color channels in this profile are
- // identical and can be represented by a single skcms_TransferFunction,
- // skcms_Parse() sets tf to that function and has_tf to true.
- bool has_tf;
- skcms_TransferFunction tf;
-
// 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;
diff --git a/src/ICCProfile.c b/src/ICCProfile.c
index cf0cc5b..71381dd 100644
--- a/src/ICCProfile.c
+++ b/src/ICCProfile.c
@@ -285,26 +285,6 @@
return false;
}
-static bool get_transfer_function(const skcms_ICCProfile* profile,
- skcms_TransferFunction* transferFunction) {
- if (!profile->has_trc) {
- return false;
- }
-
- const skcms_Curve* trc = profile->trc;
- if (trc[0].table_entries || trc[1].table_entries || trc[2].table_entries) {
- return false;
- }
-
- if (0 != memcmp(&trc[0].parametric, &trc[1].parametric, SAFE_SIZEOF(trc[0].parametric)) ||
- 0 != memcmp(&trc[0].parametric, &trc[2].parametric, SAFE_SIZEOF(trc[0].parametric))) {
- return false;
- }
-
- *transferFunction = trc[0].parametric;
- return true;
-}
-
bool skcms_ApproximateTransferFunction(const skcms_ICCProfile* profile,
skcms_TransferFunction* fn,
float* max_error) {
@@ -788,8 +768,6 @@
profile->has_trc = true;
}
- profile->has_tf = get_transfer_function(profile, &profile->tf);
-
skcms_ICCTag rXYZ, gXYZ, bXYZ;
if (skcms_GetTagBySignature(profile, make_signature('r', 'X', 'Y', 'Z'), &rXYZ) &&
skcms_GetTagBySignature(profile, make_signature('g', 'X', 'Y', 'Z'), &gXYZ) &&
diff --git a/src/Transform.c b/src/Transform.c
index 9635e11..575ac50 100644
--- a/src/Transform.c
+++ b/src/Transform.c
@@ -741,13 +741,21 @@
next_stage(i,ip,ctx, r,g,b,a);
}
-static void transfer_function(int i, void** ip, Context* ctx, F r, F g, F b, F a) {
+static void transfer_function_r(int i, void** ip, Context* ctx, F r, F g, F b, F a) {
const skcms_TransferFunction* tf = *ctx->args++;
-
r = apply_transfer_function(tf, r);
- g = apply_transfer_function(tf, g);
- b = apply_transfer_function(tf, b);
+ next_stage(i,ip,ctx, r,g,b,a);
+}
+static void transfer_function_g(int i, void** ip, Context* ctx, F r, F g, F b, F a) {
+ const skcms_TransferFunction* tf = *ctx->args++;
+ g = apply_transfer_function(tf, g);
+ next_stage(i,ip,ctx, r,g,b,a);
+}
+
+static void transfer_function_b(int i, void** ip, Context* ctx, F r, F g, F b, F a) {
+ const skcms_TransferFunction* tf = *ctx->args++;
+ b = apply_transfer_function(tf, b);
next_stage(i,ip,ctx, r,g,b,a);
}
@@ -780,6 +788,13 @@
return 0;
}
+static bool is_parametric(const skcms_ICCProfile* profile) {
+ return profile->has_trc
+ && profile->trc[0].table_entries == 0
+ && profile->trc[1].table_entries == 0
+ && profile->trc[2].table_entries == 0;
+}
+
bool skcms_Transform(const void* src, skcms_PixelFormat srcFmt, const skcms_ICCProfile* srcProfile,
void* dst, skcms_PixelFormat dstFmt, const skcms_ICCProfile* dstProfile,
size_t nz) {
@@ -809,7 +824,7 @@
void** ip = program;
const void** args = arguments;
- skcms_TransferFunction inv_dst_tf;
+ skcms_TransferFunction inv_dst_tf_r, inv_dst_tf_g, inv_dst_tf_b;
skcms_Matrix3x3 from_xyz;
switch (srcFmt >> 1) {
@@ -835,9 +850,11 @@
// TODO: A2B, Lab -> XYZ, tables, etc...
// 1) Src RGB to XYZ
- if (srcProfile->has_tf && srcProfile->has_toXYZD50) {
- *ip++ = (void*)transfer_function; *args++ = &srcProfile->tf;
- *ip++ = (void*)matrix_3x3; *args++ = &srcProfile->toXYZD50;
+ if (is_parametric(srcProfile) && srcProfile->has_toXYZD50) {
+ *ip++ = (void*)transfer_function_r; *args++ = &srcProfile->trc[0].parametric;
+ *ip++ = (void*)transfer_function_g; *args++ = &srcProfile->trc[1].parametric;
+ *ip++ = (void*)transfer_function_b; *args++ = &srcProfile->trc[2].parametric;
+ *ip++ = (void*)matrix_3x3; *args++ = &srcProfile->toXYZD50;
} else {
return false;
}
@@ -845,12 +862,16 @@
// 2) Lab <-> XYZ (if PCS is different)
// 3) Dst XYZ to RGB
- if (dstProfile->has_tf &&
+ if (is_parametric(dstProfile) &&
+ skcms_TransferFunction_invert(&dstProfile->trc[0].parametric, &inv_dst_tf_r) &&
+ skcms_TransferFunction_invert(&dstProfile->trc[1].parametric, &inv_dst_tf_g) &&
+ skcms_TransferFunction_invert(&dstProfile->trc[2].parametric, &inv_dst_tf_b) &&
dstProfile->has_toXYZD50 &&
- skcms_TransferFunction_invert(&dstProfile->tf, &inv_dst_tf) &&
skcms_Matrix3x3_invert(&dstProfile->toXYZD50, &from_xyz)) {
- *ip++ = (void*)matrix_3x3; *args++ = &from_xyz;
- *ip++ = (void*)transfer_function; *args++ = &inv_dst_tf;
+ *ip++ = (void*)matrix_3x3; *args++ = &from_xyz;
+ *ip++ = (void*)transfer_function_r; *args++ = &inv_dst_tf_r;
+ *ip++ = (void*)transfer_function_g; *args++ = &inv_dst_tf_g;
+ *ip++ = (void*)transfer_function_b; *args++ = &inv_dst_tf_b;
} else {
return false;
}
diff --git a/test_only.c b/test_only.c
index 96c4d50..71b355c 100644
--- a/test_only.c
+++ b/test_only.c
@@ -10,9 +10,10 @@
#endif
#include "skcms.h"
-#include "test_only.h"
#include "src/TransferFunction.h"
+#include "test_only.h"
#include <stdlib.h>
+#include <string.h>
static void signature_to_string(uint32_t sig, char* str) {
str[0] = (char)((sig >> 24) & 0xFF);
@@ -47,6 +48,25 @@
}
}
+static bool has_single_transfer_function(const skcms_ICCProfile* profile,
+ skcms_TransferFunction* tf) {
+ const skcms_Curve* trc = profile->trc;
+ if (profile->has_trc &&
+ trc[0].table_entries == 0 &&
+ trc[1].table_entries == 0 &&
+ trc[2].table_entries == 0) {
+
+ if (0 != memcmp(&trc[0].parametric, &trc[1].parametric, sizeof(skcms_TransferFunction)) ||
+ 0 != memcmp(&trc[0].parametric, &trc[2].parametric, sizeof(skcms_TransferFunction))) {
+ return false;
+ }
+
+ memcpy(tf, &trc[0].parametric, sizeof(skcms_TransferFunction));
+ return true;
+ }
+ return false;
+}
+
void dump_profile(const skcms_ICCProfile* profile, FILE* fp, bool for_unit_test) {
fprintf(fp, "%20s : 0x%08X : %u\n", "Size", profile->size, profile->size);
dump_sig_field(fp, "CMM type", profile->cmm_type);
@@ -94,9 +114,11 @@
fprintf(fp, "\n");
skcms_TransferFunction tf;
+ bool has_single_tf = has_single_transfer_function(profile, &tf);
+
float max_error;
- if (profile->has_tf) {
- dump_transfer_function(fp, "TRC", &profile->tf);
+ if (has_single_tf) {
+ dump_transfer_function(fp, "TRC", &tf);
} else if (skcms_ApproximateTransferFunction(profile, &tf, &max_error)) {
if (for_unit_test) {
// The approximated transfer function can vary significantly, due to FMA, etc. In unit
@@ -113,7 +135,7 @@
}
}
- if (!profile->has_tf && profile->has_trc) {
+ if (!has_single_tf && profile->has_trc) {
const char* trcNames[3] = { "rTRC", "gTRC", "bTRC" };
for (int i = 0; i < 3; ++i) {
dump_curve(fp, trcNames[i], &profile->trc[i]);
diff --git a/tests.c b/tests.c
index 0034238..cadde07 100644
--- a/tests.c
+++ b/tests.c
@@ -892,16 +892,16 @@
skcms_ICCProfile p;
expect( load_file("profiles/mobile/sRGB_parametric.icc", &ptr, &len) );
- expect( skcms_Parse(ptr, len, &p) && p.has_tf && skcms_IsSRGB(&p.tf) );
+ expect( skcms_Parse(ptr, len, &p) && p.has_trc && skcms_IsSRGB(&p.trc[0].parametric) );
free(ptr);
expect( load_file("profiles/mobile/Display_P3_parametric.icc", &ptr, &len) );
- expect( skcms_Parse(ptr, len, &p) && p.has_tf && skcms_IsSRGB(&p.tf) );
+ expect( skcms_Parse(ptr, len, &p) && p.has_trc && skcms_IsSRGB(&p.trc[0].parametric) );
free(ptr);
// TODO: relax skcms_IsSRGB() so that this one is seen as sRGB too? It's not far.
expect( load_file("profiles/mobile/iPhone7p.icc", &ptr, &len) );
- expect( skcms_Parse(ptr, len, &p) && p.has_tf && !skcms_IsSRGB(&p.tf) );
+ expect( skcms_Parse(ptr, len, &p) && p.has_trc && !skcms_IsSRGB(&p.trc[0].parametric) );
free(ptr);
}
@@ -915,7 +915,9 @@
expect( skcms_Parse(ptr, len, &sRGB) );
skcms_ICCProfile linear_sRGB = sRGB;
- linear_sRGB.tf = (skcms_TransferFunction){ 1,1,0,0,0,0,0 };
+ linear_sRGB.trc[0].parametric = (skcms_TransferFunction){ 1,1,0,0,0,0,0 };
+ linear_sRGB.trc[1].parametric = (skcms_TransferFunction){ 1,1,0,0,0,0,0 };
+ linear_sRGB.trc[2].parametric = (skcms_TransferFunction){ 1,1,0,0,0,0,0 };
// Enough to hit all distinct bytes when interpreted as RGB 888.
uint8_t src[258],
@@ -929,7 +931,7 @@
258/3) );
for (int i = 0; i < 256; i++) {
- float linear = skcms_TransferFunction_eval(&sRGB.tf, i * (1/255.0f));
+ float linear = skcms_TransferFunction_eval(&sRGB.trc[0].parametric, i * (1/255.0f));
uint8_t expected = (uint8_t)(linear * 255.0f + 0.5f);
// There is one known failure today: