diff options
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | TODO | 1 | ||||
-rw-r--r-- | libglitter.h | 55 | ||||
-rw-r--r-- | libglitter_desaturate_double.c | 2 | ||||
-rw-r--r-- | libglitter_get_colour_space_conversion_matrix_double.c | 40 | ||||
-rw-r--r-- | libglitter_get_colour_space_conversion_matrix_float.c | 4 | ||||
-rw-r--r-- | libglitter_per_channel_desaturate_double.c | 49 | ||||
-rw-r--r-- | libglitter_per_channel_desaturate_float.c | 6 |
8 files changed, 135 insertions, 25 deletions
@@ -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: @@ -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" |