commit dc512d040c7d081ed96b1919420aebd646968879
Author:     Hiltjo Posthuma <[email protected]>
AuthorDate: Mon Mar 21 21:06:06 2016 +0100
Commit:     FRIGN <[email protected]>
CommitDate: Mon Mar 21 21:37:13 2016 +0100

    add ff2ppm(1)
    
    ff2ppm can convert farbfeld images to PPM (P6 binary format, 24-bit RGB).
    ff2ppm has an option -b to set the background color, for example for png 
files:
    
    png2ff < test.png | ff2ppm -b '#00ff00' > test.ppm

diff --git a/Makefile b/Makefile
index 236351f..63b4d0a 100644
--- a/Makefile
+++ b/Makefile
@@ -2,12 +2,13 @@
 # See LICENSE file for copyright and license details
 include config.mk
 
-BIN = png2ff ff2png jpg2ff
+BIN = png2ff ff2png jpg2ff ff2ppm
 SRC = ${BIN:=.c}
+HDR = arg.h
 MAN1 = 2ff.1 ${BIN:=.1}
 MAN5 = farbfeld.5
 
-all: png2ff ff2png jpg2ff
+all: png2ff ff2png jpg2ff ff2ppm
 
 .c:
        @echo CC $<
@@ -21,7 +22,7 @@ dist: clean
        @echo creating dist tarball
        @mkdir -p farbfeld-${VERSION}
        @cp -R FORMAT LICENSE Makefile README TODO config.mk \
-               2ff ${SRC} ${MAN1} ${MAN5} farbfeld-${VERSION}
+               2ff ${HDR} ${SRC} ${MAN1} ${MAN5} farbfeld-${VERSION}
        @tar -cf farbfeld-${VERSION}.tar farbfeld-${VERSION}
        @gzip farbfeld-${VERSION}.tar
        @rm -rf farbfeld-${VERSION}
diff --git a/ff2ppm.1 b/ff2ppm.1
new file mode 100644
index 0000000..7ada6c8
--- /dev/null
+++ b/ff2ppm.1
@@ -0,0 +1,48 @@
+.Dd 2016-03-21
+.Dt FF2PPM 1
+.Os suckless.org
+.Sh NAME
+.Nm ff2ppm
+.Nd convert farbfeld to PPM (binary)
+.Sh SYNOPSIS
+.Nm
+.Op Fl b Ar color
+.Sh DESCRIPTION
+.Nm
+reads a
+.Xr farbfeld 5
+image from stdin, converts it to a PPM image (P6 binary format, RGB) and
+writes the result to stdout.
+.Pp
+In case of an error
+.Nm
+writes a diagnostic message to stderr.
+.Sh OPTIONS
+.Bl -tag -width Ds
+.It Fl b Ar color
+.Ar color
+to mix with the background alpha channel, the default is white.
+.Pp
+The following formats are supported:
+"#rrggbb", "#rrrrggggbbbb" and the short-form "#rgb" which expands to 
"#rrggbb".
+.El
+.Sh EXIT STATUS
+.Bl -tag -width Ds
+.It 0
+Image processed successfully.
+.It 1
+An error occurred.
+.El
+.Sh EXAMPLES
+$
+png2ff < test.png |
+.Nm
+-b '#00ff00' > test.ppm
+.Sh SEE ALSO
+.Xr 2ff 1 ,
+.Xr bunzip2 1 ,
+.Xr bzip2 1 ,
+.Xr png2ff 1 ,
+.Xr farbfeld 5
+.Sh AUTHORS
+.An Hiltjo Posthuma Aq Mt [email protected]
diff --git a/ff2ppm.c b/ff2ppm.c
new file mode 100644
index 0000000..7f6aa61
--- /dev/null
+++ b/ff2ppm.c
@@ -0,0 +1,125 @@
+/* See LICENSE file for copyright and license details. */
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "arg.h"
+
+char *argv0;
+
+static void
+usage(void)
+{
+       fprintf(stderr, "usage: %s [-b #rrggbb]\n", argv0);
+       exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+       size_t rowlen;
+       uint32_t hdr[4], width, height, i, j, k;
+       uint16_t *row, mr = 0xffff, mg = 0xffff, mb = 0xffff;
+       uint8_t *rowout;
+       char *color;
+       unsigned int r = 0xff, g = 0xff, b = 0xff;
+       float a;
+
+       argv0 = argv[0];
+       ARGBEGIN {
+       case 'b':
+               for (color = EARGF(usage()); *color && *color == '#'; color++)
+                       ;
+
+               switch (strlen(color)) {
+               case 3:
+                       if (sscanf(color, "%1x%1x%1x", &r, &g, &b) != 3)
+                               usage();
+                       mr = (r | r << 4) * 257;
+                       mg = (g | g << 4) * 257;
+                       mb = (b | b << 4) * 257;
+                       break;
+               case 6:
+                       if (sscanf(color, "%2x%2x%2x", &r, &g, &b) != 3)
+                               usage();
+                       mr = r * 257;
+                       mg = g * 257;
+                       mb = b * 257;
+                       break;
+               case 12:
+                       if (sscanf(color, "%4x%4x%4x", &r, &g, &b) != 3)
+                               usage();
+                       mr = r;
+                       mg = g;
+                       mb = b;
+                       break;
+               default:
+                       usage();
+               }
+               break;
+       default:
+               usage();
+       } ARGEND
+
+       if (argc)
+               usage();
+
+       /* header */
+       if (fread(hdr, sizeof(*hdr), 4, stdin) != 4) {
+               fprintf(stderr, "%s: fread: %s\n", argv0, strerror(errno));
+               return 1;
+       }
+       if (memcmp("farbfeld", hdr, sizeof("farbfeld") - 1)) {
+               fprintf(stderr, "%s: invalid magic value\n", argv0);
+               return 1;
+       }
+       if (!(width = ntohl(hdr[2]))) {
+               fprintf(stderr, "%s: invalid width: zero\n", argv0);
+               return 1;
+       }
+       if (!(height = ntohl(hdr[3]))) {
+               fprintf(stderr, "%s: invalid height: zero\n", argv0);
+               return 1;
+       }
+       if (width > SIZE_MAX / ((sizeof("RGBA") - 1) * sizeof(uint16_t))) {
+               fprintf(stderr, "%s: row length integer overflow\n", argv0);
+               return 1;
+       }
+
+       rowlen = width * (sizeof("RGBA") - 1);
+       if (!(row = malloc(rowlen * sizeof(uint16_t)))) {
+               fprintf(stderr, "%s: malloc: %s\n", argv0, strerror(errno));
+               return 1;
+       }
+       if (!(rowout = malloc(width * sizeof("RGB") - 1))) {
+               fprintf(stderr, "%s: malloc: %s\n", argv0, strerror(errno));
+               return 1;
+       }
+
+       /* PPM binary */
+       printf("P6\n%" PRIu32 " %" PRIu32 "\n255\n", width, height);
+
+       /* write rows */
+       for (i = 0; i < height; ++i) {
+               if (fread(row, sizeof(uint16_t), rowlen, stdin) != rowlen) {
+                       fprintf(stderr, "%s: fread: %s\n", argv0, 
strerror(errno));
+                       return 1;
+               }
+               for (j = 0, k = 0; j < rowlen; j += 4, k += 3) {
+                       a = ntohs(row[j + 3]) / 65535.0f;
+                       rowout[k]     = ((ntohs(row[j]) * a)     + (mr * (1 - 
a))) / 257;
+                       rowout[k + 1] = ((ntohs(row[j + 1]) * a) + (mg * (1 - 
a))) / 257;
+                       rowout[k + 2] = ((ntohs(row[j + 2]) * a) + (mb * (1 - 
a))) / 257;
+               }
+               if (fwrite(rowout, 3, width, stdout) != width) {
+                       fprintf(stderr, "%s: fwrite: %s\n", argv0, 
strerror(errno));
+                       return 1;
+               }
+       }
+       return 0;
+}

Reply via email to