summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPekka Paalanen <pekka.paalanen@collabora.com>2024-04-10 14:19:45 +0300
committerPekka Paalanen <pq@iki.fi>2024-04-19 12:19:36 +0000
commit94ccce4e3866c42e62ea68c66698b4b678bbb066 (patch)
treeaa3898108667b35b64574181ba3aef560fd42bc7
parent7d38e044dd086fad7c81c790de0b9050c224f0e5 (diff)
tests: replace mat2XYZ
The primaries and the white point are the fundamental definition of the color spaces in these tests. Instead of hard-coding mat2XYZ, use LittleCMS to derive the result from the fundamental definition. This removes derived hard-coded constants, which is a benefit in itself. How these constants were originally produced was not mentioned in 0c5860fafb079b8edba66e4e805d26b563c8e529 but I was able to reproduce them with python3: import colour import numpy as np x = colour.RGB_COLOURSPACES['sRGB'] w_d50 = np.array([0.34567, 0.35850]) print(x.chromatically_adapt(w_d50, 'D50', 'Bradford')) It's identical to 3-4 decimals of the hardcoded values, and also for Adobe RGB. I printed the LittleCMS generated values as well, and they are the same as with python up to roughly 4 decimals. Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
-rw-r--r--tests/color-icc-output-test.c6
-rw-r--r--tests/color-management-test.c3
-rw-r--r--tests/lcms_util.c73
-rw-r--r--tests/lcms_util.h6
4 files changed, 57 insertions, 31 deletions
diff --git a/tests/color-icc-output-test.c b/tests/color-icc-output-test.c
index 9c71a239..5cd10afb 100644
--- a/tests/color-icc-output-test.c
+++ b/tests/color-icc-output-test.c
@@ -59,9 +59,6 @@ const struct lcms_pipeline pipeline_sRGB = {
.mat = LCMSMAT3(1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0),
- .mat2XYZ = LCMSMAT3(0.436037, 0.385124, 0.143039,
- 0.222482, 0.716913, 0.060605,
- 0.013922, 0.097078, 0.713899),
.post_fn = TRANSFER_FN_SRGB_EOTF_INVERSE
};
@@ -76,9 +73,6 @@ const struct lcms_pipeline pipeline_adobeRGB = {
.mat = LCMSMAT3( 0.715127, 0.284868, 0.000005,
0.000001, 0.999995, 0.000004,
-0.000003, 0.041155, 0.958848),
- .mat2XYZ = LCMSMAT3(0.609740, 0.205279, 0.149181,
- 0.311111, 0.625681, 0.063208,
- 0.019469, 0.060879, 0.744552),
.post_fn = TRANSFER_FN_ADOBE_RGB_EOTF_INVERSE
};
diff --git a/tests/color-management-test.c b/tests/color-management-test.c
index 5db56153..ec748667 100644
--- a/tests/color-management-test.c
+++ b/tests/color-management-test.c
@@ -61,9 +61,6 @@ const struct lcms_pipeline pipeline_sRGB = {
.mat = LCMSMAT3(1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0),
- .mat2XYZ = LCMSMAT3(0.436037, 0.385124, 0.143039,
- 0.222482, 0.716913, 0.060605,
- 0.013922, 0.097078, 0.713899),
.post_fn = TRANSFER_FN_SRGB_EOTF_INVERSE
};
diff --git a/tests/lcms_util.c b/tests/lcms_util.c
index 7478a967..3fcd5712 100644
--- a/tests/lcms_util.c
+++ b/tests/lcms_util.c
@@ -32,11 +32,12 @@
#include <assert.h>
#include <stdlib.h>
+#include <libweston/matrix.h>
#include "shared/helpers.h"
#include "color_util.h"
#include "lcms_util.h"
-static cmsCIExyY wp_d65 = { 0.31271, 0.32902, 1.0 };
+static const cmsCIExyY wp_d65 = { 0.31271, 0.32902, 1.0 };
/*
* MPE tone curves can only use LittleCMS parametric curve types 6-8 and not
@@ -280,32 +281,33 @@ roundtrip_verification(cmsPipeline *DToB, cmsPipeline *BToD, float tolerance)
assert(stat.two_norm.max < tolerance);
}
+struct transform_sampler_context {
+ cmsHTRANSFORM t;
+};
+
static cmsInt32Number
-sampler_matrix(const float src[], float dst[], void *cargo)
+transform_sampler(const float src[], float dst[], void *cargo)
{
- const struct lcmsMAT3 *mat = cargo;
- struct color_float in = { .r = src[0], .g = src[1], .b = src[2] };
- struct color_float cf;
- unsigned i;
-
- cf = color_float_apply_matrix(mat, in);
+ const struct transform_sampler_context *tsc = cargo;
- for (i = 0; i < COLOR_CHAN_NUM; i++)
- dst[i] = cf.rgb[i];
+ cmsDoTransform(tsc->t, src, dst, 1);
return 1;
}
static cmsStage *
-create_cLUT_from_matrix(cmsContext context_id, const struct lcmsMAT3 *mat,
- int dim_size)
+create_cLUT_from_transform(cmsContext context_id, const cmsHTRANSFORM t,
+ int dim_size)
{
+ struct transform_sampler_context tsc;
cmsStage *cLUT_stage;
assert(dim_size);
+ tsc.t = t;
+
cLUT_stage = cmsStageAllocCLutFloat(context_id, dim_size, 3, 3, NULL);
- cmsStageSampleCLutFloat(cLUT_stage, sampler_matrix, (void *)mat, 0);
+ cmsStageSampleCLutFloat(cLUT_stage, transform_sampler, &tsc, 0);
return cLUT_stage;
}
@@ -341,9 +343,41 @@ build_lcms_clut_profile_output(cmsContext context_id,
cmsStage *stage;
cmsStage *stage_inv_eotf;
cmsStage *stage_eotf;
- struct lcmsMAT3 mat2XYZ_inv;
+ cmsToneCurve *identity_curves[3];
+ cmsHPROFILE linear_device;
+ cmsHPROFILE pcs;
+ cmsHTRANSFORM linear_device_to_pcs;
+ cmsHTRANSFORM pcs_to_linear_device;
+
+ identity_curves[0] = identity_curves[1] = identity_curves[2] =
+ cmsBuildGamma(context_id, 1.0);
- lcmsMAT3_invert(&mat2XYZ_inv, &pipeline->mat2XYZ);
+ linear_device = cmsCreateRGBProfileTHR(context_id, &wp_d65,
+ &pipeline->prim_output,
+ identity_curves);
+ assert(cmsIsMatrixShaper(linear_device));
+ cmsFreeToneCurve(identity_curves[0]);
+
+ pcs = cmsCreateXYZProfileTHR(context_id);
+
+ /*
+ * Since linear_device is a matrix-shaper profile, all rendering intents
+ * share the same device<->PCS transformations. We only need to pick
+ * an arbitrary rendering intent that allows to turn BPC both on and off.
+ */
+ linear_device_to_pcs = cmsCreateTransformTHR(context_id,
+ linear_device, TYPE_RGB_FLT,
+ pcs, TYPE_XYZ_FLT,
+ INTENT_RELATIVE_COLORIMETRIC,
+ cmsFLAGS_NOOPTIMIZE);
+ pcs_to_linear_device = cmsCreateTransformTHR(context_id,
+ pcs, TYPE_XYZ_FLT,
+ linear_device, TYPE_RGB_FLT,
+ INTENT_RELATIVE_COLORIMETRIC,
+ cmsFLAGS_NOOPTIMIZE);
+
+ cmsCloseProfile(linear_device);
+ cmsCloseProfile(pcs);
hRGB = cmsCreateProfilePlaceholder(context_id);
cmsSetProfileVersion(hRGB, 4.3);
@@ -360,7 +394,8 @@ build_lcms_clut_profile_output(cmsContext context_id,
*/
BToD0 = cmsPipelineAlloc(context_id, 3, 3);
- stage = create_cLUT_from_matrix(context_id, &mat2XYZ_inv, clut_dim_size);
+ stage = create_cLUT_from_transform(context_id, pcs_to_linear_device,
+ clut_dim_size);
cmsPipelineInsertStage(BToD0, cmsAT_END, stage);
cmsPipelineInsertStage(BToD0, cmsAT_END, cmsStageDup(stage_inv_eotf));
@@ -375,7 +410,8 @@ build_lcms_clut_profile_output(cmsContext context_id,
DToB0 = cmsPipelineAlloc(context_id, 3, 3);
cmsPipelineInsertStage(DToB0, cmsAT_END, cmsStageDup(stage_eotf));
- stage = create_cLUT_from_matrix(context_id, &pipeline->mat2XYZ, clut_dim_size);
+ stage = create_cLUT_from_transform(context_id, linear_device_to_pcs,
+ clut_dim_size);
cmsPipelineInsertStage(DToB0, cmsAT_END, stage);
cmsWriteTag(hRGB, cmsSigDToB0Tag, DToB0);
@@ -392,6 +428,9 @@ build_lcms_clut_profile_output(cmsContext context_id,
cmsStageFree(stage_eotf);
cmsStageFree(stage_inv_eotf);
+ cmsDeleteTransform(linear_device_to_pcs);
+ cmsDeleteTransform(pcs_to_linear_device);
+
return hRGB;
}
diff --git a/tests/lcms_util.h b/tests/lcms_util.h
index 5afe671c..78feefa6 100644
--- a/tests/lcms_util.h
+++ b/tests/lcms_util.h
@@ -36,6 +36,7 @@ struct lcms_pipeline {
const char *color_space;
/**
* Chromaticities for output profile
+ * White point is assumed to be D65.
*/
cmsCIExyYTRIPLE prim_output;
/**
@@ -47,11 +48,6 @@ struct lcms_pipeline {
*/
struct lcmsMAT3 mat;
/**
- * matrix from prim_output to XYZ, for example matrix conversion
- * sRGB->XYZ, adobeRGB->XYZ, bt2020->XYZ
- */
- struct lcmsMAT3 mat2XYZ;
- /**
* tone curve enum
*/
enum transfer_fn post_fn;