aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libslim.h797
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