URI: 
       all common routines to a same util.c - ff2txt - farbfeld image to plain text visualization
  HTML git clone git://bitreich.org/ff2txt git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/ff2txt
   DIR Log
   DIR Files
   DIR Refs
   DIR Tags
   DIR README
       ---
   DIR commit a1eea6f23b8947751165e1909fd387803c7a803e
   DIR parent 2f2583b40975087c6463403508706bcc5138e833
  HTML 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 +
         M Makefile                            |       9 ++++++---
         A ascii.txt                           |      49 +++++++++++++++++++++++++++++++
         A ff2ascii.c                          |     101 +++++++++++++++++++++++++++++++
         A ff2braille.1                        |      29 +++++++++++++++++++++++++++++
         M ff2braille.c                        |      98 +++++++++++++------------------
         A ff2col.c                            |      40 +++++++++++++++++++++++++++++++
         A util.c                              |      47 +++++++++++++++++++++++++++++++
         A util.h                              |      16 ++++++++++++++++
       
       9 files changed, 330 insertions(+), 60 deletions(-)
       ---
   DIR diff --git a/.gitignore b/.gitignore
       @@ -1,3 +1,4 @@
        *.o
        *.core
        ff2braille
       +ff2col
   DIR 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
   DIR 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 
       +,.
       +_
   DIR 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;
       +}
   DIR 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
       +.
   DIR 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;
        }
   DIR 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;
       +}
   DIR 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;
       +}
   DIR 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);