aboutsummaryrefslogtreecommitdiffstats
path: root/libquanta.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--libquanta.h253
1 files changed, 253 insertions, 0 deletions
diff --git a/libquanta.h b/libquanta.h
new file mode 100644
index 0000000..89c2fa0
--- /dev/null
+++ b/libquanta.h
@@ -0,0 +1,253 @@
+/* See LICENSE file for copyright and license details. */
+#ifndef LIBQUANTA_H
+#define LIBQUANTA_H
+
+#include <stdarg.h>
+#include <stdint.h>
+#include <stddef.h>
+
+
+/**
+ * Colour-quantised image
+ */
+struct libquanta_image {
+ /**
+ * The image's width
+ */
+ size_t width;
+
+ /**
+ * The image's height
+ */
+ size_t height;
+
+ /**
+ * `.image[y * .width + x]` for `y` in [0, `.height`), `x` in [0, `.width`),
+ * will be the index of the colour at pixel (`x`, `y`). This index is the
+ * colour index in the colour palette stored separatedly in the `.palette`
+ * field of a `struct libquanta_palette`.
+ */
+ size_t image[];
+};
+
+
+/**
+ * A colour channel from an image
+ */
+struct libquanta_channel {
+ /**
+ * The number of bits per input image colour value,
+ * must be between 1 and 64 (inclusive)
+ */
+ size_t bits_in;
+
+ /**
+ * The number of bits per palette colour value,
+ * must be between 1 and `.bits_in` (inclusive)
+ */
+ size_t bits_out;
+
+ /**
+ * The image's width in cells
+ */
+ size_t image_width;
+
+ /**
+ * The image's height in cells
+ */
+ size_t image_height;
+
+ /**
+ * If image is row-major:
+ * The number of bytes per row in the image
+ *
+ * If image is column-major:
+ * The number of bytes per cell in the image
+ */
+ size_t image_row_size;
+
+ /**
+ * If image is row-major:
+ * The number of bytes per cell in the image
+ *
+ * If image is column-major:
+ * The number of bytes per column in the image
+ */
+ size_t image_cell_size;
+
+ /**
+ * The image
+ *
+ * Must not be `NULL` unless `.image_width` or `.image_height` is 0
+ *
+ * `&((const char *).image)[y * .image_row_size + x * .image_cell_size]`
+ * shall point to the colour value for cell (`x`, `y`), for the colour
+ * channel`, encoded in host-native endian; for
+ * 1 ≤ `.bits_in` ≤ 8, it shall be a `uint8_t`, for
+ * 9 ≤ `.bits_in` ≤ 16, it shall be a `uint16_t`, for
+ * 17 ≤ `.bits_in` ≤ 32, it shall be a `uint32_t`, and for
+ * 33 ≤ `.bits_in` ≤ 64, it shall be a `uint64_t`
+ */
+ const void *image;
+};
+
+
+/**
+ * Colour palette for an image
+ */
+struct libquanta_palette {
+ /**
+ * The number of colours stored in the palette, must be at least 1
+ */
+ size_t size;
+
+ /**
+ * The colour palette
+ *
+ * If the image has N colour channels, colour channel value i (within [0, N))
+ * for palette colour j (within [0, `.size`)), is `.palette[j * N + i]`
+ */
+ uint64_t palette[];
+};
+
+
+/**
+ * Get the allocation size for a `struct libquanta_palette`
+ *
+ * @param ncolours The number of colours the palette may hold
+ * @param nchannels The number of colour channels
+ * @param size_out Output parameter for the allocation size
+ * (may be `NULL`)
+ * @return 0 on success, -1 on failure
+ *
+ * @throws EOVERFLOW The palette is too large to be allocated
+ * @throws EINVAL `ncolours` or `nchannels` is 0
+ */
+int libquanta_palette_size(size_t ncolours, size_t nchannels, size_t *size_out);
+
+/**
+ * Allocate and initialise a colour palette
+ *
+ * @param ncolours The number of colours the palette may hold, must be at least 1
+ * @param nchannels The number of colour channels, must be at least 1
+ * @return Colour palette object with `.size` set to `ncolours`,
+ * allocated using malloc(3) (caller is responsible for
+ * deallocating it using free(3); `NULL` on failure
+ *
+ * @throws ENOMEM The palette is too large to be allocated,
+ * or there is not enough memory to allocate it
+ * @throws EINVAL `ncolours` or `nchannels` is 0
+ */
+struct libquanta_palette *libquanta_malloc_palette(size_t ncolours, size_t nchannels);
+
+
+/**
+ * Colour-quantise an image using some library-selected colour quantiser
+ *
+ * @param palette Colour palette to fill, `.size` must be set with the
+ * maximum number of colours, and will upon successful
+ * completion be set to the number of used colours
+ * @param args One `const struct libquanta_channel *` per colour
+ * channel, providing the image for each colour channel;
+ * the list shall be terminated by `NULL`
+ * @return Colour-quantised image, allocated using malloc(3)
+ * (caller is responsible for deallocating it using
+ * free(3); `NULL` on failure
+ *
+ * @throws EINVAL `palette` is `NULL`, `palette->size` is 0,
+ * or no colour channels are provided (the first argument
+ * stored in `args` is `NULL`)
+ * @throws ENOMEM Not enough memory available
+ *
+ * The function may write beyond to and beyond `&palette->palette[palette->size]`
+ * for `palette->size` as set after the function returns, but not as set when
+ * the function is called. The function may also have written to `palette->palette`
+ * even if the function fails.
+ */
+struct libquanta_image *libquanta_vquantise(struct libquanta_palette *palette, va_list args);
+
+/**
+ * Colour-quantise an image using some library-selected colour quantiser
+ *
+ * @param palette Colour palette to fill, `.size` must be set with the
+ * maximum number of colours, and will upon successful
+ * completion be set to the number of used colours
+ * @param ... One `const struct libquanta_channel *` per colour
+ * channel, providing the image for each colour channel;
+ * the list shall be terminated by `NULL`
+ * @return Colour-quantised image, allocated using malloc(3)
+ * (caller is responsible for deallocating it using
+ * free(3); `NULL` on failure
+ *
+ * @throws EINVAL `palette` is `NULL`, `palette->size` is 0,
+ * or no colour channels are provided (second argument is `NULL`)
+ * @throws EINVAL One of the colour channel descriptions has an invalid configuration
+ * or the colour channel descriptions do not have the same image size
+ * configured
+ * @throws ENOMEM Not enough memory available
+ *
+ * The function may write beyond to and beyond `&palette->palette[palette->size]`
+ * for `palette->size` as set after the function returns, but not as set when
+ * the function is called. The function may also have written to `palette->palette`
+ * even if the function fails.
+ */
+struct libquanta_image *libquanta_quantise(struct libquanta_palette *palette, ...);
+
+
+/**
+ * Colour-quantise an image using Wu's Colour Quantiser
+ *
+ * @param palette Colour palette to fill, `.size` must be set with the
+ * maximum number of colours, and will upon successful
+ * completion be set to the number of used colours
+ * @param args One `const struct libquanta_channel *` per colour
+ * channel, providing the image for each colour channel;
+ * the list shall be terminated by `NULL`
+ * @return Colour-quantised image, allocated using malloc(3)
+ * (caller is responsible for deallocating it using
+ * free(3); `NULL` on failure
+ *
+ * @throws EINVAL `palette` is `NULL`, `palette->size` is 0,
+ * or no colour channels are provided (the first argument
+ * stored in `args` is `NULL`)
+ * @throws EINVAL One of the colour channel descriptions has an invalid configuration
+ * or the colour channel descriptions do not have the same image size
+ * configured
+ * @throws ENOMEM Not enough memory available
+ *
+ * The function may write beyond to and beyond `&palette->palette[palette->size]`
+ * for `palette->size` as set after the function returns, but not as set when
+ * the function is called. The function may also have written to `palette->palette`
+ * even if the function fails.
+ */
+struct libquanta_image *libquanta_vquantise_wu(struct libquanta_palette *palette, va_list args);
+
+/**
+ * Colour-quantise an image using Wu's Colour Quantiser
+ *
+ * @param palette Colour palette to fill, `.size` must be set with the
+ * maximum number of colours, and will upon successful
+ * completion be set to the number of used colours
+ * @param ... One `const struct libquanta_channel *` per colour
+ * channel, providing the image for each colour channel;
+ * the list shall be terminated by `NULL`
+ * @return Colour-quantised image, allocated using malloc(3)
+ * (caller is responsible for deallocating it using
+ * free(3); `NULL` on failure
+ *
+ * @throws EINVAL `palette` is `NULL`, `palette->size` is 0,
+ * or no colour channels are provided (second argument is `NULL`)
+ * @throws EINVAL One of the colour channel descriptions has an invalid configuration
+ * or the colour channel descriptions do not have the same image size
+ * configured
+ * @throws ENOMEM Not enough memory available
+ *
+ * The function may write beyond to and beyond `&palette->palette[palette->size]`
+ * for `palette->size` as set after the function returns, but not as set when
+ * the function is called. The function may also have written to `palette->palette`
+ * even if the function fails.
+ */
+struct libquanta_image *libquanta_quantise_wu(struct libquanta_palette *palette, ...);
+
+
+#endif