aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2023-01-21 18:08:32 +0100
committerMattias Andrée <maandree@kth.se>2023-01-21 18:08:32 +0100
commit5e9e4ffc468b5f9287641e23dc375afd77177523 (patch)
tree5fc741325e6d617e5fadce7f45910bf606f50c89
parentm doc (diff)
downloadlibglitter-5e9e4ffc468b5f9287641e23dc375afd77177523.tar.gz
libglitter-5e9e4ffc468b5f9287641e23dc375afd77177523.tar.bz2
libglitter-5e9e4ffc468b5f9287641e23dc375afd77177523.tar.xz
Add integer versions of libglitter_compose_*
Signed-off-by: Mattias Andrée <maandree@kth.se>
-rw-r--r--Makefile10
-rw-r--r--libglitter.h76
-rw-r--r--libglitter_compose_double.c76
-rw-r--r--libglitter_compose_float.c1
-rw-r--r--libglitter_compose_uint16.c7
-rw-r--r--libglitter_compose_uint32.c7
-rw-r--r--libglitter_compose_uint64.c111
-rw-r--r--libglitter_compose_uint8.c7
8 files changed, 257 insertions, 38 deletions
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
@@ -3,39 +3,6 @@
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 <alloca.h>
+#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"