From 5e9e4ffc468b5f9287641e23dc375afd77177523 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Sat, 21 Jan 2023 18:08:32 +0100 Subject: Add integer versions of libglitter_compose_* MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- Makefile | 10 +++- libglitter.h | 76 +++++++++++++++++++++++++++++- libglitter_compose_double.c | 76 ++++++++++++++++-------------- libglitter_compose_float.c | 1 + libglitter_compose_uint16.c | 7 +++ libglitter_compose_uint32.c | 7 +++ libglitter_compose_uint64.c | 111 ++++++++++++++++++++++++++++++++++++++++++++ libglitter_compose_uint8.c | 7 +++ 8 files changed, 257 insertions(+), 38 deletions(-) create mode 100644 libglitter_compose_uint16.c create mode 100644 libglitter_compose_uint32.c create mode 100644 libglitter_compose_uint64.c create mode 100644 libglitter_compose_uint8.c diff --git a/Makefile b/Makefile index 14674d2..baf2581 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,11 @@ LIB_NAME = glitter OBJ =\ libglitter_compose_double.o\ - libglitter_compose_float.o + libglitter_compose_float.o\ + libglitter_compose_uint16.o\ + libglitter_compose_uint32.o\ + libglitter_compose_uint64.o\ + libglitter_compose_uint8.o HDR =\ libglitter.h @@ -30,6 +34,10 @@ all: libglitter.a libglitter.$(LIBEXT) $(OBJ): $(HDR) $(LOBJ): $(HDR) libglitter_compose_float.o: libglitter_compose_double.c +libglitter_compose_uint16.o: libglitter_compose_uint64.c libglitter_compose_double.c +libglitter_compose_uint32.o: libglitter_compose_uint64.c libglitter_compose_double.c +libglitter_compose_uint64.o: libglitter_compose_double.c +libglitter_compose_uint8.o: libglitter_compose_uint64.c libglitter_compose_double.c .c.o: $(CC) -c -o $@ $< $(CFLAGS) $(CPPFLAGS) diff --git a/libglitter.h b/libglitter.h index be25d72..ca358aa 100644 --- a/libglitter.h +++ b/libglitter.h @@ -10,6 +10,10 @@ * Create one raster per monitor colour from a raster of * subpixels (which may be further divided in the raster) * + * Note that this function does not regard the colour + * model's transfer function: it does not directly give + * you appropriate sRGB values + * * @param outputs Array of output rasters, on for each subpixel colour; * each raster must be initialised to have the value 0 * in each cell. The function may change the offset for @@ -33,7 +37,7 @@ * raster (the value of the cell is the output's index * in `outputs`); this is row-major map, and each valid * value must appear at least once - * @param ncellweights For each `i` in [0, `noutputs`), `ncellvalues[i]` + * @param ncellweights For each `i` in [0, `noutputs`), `ncellweights[i]` * shall have the value `1. / x`, where `x` is the * number of times the value `i` occurs in `cellmap` * @@ -56,7 +60,75 @@ void libglitter_compose_float(float **, size_t, const float *restrict, size_t, size_t, size_t, size_t, size_t, size_t, size_t, const uint8_t *restrict, const float *restrict); -/* TODO add integer versions */ +/** + * Create one raster per monitor colour from a raster of + * subpixels (which may be further divided in the raster) + * + * Note that this function does not regard the colour + * model's transfer function: it does not directly give + * you appropriate sRGB values + * + * @param outputs Array of output rasters, on 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 noutputs The number of output buffers + * @param input Input raster; cells are adjacent + * @param output_rowsize The number of cells in a row in each output raster + * @param output_cellsize The number of values stored in each output raster, + * between each cell, plus 1 (that is, the number of + * values per cell) + * @param input_rowsize The number of cells in a row in `input` + * @param width The horizontal number of pixels in the rasters + * @param height The vertical number of pixels in the rasters + * @param widthmul The horizontal number of cells per pixel in `input` + * @param heightmul The vertical number of cells per pixel in `input` + * @param cellmap Subpixel map of size `heightmul * widthmul` that + * maps a cell for a pixel in `input` to an output + * raster (the value of the cell is the output's index + * in `outputs`); this is row-major map, and each valid + * value must appear at least once + * @param ncellvalues For each `i` in [0, `noutputs`), `ncellvalues[i]` + * shall be the number of times the value `i` occurs + * in `cellmap` + * + * If `noutputs` is 3 and either `widthmul` or `heightmul` is 3 and + * the other one is 1, `ncellvalues` will not be used as it is preknown + * that all its values are 1 + */ +void libglitter_compose_uint64(uint64_t **, size_t, const uint64_t *restrict, + size_t, size_t, size_t, size_t, size_t, size_t, size_t, + const uint8_t *restrict, const uint8_t *restrict); + +/** + * This value is identical to `libglitter_compose_uint64`, + * apart from it parameter types, see `libglitter_compose_uint64` + * for details about this function + */ +void libglitter_compose_uint32(uint32_t **, size_t, const uint32_t *restrict, + size_t, size_t, size_t, size_t, size_t, size_t, size_t, + const uint8_t *restrict, const uint8_t *restrict); + +/** + * This value is identical to `libglitter_compose_uint64`, + * apart from it parameter types, see `libglitter_compose_uint64` + * for details about this function + */ +void libglitter_compose_uint16(uint16_t **, size_t, const uint16_t *restrict, + size_t, size_t, size_t, size_t, size_t, size_t, size_t, + const uint8_t *restrict, const uint8_t *restrict); + +/** + * This value is identical to `libglitter_compose_uint64`, + * apart from it parameter types, see `libglitter_compose_uint64` + * for details about this function + */ +void libglitter_compose_uint8(uint8_t **, size_t, const uint8_t *restrict, + size_t, size_t, size_t, size_t, size_t, size_t, size_t, + const uint8_t *restrict, const uint8_t *restrict); + /* TODO add colour space conversion and saturation */ diff --git a/libglitter_compose_double.c b/libglitter_compose_double.c index ba094f0..d0fdc3e 100644 --- a/libglitter_compose_double.c +++ b/libglitter_compose_double.c @@ -2,39 +2,6 @@ #include "libglitter.h" -static void -generic(double **outputs, size_t noutputs, const double *restrict input, - size_t output_rowsize, size_t output_cellsize, size_t input_rowsize, - size_t width, size_t height, size_t widthmul, size_t heightmul, - const uint8_t *restrict cellmap, const double *restrict ncellweights) -{ - size_t y, x, iy, ix, output_y, output_i, input_blanking; - uint8_t channel; - double value; - - output_rowsize *= output_cellsize; - input_blanking = input_rowsize * heightmul - width * widthmul; - - for (y = 0, output_y = 0; y < height; y++, output_y += output_rowsize) { - for (x = 0, output_i = output_y; x < width; x++, output_i += output_cellsize) { - - for (iy = 0; iy < heightmul; iy++) { - for (ix = 0; ix < widthmul; ix++) { - channel = cellmap[iy * widthmul + ix]; - - value = input[iy * input_rowsize + ix]; - value *= ncellweights[channel]; - - outputs[channel][output_i] += value; - } - } - input = &input[widthmul]; - } - input = &input[input_blanking]; - } -} - - static void vstrips(double **outputs_, const double *restrict input, size_t output_rowsize, size_t output_cellsize, size_t input_rowsize, size_t width, size_t height, const uint8_t *restrict cellmap) @@ -89,6 +56,42 @@ hstrips(double **outputs_, const double *restrict input, size_t output_rowsize, } +#ifndef ONLY_INT_COMPATIBLE + + +static void +generic(double **outputs, const double *restrict input, + size_t output_rowsize, size_t output_cellsize, size_t input_rowsize, + size_t width, size_t height, size_t widthmul, size_t heightmul, + const uint8_t *restrict cellmap, const double *restrict ncellweights) +{ + size_t y, x, iy, ix, output_y, output_i, input_blanking; + uint8_t channel; + double value; + + output_rowsize *= output_cellsize; + input_blanking = input_rowsize * heightmul - width * widthmul; + + for (y = 0, output_y = 0; y < height; y++, output_y += output_rowsize) { + for (x = 0, output_i = output_y; x < width; x++, output_i += output_cellsize) { + + for (iy = 0; iy < heightmul; iy++) { + for (ix = 0; ix < widthmul; ix++) { + channel = cellmap[iy * widthmul + ix]; + + value = input[iy * input_rowsize + ix]; + value *= ncellweights[channel]; + + outputs[channel][output_i] += value; + } + } + input = &input[widthmul]; + } + input = &input[input_blanking]; + } +} + + void libglitter_compose_double(double **outputs, size_t noutputs, const double *restrict input, size_t output_rowsize, size_t output_cellsize, size_t input_rowsize, @@ -100,7 +103,10 @@ libglitter_compose_double(double **outputs, size_t noutputs, const double *restr } else if (noutputs == 3 && widthmul == 1 && heightmul == 3) { hstrips(outputs, input, output_rowsize, output_cellsize, input_rowsize, width, height, cellmap); } else { - generic(outputs, noutputs, input, output_rowsize, output_cellsize, - input_rowsize, width, height, widthmul, heightmul, cellmap, ncellweights); + generic(outputs, input, output_rowsize, output_cellsize, input_rowsize, + width, height, widthmul, heightmul, cellmap, ncellweights); } } + + +#endif diff --git a/libglitter_compose_float.c b/libglitter_compose_float.c index 197aaea..6e09fd1 100644 --- a/libglitter_compose_float.c +++ b/libglitter_compose_float.c @@ -1,4 +1,5 @@ /* See LICENSE file for copyright and license details. */ +#include "libglitter.h" #define libglitter_compose_double libglitter_compose_float #define double float #include "libglitter_compose_double.c" diff --git a/libglitter_compose_uint16.c b/libglitter_compose_uint16.c new file mode 100644 index 0000000..ea24f8e --- /dev/null +++ b/libglitter_compose_uint16.c @@ -0,0 +1,7 @@ +/* See LICENSE file for copyright and license details. */ +#include "libglitter.h" +typedef uint_fast32_t greater_t; +#define greater_t greater_t +#define libglitter_compose_uint64 libglitter_compose_uint16 +#define uint64_t uint16_t +#include "libglitter_compose_uint64.c" diff --git a/libglitter_compose_uint32.c b/libglitter_compose_uint32.c new file mode 100644 index 0000000..8d74453 --- /dev/null +++ b/libglitter_compose_uint32.c @@ -0,0 +1,7 @@ +/* See LICENSE file for copyright and license details. */ +#include "libglitter.h" +typedef uint_fast64_t greater_t; +#define greater_t greater_t +#define libglitter_compose_uint64 libglitter_compose_uint32 +#define uint64_t uint32_t +#include "libglitter_compose_uint64.c" diff --git a/libglitter_compose_uint64.c b/libglitter_compose_uint64.c new file mode 100644 index 0000000..fdb9b62 --- /dev/null +++ b/libglitter_compose_uint64.c @@ -0,0 +1,111 @@ +/* See LICENSE file for copyright and license details. */ +#include "libglitter.h" +#define ONLY_INT_COMPATIBLE +#define double uint64_t +#include "libglitter_compose_double.c" +#include +#ifdef greater_t +# define MIX(A, B) (((greater_t)(A) + (greater_t)(B)) >> 1) +#else +# define greater_t double +# define MIX(A, B) (((A) >> 1) + ((B) >> 1) + ((A) & (B) & 1)) +#endif + + +static void +simple(uint64_t **outputs, const uint64_t *restrict input, + size_t output_rowsize, size_t output_cellsize, size_t input_rowsize, + size_t width, size_t height, size_t widthmul, size_t heightmul, + const uint8_t *restrict cellmap) +{ + size_t y, x, output_y, output_i, input_blanking; + uint8_t channel; + size_t cells[3][2]; + size_t cellsi[3] = {0, 0, 0}; + + output_rowsize *= output_cellsize; + input_blanking = input_rowsize * heightmul - width * widthmul; + + for (y = 0; y < heightmul; y++) { + for (x = 0; x < widthmul; x++) { + channel = cellmap[y * widthmul + x]; + cells[channel][cellsi[channel]] = y * input_rowsize + x; + cellsi[channel] += 1; + } + } + if (cellsi[0] == 1) + cells[0][1] = cells[0][0]; + if (cellsi[1] == 1) + cells[1][1] = cells[1][0]; + if (cellsi[2] == 1) + cells[2][1] = cells[2][0]; + + for (y = 0, output_y = 0; y < height; y++, output_y += output_rowsize) { + for (x = 0, output_i = output_y; x < width; x++, output_i += output_cellsize) { + + outputs[0][output_i] = (uint64_t)MIX(input[cells[0][0]], input[cells[0][1]]); + outputs[1][output_i] = (uint64_t)MIX(input[cells[0][0]], input[cells[0][1]]); + outputs[2][output_i] = (uint64_t)MIX(input[cells[0][0]], input[cells[0][1]]); + input = &input[widthmul]; + } + input = &input[input_blanking]; + } +} + + +static void +generic(uint64_t **outputs, size_t noutputs, const uint64_t *restrict input, + size_t output_rowsize, size_t output_cellsize, size_t input_rowsize, + size_t width, size_t height, size_t widthmul, size_t heightmul, + const uint8_t *restrict cellmap, const uint8_t *restrict ncellvalues) +{ + size_t y, x, iy, ix, i, output_y, output_i, input_blanking; + uint8_t channel; + greater_t *pixel; + + output_rowsize *= output_cellsize; + input_blanking = input_rowsize * heightmul - width * widthmul; + + pixel = alloca(noutputs * sizeof(greater_t)); + + for (y = 0, output_y = 0; y < height; y++, output_y += output_rowsize) { + for (x = 0, output_i = output_y; x < width; x++, output_i += output_cellsize) { + + for (i = 0; i < noutputs; i++) + pixel[i] = 0; + + for (iy = 0; iy < heightmul; iy++) { + for (ix = 0; ix < widthmul; ix++) { + channel = cellmap[iy * widthmul + ix]; + pixel[channel] += (greater_t)input[iy * input_rowsize + ix]; + } + } + + for (i = 0; i < noutputs; i++) + outputs[i][output_i] = (uint64_t)(pixel[channel] / (greater_t)ncellvalues[i]); + + input = &input[widthmul]; + } + input = &input[input_blanking]; + } +} + + +void +libglitter_compose_uint64(uint64_t **outputs, size_t noutputs, const uint64_t *restrict input, + size_t output_rowsize, size_t output_cellsize, size_t input_rowsize, + size_t width, size_t height, size_t widthmul, size_t heightmul, + const uint8_t *restrict cellmap, const uint8_t *restrict ncellvalues) +{ + if (noutputs == 3 && widthmul == 3 && heightmul == 1) { + vstrips(outputs, input, output_rowsize, output_cellsize, input_rowsize, width, height, cellmap); + } else if (noutputs == 3 && widthmul == 1 && heightmul == 3) { + hstrips(outputs, input, output_rowsize, output_cellsize, input_rowsize, width, height, cellmap); + } else if (noutputs == 3 && ncellvalues[0] <= 2 && ncellvalues[1] <= 2 && ncellvalues[2] <= 2) { + simple(outputs, input, output_rowsize, output_cellsize, input_rowsize, + width, height, widthmul, heightmul, cellmap); + } else { + generic(outputs, noutputs, input, output_rowsize, output_cellsize, + input_rowsize, width, height, widthmul, heightmul, cellmap, ncellvalues); + } +} diff --git a/libglitter_compose_uint8.c b/libglitter_compose_uint8.c new file mode 100644 index 0000000..615232b --- /dev/null +++ b/libglitter_compose_uint8.c @@ -0,0 +1,7 @@ +/* See LICENSE file for copyright and license details. */ +#include "libglitter.h" +typedef uint_fast16_t greater_t; +#define greater_t greater_t +#define libglitter_compose_uint64 libglitter_compose_uint8 +#define uint64_t uint8_t +#include "libglitter_compose_uint64.c" -- cgit v1.2.3-70-g09d2