From 4114f87af993991c7aab55ff86be3003d43244f3 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Sat, 21 Jan 2023 19:30:25 +0100 Subject: Add render context MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- Makefile | 6 +- TODO | 4 ++ common.h | 35 ++++++++++ libglitter.h | 139 +++++++++++++++++++++---------------- libglitter_compose_double.c | 30 ++++---- libglitter_compose_float.c | 3 +- libglitter_compose_uint16.c | 2 +- libglitter_compose_uint32.c | 2 +- libglitter_compose_uint64.c | 65 ++++++----------- libglitter_compose_uint8.c | 2 +- libglitter_create_render_context.c | 47 +++++++++++++ libglitter_free_render_context.c | 13 ++++ libglitter_update_render_context.c | 28 ++++++++ 13 files changed, 253 insertions(+), 123 deletions(-) create mode 100644 TODO create mode 100644 common.h create mode 100644 libglitter_create_render_context.c create mode 100644 libglitter_free_render_context.c create mode 100644 libglitter_update_render_context.c diff --git a/Makefile b/Makefile index baf2581..b0f2b07 100644 --- a/Makefile +++ b/Makefile @@ -22,9 +22,13 @@ OBJ =\ libglitter_compose_uint16.o\ libglitter_compose_uint32.o\ libglitter_compose_uint64.o\ - libglitter_compose_uint8.o + libglitter_compose_uint8.o\ + libglitter_create_render_context.o\ + libglitter_free_render_context.o\ + libglitter_update_render_context.o HDR =\ + common.h\ libglitter.h LOBJ = $(OBJ:.o=.lo) diff --git a/TODO b/TODO new file mode 100644 index 0000000..65602ac --- /dev/null +++ b/TODO @@ -0,0 +1,4 @@ +Add colour space conversion and saturation +Add support for GPU-acceleration +Add man pages +Add tests diff --git a/common.h b/common.h new file mode 100644 index 0000000..e53843a --- /dev/null +++ b/common.h @@ -0,0 +1,35 @@ +/* See LICENSE file for copyright and license details. */ +#ifndef LIBGLITTER_COMMON_H +#define LIBGLITTER_COMMON_H + +#include "libglitter.h" +#include +#include +#include +#include + + +#define RENDER_METHOD_VSTRIPS 0 +#define RENDER_METHOD_HSTRIPS 1 +#define RENDER_METHOD_SIMPLE 2 +#define RENDER_METHOD_GENERIC 3 + + +struct libglitter_context { +}; + +struct libglitter_render_context { + const uint8_t *restrict cellmap; + const uint8_t *restrict ncellvalues; + size_t noutputs; + size_t rowsize; + size_t widthmul; + size_t heightmul; + uint8_t render_method; + size_t cells[3][2]; + double *restrict cellweights_double; + float *restrict cellweights_float; +}; + + +#endif diff --git a/libglitter.h b/libglitter.h index ca358aa..68a7b0e 100644 --- a/libglitter.h +++ b/libglitter.h @@ -6,6 +6,62 @@ #include +/** + * Rendering context for an input raster's specifications + * + * Render context's are thread-safe, however updating them are not + */ +typedef struct libglitter_render_context LIBGLITTER_RENDER_CONTEXT; + + +/** + * Create a render context for an input raster's specifications + * + * Render context's are thread-safe + * + * @param noutputs The number of output buffers + * @param rowsize The number of cells per row in the input raster + * @param widthmul The horizontal number of cells per pixel in the input raster + * @param heightmul The vertical number of cells per pixel in the input raster + * @param cellmap Subpixel map of size `heightmul * widthmul` that maps a + * cell for a pixel in the input raster to an output raster + * (the output raster's index); 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` + * @return A render context that can be deallocate using + * `libglitter_free_render_context` or updated with + * `libglitter_update_render_context`; `NULL` on failure + * + * @throws ENOMEM Couldn't not allocate enough memory + * + * 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 + */ +LIBGLITTER_RENDER_CONTEXT *libglitter_create_render_context(size_t, size_t, size_t, size_t, + const uint8_t *, const uint8_t *); + +/** + * Update a render context (created by `libglitter_create_render_context`) + * for a new input raster buffer + * + * Updating a render context is not thread-safe + * + * @param this The render context to refresh + * @param rowsize The number of cells per row in the input raster + */ +void libglitter_update_render_context(LIBGLITTER_RENDER_CONTEXT *, size_t); + +/** + * Deallocates a render context (created by `libglitter_create_render_context`) + * + * @param this The render context to deallocate + */ +void libglitter_free_render_context(LIBGLITTER_RENDER_CONTEXT *); + + /** * Create one raster per monitor colour from a raster of * subpixels (which may be further divided in the raster) @@ -14,51 +70,32 @@ * 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 - * 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 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 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 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` - * - * The initialisation requirement on the buffers in `outputs` - * does not apply if `noutputs` is 3 and either `widthmul` or - * `heightmul` is 3 and the other one is 1; additionally, in - * this case `ncellweights` will not be used as it is preknown - * that all its values are 1 + * @param render_ctx Rendering context created for the input raster's + * specification */ -void libglitter_compose_double(double **, size_t, const double *restrict, - size_t, size_t, size_t, size_t, size_t, size_t, size_t, - const uint8_t *restrict, const double *restrict); +void libglitter_compose_double(double **, const double *restrict, size_t, size_t, + size_t, size_t, const LIBGLITTER_RENDER_CONTEXT *); /** * This value is identical to `libglitter_compose_double`, * apart from it parameter types, see `libglitter_compose_double` * for details about this function */ -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); +void libglitter_compose_float(float **, const float *restrict, size_t, size_t, + size_t, size_t, const LIBGLITTER_RENDER_CONTEXT *); /** * Create one raster per monitor colour from a raster of @@ -74,62 +111,42 @@ void libglitter_compose_float(float **, size_t, const float *restrict, * 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 + * @param render_ctx Rendering context created for the input raster's + * specification */ -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); +void libglitter_compose_uint64(uint64_t **, const uint64_t *restrict, size_t, size_t, + size_t, size_t, const LIBGLITTER_RENDER_CONTEXT *); /** * 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); +void libglitter_compose_uint32(uint32_t **, const uint32_t *restrict, size_t, size_t, + size_t, size_t, const LIBGLITTER_RENDER_CONTEXT *); /** * 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); +void libglitter_compose_uint16(uint16_t **, const uint16_t *restrict, size_t, size_t, + size_t, size_t, const LIBGLITTER_RENDER_CONTEXT *); /** * 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 */ +void libglitter_compose_uint8(uint8_t **, const uint8_t *restrict, size_t, size_t, + size_t, size_t, const LIBGLITTER_RENDER_CONTEXT *); #endif diff --git a/libglitter_compose_double.c b/libglitter_compose_double.c index d0fdc3e..5a8d361 100644 --- a/libglitter_compose_double.c +++ b/libglitter_compose_double.c @@ -1,5 +1,5 @@ /* See LICENSE file for copyright and license details. */ -#include "libglitter.h" +#include "common.h" static void @@ -60,12 +60,12 @@ hstrips(double **outputs_, const double *restrict input, size_t output_rowsize, static void -generic(double **outputs, const double *restrict input, +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) + const uint8_t *restrict cellmap, const double *restrict cellweights) { - size_t y, x, iy, ix, output_y, output_i, input_blanking; + size_t y, x, iy, ix, i, output_y, output_i, input_blanking; uint8_t channel; double value; @@ -75,12 +75,14 @@ generic(double **outputs, const double *restrict input, 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++) + outputs[i][output_i] = 0; 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]; + value *= cellweights[channel]; outputs[channel][output_i] += value; } @@ -93,18 +95,16 @@ generic(double **outputs, const double *restrict input, 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, - size_t width, size_t height, size_t widthmul, size_t heightmul, - const uint8_t *restrict cellmap, const double *restrict ncellweights) +libglitter_compose_double(double **outputs, const double *restrict input, size_t output_rowsize, size_t output_cellsize, + size_t width, size_t height, const LIBGLITTER_RENDER_CONTEXT *render_ctx) { - 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); + if (render_ctx->render_method == RENDER_METHOD_VSTRIPS) { + vstrips(outputs, input, output_rowsize, output_cellsize, render_ctx->rowsize, width, height, render_ctx->cellmap); + } else if (render_ctx->render_method == RENDER_METHOD_HSTRIPS) { + hstrips(outputs, input, output_rowsize, output_cellsize, render_ctx->rowsize, width, height, render_ctx->cellmap); } else { - generic(outputs, input, output_rowsize, output_cellsize, input_rowsize, - width, height, widthmul, heightmul, cellmap, ncellweights); + generic(outputs, render_ctx->noutputs, input, output_rowsize, output_cellsize, render_ctx->rowsize, width, height, + render_ctx->widthmul, render_ctx->heightmul, render_ctx->cellmap, render_ctx->cellweights_double); } } diff --git a/libglitter_compose_float.c b/libglitter_compose_float.c index 6e09fd1..2195ed3 100644 --- a/libglitter_compose_float.c +++ b/libglitter_compose_float.c @@ -1,5 +1,6 @@ /* See LICENSE file for copyright and license details. */ -#include "libglitter.h" +#include "common.h" #define libglitter_compose_double libglitter_compose_float +#define cellweights_double cellweights_float #define double float #include "libglitter_compose_double.c" diff --git a/libglitter_compose_uint16.c b/libglitter_compose_uint16.c index ea24f8e..b1bebe0 100644 --- a/libglitter_compose_uint16.c +++ b/libglitter_compose_uint16.c @@ -1,5 +1,5 @@ /* See LICENSE file for copyright and license details. */ -#include "libglitter.h" +#include "common.h" typedef uint_fast32_t greater_t; #define greater_t greater_t #define libglitter_compose_uint64 libglitter_compose_uint16 diff --git a/libglitter_compose_uint32.c b/libglitter_compose_uint32.c index 8d74453..a455ee3 100644 --- a/libglitter_compose_uint32.c +++ b/libglitter_compose_uint32.c @@ -1,5 +1,5 @@ /* See LICENSE file for copyright and license details. */ -#include "libglitter.h" +#include "common.h" typedef uint_fast64_t greater_t; #define greater_t greater_t #define libglitter_compose_uint64 libglitter_compose_uint32 diff --git a/libglitter_compose_uint64.c b/libglitter_compose_uint64.c index fdb9b62..91d6b88 100644 --- a/libglitter_compose_uint64.c +++ b/libglitter_compose_uint64.c @@ -1,9 +1,8 @@ /* See LICENSE file for copyright and license details. */ -#include "libglitter.h" +#include "common.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 @@ -13,40 +12,24 @@ 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) +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, const LIBGLITTER_RENDER_CONTEXT *render_ctx) { 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}; + size_t cell00 = render_ctx->cells[0][0], cell01 = render_ctx->cells[0][1]; + size_t cell10 = render_ctx->cells[1][0], cell11 = render_ctx->cells[1][1]; + size_t cell20 = render_ctx->cells[2][0], cell21 = render_ctx->cells[2][1]; 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]; + input_blanking = input_rowsize * render_ctx->heightmul - width * render_ctx->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) { - 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]; + outputs[0][output_i] = (uint64_t)MIX(input[cell00], input[cell01]); + outputs[1][output_i] = (uint64_t)MIX(input[cell10], input[cell11]); + outputs[2][output_i] = (uint64_t)MIX(input[cell20], input[cell21]); + input = &input[render_ctx->widthmul]; } input = &input[input_blanking]; } @@ -82,7 +65,7 @@ generic(uint64_t **outputs, size_t noutputs, const uint64_t *restrict input, } for (i = 0; i < noutputs; i++) - outputs[i][output_i] = (uint64_t)(pixel[channel] / (greater_t)ncellvalues[i]); + outputs[i][output_i] = (uint64_t)(pixel[i] / (greater_t)ncellvalues[i]); input = &input[widthmul]; } @@ -92,20 +75,18 @@ generic(uint64_t **outputs, size_t noutputs, const uint64_t *restrict input, 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) +libglitter_compose_uint64(uint64_t **outputs, const uint64_t *restrict input, size_t output_rowsize, size_t output_cellsize, + size_t width, size_t height, const LIBGLITTER_RENDER_CONTEXT *render_ctx) { - 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); + if (render_ctx->render_method == RENDER_METHOD_VSTRIPS) { + vstrips(outputs, input, output_rowsize, output_cellsize, render_ctx->rowsize, width, height, render_ctx->cellmap); + } else if (render_ctx->render_method == RENDER_METHOD_HSTRIPS) { + hstrips(outputs, input, output_rowsize, output_cellsize, render_ctx->rowsize, width, height, render_ctx->cellmap); + } else if (render_ctx->render_method == RENDER_METHOD_SIMPLE) { + simple(outputs, input, output_rowsize, output_cellsize, render_ctx->rowsize, width, height, render_ctx); } else { - generic(outputs, noutputs, input, output_rowsize, output_cellsize, - input_rowsize, width, height, widthmul, heightmul, cellmap, ncellvalues); + generic(outputs, render_ctx->noutputs, input, output_rowsize, output_cellsize, + render_ctx->rowsize, width, height, render_ctx->widthmul, render_ctx->heightmul, + render_ctx->cellmap, render_ctx->ncellvalues); } } diff --git a/libglitter_compose_uint8.c b/libglitter_compose_uint8.c index 615232b..2c781f7 100644 --- a/libglitter_compose_uint8.c +++ b/libglitter_compose_uint8.c @@ -1,5 +1,5 @@ /* See LICENSE file for copyright and license details. */ -#include "libglitter.h" +#include "common.h" typedef uint_fast16_t greater_t; #define greater_t greater_t #define libglitter_compose_uint64 libglitter_compose_uint8 diff --git a/libglitter_create_render_context.c b/libglitter_create_render_context.c new file mode 100644 index 0000000..53b0705 --- /dev/null +++ b/libglitter_create_render_context.c @@ -0,0 +1,47 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +LIBGLITTER_RENDER_CONTEXT * +libglitter_create_render_context(size_t noutputs, size_t rowsize, size_t widthmul, size_t heightmul, + const uint8_t *cellmap, const uint8_t *ncellvalues) +{ + struct libglitter_render_context *this; + size_t i; + + this = calloc(1, sizeof(*this)); + if (!this) + return NULL; + + this->cellmap = cellmap; + this->ncellvalues = ncellvalues; + this->noutputs = noutputs; + this->widthmul = widthmul; + this->heightmul = heightmul; + + this->cellweights_double = calloc(noutputs, sizeof(*this->cellweights_double)); + if (!this->cellweights_double) + goto fail; + this->cellweights_float = calloc(noutputs, sizeof(*this->cellweights_float)); + if (!this->cellweights_float) + goto fail; + + this->render_method = + (noutputs == 3 && widthmul == 3 && heightmul == 1) ? RENDER_METHOD_VSTRIPS : + (noutputs == 3 && widthmul == 1 && heightmul == 3) ? RENDER_METHOD_HSTRIPS : + (noutputs == 3 && ncellvalues[0] <= 2 && ncellvalues[1] <= 2 && ncellvalues[2] <= 2) ? RENDER_METHOD_SIMPLE : + RENDER_METHOD_GENERIC; + + for (i = 0; i < noutputs; i++) { + this->cellweights_double[i] = 1 / (double)ncellvalues[i]; + this->cellweights_float[i] = 1 / (float)ncellvalues[i]; + } + + libglitter_update_render_context(this, rowsize); + + return this; + +fail: + libglitter_free_render_context(this); + return NULL; +} diff --git a/libglitter_free_render_context.c b/libglitter_free_render_context.c new file mode 100644 index 0000000..4eb15c2 --- /dev/null +++ b/libglitter_free_render_context.c @@ -0,0 +1,13 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +void +libglitter_free_render_context(LIBGLITTER_RENDER_CONTEXT *this) +{ + if (this) { + free(this->cellweights_double); + free(this->cellweights_float); + free(this); + } +} diff --git a/libglitter_update_render_context.c b/libglitter_update_render_context.c new file mode 100644 index 0000000..318ec87 --- /dev/null +++ b/libglitter_update_render_context.c @@ -0,0 +1,28 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +void +libglitter_update_render_context(LIBGLITTER_RENDER_CONTEXT *this, size_t rowsize) +{ + size_t y, x; + uint8_t channel; + size_t cellsi[3] = {0, 0, 0}; + + if (this && this->render_method == RENDER_METHOD_SIMPLE && this->rowsize != rowsize) { + this->rowsize = rowsize; + for (y = 0; y < this->heightmul; y++) { + for (x = 0; x < this->widthmul; x++) { + channel = this->cellmap[y * this->widthmul + x]; + this->cells[channel][cellsi[channel]] = y * rowsize + x; + cellsi[channel] += 1; + } + } + if (cellsi[0] == 1) + this->cells[0][1] = this->cells[0][0]; + if (cellsi[1] == 1) + this->cells[1][1] = this->cells[1][0]; + if (cellsi[2] == 1) + this->cells[2][1] = this->cells[2][0]; + } +} -- cgit v1.2.3-70-g09d2