ff2txt

display a farbfeld(5)-formatted image as braille or ascii text
Log | Files | Refs | README

commit a1eea6f23b8947751165e1909fd387803c7a803e
parent 2f2583b40975087c6463403508706bcc5138e833
Author: Josuah Demangeon <mail@josuah.net>
Date:   Mon, 29 Jan 2018 08:26:30 +0100

all common routines to a same util.c

Diffstat:
M.gitignore | 1+
MMakefile | 9++++++---
Aascii.txt | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Aff2ascii.c | 101+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aff2braille.1 | 29+++++++++++++++++++++++++++++
Mff2braille.c | 98+++++++++++++++++++++++++++++++++----------------------------------------------
Aff2col.c | 40++++++++++++++++++++++++++++++++++++++++
Autil.c | 47+++++++++++++++++++++++++++++++++++++++++++++++
Autil.h | 16++++++++++++++++
9 files changed, 330 insertions(+), 60 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -1,3 +1,4 @@ *.o *.core ff2braille +ff2col diff --git a/Makefile b/Makefile @@ -1,8 +1,11 @@ CFLAGS = -std=c89 -pedantic -Wall -Wextra -Werror -all: ff2braille +all: ff2braille ff2col -ff2braille: ff2braille.o - cc -o $@ ff2braille.o $(LDFLAGS) +ff2braille: ff2braille.o util.o util.h + cc -o $@ ff2braille.o util.o $(LDFLAGS) + +ff2col: ff2col.o util.o util.h + cc -o $@ ff2col.o util.o $(LDFLAGS) install: mkdir -p ${PREFIX}/bin diff --git a/ascii.txt b/ascii.txt @@ -0,0 +1,49 @@ + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + + + +! # $ % & ( ) / 0 1 2 3 4 5 6 7 8 9 : ; < > ? + +@ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] + +{ | } + +` ^ ~ " ' +* + - = +b d f l k t +a c e h i m n o r s u v w x z +g j p q y +,. +_ diff --git a/ff2ascii.c b/ff2ascii.c @@ -0,0 +1,101 @@ +/* + * Transforming an image into a braille character text is transforming a + * matrice this way: + * + * farbfeld image braille characters + * + * [[a0 a1 a2 a3 a4 a5] [[[a0 a1 [a2 a3 [a4 a5 \ + * [b0 b1 b2 b3 b4 b5] b0 b1 / b2 b3 / b4 b5 |<- One braille + * [c0 c1 c2 c3 c4 c5] c0 c1 / c2 c3 / c4 c5 | character + * [d0 d1 d2 d3 d4 d5] => d0 d1] d2 d3] d4 d5]] / + * [e0 e1 e2 e3 e4 e5] [[e0 e1 [e2 e3 [e4 e5 + * [f0 f1 f2 f3 f4 f5] f0 f1 / f2 f3 / f4 f5 + * [g0 g1 g2 g3 g4 g5] g0 g1 / g2 g3 / g4 g5 + * [h0 h1 h2 h3 h4 h5]] h0 h1] h2 h3] h4 h5]]] + * + * braille characters written as a line: + * + * [[[a0 a1 b0 b1 c0 c1 d0 d1] <- One braille character + * [a2 a3 b2 b3 c2 c3 d2 d3] + * [a4 a5 b4 b5 c4 c5 d4 d5]] <- One row of braille characters + * [[e0 e1 f0 f1 g0 g1 h0 h1] + * [e2 e3 f2 f3 g2 g3 h2 h3] + * [e4 e5 f4 f5 g4 g5 h4 h5]]] <- Two row of braille characters + * + * Although the encoding of braille keeps 1 4 + * the characters encoded with only six 2 5 + * dots first, as only these are used for 3 6 + * encoding letters: 7 8 + */ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <stdint.h> + +#include "util.h" + +void +print_utf8_3byte(long rune) +{ + printf("%c%c%c", + (char)(0xe0 | (0x0f & (rune >> 12))), /* 1110xxxx */ + (char)(0x80 | (0x3f & (rune >> 6))), /* 10xxxxxx */ + (char)(0x80 | (0x3f & (rune)))); /* 10xxxxxx */ +} + +int +is_on(struct col *rows[4], uint32_t width, uint32_t height, uint32_t w, + uint32_t h) +{ + uint16_t sum; + + if (w >= width || h >= height) + return 0; + + /* divide first to avoid overflow */ + sum = rows[h][w].red / 4; + sum += rows[h][w].green / 4; + sum += rows[h][w].blue / 4; + sum += rows[h][w].alpha / 4; + return sum >= UINT16_MAX / 2; +} + +void +print_4_rows(struct col *rows[4], uint32_t width, uint32_t height) +{ + uint32_t w; + + for (w = 0; w < width; w += 2) + print_utf8_3byte(BRAILLE_START + + 0x01 * is_on(rows, width, height, w + 0, 0) + + 0x08 * is_on(rows, width, height, w + 1, 0) + + 0x02 * is_on(rows, width, height, w + 0, 1) + + 0x10 * is_on(rows, width, height, w + 1, 1) + + 0x04 * is_on(rows, width, height, w + 0, 2) + + 0x20 * is_on(rows, width, height, w + 1, 2) + + 0x40 * is_on(rows, width, height, w + 0, 3) + + 0x80 * is_on(rows, width, height, w + 1, 3)); + putchar('\n'); +} + +int +main(void) +{ + struct col buf[MAX_WIDTH * 4], *rows[4]; + uint32_t width, height, h, r, i; + + read_header(&width, &height); + + for (i = 0; i < 4; i++) + rows[i] = buf + width * i; + + for (h = 0; h < height; h += 4) { + r = fread(buf, sizeof(*buf), width * 4, stdin); + if (r % width != 0) + err("invalid line width"); + print_4_rows(rows, width, r / width); + if (ferror(stdin)) + err("fread stdin"); + } + return 0; +} diff --git a/ff2braille.1 b/ff2braille.1 @@ -0,0 +1,29 @@ +.Dt FF2BRAILLE 1 +.Dd $Mdocdate: January 22 2018$ +.Os +. +. +.Sh NAME +. +.Nm ff2braille +.Nd farbfeld to text braille pattern image conversion +. +. +.Sh SYNOPSIS +. +.Nm +. +. +.Sh DESCRIPTION +. +.Nm +reads a +.Xr farbfeld 5 +image from stdin and write a text representation of the image using braille +characters to stdout. +. +. +.Sh EXIT STATUS +. +.Ex -std +. diff --git a/ff2braille.c b/ff2braille.c @@ -1,4 +1,32 @@ -#include <arpa/inet.h> +/* + * Transforming an image into a braille character text is transforming a + * matrice this way: + * + * farbfeld image braille characters + * + * [[a0 a1 a2 a3 a4 a5] [[[a0 a1 [a2 a3 [a4 a5 \ + * [b0 b1 b2 b3 b4 b5] b0 b1 / b2 b3 / b4 b5 |<- One braille + * [c0 c1 c2 c3 c4 c5] c0 c1 / c2 c3 / c4 c5 | character + * [d0 d1 d2 d3 d4 d5] => d0 d1] d2 d3] d4 d5]] / + * [e0 e1 e2 e3 e4 e5] [[e0 e1 [e2 e3 [e4 e5 + * [f0 f1 f2 f3 f4 f5] f0 f1 / f2 f3 / f4 f5 + * [g0 g1 g2 g3 g4 g5] g0 g1 / g2 g3 / g4 g5 + * [h0 h1 h2 h3 h4 h5]] h0 h1] h2 h3] h4 h5]]] + * + * braille characters written as a line: + * + * [[[a0 a1 b0 b1 c0 c1 d0 d1] <- One braille character + * [a2 a3 b2 b3 c2 c3 d2 d3] + * [a4 a5 b4 b5 c4 c5 d4 d5]] <- One row of braille characters + * [[e0 e1 f0 f1 g0 g1 h0 h1] + * [e2 e3 f2 f3 g2 g3 h2 h3] + * [e4 e5 f4 f5 g4 g5 h4 h5]]] <- Two row of braille characters + * + * Although the encoding of braille keeps 1 4 + * the characters encoded with only six 2 5 + * dots first, as only these are used for 3 6 + * encoding letters: 7 8 + */ #include <stdio.h> #include <string.h> @@ -7,41 +35,6 @@ #include "util.h" -#define MAX_WIDTH (1 << 12) -#define BRAILLE_START 10240 -#define COLORS 4 - -#define LEN(X) (sizeof(X) / sizeof(*X)) - -struct col { - uint16_t red; - uint16_t green; - uint16_t blue; - uint16_t alpha; -}; - -void -err(char *msg) -{ - perror(msg); - exit(1); -} - -void -read_header(uint32_t *width, uint32_t *h) -{ - uint32_t header[4]; - - if (fread(header, sizeof(*header), LEN(header), stdin) != LEN(header)) - err("fread"); - - if (memcmp("farbfeld", header, sizeof("farbfeld") - 1)) - err("invalid magic value\n"); - - *width = ntohl(header[2]); - *h = ntohl(header[3]); -} - void print_utf8_3byte(long rune) { @@ -52,20 +45,13 @@ print_utf8_3byte(long rune) } int -is_on(struct col *rows[4], uint32_t width, uint32_t height, uint32_t w, - uint32_t h) +is_on(struct col *rows[4], uint32_t width, uint32_t height, + uint32_t w, uint32_t h) { - uint16_t sum; - if (w >= width || h >= height) return 0; - /* divide first to avoid overflow */ - sum = rows[h][w].red / 4; - sum += rows[h][w].green / 4; - sum += rows[h][w].blue / 4; - sum += rows[h][w].alpha / 4; - return sum >= UINT16_MAX / 2; + return is_bright(rows[h][w]); } void @@ -75,14 +61,14 @@ print_4_rows(struct col *rows[4], uint32_t width, uint32_t height) for (w = 0; w < width; w += 2) print_utf8_3byte(BRAILLE_START + - 1 * is_on(rows, width, height, w + 0, 0) + - 8 * is_on(rows, width, height, w + 1, 0) + - 2 * is_on(rows, width, height, w + 0, 1) + - 16 * is_on(rows, width, height, w + 1, 1) + - 4 * is_on(rows, width, height, w + 0, 2) + - 32 * is_on(rows, width, height, w + 1, 2) + - 64 * is_on(rows, width, height, w + 0, 3) + - 128 * is_on(rows, width, height, w + 1, 3)); + 0x01 * is_on(rows, width, height, w + 0, 0) + + 0x08 * is_on(rows, width, height, w + 1, 0) + + 0x02 * is_on(rows, width, height, w + 0, 1) + + 0x10 * is_on(rows, width, height, w + 1, 1) + + 0x04 * is_on(rows, width, height, w + 0, 2) + + 0x20 * is_on(rows, width, height, w + 1, 2) + + 0x40 * is_on(rows, width, height, w + 0, 3) + + 0x80 * is_on(rows, width, height, w + 1, 3)); putchar('\n'); } @@ -93,8 +79,6 @@ main(void) uint32_t width, height, h, r, i; read_header(&width, &height); - if (width == 0 || height == 0) - err("empty image"); for (i = 0; i < 4; i++) rows[i] = buf + width * i; @@ -103,9 +87,9 @@ main(void) r = fread(buf, sizeof(*buf), width * 4, stdin); if (r % width != 0) err("invalid line width"); - print_4_rows(rows, width, r / width); if (ferror(stdin)) err("fread stdin"); + print_4_rows(rows, width, r / width); } return 0; } diff --git a/ff2col.c b/ff2col.c @@ -0,0 +1,40 @@ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <stdint.h> + +#include "util.h" + +void +print_2_rows(struct col *buf, uint32_t width, int height) +{ + size_t w; + int up, dn; + char *map = " '.:"; + + for (w = 0; w < width; w += 2) { + up = height > 0 && is_bright(buf[w]) ? 0x1 : 0x0; + dn = height > 1 && is_bright(buf[w + width]) ? 0x2 : 0x0; + putchar(map[up & dn]); + } + putchar('\n'); +} + +int +main(void) +{ + struct col buf[MAX_WIDTH * 2]; + uint32_t width, height, h, r; + + read_header(&width, &height); + + for (h = 0; h < height; h += 2) { + r = fread(buf, sizeof(*buf), width * 2, stdin); + if (r % width != 0) + err("invalid line width"); + if (ferror(stdin)) + err("fread stdin"); + print_2_rows(buf, width, r / width); + } + return 0; +} diff --git a/util.c b/util.c @@ -0,0 +1,47 @@ +#include <arpa/inet.h> + +#include <stdint.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "util.h" + +void +err(char *msg) +{ + perror(msg); + exit(1); +} + +void +read_header(uint32_t *width, uint32_t *height) +{ + uint32_t header[4]; + + if (fread(header, sizeof(*header), LEN(header), stdin) != LEN(header)) + err("fread"); + + if (memcmp("farbfeld", header, sizeof("farbfeld") - 1)) + err("invalid magic value\n"); + + *width = ntohl(header[2]); + *height = ntohl(header[3]); + + if (width == 0 || height == 0) + err("empty image"); +} + +int +is_bright(struct col col) +{ + int32_t sum; + + /* divide first to avoid overflow */ + sum = htonl(col.red) / 4; + sum += htonl(col.green) / 4; + sum += htonl(col.blue) / 4; + sum += htonl(col.alpha) / 4; + + return sum <= UINT16_MAX / 2; +} diff --git a/util.h b/util.h @@ -0,0 +1,16 @@ +#define MAX_WIDTH (1 << 12) +#define BRAILLE_START 10240 +#define COLORS 4 + +#define LEN(X) (sizeof(X) / sizeof(*X)) + +struct col { + uint16_t red; + uint16_t green; + uint16_t blue; + uint16_t alpha; +}; + +void err(char *); +void read_header(uint32_t *, uint32_t *); +int is_bright(struct col);