aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile3
-rw-r--r--TODO1
-rw-r--r--libglitter.h55
-rw-r--r--libglitter_desaturate_double.c2
-rw-r--r--libglitter_get_colour_space_conversion_matrix_double.c40
-rw-r--r--libglitter_get_colour_space_conversion_matrix_float.c4
-rw-r--r--libglitter_per_channel_desaturate_double.c49
-rw-r--r--libglitter_per_channel_desaturate_float.c6
8 files changed, 135 insertions, 25 deletions
diff --git a/Makefile b/Makefile
index 7db2755..8714567 100644
--- a/Makefile
+++ b/Makefile
@@ -29,6 +29,8 @@ OBJ =\
libglitter_free_render_context.o\
libglitter_get_colour_space_conversion_matrix_double.o\
libglitter_get_colour_space_conversion_matrix_float.o\
+ libglitter_per_channel_desaturate_double.o\
+ libglitter_per_channel_desaturate_float.o\
libglitter_split_uint32_raster.o\
libglitter_split_uint64_raster.o\
libglitter_update_render_context.o
@@ -49,6 +51,7 @@ libglitter_compose_uint32.o: libglitter_compose_uint64.c libglitter_compose_doub
libglitter_compose_uint64.o: libglitter_compose_double.c
libglitter_compose_uint8.o: libglitter_compose_uint64.c libglitter_compose_double.c
libglitter_desaturate_float.o: libglitter_desaturate_double.c
+libglitter_per_channel_desaturate_float.o: libglitter_per_channel_desaturate_double.c
libglitter_split_uint32_raster.o: libglitter_split_uint64_raster.c
.c.o:
diff --git a/TODO b/TODO
index 549f3cc..4a19051 100644
--- a/TODO
+++ b/TODO
@@ -1,5 +1,4 @@
Add colour space conversion
-Add transfer function application function
Add support for GPU-acceleration
Add man pages
Add tests
diff --git a/libglitter.h b/libglitter.h
index 7263ec7..50d451d 100644
--- a/libglitter.h
+++ b/libglitter.h
@@ -212,27 +212,67 @@ void libglitter_split_uint32_raster(uint8_t *[3], uint8_t **, uint32_t *, uint32
* @param height The vertical number of pixels in the rasters
* @param saturation The subpixel rendering saturation, 1 for regular
* subpixel rendering, 0 for greyscale, values
- * inbetween for a compromise
+ * in between for a compromise
* @param primary_ys The CIE Y value (in e.g. CIE xyY or CIE XYZ) for
* each subpixel colour; or `NULL` for the sRGB values
* (this is only allowed if there are exactly 3 rasters)
*/
-void libglitter_desaturate_double(double **, size_t, size_t, size_t, size_t, size_t, double, const double *);
+void libglitter_desaturate_double(double **, size_t, size_t, size_t, size_t, size_t, double, const double *restrict);
/**
* This value is identical to `libglitter_desaturate_double`,
* apart from it parameter types, see `libglitter_desaturate_double`
* for details about this function
*/
-void libglitter_desaturate_float(float **, size_t, size_t, size_t, size_t, size_t, float, const float *);
+void libglitter_desaturate_float(float **, size_t, size_t, size_t, size_t, size_t, float, const float *restrict);
+
+/**
+ * Transform rasters from fully using subpixel rendering to
+ * balance between subpixel rendering and greyscale antialiasing
+ *
+ * @param rasters Array of rasters, one for each subpixel colour.
+ * The function may change the offset for each raster,
+ * as such, the given pointer shall not be used anywhere
+ * else during the execution of the function and the
+ * inner pointers shall be considered undefined after
+ * the execution of the function
+ * @param nrasters The number of rasters
+ * @param rowsize The number of cells in a row in each raster
+ * @param cellsize The number of values stored in each raster,
+ * between each cell, plus 1 (that is, the number of
+ * values per cell)
+ * @param width The horizontal number of pixels in the rasters
+ * @param height The vertical number of pixels in the rasters
+ * @param saturations The subpixel rendering saturation for each raster,
+ * 1 for regular subpixel rendering, 0 for greyscale,
+ * values in between for a compromise
+ * @param primary_ys The CIE Y value (in e.g. CIE xyY or CIE XYZ) for
+ * each subpixel colour; or `NULL` for the sRGB values
+ * (this is only allowed if there are exactly 3 rasters)
+ */
+void libglitter_per_channel_desaturate_double(double **, size_t, size_t, size_t, size_t, size_t,
+ const double *restrict, const double *restrict);
+
+/**
+ * This value is identical to `libglitter_per_channel_desaturate_double`,
+ * apart from it parameter types, see `libglitter_per_channel_desaturate_double`
+ * for details about this function
+ */
+void libglitter_per_channel_desaturate_float(float **, size_t, size_t, size_t, size_t, size_t,
+ const float *restrict, const float *restrict);
/**
* Get the matrix each pixel shall be multiplied with
* to convert it from the output's colour space to sRGB
+ * or CIE XYZ
*
- * This is useful when the output does not use sRGB,
- * but the application does
+ * This is useful when the output does not use sRGB, or
+ * CIE XYZ, but the application does. If the application
+ * uses some other colour space, this function can output
+ * the conversion matrix for the CIE XYZ colour space,
+ * which can that be right-hand multiplied to get the
+ * conversion matrix for some other colour
*
* @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
@@ -244,13 +284,14 @@ void libglitter_desaturate_float(float **, size_t, size_t, size_t, size_t, size_
* @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, normally 1
+ * @param xyz Whether the output conversion matrix should be to CIE XYZ rather the sRGB
*
* `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);
+ double, double, double, double, double, int);
/**
* This value is identical to `libglitter_get_colour_space_conversion_matrix_double`,
@@ -258,7 +299,7 @@ void libglitter_get_colour_space_conversion_matrix_double(double[3][3], 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);
+ float, float, float, float, float, int);
#endif
diff --git a/libglitter_desaturate_double.c b/libglitter_desaturate_double.c
index 62eaa3a..43fc990 100644
--- a/libglitter_desaturate_double.c
+++ b/libglitter_desaturate_double.c
@@ -9,7 +9,7 @@
void
libglitter_desaturate_double(double **rasters, size_t nrasters, size_t rowsize, size_t cellsize,
- size_t width, size_t height, double saturation, const double *primary_ys)
+ size_t width, size_t height, double saturation, const double *restrict primary_ys)
{
size_t y, x, ch, raster_y, raster_i;
double intensity;
diff --git a/libglitter_get_colour_space_conversion_matrix_double.c b/libglitter_get_colour_space_conversion_matrix_double.c
index fd3ecbc..3ee734d 100644
--- a/libglitter_get_colour_space_conversion_matrix_double.c
+++ b/libglitter_get_colour_space_conversion_matrix_double.c
@@ -48,7 +48,7 @@ invert(double m[3][4])
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 white_x, double white_y, double white_Y, int xyz)
{
double mat[3][4];
double x1, x2, x3;
@@ -74,17 +74,29 @@ libglitter_get_colour_space_conversion_matrix_double(double matrix[3][3], double
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];
+ * the output RGB-to-CIE XYZ conversion matrix.
+ * If sRGB is desired, it is multiplied by the
+ * CIE XYZ-to-sRGB conversion matrix to get the
+ * output RGB-to-sRGB conversion matrix. */
+ if (!xyz) {
+ 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];
+ } else {
+ matrix[0][0] = x1;
+ matrix[0][1] = x2;
+ matrix[0][2] = x3;
+ matrix[1][0] = y1;
+ matrix[1][1] = y2;
+ matrix[1][2] = y3;
+ matrix[2][0] = z1;
+ matrix[2][1] = z2;
+ matrix[2][2] = z3;
+ }
}
diff --git a/libglitter_get_colour_space_conversion_matrix_float.c b/libglitter_get_colour_space_conversion_matrix_float.c
index 022c2a4..6e215c9 100644
--- a/libglitter_get_colour_space_conversion_matrix_float.c
+++ b/libglitter_get_colour_space_conversion_matrix_float.c
@@ -5,14 +5,14 @@
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)
+ float white_x, float white_y, float white_Y, int xyz)
{
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);
+ (double)white_x, (double)white_y, (double)white_Y, xyz);
matrix[0][0] = (float)double_matrix[0][0];
matrix[0][1] = (float)double_matrix[0][1];
matrix[0][2] = (float)double_matrix[0][2];
diff --git a/libglitter_per_channel_desaturate_double.c b/libglitter_per_channel_desaturate_double.c
new file mode 100644
index 0000000..8561708
--- /dev/null
+++ b/libglitter_per_channel_desaturate_double.c
@@ -0,0 +1,49 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+
+#if defined(__GNUC__) && !defined(__clang__)
+# pragma GCC diagnostic ignored "-Wunsuffixed-float-constants"
+#endif
+
+
+void
+libglitter_per_channel_desaturate_double(double **rasters, size_t nrasters, size_t rowsize,
+ size_t cellsize, size_t width, size_t height,
+ const double *saturations, const double *primary_ys)
+{
+ size_t y, x, ch, raster_y, raster_i;
+ double intensity;
+
+ rowsize *= cellsize;
+
+ if (nrasters == 3) {
+ double *raster1 = rasters[0], saturation1 = saturations[0];
+ double *raster2 = rasters[1], saturation2 = saturations[1];
+ double *raster3 = rasters[2], saturation3 = saturations[2];
+ double primary1_y = primary_ys ? primary_ys[0] : (double)0.212673370378408277403536885686;
+ double primary2_y = primary_ys ? primary_ys[1] : (double)0.715151730491031756287156895269;
+ double primary3_y = primary_ys ? primary_ys[2] : (double)0.072174899130559869164791564344;
+ for (y = 0, raster_y = 0; y < height; y++, raster_y += rowsize) {
+ for (x = 0, raster_i = raster_y; x < width; x++, raster_i += cellsize) {
+ intensity = raster1[raster_i] * primary1_y;
+ intensity += raster2[raster_i] * primary2_y;
+ intensity += raster3[raster_i] * primary3_y;
+ raster1[raster_i] = fma(raster1[raster_i] - intensity, saturation1, intensity);
+ raster2[raster_i] = fma(raster2[raster_i] - intensity, saturation2, intensity);
+ raster3[raster_i] = fma(raster3[raster_i] - intensity, saturation3, intensity);
+ }
+ }
+
+ } else {
+ for (y = 0, raster_y = 0; y < height; y++, raster_y += rowsize) {
+ for (x = 0, raster_i = raster_y; x < width; x++, raster_i += cellsize) {
+ intensity = 0;
+ for (ch = 0; ch < nrasters; ch++)
+ intensity += rasters[ch][raster_i] * primary_ys[ch];
+ for (ch = 0; ch < nrasters; ch++)
+ rasters[ch][raster_i] = fma(rasters[ch][raster_i] - intensity, saturations[ch], intensity);
+ }
+ }
+ }
+}
diff --git a/libglitter_per_channel_desaturate_float.c b/libglitter_per_channel_desaturate_float.c
new file mode 100644
index 0000000..fd522ed
--- /dev/null
+++ b/libglitter_per_channel_desaturate_float.c
@@ -0,0 +1,6 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#define libglitter_per_channel_desaturate_double libglitter_per_channel_desaturate_float
+#define double float
+#define fma fmaf
+#include "libglitter_per_channel_desaturate_double.c"