load slide image on-demand

On Sat, Jun 04, 2016 at 05:28:31PM +0200, Markus Teich wrote:
> Hiltjo Posthuma wrote:
> > previously an image file would be opened but only ffread when advancing to
> > the slide, but when the slide was not used it gave an error:
> >
> > 	/usr/local/bin/2ff: failed to convert image/png
>
> Heyho Hiltjo,
>
> thanks for the patch. Unfortunately it does not work if the first slide contains
> an image (ffopen is only called in advance). I think it would be good to merge
> ffopen and ffread instead into a single function ffload. This makes the `LOADED`
> state clearer and also enforces that the fd is closed in the same function where
> it is opened. This ffload function should then be called in advance() replacing
> the ffread() calls if the image is not loaded yet and once in load() for the
> first slide if it is an image.
>

Ah yes, sorry for the oversight.

> If you want to take this new approach, go for it, otherwise I'll look into it
> myself.
>

I have attached a patch that does this, I hope you'll like it.

Also I'm not sure if we need the below code in advance(), I have removed it in
the patch:

        if (slidecount > idx + 1 && slides[idx + 1].img)
                ffread(slides[idx + 1].img);
        if (0 < idx && slides[idx - 1].img)
                ffread(slides[idx - 1].img);

That seems to preload the next and previous slide image right? A minor issue I
notice also is that images seem to flicker, it uses XPutImage directly to
xw.win. Maybe it can be replaced with a backbuffer then XCopyArea? What do you
think?

In advance() it should also not always be needed to rescale the image.

--
Kind regards,
Hiltjo

From 97bebdcab4003f9acdfdd4bdf424449299ffd61d Mon Sep 17 00:00:00 2001
From: Hiltjo Posthuma <hiltjo@codemadness.org>
Date: Sat, 4 Jun 2016 21:34:25 +0200
Subject: [PATCH] merge ffread and ffopen into one function
This commit is contained in:
Hiltjo Posthuma 2016-06-04 21:47:39 +02:00 committed by Markus Teich
parent 44a50ad948
commit fd303ee9c1

79
sent.c
View File

@ -89,9 +89,8 @@ typedef struct {
const Arg arg; const Arg arg;
} Shortcut; } Shortcut;
static Image *ffopen(char *filename);
static void fffree(Image *img); static void fffree(Image *img);
static void ffread(Image *img); static Image *ffread(char *filename);
static void ffprepare(Image *img); static void ffprepare(Image *img);
static void ffscale(Image *img); static void ffscale(Image *img);
static void ffdraw(Image *img); static void ffdraw(Image *img);
@ -159,14 +158,27 @@ filter(int fd, const char *cmd)
return fds[0]; return fds[0];
} }
Image * void
ffopen(char *filename) fffree(Image *img)
{ {
free(img->buf);
if (img->ximg)
XDestroyImage(img->ximg);
free(img);
}
Image *
ffread(char *filename)
{
uint32_t y, x;
uint16_t *row;
uint8_t opac, fg_r, fg_g, fg_b, bg_r, bg_g, bg_b;
size_t rowlen, off, nbytes, i;
ssize_t count;
unsigned char hdr[16]; unsigned char hdr[16];
char *bin = NULL; char *bin = NULL;
regex_t regex; regex_t regex;
Image *img; Image *img;
size_t i;
int tmpfd, fd; int tmpfd, fd;
for (i = 0; i < LEN(filters); i++) { for (i = 0; i < LEN(filters); i++) {
@ -178,13 +190,11 @@ ffopen(char *filename)
break; break;
} }
} }
if (!bin) if (!bin)
return NULL; return NULL;
if ((fd = open(filename, O_RDONLY)) < 0) { if ((fd = open(filename, O_RDONLY)) < 0)
die("sent: Unable to open file %s:", filename); die("sent: Unable to open file %s:", filename);
}
tmpfd = fd; tmpfd = fd;
fd = filter(fd, bin); fd = filter(fd, bin);
@ -192,10 +202,7 @@ ffopen(char *filename)
die("sent: Unable to filter %s:", filename); die("sent: Unable to filter %s:", filename);
close(tmpfd); close(tmpfd);
if (read(fd, hdr, 16) != 16) if (read(fd, hdr, 16) != 16 || memcmp("farbfeld", hdr, 8))
return NULL;
if (memcmp("farbfeld", hdr, 8))
return NULL; return NULL;
img = calloc(1, sizeof(Image)); img = calloc(1, sizeof(Image));
@ -203,31 +210,6 @@ ffopen(char *filename)
img->bufwidth = ntohl(*(uint32_t *)&hdr[8]); img->bufwidth = ntohl(*(uint32_t *)&hdr[8]);
img->bufheight = ntohl(*(uint32_t *)&hdr[12]); img->bufheight = ntohl(*(uint32_t *)&hdr[12]);
return img;
}
void
fffree(Image *img)
{
free(img->buf);
if (img->ximg)
XDestroyImage(img->ximg);
free(img);
}
void
ffread(Image *img)
{
uint32_t y, x;
uint16_t *row;
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;
if (img->state & LOADED)
return;
if (img->buf) if (img->buf)
free(img->buf); free(img->buf);
/* internally the image is stored in 888 format */ /* internally the image is stored in 888 format */
@ -237,9 +219,8 @@ ffread(Image *img)
/* scratch buffer to read row by row */ /* scratch buffer to read row by row */
rowlen = img->bufwidth * 2 * strlen("RGBA"); rowlen = img->bufwidth * 2 * strlen("RGBA");
row = malloc(rowlen); row = malloc(rowlen);
if (!row) { if (!row)
die("sent: Unable to malloc buffer for image row.\n"); die("sent: Unable to malloc buffer for image row.\n");
}
/* extract window background color channels for transparency */ /* extract window background color channels for transparency */
bg_r = (sc[ColBg].pixel >> 16) % 256; bg_r = (sc[ColBg].pixel >> 16) % 256;
@ -270,6 +251,8 @@ ffread(Image *img)
free(row); free(row);
close(img->fd); close(img->fd);
img->state |= LOADED; img->state |= LOADED;
return img;
} }
void void
@ -444,13 +427,11 @@ load(FILE *fp)
memmove(s->lines[s->linecount], &s->lines[s->linecount][1], blen); memmove(s->lines[s->linecount], &s->lines[s->linecount][1], blen);
s->linecount++; s->linecount++;
} while ((p = fgets(buf, sizeof(buf), fp)) && strcmp(buf, "\n") != 0); } while ((p = fgets(buf, sizeof(buf), fp)) && strcmp(buf, "\n") != 0);
slidecount++; slidecount++;
if (!p) if (!p)
break; break;
} }
if (slidecount && slides[0].embed && slides[0].embed[0])
slides[0].img = ffopen(slides[0].embed);
} }
void void
@ -462,13 +443,7 @@ advance(const Arg *arg)
if (slides[idx].img) if (slides[idx].img)
slides[idx].img->state &= ~(DRAWN | SCALED); slides[idx].img->state &= ~(DRAWN | SCALED);
idx = new_idx; idx = new_idx;
if (!slides[idx].img && slides[idx].embed && slides[idx].embed[0])
slides[idx].img = ffopen(slides[idx].embed);
xdraw(); xdraw();
if (slidecount > idx + 1 && slides[idx + 1].img)
ffread(slides[idx + 1].img);
if (0 < idx && slides[idx - 1].img)
ffread(slides[idx - 1].img);
} }
} }
@ -514,7 +489,11 @@ void
xdraw() xdraw()
{ {
unsigned int height, width, i; unsigned int height, width, i;
Image *im = slides[idx].img; Image *im;
if (!slides[idx].img && slides[idx].embed && slides[idx].embed[0])
slides[idx].img = ffread(slides[idx].embed);
im = slides[idx].img;
getfontsize(&slides[idx], &width, &height); getfontsize(&slides[idx], &width, &height);
XClearWindow(xw.dpy, xw.win); XClearWindow(xw.dpy, xw.win);
@ -532,8 +511,6 @@ xdraw()
0); 0);
drw_map(d, xw.win, 0, 0, xw.w, xw.h); drw_map(d, xw.win, 0, 0, xw.w, xw.h);
} else { } else {
if (!(im->state & LOADED))
ffread(im);
if (!(im->state & SCALED)) if (!(im->state & SCALED))
ffprepare(im); ffprepare(im);
if (!(im->state & DRAWN)) if (!(im->state & DRAWN))