aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2023-01-22 01:06:50 +0100
committerMattias Andrée <maandree@kth.se>2023-01-22 01:08:26 +0100
commitb8ece8550e52b26924e5096d03706dc379ec46d4 (patch)
tree30f73817e7e5c69d066bedea2dddf5d27637eae8
parentFetching output colour space belongs in libfonts, not libglitter (diff)
downloadlibglitter-b8ece8550e52b26924e5096d03706dc379ec46d4.tar.gz
libglitter-b8ece8550e52b26924e5096d03706dc379ec46d4.tar.bz2
libglitter-b8ece8550e52b26924e5096d03706dc379ec46d4.tar.xz
Add libglitter_get_colour_space_conversion_matrix_{double,float}
Signed-off-by: Mattias Andrée <maandree@kth.se>
-rw-r--r--Makefile2
-rw-r--r--libglitter.h42
-rw-r--r--libglitter_get_colour_space_conversion_matrix_double.c90
-rw-r--r--libglitter_get_colour_space_conversion_matrix_float.c25
4 files changed, 159 insertions, 0 deletions
diff --git a/Makefile b/Makefile
index e36b3fb..4731a2f 100644
--- a/Makefile
+++ b/Makefile
@@ -27,6 +27,8 @@ OBJ =\
libglitter_desaturate_float.o\
libglitter_create_render_context.o\
libglitter_free_render_context.o\
+ libglitter_get_colour_space_conversion_matrix_double.o\
+ libglitter_get_colour_space_conversion_matrix_float.o\
libglitter_update_render_context.o
HDR =\
diff --git a/libglitter.h b/libglitter.h
index 0fc5888..4cd64bf 100644
--- a/libglitter.h
+++ b/libglitter.h
@@ -7,6 +7,14 @@
/**
+ * The CIE xyY values of the D65 illuminant
+ */
+#define LIBGLITTER_ILLUMINANT_D65\
+ 0.312726871026564878786047074755,\
+ 0.329023206641284038376227272238, 1.0\
+
+
+/**
* Rendering context for an input raster's specifications
*
* Render context's are thread-safe, however updating them are not
@@ -183,4 +191,38 @@ void libglitter_desaturate_double(double **, size_t, size_t, size_t, size_t, siz
void libglitter_desaturate_float(float **, size_t, size_t, size_t, size_t, size_t, float, const float *);
+/**
+ * Get the matrix each pixel shall be multiplied with
+ * to convert it from the output's colour space to sRGB
+ *
+ * This is useful when the output does not use sRGB,
+ * but the application does
+ *
+ * @param matrix Output buffer for the conversion matrix
+ * @param c1x The CIE x value (as in CIE xyY) of the output's first primary colour
+ * @param c1y The CIE y value (as in CIE xyY) of the output's first primary colour
+ * @param c2x The CIE x value (as in CIE xyY) of the output's second primary colour
+ * @param c2y The CIE y value (as in CIE xyY) of the output's second primary colour
+ * @param c3x The CIE x value (as in CIE xyY) of the output's third primary colour
+ * @param c3y The CIE y value (as in CIE xyY) of the output's third primary colour
+ * @param white_x The CIE x value (as in CIE xyY) of the output's white point
+ * @param white_y The CIE y value (as in CIE xyY) of the output's white point
+ * @param white_Y The CIE Y value (as in CIE xyY) of the output's white point
+ *
+ * `LIBGLITTER_ILLUMINANT_D65` can be input in place of
+ * `white_x, white_y, white_Y` (it expands to three arguments)
+ * if the output's whitepoint is the D65 illuminant
+ */
+void libglitter_get_colour_space_conversion_matrix_double(double[3][3], double, double, double, double,
+ double, double, double, double, double);
+
+/**
+ * This value is identical to `libglitter_get_colour_space_conversion_matrix_double`,
+ * apart from it parameter types, see `libglitter_get_colour_space_conversion_matrix_double`
+ * for details about this function
+ */
+void libglitter_get_colour_space_conversion_matrix_float(float[3][3], float, float, float, float,
+ float, float, float, float, float);
+
+
#endif
diff --git a/libglitter_get_colour_space_conversion_matrix_double.c b/libglitter_get_colour_space_conversion_matrix_double.c
new file mode 100644
index 0000000..fd3ecbc
--- /dev/null
+++ b/libglitter_get_colour_space_conversion_matrix_double.c
@@ -0,0 +1,90 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+#define X(x, y) ((x) / (y))
+#define Z(x, y) ((1 - (x)) / (y) - 1)
+
+
+#if defined(__GNUC__) && !defined(__clang__)
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wunsuffixed-float-constants"
+#endif
+
+
+/**
+ * CIE XYZ-to-sRGB conversion matrix
+ */
+static const double srgb[3][3] = {
+ { 3.240446254647737056586720427731, -1.537134761820080353089679192635, -0.498530193022728773666329971093},
+ {-0.969266606244679751469561779231, 1.876011959788370209167851498933, 0.041556042214430065351304932619},
+ { 0.055643503564352832235773149705, -0.204026179735960239147729566866, 1.057226567722703292062647051353}};
+
+
+#if defined(__GNUC__) && !defined(__clang__)
+# pragma GCC diagnostic pop
+#endif
+
+
+static void
+invert(double m[3][4])
+{
+ double t;
+ size_t i;
+
+ /* Set m[0][0] = 1 */ for (t = m[0][0], i = 0; i < 4; i++) m[0][i] /= t;
+ /* Set m[1][0] = 0 */ for (t = m[1][0], i = 0; i < 4; i++) m[1][i] -= t * m[0][i];
+ /* Set m[2][0] = 0 */ for (t = m[2][0], i = 0; i < 4; i++) m[2][i] -= t * m[0][i];
+
+ /* Set m[1][1] = 1 */ for (t = m[1][1], i = 1; i < 4; i++) m[1][i] /= t;
+ /* Set m[2][1] = 0 */ for (t = m[2][1], i = 1; i < 4; i++) m[2][i] -= t * m[1][i];
+ /* Set m[0][1] = 0 */ for (t = m[0][1], i = 1; i < 4; i++) m[0][i] -= t * m[1][i];
+
+ /* Set m[2][2] = 1 */ for (t = m[2][2], i = 2; i < 4; i++) m[2][i] /= t;
+ /* Set m[1][2] = 0 */ for (t = m[1][2], i = 2; i < 4; i++) m[1][i] -= t * m[2][i];
+ /* Set m[0][2] = 0 */ for (t = m[0][2], i = 2; i < 4; i++) m[0][i] -= t * m[2][i];
+}
+
+
+void
+libglitter_get_colour_space_conversion_matrix_double(double matrix[3][3], double c1x, double c1y,
+ double c2x, double c2y, double c3x, double c3y,
+ double white_x, double white_y, double white_Y)
+{
+ double mat[3][4];
+ double x1, x2, x3;
+ double y1, y2, y3;
+ double z1, z2, z3;
+
+ /* Get colour space in CIE XYZ */
+ mat[0][0] = x1 = X(c1x, c1y);
+ mat[0][1] = x2 = X(c2x, c2y);
+ mat[0][2] = x3 = X(c3x, c3y);
+ mat[1][3] = X(white_x, white_y) * white_Y;
+ mat[1][0] = 1;
+ mat[1][1] = 1;
+ mat[1][2] = 1;
+ mat[1][3] = white_Y;
+ mat[2][0] = z1 = Z(c1x, c1y);
+ mat[2][1] = z2 = Z(c2x, c2y);
+ mat[2][2] = z3 = Z(c3x, c3y);
+ mat[2][3] = Z(white_x, white_y) * white_Y;
+ invert(mat);
+ y1 = mat[0][3];
+ y2 = mat[1][3];
+ y3 = mat[2][3];
+
+ /* [[x1, x2, x3], [y1, y2, y3], [z1, z2, z3]] is
+ * the output RGB-to-CIE XYZ conversion matrix. It
+ * is multiplied by the CIE XYZ-to-sRGB conversion
+ * matrix to get the output RGB-to-sRGB conversion
+ * matrix. */
+ matrix[0][0] = x1 * srgb[0][0] + x2 * srgb[1][0] + x3 * srgb[2][0];
+ matrix[0][1] = x1 * srgb[0][1] + x2 * srgb[1][1] + x3 * srgb[2][1];
+ matrix[0][2] = x1 * srgb[0][2] + x2 * srgb[1][2] + x3 * srgb[2][2];
+ matrix[1][0] = y1 * srgb[0][0] + y2 * srgb[1][0] + y3 * srgb[2][0];
+ matrix[1][1] = y1 * srgb[0][1] + y2 * srgb[1][1] + y3 * srgb[2][1];
+ matrix[1][2] = y1 * srgb[0][2] + y2 * srgb[1][2] + y3 * srgb[2][2];
+ matrix[2][0] = z1 * srgb[0][0] + z2 * srgb[1][0] + z3 * srgb[2][0];
+ matrix[2][1] = z1 * srgb[0][1] + z2 * srgb[1][1] + z3 * srgb[2][1];
+ matrix[2][2] = z1 * srgb[0][2] + z2 * srgb[1][2] + z3 * srgb[2][2];
+}
diff --git a/libglitter_get_colour_space_conversion_matrix_float.c b/libglitter_get_colour_space_conversion_matrix_float.c
new file mode 100644
index 0000000..022c2a4
--- /dev/null
+++ b/libglitter_get_colour_space_conversion_matrix_float.c
@@ -0,0 +1,25 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+
+void
+libglitter_get_colour_space_conversion_matrix_float(float matrix[3][3], float c1x, float c1y,
+ float c2x, float c2y, float c3x, float c3y,
+ float white_x, float white_y, float white_Y)
+{
+ double double_matrix[3][3];
+ libglitter_get_colour_space_conversion_matrix_double(double_matrix,
+ (double)c1x, (double)c1y,
+ (double)c2x, (double)c2y,
+ (double)c3x, (double)c3y,
+ (double)white_x, (double)white_y, (double)white_Y);
+ matrix[0][0] = (float)double_matrix[0][0];
+ matrix[0][1] = (float)double_matrix[0][1];
+ matrix[0][2] = (float)double_matrix[0][2];
+ matrix[1][0] = (float)double_matrix[1][0];
+ matrix[1][1] = (float)double_matrix[1][1];
+ matrix[1][2] = (float)double_matrix[1][2];
+ matrix[2][0] = (float)double_matrix[2][0];
+ matrix[2][1] = (float)double_matrix[2][1];
+ matrix[2][2] = (float)double_matrix[2][2];
+}