commit 04bdedd131129bc14345251003f960ca6da19f10 Author: Camden Dixie O'Brien Date: Sat Sep 20 13:31:22 2025 +0100 Write simple farbfeld-writing module diff --git a/include/ff.h b/include/ff.h new file mode 100644 index 0000000..d80063b --- /dev/null +++ b/include/ff.h @@ -0,0 +1,8 @@ +#ifndef FF_H +#define FF_H + +#include "img.h" + +void ff_write(int fd, img_t img); + +#endif diff --git a/include/img.h b/include/img.h new file mode 100644 index 0000000..d4d9619 --- /dev/null +++ b/include/img.h @@ -0,0 +1,15 @@ +#ifndef IMG_H +#define IMG_H + +#include + +typedef struct { + uint16_t r, g, b, a; +} pix_t; + +typedef struct { + uint32_t w, h; + pix_t *pix; +} img_t; + +#endif diff --git a/src/ff.c b/src/ff.c new file mode 100644 index 0000000..0cc9c77 --- /dev/null +++ b/src/ff.c @@ -0,0 +1,84 @@ +#include "ff.h" + +#include +#include +#include +#include +#include +#include +#include + +#define MAGIC "farbfeld" +#define MAGICLEN 8 + +#define BUFSIZE 4096 + +#define MIN(x, y) ((x) < (y) ? (x) : (y)) + +static uint8_t buf[BUFSIZE]; + +static uint8_t *loadpix(uint8_t *p, const pix_t *pix, unsigned n) +{ + for (unsigned i = 0; i < n; ++i) { + *((uint16_t *)p) = htons(pix[i].r); + p += sizeof(uint16_t); + *((uint16_t *)p) = htons(pix[i].g); + p += sizeof(uint16_t); + *((uint16_t *)p) = htons(pix[i].b); + p += sizeof(uint16_t); + *((uint16_t *)p) = htons(pix[i].a); + p += sizeof(uint16_t); + } + return p; +} + +static void writebuf(int fd, size_t size) +{ + while (1) { + errno = 0; + const ssize_t res = write(fd, buf, size); + + if (res == (ssize_t)size) { + return; + } else if (res > 0) { + fputs( + "Error writing image: Couldn't write entire buffer" + " (storage may be full)\n", + stderr); + exit(1); + } else { + if (errno == EINTR) { + continue; + } else { + perror("Error writing image"); + exit(1); + } + } + } +} + +void ff_write(int fd, img_t img) +{ + uint8_t *p = buf; + + memcpy(p, MAGIC, MAGICLEN); + p += MAGICLEN; + *((uint32_t *)p) = htonl(img.w); + p += sizeof(uint32_t); + *((uint32_t *)p) = htonl(img.h); + p += sizeof(uint32_t); + + const pix_t *pix = img.pix; + unsigned rem = img.w * img.h; + while (rem > 0) { + const unsigned cap = (BUFSIZE - (p - buf)) / sizeof(pix_t); + const unsigned n = MIN(rem, cap); + + p = loadpix(p, pix, n); + pix += n; + rem -= n; + + writebuf(fd, p - buf); + p = buf; + } +}