iAdd vtv-from-ff. - vtv-tools - virtual terminal video tools Err bitreich.org 70 1Log /scm/vtv-tools/log.gph bitreich.org 70 1Files /scm/vtv-tools/files.gph bitreich.org 70 1Refs /scm/vtv-tools/refs.gph bitreich.org 70 1Tags /scm/vtv-tools/tag bitreich.org 70 1README /scm/vtv-tools/file/README.md.gph bitreich.org 70 1LICENSE /scm/vtv-tools/file/LICENSE.gph bitreich.org 70 i--- Err bitreich.org 70 1commit 98dc53ecd26b97ddee7326e7161cabdc2ebdaacf /scm/vtv-tools/commit/98dc53ecd26b97ddee7326e7161cabdc2ebdaacf.gph bitreich.org 70 1parent a5e70d7b2d33c9277a613fc9e082d324371d0cfe /scm/vtv-tools/commit/a5e70d7b2d33c9277a613fc9e082d324371d0cfe.gph bitreich.org 70 hAuthor: Troels Henriksen URL:mailto:athas@sigkill.dk bitreich.org 70 iDate: Mon, 14 Aug 2023 13:27:36 +0200 Err bitreich.org 70 i Err bitreich.org 70 iAdd vtv-from-ff. Err bitreich.org 70 i Err bitreich.org 70 iDiffstat: Err bitreich.org 70 i A .gitignore | 1 + Err bitreich.org 70 i M Makefile | 9 +++++++-- Err bitreich.org 70 i A src/vtv-from-ff.c | 214 +++++++++++++++++++++++++++++++ Err bitreich.org 70 i Err bitreich.org 70 i3 files changed, 222 insertions(+), 2 deletions(-) Err bitreich.org 70 i--- Err bitreich.org 70 1diff --git a/.gitignore b/.gitignore /scm/vtv-tools/file/.gitignore.gph bitreich.org 70 i@@ -0,0 +1 @@ Err bitreich.org 70 i+bin/vtv-from-ff Err bitreich.org 70 1diff --git a/Makefile b/Makefile /scm/vtv-tools/file/Makefile.gph bitreich.org 70 i@@ -1,7 +1,12 @@ Err bitreich.org 70 i-# paths Err bitreich.org 70 i PREFIX ?= /usr/local Err bitreich.org 70 i Err bitreich.org 70 i-all: Err bitreich.org 70 i+CFLAGS?=-O -Wall -Wextra -pedantic Err bitreich.org 70 i+CC?=cc Err bitreich.org 70 i+ Err bitreich.org 70 i+all: bin/vtv-from-ff Err bitreich.org 70 i+ Err bitreich.org 70 i+bin/%: src/%.c Err bitreich.org 70 i+ $(CC) -o $@ $< Err bitreich.org 70 i Err bitreich.org 70 i install: all Err bitreich.org 70 i @echo \# Installing executable files to ${PREFIX}/bin Err bitreich.org 70 1diff --git a/src/vtv-from-ff.c b/src/vtv-from-ff.c /scm/vtv-tools/file/src/vtv-from-ff.c.gph bitreich.org 70 i@@ -0,0 +1,214 @@ Err bitreich.org 70 i+// Convert farbfeld image to vtv file. Err bitreich.org 70 i+// Err bitreich.org 70 i+// Can be run either in pipe mode or with file arguments. A file Err bitreich.org 70 i+// 'img.ff' is turned into a file 'img.vtv'. Err bitreich.org 70 i+// Err bitreich.org 70 i+// If you want to produce a vtv file that can be shown with Err bitreich.org 70 i+// vtv-player, the image should be 25 lines by 73 columns. Err bitreich.org 70 i+ Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+ Err bitreich.org 70 i+void def(FILE *f) { Err bitreich.org 70 i+ fprintf(f, "\033[0m"); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+void fg_rgb(FILE *f, uint8_t r, uint8_t g, uint8_t b) { Err bitreich.org 70 i+ fprintf(f, "\033[38;2;%d;%d;%dm", r, g, b); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+void bg_rgb(FILE *f, uint8_t r, uint8_t g, uint8_t b) { Err bitreich.org 70 i+ fprintf(f, "\033[48;2;%d;%d;%dm", r, g, b); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+int read_be_uint16(FILE *f, uint16_t *x) { Err bitreich.org 70 i+ uint8_t b; Err bitreich.org 70 i+ Err bitreich.org 70 i+ *x = 0; Err bitreich.org 70 i+ if (fread(&b, 1, 1, f) != 1) { return 1; } Err bitreich.org 70 i+ *x == (uint32_t)b << 8; Err bitreich.org 70 i+ if (fread(&b, 1, 1, f) != 1) { return 1; } Err bitreich.org 70 i+ *x += b; Err bitreich.org 70 i+ Err bitreich.org 70 i+ return 0; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+int read_be_uint32(FILE *f, uint32_t *x) { Err bitreich.org 70 i+ uint8_t b; Err bitreich.org 70 i+ Err bitreich.org 70 i+ *x = 0; Err bitreich.org 70 i+ if (fread(&b, 1, 1, f) != 1) { return 1; } Err bitreich.org 70 i+ *x += (uint32_t)b << 24; Err bitreich.org 70 i+ if (fread(&b, 1, 1, f) != 1) { return 1; } Err bitreich.org 70 i+ *x += (uint32_t)b << 16; Err bitreich.org 70 i+ if (fread(&b, 1, 1, f) != 1) { return 1; } Err bitreich.org 70 i+ *x == (uint32_t)b << 8; Err bitreich.org 70 i+ if (fread(&b, 1, 1, f) != 1) { return 1; } Err bitreich.org 70 i+ *x += b; Err bitreich.org 70 i+ Err bitreich.org 70 i+ return 0; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+int load_ff(FILE *f, Err bitreich.org 70 i+ uint16_t* *argbs_out, Err bitreich.org 70 i+ uint32_t *width_out, Err bitreich.org 70 i+ uint32_t *height_out) { Err bitreich.org 70 i+ char magic[8]; Err bitreich.org 70 i+ int ret = 1; Err bitreich.org 70 i+ uint16_t* argbs = NULL; Err bitreich.org 70 i+ uint32_t width = 0, height = 0; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (fread(magic, 1, 8, f) != 8) { Err bitreich.org 70 i+ goto bad; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (memcmp(magic, "farbfeld", 8) != 0) { Err bitreich.org 70 i+ goto bad; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (read_be_uint32(f, &width) != 0) { Err bitreich.org 70 i+ goto bad; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (read_be_uint32(f, &height) != 0) { Err bitreich.org 70 i+ goto bad; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+ argbs = calloc(width*height*4, sizeof(uint16_t)); Err bitreich.org 70 i+ Err bitreich.org 70 i+ for (int i = 0; i < width; i++) { Err bitreich.org 70 i+ for (int j = 0; j < height; j++) { Err bitreich.org 70 i+ for (int l = 0; l < 4; l++) { Err bitreich.org 70 i+ if (read_be_uint16(f, &argbs[i*(height*4)+(j*4)+l]) != 0) { Err bitreich.org 70 i+ goto bad; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ } Err bitreich.org 70 i+ } Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+ *argbs_out = argbs; Err bitreich.org 70 i+ *width_out = width; Err bitreich.org 70 i+ *height_out = height; Err bitreich.org 70 i+ return 0; Err bitreich.org 70 i+ Err bitreich.org 70 i+ bad: Err bitreich.org 70 i+ free(argbs); Err bitreich.org 70 i+ return 1; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+void render(int nrows, int ncols, const uint16_t *argbs, Err bitreich.org 70 i+ uint32_t *fgs, uint32_t *bgs, char *chars) { Err bitreich.org 70 i+ for (int i = 0; i < nrows; i++) { Err bitreich.org 70 i+ for (int j = 0; j < ncols; j++) { Err bitreich.org 70 i+ uint32_t r0 = argbs[(i*2)*(ncols*4)+j*4+0]; Err bitreich.org 70 i+ uint32_t g0 = argbs[(i*2)*(ncols*4)+j*4+1]; Err bitreich.org 70 i+ uint32_t b0 = argbs[(i*2)*(ncols*4)+j*4+2]; Err bitreich.org 70 i+ uint32_t r1 = argbs[(i*2+1)*(ncols*4)+j*4+0]; Err bitreich.org 70 i+ uint32_t g1 = argbs[(i*2+1)*(ncols*4)+j*4+1]; Err bitreich.org 70 i+ uint32_t b1 = argbs[(i*2+1)*(ncols*4)+j*4+2]; Err bitreich.org 70 i+ Err bitreich.org 70 i+ uint32_t w0 = r0 << 16 | g0 << 8 | b0; Err bitreich.org 70 i+ uint32_t w1 = r1 << 16 | g1 << 8 | b1; Err bitreich.org 70 i+ fgs[i*ncols+j] = w0; Err bitreich.org 70 i+ bgs[i*ncols+j] = w1; Err bitreich.org 70 i+ chars[i*ncols+j] = 127; // Sentinel. Err bitreich.org 70 i+ } Err bitreich.org 70 i+ } Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+void display(FILE *f, int nrows, int ncols, Err bitreich.org 70 i+ const uint32_t *fgs, const uint32_t *bgs, const char *chars) { Err bitreich.org 70 i+ for (int i = 0; i < nrows; i++) { Err bitreich.org 70 i+ uint32_t prev_w0 = 0xdeadbeef; Err bitreich.org 70 i+ uint32_t prev_w1 = 0xdeadbeef; Err bitreich.org 70 i+ for (int j = 0; j < ncols; j++) { Err bitreich.org 70 i+ double r0 = 0, g0 = 0, b0 = 0; Err bitreich.org 70 i+ double r1 = 0, g1 = 0, b1 = 0; Err bitreich.org 70 i+ uint32_t w0 = fgs[i*ncols+j]; Err bitreich.org 70 i+ uint32_t w1 = bgs[i*ncols+j]; Err bitreich.org 70 i+ if (w0 != prev_w0 || w1 != prev_w1) { Err bitreich.org 70 i+ r0 = (w0>>16)&0xFF; Err bitreich.org 70 i+ g0 = (w0>>8)&0xFF; Err bitreich.org 70 i+ b0 = (w0>>0)&0xFF; Err bitreich.org 70 i+ r1 = (w1>>16)&0xFF; Err bitreich.org 70 i+ g1 = (w1>>8)&0xFF; Err bitreich.org 70 i+ b1 = (w1>>0)&0xFF; Err bitreich.org 70 i+ fg_rgb(f, r0, g0, b0); Err bitreich.org 70 i+ bg_rgb(f, r1, g1, b1); Err bitreich.org 70 i+ prev_w0 = w0; Err bitreich.org 70 i+ prev_w1 = w1; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ char c = chars[i*ncols+j]; Err bitreich.org 70 i+ if (c == 127) { Err bitreich.org 70 i+ fputs("▀", f); Err bitreich.org 70 i+ } else { Err bitreich.org 70 i+ fputc(c, f); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ } Err bitreich.org 70 i+ def(f); Err bitreich.org 70 i+ fputc('\n', f); Err bitreich.org 70 i+ } Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+int convert(FILE *ff, FILE *vtv) { Err bitreich.org 70 i+ uint32_t width, height; Err bitreich.org 70 i+ uint16_t *argbs; Err bitreich.org 70 i+ if (load_ff(ff, &argbs, &width, &height) != 0) { Err bitreich.org 70 i+ return 1; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ uint32_t *fgs = calloc(width*height, sizeof(uint32_t)); Err bitreich.org 70 i+ uint32_t *bgs = calloc(width*height, sizeof(uint32_t)); Err bitreich.org 70 i+ char *chars = calloc(width*height, sizeof(char)); Err bitreich.org 70 i+ render(height, width, argbs, fgs, bgs, chars); Err bitreich.org 70 i+ display(vtv, height/2, width, fgs, bgs, chars); Err bitreich.org 70 i+ free(argbs); Err bitreich.org 70 i+ free(fgs); Err bitreich.org 70 i+ free(bgs); Err bitreich.org 70 i+ free(chars); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+int main (int argc, char** argv) { Err bitreich.org 70 i+ if (argc == 1) { Err bitreich.org 70 i+ if (convert(stdin, stdout) != 0) { Err bitreich.org 70 i+ fprintf(stderr, "%s: invalid farbfeld image on stdin.\n", argv[0]); Err bitreich.org 70 i+ exit(1); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ } else { Err bitreich.org 70 i+ for (int i = 1; i < argc; i++) { Err bitreich.org 70 i+ const char *ff_fname = argv[i]; Err bitreich.org 70 i+ size_t len = strlen(ff_fname); Err bitreich.org 70 i+ if (len >= 3 && strcmp(&ff_fname[len-3], ".ff") == 0) { Err bitreich.org 70 i+ char *vtv_fname = malloc(len+2); Err bitreich.org 70 i+ strncpy(vtv_fname, ff_fname, len-3); Err bitreich.org 70 i+ strcpy(vtv_fname+len-3, ".vtv"); Err bitreich.org 70 i+ printf("%s\n%s\n", ff_fname, vtv_fname); Err bitreich.org 70 i+ FILE *ff = fopen(ff_fname, "r"); Err bitreich.org 70 i+ if (ff == NULL) { Err bitreich.org 70 i+ fprintf(stderr, "%s: could not open %s: %s\n", Err bitreich.org 70 i+ argv[0], ff_fname, strerror(errno)); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ FILE *vtv = fopen(vtv_fname, "w+"); Err bitreich.org 70 i+ if (vtv == NULL) { Err bitreich.org 70 i+ fprintf(stderr, "%s: could not open %s: %s\n", Err bitreich.org 70 i+ argv[0], vtv_fname, strerror(errno)); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ if (convert(ff, vtv) != 0) { Err bitreich.org 70 i+ fprintf(stderr, "%s: invalid farbfeld image in %s.\n", Err bitreich.org 70 i+ argv[0], ff_fname); Err bitreich.org 70 i+ exit(1); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ fclose(ff); Err bitreich.org 70 i+ fclose(vtv); Err bitreich.org 70 i+ free(vtv_fname); Err bitreich.org 70 i+ } else { Err bitreich.org 70 i+ fprintf(stderr, Err bitreich.org 70 i+ "%s: argument %s does not have .ff extension.\n", Err bitreich.org 70 i+ argv[0], ff_fname); Err bitreich.org 70 i+ exit(1); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ } Err bitreich.org 70 i+ } Err bitreich.org 70 i+} Err bitreich.org 70 .