diff options
-rw-r--r-- | libslim.h | 797 |
1 files changed, 797 insertions, 0 deletions
diff --git a/libslim.h b/libslim.h new file mode 100644 index 0000000..da5bc98 --- /dev/null +++ b/libslim.h @@ -0,0 +1,797 @@ +/** + * ISC License + * + * © 2019 Mattias Andrée <maandree@kth.se> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef LIBSLIM_H +#define LIBSLIM_H + +#include <stddef.h> +#include <stdint.h> +#include <string.h> + + +struct libslim_image_meta { + size_t width; + size_t height; + size_t hblank; +}; + +#define LIBSLIM_DECLARE_FORMAT(SUFFIX, PIXEL)\ + struct libslim_pixel_##SUFFIX PIXEL;\ + struct libslim_image_##SUFFIX {\ + struct libslim_image_meta meta;\ + struct libslim_pixel_##SUFFIX *data;\ + } + +LIBSLIM_DECLARE_FORMAT(xyza_f, { float x, y, z, a; }); +LIBSLIM_DECLARE_FORMAT(xyza_d, { double x, y, z, a; }); +LIBSLIM_DECLARE_FORMAT(xyza_ld, { long double x, y, z, a; }); + +LIBSLIM_DECLARE_FORMAT(xyz_f, { float x, y, z; }); +LIBSLIM_DECLARE_FORMAT(xyz_d, { double x, y, z; }); +LIBSLIM_DECLARE_FORMAT(xyz_ld, { long double x, y, z; }); + +LIBSLIM_DECLARE_FORMAT(rgba_f, { float r, g, b, a; }); +LIBSLIM_DECLARE_FORMAT(rgba_d, { double r, g, b, a; }); +LIBSLIM_DECLARE_FORMAT(rgba_ld, { long double r, g, b, a; }); + +LIBSLIM_DECLARE_FORMAT(rgb_f, { float r, g, b; }); +LIBSLIM_DECLARE_FORMAT(rgb_d, { double r, g, b; }); +LIBSLIM_DECLARE_FORMAT(rgb_ld, { long double r, g, b; }); + + + +/* Replace an entire row, of an image, with a single colour */ +#define libslim_set_colour_row(OUT, COLOUR)\ + do {\ + size_t x__, y__;\ + size_t w__ = (OUT)->meta.width;\ + for (x__ = 0; x__ < w__; x__++)\ + (OUT)->data[x__] = *(COLOUR);\ + } while (0) + + +/* Replace an entire image with a single colour */ +#define libslim_set_colour(OUT, COLOUR)\ + do {\ + size_t x__, y__;\ + size_t h__ = (OUT)->meta.height;\ + size_t w__ = (OUT)->meta.width;\ + void *out__ = (OUT)->data;\ + for (y__ = 0; y__ < h__; y__++) {\ + for (x__ = 0; x__ < w__; x__++)\ + (OUT)->data[x__] = (COLOUR);\ + (OUT)->data += (OUT)->meta.width + (OUT)->meta.hblank;\ + }\ + (OUT)->data = out__;\ + } while (0) + + +/* Horizontally flip a row of an image */ +#define libslim_flop_row(OUT, IN)\ + do {\ + size_t i__;\ + size_t n__ = (IN)->meta.width - 1;\ + for (i__ = 0; i__ < n__; i__++)\ + (OUT)->data[n__ - i__] = (IN)->data[i__];\ + } while (0) + + +/* Horizontally flip an image */ +#define libslim_flop(OUT, IN)\ + do {\ + size_t i__;\ + size_t n__ = (IN)->meta.width - 1;\ + size_t h__ = (IN)->meta.height;\ + void *in__ = (IN)->data;\ + void *out__ = (OUT)->data;\ + (OUT)->meta.width = (IN)->meta.width;\ + (OUT)->meta.height = (IN)->meta.height;\ + while (h__--) {\ + for (i__ = 0; i__ < n__; i__++)\ + (OUT)->data[n__ - i__] = (IN)->data[i__];\ + (IN)->data += (IN)->meta.width + (IN)->meta.hblank;\ + (OUT)->data += (OUT)->meta.width + (OUT)->meta.hblank;\ + }\ + (IN)->data = in__;\ + (OUT)->data = out__;\ + } while (0) + + +/* Vertically flip an image */ +#define libslim_flip(OUT, IN)\ + do {\ + size_t i__;\ + size_t n__ = (IN)->meta.height - 1;\ + size_t w__ = (IN)->meta.width * sizeof(*(IN)->data);\ + void *in__ = (IN)->data;\ + void *out__ = (OUT)->data;\ + (OUT)->meta.width = (IN)->meta.width;\ + (OUT)->meta.height = (IN)->meta.height;\ + (OUT)->data += n__ * ((OUT)->meta.width + (OUT)->meta.hblank);\ + for (i__ = 0; i__ < n__; i__++) {\ + memcpy((OUT)->data, (IN)->data, w__);\ + (IN)->data += (IN)->meta.width + (IN)->meta.hblank;\ + (OUT)->data -= (OUT)->meta.width + (OUT)->meta.hblank;\ + }\ + (IN)->data = in__;\ + (OUT)->data = out__;\ + } while (0) + + +/* Transpose an image */ +#define libslim_transpose(OUT, IN)\ + do {\ + size_t x__, y__, i__;\ + size_t rw__ = (OUT)->meta.width + (OUT)->meta.hblank;\ + size_t w__ = (IN)->meta.width;\ + size_t h__ = (IN)->meta.height;\ + void *in__ = (IN)->data;\ + void *out__ = (OUT)->data;\ + (OUT)->meta.width = (IN)->meta.height;\ + (OUT)->meta.height = (IN)->meta.width;\ + for (y__ = 0; y__ < h__; y__++) {\ + for (x__ = i__ = 0; x__ < w__; x__++, i__ += rw__)\ + (OUT)->data[i__] = (IN)->data[x__];\ + (IN)->data += (IN)->meta.width + (IN)->meta.hblank;\ + (OUT)->data += 1;\ + }\ + (IN)->data = in__;\ + (OUT)->data = in__;\ + } while (0) + + +/* Rotate an image 90 degrees clockwise */ +#define libslim_rotate_90(OUT, IN)\ + do {\ + libslim_transpose((IN), (OUT));\ + libslim_flop((IN), (OUT));\ + } while (0) + + +/* Rotate an image 180 degrees */ +#define libslim_rotate_180(OUT, IN)\ + do {\ + libslim_flip((IN), (OUT));\ + libslim_flop((IN), (OUT));\ + } while (0) + + +/* Rotate an image 270 degrees clockwise */ +#define libslim_rotate_270(OUT, IN)\ + do {\ + libslim_flop((IN), (OUT));\ + libslim_transpose((IN), (OUT));\ + } while (0) + + +/* Swap channels in an image with 4 channels */ +#define libslim_swap_channels_4(OUT, IN, IN_CH1, OUT_CH1, IN_CH2, OUT_CH2, IN_CH3, OUT_CH3, IN_CH4, OUT_CH4)\ + do {\ + size_t x__, y__;\ + size_t h__ = (IN)->meta.height;\ + size_t w__ = (IN)->meta.width;\ + void *in__ = (IN)->data;\ + void *out__ = (OUT)->data;\ + (OUT)->meta.height = h__;\ + (OUT)->meta.width = w__;\ + for (y__ = 0; y__ < h__; y__++) {\ + for (x__ = 0; x__ < w__; x__++) {\ + (OUT)->data[x__].OUT_CH1 = (IN)->data[x__].IN_CH1;\ + (OUT)->data[x__].OUT_CH2 = (IN)->data[x__].IN_CH2;\ + (OUT)->data[x__].OUT_CH3 = (IN)->data[x__].IN_CH3;\ + (OUT)->data[x__].OUT_CH4 = (IN)->data[x__].IN_CH4;\ + }\ + (IN)->data += (IN)->meta.width + (IN)->meta.hblank;\ + (OUT)->data += (OUT)->meta.width + (OUT)->meta.hblank;\ + }\ + (IN)->data = in__;\ + (OUT)->data = out__;\ + } while (0) + + +/* Swap channels in a row of an image with 4 channels */ +#define libslim_swap_channels_4_row(OUT, IN, IN_CH1, OUT_CH1, IN_CH2, OUT_CH2, IN_CH3, OUT_CH3, IN_CH4, OUT_CH4)\ + do {\ + size_t i__;\ + size_t n__ = (IN)->meta.width;\ + for (i__ = 0; i__ < n__; i__++) {\ + (OUT)->data[i__].OUT_CH1 = (IN)->data[i__].IN_CH1;\ + (OUT)->data[i__].OUT_CH2 = (IN)->data[i__].IN_CH2;\ + (OUT)->data[i__].OUT_CH3 = (IN)->data[i__].IN_CH3;\ + (OUT)->data[i__].OUT_CH4 = (IN)->data[i__].IN_CH4;\ + }\ + } while (0) + + +/* Swap channels in an image with 3 channels */ +#define libslim_swap_channels_3(OUT, IN, IN_CH1, OUT_CH1, IN_CH2, OUT_CH2, IN_CH3, OUT_CH3)\ + do {\ + size_t x__, y__;\ + size_t h__ = (IN)->meta.height;\ + size_t w__ = (IN)->meta.width;\ + void *in__ = (IN)->data;\ + void *out__ = (OUT)->data;\ + (OUT)->meta.height = h__;\ + (OUT)->meta.width = w__;\ + for (y__ = 0; y__ < h__; y__++) {\ + for (x__ = 0; x__ < w__; x__++) {\ + (OUT)->data[x__].OUT_CH1 = (IN)->data[x__].IN_CH1;\ + (OUT)->data[x__].OUT_CH2 = (IN)->data[x__].IN_CH2;\ + (OUT)->data[x__].OUT_CH3 = (IN)->data[x__].IN_CH3;\ + }\ + (IN)->data += (IN)->meta.width + (IN)->meta.hblank;\ + (OUT)->data += (OUT)->meta.width + (OUT)->meta.hblank;\ + }\ + (IN)->data = in__;\ + (OUT)->data = out__;\ + } while (0) + + +/* Swap channels in a row of an image with 3 channels */ +#define libslim_swap_channels_3_row(OUT, IN, IN_CH1, OUT_CH1, IN_CH2, OUT_CH2, IN_CH3, OUT_CH3)\ + do {\ + size_t i__;\ + size_t n__ = (IN)->meta.width;\ + for (i__ = 0; i__ < n__; i__++) {\ + (OUT)->data[i__].OUT_CH1 = (IN)->data[i__].IN_CH1;\ + (OUT)->data[i__].OUT_CH2 = (IN)->data[i__].IN_CH2;\ + (OUT)->data[i__].OUT_CH3 = (IN)->data[i__].IN_CH3;\ + }\ + } while (0) + + +/* Swap channels in an image with 2 channels */ +#define libslim_swap_channels_2(OUT, IN, IN_CH1, OUT_CH1, IN_CH2, OUT_CH2)\ + do {\ + size_t x__, y__;\ + size_t h__ = (IN)->meta.height;\ + size_t w__ = (IN)->meta.width;\ + void *in__ = (IN)->data;\ + void *out__ = (OUT)->data;\ + (OUT)->meta.height = h__;\ + (OUT)->meta.width = w__;\ + for (y__ = 0; y__ < h__; y__++) {\ + for (x__ = 0; x__ < w__; x__++) {\ + (OUT)->data[x__].OUT_CH1 = (IN)->data[x__].IN_CH1;\ + (OUT)->data[x__].OUT_CH2 = (IN)->data[x__].IN_CH2;\ + }\ + (IN)->data += (IN)->meta.width + (IN)->meta.hblank;\ + (OUT)->data += (OUT)->meta.width + (OUT)->meta.hblank;\ + }\ + (IN)->data = in__;\ + (OUT)->data = out__;\ + } while (0) + + +/* Swap channels in a row of an image with 2 channels */ +#define libslim_swap_channels_2_row(OUT, IN, IN_CH1, OUT_CH1, IN_CH2, OUT_CH2)\ + do {\ + size_t i__;\ + size_t n__ = (IN)->meta.width;\ + for (i__ = 0; i__ < n__; i__++) {\ + (OUT)->data[i__].OUT_CH1 = (IN)->data[i__].IN_CH1;\ + (OUT)->data[i__].OUT_CH2 = (IN)->data[i__].IN_CH2;\ + }\ + } while (0) + + +/* Set the values of 3 channels in all pixels in an image */ +#define libslim_set_3_channels(OUT, IN, COLOUR, CH1, CH2, CH3)\ + do {\ + size_t x__, y__;\ + size_t h__ = (IN)->meta.height;\ + size_t w__ = (IN)->meta.width;\ + void *in__ = (IN)->data;\ + void *out__ = (OUT)->data;\ + (OUT)->meta.height = h__;\ + (OUT)->meta.width = w__;\ + for (y__ = 0; y__ < h__; y__++) {\ + for (x__ = 0; x__ < w__; x__++) {\ + (OUT)->data[x__] = (IN)->data[x__];\ + (OUT)->data[x__].CH1 = (COLOUR)->CH1;\ + (OUT)->data[x__].CH2 = (COLOUR)->CH2;\ + (OUT)->data[x__].CH3 = (COLOUR)->CH3;\ + }\ + (IN)->data += (IN)->meta.width + (IN)->meta.hblank;\ + (OUT)->data += (OUT)->meta.width + (OUT)->meta.hblank;\ + }\ + (IN)->data = in__;\ + (OUT)->data = out__;\ + } while (0) + + +/* Set the values of 3 channels in all pixels in a row of an image */ +#define libslim_set_3_channels_row(OUT, IN, COLOUR, CH1, CH2, CH3)\ + do {\ + size_t i__;\ + size_t n__ = (IN)->meta.width;\ + for (i__ = 0; i__ < n__; i__++) {\ + (OUT)->data[i__] = (IN)->data[i__];\ + (OUT)->data[i__].CH1 = (COLOUR)->CH1;\ + (OUT)->data[i__].CH2 = (COLOUR)->CH2;\ + (OUT)->data[i__].CH3 = (COLOUR)->CH3;\ + }\ + } while (0) + + +/* Set the values of 2 channels in all pixels in an image */ +#define libslim_set_2_channels(OUT, IN, COLOUR, CH1, CH2)\ + do {\ + size_t x__, y__;\ + size_t h__ = (IN)->meta.height;\ + size_t w__ = (IN)->meta.width;\ + void *in__ = (IN)->data;\ + void *out__ = (OUT)->data;\ + (OUT)->meta.height = h__;\ + (OUT)->meta.width = w__;\ + for (y__ = 0; y__ < h__; y__++) {\ + for (x__ = 0; x__ < w__; x__++) {\ + (OUT)->data[x__] = (IN)->data[x__];\ + (OUT)->data[x__].CH1 = (COLOUR)->CH1;\ + (OUT)->data[x__].CH2 = (COLOUR)->CH2;\ + }\ + (IN)->data += (IN)->meta.width + (IN)->meta.hblank;\ + (OUT)->data += (OUT)->meta.width + (OUT)->meta.hblank;\ + }\ + (IN)->data = in__;\ + (OUT)->data = out__;\ + } while (0) + + +/* Set the values of 2 channels in all pixels in a row of an image */ +#define libslim_set_2_channels_row(OUT, IN, COLOUR, CH1, CH2)\ + do {\ + size_t i__;\ + size_t n__ = (IN)->meta.width;\ + for (i__ = 0; i__ < n__; i__++) {\ + (OUT)->data[i__] = (IN)->data[i__];\ + (OUT)->data[i__].CH1 = (COLOUR)->CH1;\ + (OUT)->data[i__].CH2 = (COLOUR)->CH2;\ + }\ + } while (0) + + +/* Set the values of 1 channel in all pixels in an image */ +#define libslim_set_1_channel(OUT, IN, COLOUR, CH)\ + do {\ + size_t x__, y__;\ + size_t h__ = (IN)->meta.height;\ + size_t w__ = (IN)->meta.width;\ + void *in__ = (IN)->data;\ + void *out__ = (OUT)->data;\ + (OUT)->meta.height = h__;\ + (OUT)->meta.width = w__;\ + for (y__ = 0; y__ < h__; y__++) {\ + for (x__ = 0; x__ < w__; x__++) {\ + (OUT)->data[x__] = (IN)->data[x__];\ + (OUT)->data[x__].CH = (COLOUR)->CH;\ + }\ + (IN)->data += (IN)->meta.width + (IN)->meta.hblank;\ + (OUT)->data += (OUT)->meta.width + (OUT)->meta.hblank;\ + }\ + (IN)->data = in__;\ + (OUT)->data = out__;\ + } while (0) + + +/* Set the values of 1 channel in all pixels in a row of an image */ +#define libslim_set_1_channel_row(OUT, IN, COLOUR, CH)\ + do {\ + size_t i__;\ + size_t n__ = (IN)->meta.width;\ + for (i__ = 0; i__ < n__; i__++) {\ + (OUT)->data[i__] = (IN)->data[i__];\ + (OUT)->data[i__].CH = (COLOUR)->CH;\ + }\ + } while (0) + + +/* Crop an image */ +#define libslim_crop(OUT, IN, LEFT, TOP, WIDTH, HEIGHT)\ + do {\ + size_t i__;\ + size_t w__ = (WIDTH);\ + size_t h__ = (HEIGHT);\ + size_t rw__ = w__ * sizeof(*(IN)->data);\ + void *in__ = (IN)->data;\ + void *out__ = (OUT)->data;\ + (OUT)->meta.width = w__;\ + (OUT)->meta.height = h__;\ + (IN)->data += (LEFT);\ + (IN)->data += (TOP) * ((IN)->meta.width + (IN)->meta.hblank);\ + for (i__ = 0; i__ < h__; i__++) {\ + memcpy((OUT)->data, (IN)->data, rw__);\ + (IN)->data += (IN)->meta.width + (IN)->meta.hblank;\ + (OUT)->data += (OUT)->meta.width + (OUT)->meta.hblank;\ + }\ + (IN)->data = in__;\ + (OUT)->data = out__;\ + } while (0) + + +/* Premultiply 3 channels in all pixels in an image */ +#define libslim_premultiply_3_channels(OUT, IN, CH1, CH2, CH3)\ + do {\ + size_t x__, y__;\ + size_t h__ = (IN)->meta.height;\ + size_t w__ = (IN)->meta.width;\ + void *in__ = (IN)->data;\ + void *out__ = (OUT)->data;\ + (OUT)->meta.height = h__;\ + (OUT)->meta.width = w__;\ + for (y__ = 0; y__ < h__; y__++) {\ + for (x__ = 0; x__ < w__; x__++) {\ + (OUT)->data[x__].CH1 = (IN)->data[x__].CH1 * (IN)->data[x__].a;\ + (OUT)->data[x__].CH2 = (IN)->data[x__].CH2 * (IN)->data[x__].a;\ + (OUT)->data[x__].CH3 = (IN)->data[x__].CH3 * (IN)->data[x__].a;\ + (OUT)->data[x__].a = (IN)->data[x__].a;\ + }\ + (IN)->data += (IN)->meta.width + (IN)->meta.hblank;\ + (OUT)->data += (OUT)->meta.width + (OUT)->meta.hblank;\ + }\ + (IN)->data = in__;\ + (OUT)->data = out__;\ + } while (0) + + +/* Premultiply 3 channels in all pixels in a row of an image */ +#define libslim_premultiply_3_channels_row(OUT, IN, CH1, CH2, CH3)\ + do {\ + size_t i__;\ + size_t n__ = (IN)->meta.width;\ + for (i__ = 0; i__ < n__; i__++) {\ + (OUT)->data[i__].CH1 = (IN)->data[i__].CH1 * (IN)->data[i__].a;\ + (OUT)->data[i__].CH2 = (IN)->data[i__].CH2 * (IN)->data[i__].a;\ + (OUT)->data[i__].CH3 = (IN)->data[i__].CH3 * (IN)->data[i__].a;\ + (OUT)->data[i__].a = (IN)->data[i__].a;\ + }\ + } while (0) + + +/* Premultiply 2 channels in all pixels in an image */ +#define libslim_premultiply_2_channels(OUT, IN, CH1, CH2)\ + do {\ + size_t x__, y__;\ + size_t h__ = (IN)->meta.height;\ + size_t w__ = (IN)->meta.width;\ + void *in__ = (IN)->data;\ + void *out__ = (OUT)->data;\ + (OUT)->meta.height = h__;\ + (OUT)->meta.width = w__;\ + for (y__ = 0; y__ < h__; y__++) {\ + for (x__ = 0; x__ < w__; x__++) {\ + (OUT)->data[x__].CH1 = (IN)->data[x__].CH1 * (IN)->data[x__].a;\ + (OUT)->data[x__].CH2 = (IN)->data[x__].CH2 * (IN)->data[x__].a;\ + (OUT)->data[x__].a = (IN)->data[x__].a;\ + }\ + (IN)->data += (IN)->meta.width + (IN)->meta.hblank;\ + (OUT)->data += (OUT)->meta.width + (OUT)->meta.hblank;\ + }\ + (IN)->data = in__;\ + (OUT)->data = out__;\ + } while (0) + + +/* Premultiply 2 channels in all pixels in a row of an image */ +#define libslim_premultiply_2_channels_row(OUT, IN, CH1, CH2)\ + do {\ + size_t i__;\ + size_t n__ = (IN)->meta.width;\ + for (i__ = 0; i__ < n__; i__++) {\ + (OUT)->data[i__].CH1 = (IN)->data[i__].CH1 * (IN)->data[i__].a;\ + (OUT)->data[i__].CH2 = (IN)->data[i__].CH2 * (IN)->data[i__].a;\ + (OUT)->data[i__].a = (IN)->data[i__].a;\ + }\ + } while (0) + + +/* Premultiply 1 channel in all pixels in an image */ +#define libslim_premultiply_1_channel(OUT, IN, CH)\ + do {\ + size_t x__, y__;\ + size_t h__ = (IN)->meta.height;\ + size_t w__ = (IN)->meta.width;\ + void *in__ = (IN)->data;\ + void *out__ = (OUT)->data;\ + (OUT)->meta.height = h__;\ + (OUT)->meta.width = w__;\ + for (y__ = 0; y__ < h__; y__++) {\ + for (x__ = 0; x__ < w__; x__++) {\ + (OUT)->data[x__].CH = (IN)->data[x__].CH * (IN)->data[x__].a;\ + (OUT)->data[x__].a = (IN)->data[x__].a;\ + }\ + (IN)->data += (IN)->meta.width + (IN)->meta.hblank;\ + (OUT)->data += (OUT)->meta.width + (OUT)->meta.hblank;\ + }\ + (IN)->data = in__;\ + (OUT)->data = out__;\ + } while (0) + + +/* Premultiply 1 channel in all pixels in a row of an image */ +#define libslim_premultiply_1_channel_row(OUT, IN, CH)\ + do {\ + size_t i__;\ + size_t n__ = (IN)->meta.width;\ + for (i__ = 0; i__ < n__; i__++) {\ + (OUT)->data[i__].CH = (IN)->data[i__].CH * (IN)->data[i__].a;\ + (OUT)->data[i__].a = (IN)->data[i__].a;\ + }\ + } while (0) + + +/* Unpremultiply 3 channels in all pixels in an image */ +#define libslim_unpremultiply_3_channels(OUT, IN, CH1, CH2, CH3)\ + do {\ + size_t x__, y__;\ + size_t h__ = (IN)->meta.height;\ + size_t w__ = (IN)->meta.width;\ + void *in__ = (IN)->data;\ + void *out__ = (OUT)->data;\ + (OUT)->meta.height = h__;\ + (OUT)->meta.width = w__;\ + for (y__ = 0; y__ < h__; y__++) {\ + for (x__ = 0; x__ < w__; x__++) {\ + (OUT)->data[x__] = (IN)->data[x__];\ + if ((IN)->data[i__].a) {\ + (OUT)->data[x__].CH1 /= (IN)->data[x__].a;\ + (OUT)->data[x__].CH2 /= (IN)->data[x__].a;\ + (OUT)->data[x__].CH3 /= (IN)->data[x__].a;\ + }\ + }\ + (IN)->data += (IN)->meta.width + (IN)->meta.hblank;\ + (OUT)->data += (OUT)->meta.width + (OUT)->meta.hblank;\ + }\ + (IN)->data = in__;\ + (OUT)->data = out__;\ + } while (0) + + +/* Unpremultiply 3 channels in all pixels in a row of an image */ +#define libslim_unpremultiply_3_channels_row(OUT, IN, CH1, CH2, CH3)\ + do {\ + size_t i__;\ + size_t n__ = (IN)->meta.width;\ + for (i__ = 0; i__ < n__; i__++) {\ + (OUT)->data[i__] = (IN)->data[i__];\ + if ((IN)->data[i__].a) {\ + (OUT)->data[i__].CH1 /= (IN)->data[i__].a;\ + (OUT)->data[i__].CH2 /= (IN)->data[i__].a;\ + (OUT)->data[i__].CH3 /= (IN)->data[i__].a;\ + }\ + }\ + } while (0) + + +/* Unpremultiply 2 channels in all pixels in an image */ +#define libslim_unpremultiply_2_channels(OUT, IN, CH1, CH2)\ + do {\ + size_t x__, y__;\ + size_t h__ = (IN)->meta.height;\ + size_t w__ = (IN)->meta.width;\ + void *in__ = (IN)->data;\ + void *out__ = (OUT)->data;\ + (OUT)->meta.height = h__;\ + (OUT)->meta.width = w__;\ + for (y__ = 0; y__ < h__; y__++) {\ + for (x__ = 0; x__ < w__; x__++) {\ + (OUT)->data[x__] = (IN)->data[x__];\ + if ((IN)->data[i__].a) {\ + (OUT)->data[x__].CH1 /= (IN)->data[x__].a;\ + (OUT)->data[x__].CH2 /= (IN)->data[x__].a;\ + }\ + }\ + (IN)->data += (IN)->meta.width + (IN)->meta.hblank;\ + (OUT)->data += (OUT)->meta.width + (OUT)->meta.hblank;\ + }\ + (IN)->data = in__;\ + (OUT)->data = out__;\ + } while (0) + + +/* Unpremultiply 2 channels in all pixels in a row of an image */ +#define libslim_unpremultiply_2_channels_row(OUT, IN, CH1, CH2)\ + do {\ + size_t i__;\ + size_t n__ = (IN)->meta.width;\ + for (i__ = 0; i__ < n__; i__++) {\ + (OUT)->data[i__] = (IN)->data[i__];\ + if ((IN)->data[i__].a) {\ + (OUT)->data[i__].CH1 /= (IN)->data[i__].a;\ + (OUT)->data[i__].CH2 /= (IN)->data[i__].a;\ + }\ + }\ + } while (0) + + +/* Unpremultiply 1 channel in all pixels in an image */ +#define libslim_unpremultiply_1_channel(OUT, IN, CH)\ + do {\ + size_t x__, y__;\ + size_t h__ = (IN)->meta.height;\ + size_t w__ = (IN)->meta.width;\ + void *in__ = (IN)->data;\ + void *out__ = (OUT)->data;\ + (OUT)->meta.height = h__;\ + (OUT)->meta.width = w__;\ + for (y__ = 0; y__ < h__; y__++) {\ + for (x__ = 0; x__ < w__; x__++) {\ + (OUT)->data[x__] = (IN)->data[x__];\ + if ((IN)->data[i__].a)\ + (OUT)->data[x__].CH /= (IN)->data[x__].a;\ + }\ + (IN)->data += (IN)->meta.width + (IN)->meta.hblank;\ + (OUT)->data += (OUT)->meta.width + (OUT)->meta.hblank;\ + }\ + (IN)->data = in__;\ + (OUT)->data = out__;\ + } while (0) + + +/* Unpremultiply 1 channel in all pixels in a row of an image */ +#define libslim_unpremultiply_1_channel_row(OUT, IN, CH)\ + do {\ + size_t i__;\ + size_t n__ = (IN)->meta.width;\ + for (i__ = 0; i__ < n__; i__++) {\ + (OUT)->data[i__] = (IN)->data[i__];\ + if ((IN)->data[i__].a)\ + (OUT)->data[i__].CH /= (IN)->data[i__].a;\ + }\ + } while (0) + + +/* Unpremultiply 3 channels in all pixels in an image */ +#define libslim_unpremultiply_3_channels_zero(OUT, IN, ZERO, CH1, CH2, CH3)\ + do {\ + size_t x__, y__;\ + size_t h__ = (IN)->meta.height;\ + size_t w__ = (IN)->meta.width;\ + void *in__ = (IN)->data;\ + void *out__ = (OUT)->data;\ + (OUT)->meta.height = h__;\ + (OUT)->meta.width = w__;\ + for (y__ = 0; y__ < h__; y__++) {\ + for (x__ = 0; x__ < w__; x__++) {\ + (OUT)->data[x__] = (IN)->data[x__];\ + if ((IN)->data[i__].a) {\ + (OUT)->data[x__].CH1 /= (IN)->data[x__].a;\ + (OUT)->data[x__].CH2 /= (IN)->data[x__].a;\ + (OUT)->data[x__].CH3 /= (IN)->data[x__].a;\ + } else {\ + (OUT)->data[x__].CH1 = (ZERO)->CH1;\ + (OUT)->data[x__].CH2 = (ZERO)->CH2;\ + (OUT)->data[x__].CH3 = (ZERO)->CH3;\ + } + }\ + (IN)->data += (IN)->meta.width + (IN)->meta.hblank;\ + (OUT)->data += (OUT)->meta.width + (OUT)->meta.hblank;\ + }\ + (IN)->data = in__;\ + (OUT)->data = out__;\ + } while (0) + + +/* Unpremultiply 3 channels in all pixels in a row of an image */ +#define libslim_unpremultiply_3_channels_zero_row(OUT, IN, ZERO, CH1, CH2, CH3)\ + do {\ + size_t i__;\ + size_t n__ = (IN)->meta.width;\ + for (i__ = 0; i__ < n__; i__++) {\ + (OUT)->data[i__] = (IN)->data[i__];\ + if ((IN)->data[i__].a) {\ + (OUT)->data[i__].CH1 /= (IN)->data[i__].a;\ + (OUT)->data[i__].CH2 /= (IN)->data[i__].a;\ + (OUT)->data[i__].CH3 /= (IN)->data[i__].a;\ + } else {\ + (OUT)->data[x__].CH1 = (ZERO)->CH1;\ + (OUT)->data[x__].CH2 = (ZERO)->CH2;\ + (OUT)->data[x__].CH3 = (ZERO)->CH3;\ + }\ + }\ + } while (0) + + +/* Unpremultiply 2 channels in all pixels in an image */ +#define libslim_unpremultiply_2_channels_zero(OUT, IN, ZERO, CH1, CH2)\ + do {\ + size_t x__, y__;\ + size_t h__ = (IN)->meta.height;\ + size_t w__ = (IN)->meta.width;\ + void *in__ = (IN)->data;\ + void *out__ = (OUT)->data;\ + (OUT)->meta.height = h__;\ + (OUT)->meta.width = w__;\ + for (y__ = 0; y__ < h__; y__++) {\ + for (x__ = 0; x__ < w__; x__++) {\ + (OUT)->data[x__] = (IN)->data[x__];\ + if ((IN)->data[i__].a) {\ + (OUT)->data[x__].CH1 /= (IN)->data[x__].a;\ + (OUT)->data[x__].CH2 /= (IN)->data[x__].a;\ + } else {\ + (OUT)->data[x__].CH1 = (ZERO)->CH1;\ + (OUT)->data[x__].CH2 = (ZERO)->CH2;\ + }\ + }\ + (IN)->data += (IN)->meta.width + (IN)->meta.hblank;\ + (OUT)->data += (OUT)->meta.width + (OUT)->meta.hblank;\ + }\ + (IN)->data = in__;\ + (OUT)->data = out__;\ + } while (0) + + +/* Unpremultiply 2 channels in all pixels in a row of an image */ +#define libslim_unpremultiply_2_channels_zero_row(OUT, IN, ZERO, CH1, CH2)\ + do {\ + size_t i__;\ + size_t n__ = (IN)->meta.width;\ + for (i__ = 0; i__ < n__; i__++) {\ + (OUT)->data[i__] = (IN)->data[i__];\ + if ((IN)->data[i__].a) {\ + (OUT)->data[i__].CH1 /= (IN)->data[i__].a;\ + (OUT)->data[i__].CH2 /= (IN)->data[i__].a;\ + } else {\ + (OUT)->data[x__].CH1 = (ZERO)->CH1;\ + (OUT)->data[x__].CH2 = (ZERO)->CH2;\ + }\ + }\ + } while (0) + + +/* Unpremultiply 1 channel in all pixels in an image */ +#define libslim_unpremultiply_1_channel_zero(OUT, IN, ZERO, CH)\ + do {\ + size_t x__, y__;\ + size_t h__ = (IN)->meta.height;\ + size_t w__ = (IN)->meta.width;\ + void *in__ = (IN)->data;\ + void *out__ = (OUT)->data;\ + (OUT)->meta.height = h__;\ + (OUT)->meta.width = w__;\ + for (y__ = 0; y__ < h__; y__++) {\ + for (x__ = 0; x__ < w__; x__++) {\ + (OUT)->data[x__] = (IN)->data[x__];\ + if ((IN)->data[i__].a)\ + (OUT)->data[x__].CH /= (IN)->data[x__].a;\ + else\ + (OUT)->data[x__].CH = (ZERO)->CH;\ + }\ + (IN)->data += (IN)->meta.width + (IN)->meta.hblank;\ + (OUT)->data += (OUT)->meta.width + (OUT)->meta.hblank;\ + }\ + (IN)->data = in__;\ + (OUT)->data = out__;\ + } while (0) + + +/* Unpremultiply 1 channel in all pixels in a row of an image */ +#define libslim_unpremultiply_1_channel_zero_row(OUT, IN, ZERO, CH)\ + do {\ + size_t i__;\ + size_t n__ = (IN)->meta.width;\ + for (i__ = 0; i__ < n__; i__++) {\ + (OUT)->data[i__] = (IN)->data[i__];\ + if ((IN)->data[i__].a)\ + (OUT)->data[i__].CH /= (IN)->data[i__].a;\ + else\ + (OUT)->data[x__].CH = (ZERO)->CH;\ + }\ + } while (0) + + +#endif |