/* See LICENSE file for copyright and license details. */ #include #include #include #include #include #include #include "libquanta.h" static void die(const char *msg) { perror(msg); exit(1); } static void xfread(void *ptr, size_t size, size_t n) { if (fread(ptr, size, n, stdin) != n) { if (feof(stdin)) fprintf(stderr, "Unexpected EOF\n"); else perror("fread"); exit(1); } } static uint32_t read_be32(void) { uint32_t be; xfread(&be, 1, sizeof(be)); return ntohl(be); } static uint16_t read_be16(void) { uint16_t be; xfread(&be, 1, sizeof(be)); return ntohs(be); } static void xfwrite(const void *ptr, size_t size, size_t n) { if (fwrite(ptr, size, n, stdout) != n) die("fwrite"); } static void write_be32(uint32_t v) { uint32_t be = htonl(v); xfwrite(&be, 1, sizeof(be)); } static void write_be16(uint16_t v) { uint16_t be = htons(v); xfwrite(&be, 1, sizeof(be)); } static size_t parse_opt_zu(const char *s, size_t def) { char *end = NULL; unsigned long int v; if (!s || !*s) return def; errno = 0; v = strtoul(s, &end, 10); if (errno || end == s || *end || v == 0) return def; return (size_t)v; } int main(void) { size_t max_colours = parse_opt_zu(getenv("QUANTA_COLOURS"), 16); char magic[8]; size_t w, h, size, i, j; uint16_t *chimgs[4]; struct libquanta_channel chs[4]; struct libquanta_palette *pal; struct libquanta_image *img; xfread(magic, 1, 8); if (memcmp(magic, "farbfeld", 8)) { fprintf(stderr, "Input is not farbfeld\n"); return 1; } w = (size_t)read_be32(); h = (size_t)read_be32(); if (!w || !h) { fprintf(stderr, "Empty image\n"); return 1; } if (w > SIZE_MAX / h) { fprintf(stderr, "Image too large\n"); return 1; } size = w * h; memset(chs, 0, sizeof(chs)); for (i = 0; i < 4; i++) { chimgs[i] = calloc(size, sizeof(**chimgs)); if (!chimgs[i]) die("calloc"); chs[i].bits_in = 16; chs[i].bits_out = 16; chs[i].image_width = w; chs[i].image_height = h; chs[i].image_row_size = w * sizeof(uint16_t); chs[i].image_cell_size = sizeof(uint16_t); chs[i].image = chimgs[i]; } for (j = 0; j < size; j++) for (i = 0; i < 4; i++) chimgs[i][j] = read_be16(); pal = libquanta_malloc_palette(max_colours, 4); if (!pal) die("libquanta_malloc_palette"); img = libquanta_quantise(pal, &chs[0], &chs[1], &chs[2], &chs[3], NULL); if (!img) die("libquanta_quantise"); xfwrite("farbfeld", 1, 8); write_be32((uint32_t)w); write_be32((uint32_t)h); for (j = 0; j < size; j++) for (i = 0; i < 4; i++) write_be16((uint16_t)pal->palette[img->image[j] * 4 + i]); free(img); free(pal); for (i = 4; i--;) free(chimgs[i]); fflush(stdout); return 0; }