Since the PNM/PAM format already exist as a minimal intermediate
representation with a rich set of commandline tools to manipulate them,
use Netpbm to handle images.
---
 README.md    |   8 ++---
 config.def.h |   5 +--
 config.mk    |   2 +-
 example      |   2 +-
 sent.c       | 105 ++++++++++++++++++++++++++++++-----------------------------
 5 files changed, 62 insertions(+), 60 deletions(-)

diff --git a/README.md b/README.md
index 3fda5ee..43ba423 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
 sent is a simple plaintext presentation tool.
 
 sent does not need latex, libreoffice or any other fancy file format, it uses
-plaintext files to describe the slides and can include images via farbfeld.
+plaintext files to describe the slides and can include images via libnetpbm.
 Every paragraph represents a slide in the presentation.
 
 The presentation is displayed in a simple X11 window. The content of each slide
@@ -11,8 +11,8 @@ worry about alignment. Instead you can really concentrate on 
the content.
 
 Dependencies
 
-You need Xlib to build sent and the farbfeld[0] tools installed to use images 
in
-your presentations.
+You need Xlib and libnetpbm to build sent and the Netpbm tools installed to use
+images in your presentations.
 
 Demo
 
@@ -53,5 +53,3 @@ Development
 
 sent is developed at http://tools.suckless.org/sent
 
-
-0: http://git.2f30.org/farbfeld/about/
diff --git a/config.def.h b/config.def.h
index 94ed09e..3a4f1d8 100644
--- a/config.def.h
+++ b/config.def.h
@@ -47,6 +47,7 @@ static Shortcut shortcuts[] = {
 };
 
 static Filter filters[] = {
-       { "\\.png$",       "png2ff" },
-       { "\\.(jpg|gif)$", "2ff" },
+       { "\\.png$",       "pngtopam -alphapam" },
+       { "\\.(jpg|gif)$", "anytopnm" },
+       { "\\.p[bgp]m$",   "cat" },
 };
diff --git a/config.mk b/config.mk
index 52d5fb1..78055bd 100644
--- a/config.mk
+++ b/config.mk
@@ -12,7 +12,7 @@ X11LIB = /usr/X11R6/lib
 
 # includes and libs
 INCS = -I. -I/usr/include -I/usr/include/freetype2 -I${X11INC}
-LIBS = -L/usr/lib -lc -lm -L${X11LIB} -lXft -lfontconfig -lX11
+LIBS = -L/usr/lib -lc -lm -L${X11LIB} -lXft -lfontconfig -lX11 -lnetpbm
 
 # flags
 CPPFLAGS = -DVERSION=\"${VERSION}\" -D_XOPEN_SOURCE=600
diff --git a/example b/example
index 8b385f0..f7f6f61 100644
--- a/example
+++ b/example
@@ -20,7 +20,7 @@ easy to use
 
 depends on
 ♽ Xlib
-☃ farbfeld
+☃ libnetpbm
 
 ~1000 lines of code
 
diff --git a/sent.c b/sent.c
index 99361e8..978e3ef 100644
--- a/sent.c
+++ b/sent.c
@@ -12,6 +12,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <netpbm/pam.h>
 #include <X11/keysym.h>
 #include <X11/XKBlib.h>
 #include <X11/Xatom.h>
@@ -41,7 +42,7 @@ typedef struct {
        unsigned int bufwidth, bufheight;
        imgstate state;
        XImage *ximg;
-       int fd;
+       struct pam pamimg;
        int numpasses;
 } Image;
 
@@ -87,12 +88,12 @@ typedef struct {
        const Arg arg;
 } Shortcut;
 
-static Image *ffopen(char *filename);
-static void fffree(Image *img);
-static int ffread(Image *img);
-static int ffprepare(Image *img);
-static void ffscale(Image *img);
-static void ffdraw(Image *img);
+static Image *pamopen(char *filename);
+static void pamfree(Image *img);
+static int pamread(Image *img);
+static int pamprepare(Image *img);
+static void pamscale(Image *img);
+static void pamdraw(Image *img);
 
 static void getfontsize(Slide *s, unsigned int *width, unsigned int *height);
 static void cleanup();
@@ -159,9 +160,9 @@ filter(int fd, const char *cmd)
        return fds[0];
 }
 
-Image *ffopen(char *filename)
+Image *pamopen(char *filename)
 {
-       unsigned char hdr[16];
+       struct pam inpam;
        char *bin = NULL;
        regex_t regex;
        Image *img;
@@ -192,21 +193,17 @@ Image *ffopen(char *filename)
                eprintf("Unable to filter %s:", filename);
        close(tmpfd);
 
-       if (read(fd, hdr, 16) != 16)
-               return NULL;
-
-       if (memcmp("farbfeld", hdr, 8))
-               return NULL;
+       pnm_readpaminit(fdopen(fd, "r"), &inpam, PAM_STRUCT_SIZE(tuple_type));
 
        img = calloc(1, sizeof(Image));
-       img->fd = fd;
-       img->bufwidth = ntohl(*(uint32_t *)&hdr[8]);
-       img->bufheight = ntohl(*(uint32_t *)&hdr[12]);
+       img->pamimg = inpam;
+       img->bufwidth = inpam.width;
+       img->bufheight = inpam.height;
 
        return img;
 }
 
-void fffree(Image *img)
+void pamfree(Image *img)
 {
        free(img->buf);
        if (img->ximg)
@@ -214,14 +211,13 @@ void fffree(Image *img)
        free(img);
 }
 
-int ffread(Image *img)
+int pamread(Image *img)
 {
-       uint32_t y, x;
-       uint16_t *row;
+       uint32_t y, x, depth;
        uint8_t opac;
        uint8_t fg_r, fg_g, fg_b, bg_r, bg_g, bg_b;
-       size_t rowlen, off, nbytes;
-       ssize_t count;
+       tuple *pamrow;
+       size_t off;
 
        if (!img)
                return 0;
@@ -236,9 +232,8 @@ int ffread(Image *img)
                return 0;
 
        /* scratch buffer to read row by row */
-       rowlen = img->bufwidth * 2 * strlen("RGBA");
-       row = malloc(rowlen);
-       if (!row) {
+       pamrow = pnm_allocpamrow(&(img->pamimg));
+       if (!pamrow) {
                free(img->buf);
                img->buf = NULL;
                return 0;
@@ -249,19 +244,25 @@ int ffread(Image *img)
        bg_g = (sc->bg.pix >>  8) % 256;
        bg_b = (sc->bg.pix >>  0) % 256;
 
+       depth = img->pamimg.depth;
+
        for (off = 0, y = 0; y < img->bufheight; y++) {
-               nbytes = 0;
-               while (nbytes < rowlen) {
-                       count = read(img->fd, (char *)row + nbytes, rowlen - 
nbytes);
-                       if (count < 0)
-                               eprintf("Unable to read from pipe:");
-                       nbytes += count;
-               }
-               for (x = 0; x < rowlen / 2; x += 4) {
-                       fg_r = ntohs(row[x + 0]) / 256;
-                       fg_g = ntohs(row[x + 1]) / 256;
-                       fg_b = ntohs(row[x + 2]) / 256;
-                       opac = ntohs(row[x + 3]) / 256;
+               pnm_readpamrow(&(img->pamimg), pamrow);
+               for (x = 0; x < img->bufwidth; x++) {
+                       fg_r = 255*pamrow[x][0] / img->pamimg.maxval;
+
+                       if (depth < 3) {
+                               fg_g = fg_b = fg_r;
+                       } else {
+                               fg_g = 255*pamrow[x][1] / img->pamimg.maxval;
+                               fg_b = 255*pamrow[x][2] / img->pamimg.maxval;
+                       }
+                       /* check for alpha channel */
+                       if ((depth & 1) == 0) {
+                               opac = 255*pamrow[x][depth - 1] / 
img->pamimg.maxval;
+                       } else {
+                               opac = 255;
+                       }
                        /* blend opaque part of image data with window 
background color to
                         * emulate transparency */
                        img->buf[off++] = (fg_r * opac + bg_r * (255 - opac)) / 
256;
@@ -270,14 +271,14 @@ int ffread(Image *img)
                }
        }
 
-       free(row);
-       close(img->fd);
+       pnm_freepamrow(pamrow);
+       fclose(img->pamimg.file);
        img->state |= LOADED;
 
        return 1;
 }
 
-int ffprepare(Image *img)
+int pamprepare(Image *img)
 {
        int depth = DefaultDepth(xw.dpy, xw.scr);
        int width = xw.uw;
@@ -314,12 +315,12 @@ int ffprepare(Image *img)
                return 0;
        }
 
-       ffscale(img);
+       pamscale(img);
        img->state |= SCALED;
        return 1;
 }
 
-void ffscale(Image *img)
+void pamscale(Image *img)
 {
        unsigned int x, y;
        unsigned int width = img->ximg->width;
@@ -344,7 +345,7 @@ void ffscale(Image *img)
        }
 }
 
-void ffdraw(Image *img)
+void pamdraw(Image *img)
 {
        int xoffset = (xw.w - img->ximg->width) / 2;
        int yoffset = (xw.h - img->ximg->height) / 2;
@@ -401,7 +402,7 @@ void cleanup()
                                free(slides[i].lines[j]);
                        free(slides[i].lines);
                        if (slides[i].img)
-                               fffree(slides[i].img);
+                               pamfree(slides[i].img);
                }
                free(slides);
                slides = NULL;
@@ -480,7 +481,7 @@ void load(FILE *fp)
                        /* only make image slide if first line of a slide 
starts with @ */
                        if (s->linecount == 0 && s->lines[0][0] == '@') {
                                memmove(s->lines[0], &s->lines[0][1], blen);
-                               s->img = ffopen(s->lines[0]);
+                               s->img = pamopen(s->lines[0]);
                        }
 
                        if (s->lines[s->linecount][0] == '\\')
@@ -502,9 +503,9 @@ void advance(const Arg *arg)
                        slides[idx].img->state &= ~(DRAWN | SCALED);
                idx = new_idx;
                xdraw();
-               if (slidecount > idx + 1 && slides[idx + 1].img && 
!ffread(slides[idx + 1].img))
+               if (slidecount > idx + 1 && slides[idx + 1].img && 
!pamread(slides[idx + 1].img))
                        die("Unable to read image %s", slides[idx + 
1].lines[0]);
-               if (0 < idx && slides[idx - 1].img && !ffread(slides[idx - 
1].img))
+               if (0 < idx && slides[idx - 1].img && !pamread(slides[idx - 
1].img))
                        die("Unable to read image %s", slides[idx - 
1].lines[0]);
        }
 }
@@ -569,12 +570,12 @@ void xdraw()
                                 slides[idx].lines[i],
                                 0);
                drw_map(d, xw.win, 0, 0, xw.w, xw.h);
-       } else if (!(im->state & LOADED) && !ffread(im)) {
+       } else if (!(im->state & LOADED) && !pamread(im)) {
                eprintf("Unable to read image %s", slides[idx].lines[0]);
-       } else if (!(im->state & SCALED) && !ffprepare(im)) {
+       } else if (!(im->state & SCALED) && !pamprepare(im)) {
                eprintf("Unable to prepare image %s for drawing", 
slides[idx].lines[0]);
        } else if (!(im->state & DRAWN)) {
-               ffdraw(im);
+               pamdraw(im);
        }
 }
 
@@ -710,6 +711,8 @@ int main(int argc, char *argv[])
                usage();
        } ARGEND;
 
+       pm_init(argv[0], 0);
+
        for (i = 0; i < argc; i++) {
                if ((fp = strcmp(argv[i], "-") ? fopen(argv[i], "r") : stdin)) {
                        load(fp);
-- 
2.4.10


Reply via email to