#ifndef LIBFF_H #define LIBFF_H /* libff * * A very slim library to work with Farbfeld images. * * Upstream, format reference: http://tools.suckless.org/farbfeld/ */ #define __FF__ "libff" #include #include #include #include #include #include struct FFImage { uint32_t width, height; uint16_t *data; }; /* Initialize a struct FFImage of the given size. Careful, discards any * existing data. */ bool ff_init_empty(struct FFImage *image, uint32_t w, uint32_t h) { image->width = w; image->height = h; image->data = calloc(image->width * image->height * 4, sizeof (uint16_t)); if (!image->data) { fprintf(stderr, __FF__": Could not allocate memory in ff_init_empty\n"); return false; } return true; } /* Load a farbfeld image from a file. Careful, discards any existing * data in "image". */ bool ff_load(char *path, struct FFImage *image) { FILE *fp = NULL; uint32_t hdr[4], x, y, rgba; image->data = NULL; fp = fopen(path, "r"); if (!fp) { fprintf(stderr, __FF__": Could not open image file '%s'\n", path); goto errout; } if (fread(hdr, sizeof (uint32_t), 4, fp) != 4) { fprintf(stderr, __FF__": Could not read farbfeld header from '%s'\n", path); goto errout; } if (memcmp("farbfeld", hdr, (sizeof "farbfeld") - 1) != 0) { fprintf(stderr, __FF__": Magic number is not 'farbfeld', path '%s'\n", path); goto errout; } image->width = ntohl(hdr[2]); image->height = ntohl(hdr[3]); image->data = calloc(image->width * image->height * 4, sizeof (uint16_t)); if (!image->data) { fprintf(stderr, __FF__": Could not allocate memory, image->data for '%s'\n", path); goto errout; } if (fread(image->data, image->width * image->height * 4 * sizeof (uint16_t), 1, fp) != 1) { fprintf(stderr, __FF__": Unexpected EOF when reading '%s'\n", path); goto errout; } for (y = 0; y < image->height; y++) for (x = 0; x < image->width; x++) for (rgba = 0; rgba < 4; rgba++) image->data[(y * image->width + x) * 4 + rgba] = ntohs(image->data[(y * image->width + x) * 4 + rgba]); fclose(fp); return true; errout: free(image->data); if (fp) fclose(fp); return false; } /* Write a farbfeld image to a file. */ bool ff_save(struct FFImage *image, char *path) { FILE *fp = NULL; uint32_t x, y, w, h, rgba; uint16_t *conv_data = NULL; conv_data = calloc(image->width * image->height * 4, sizeof (uint16_t)); if (!conv_data) return false; for (y = 0; y < image->height; y++) for (x = 0; x < image->width; x++) for (rgba = 0; rgba < 4; rgba++) conv_data[(y * image->width + x) * 4 + rgba] = htons(image->data[(y * image->width + x) * 4 + rgba]); fp = fopen(path, "w"); if (!fp) { fprintf(stderr, __FF__": Could not open image file '%s'\n", path); free(conv_data); return false; } fprintf(fp, "farbfeld"); w = htonl(image->width); h = htonl(image->height); fwrite(&w, sizeof (uint32_t), 1, fp); fwrite(&h, sizeof (uint32_t), 1, fp); fwrite(conv_data, sizeof (uint16_t) * image->width * image->height * 4, 1, fp); fclose(fp); free(conv_data); return true; } #undef __FF__ #endif /* LIBFF_H */