From d03e258e2b4e8aa1f9db2f4f272e1df4f6e3d66f Mon Sep 17 00:00:00 2001 From: glenda Date: Sat, 1 Feb 2025 06:25:36 +0000 Subject: [PATCH] mostly done with images --- pres.c | 185 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 180 insertions(+), 5 deletions(-) diff --git a/pres.c b/pres.c index 22d98293a6b56fc06244d8d3d6453157e03a0a47..f852a50c85224e8ad64c63bfde0d8bbbfa766dbd 100644 --- a/pres.c +++ b/pres.c @@ -30,9 +30,21 @@ Menu menu = { .item = menuitems }; +char *mimetab[] = { + "image/png", "png", + "image/jpeg", "jpg", + "image/ppm", "ppm", + "image/tiff", "tif", + "image/bmp", "bmp", + + "audio/mpeg", "", /* bug in file(1) */ + "image/p9bit", "", + nil +}; + int checkonly, lightmode, nslides, cslide, xm, ym; char *file, *contents, *offset, *tfname, *hfname; -Image *bg,*fg,*tmp; +Image *bg,*fg,*tmp, **images; Font *tfont, *hfont; Slide **slides; @@ -168,7 +180,7 @@ checkerr(Slide *s, char *msg, ...) va_start(args, msg); - fprint(2,"%s:%d: %s: ", file, s->linum, s->cmd); + fprint(2,"%s:%d: %%%s: ", file, s->linum, s->cmd); vfprint(2,msg, args); fprint(2,"\n"); } @@ -196,6 +208,8 @@ checkfile(void) continue; else if(strcmp(s->cmd, "text") == 0) continue; + else if(strcmp(s->cmd, "gallery") == 0) + continue; else if(strcmp(s->cmd, "title") == 0){ if(s->arg == nil){ waserr = 1; @@ -211,6 +225,154 @@ checkfile(void) exits("checkfile"); } +// FIXME: some of this could be done in-process but i am lazy +// TODO: should check image formats in checkimage() instead +void +loadimages(void){ + const Slide *s; + Image **nextimg, *cimg; + Waitmsg *wm; + Point idims, sdims; + int i, j, n, cols, rows, p[2], fd; + char buf[64], buf2[64], *conv; + + if(images != nil) + return; + + s = slides[cslide]; + + images = calloc(s->nlines, sizeof(Image*)); + nextimg = images; + + pipe(p); + + cols = 0; + i = 0; + while(i < s->nlines && *(s->lines[i]) == '\0') i++; + for(; i < s->nlines; i++){ + cols++; + while(i < s->nlines && *(s->lines[i]) != '\0') i++; + while(i < s->nlines && *(s->lines[i]) == '\0') i++; + } + + rows = 0; + + for(i = 0; i < s->nlines; i++){ + if(*(s->lines[i]) == '\0'){ + rows = 0; + continue; + } + if(rows == 0){ + j = i; + while(j < s->nlines && *(s->lines[j++]) != '\0') + rows++; + } + + sdims = subpt(screen->r.max, screen->r.min); + sdims.x /= cols; + sdims.y /= rows; + + if(fork() == 0){ + close(1); + dup(p[0], 1); + execl("/bin/file", "file", "-m", s->lines[i], nil); + } + wm = wait(); + if(wm->msg != nil && *wm->msg != '\0') + sysfatal("%s", wm->msg); + free(wm); + + n = read(p[1], buf, sizeof(buf)); + buf[n - 1] = '\0'; /* replace the newline */ + + conv = nil; + for(j = 0; mimetab[j] != nil; j+=2){ + if(strcmp(buf, mimetab[j]) == 0){ + conv = mimetab[j+1]; + break; + } + } + if(conv == nil) + sysfatal("unknown image format '%s'", buf); + + if(fork() == 0){ + close(1); + dup(p[0], 1); + if(*conv == '\0') + execl("/bin/cat", "cat", s->lines[i], nil); + else{ + sprint(buf, "/bin/%s", conv); + execl(buf, conv, "-c", s->lines[i], nil); + } + } + cimg = readimage(display, p[1], 0); + if(cimg == nil) + sysfatal("couldn't convert '%s': %r", s->lines[i]); + waitpid(); + + idims = subpt(cimg->r.max, cimg->r.min); + + sprint(buf, "/tmp/%s.%d.img", argv0, getpid()); + fd = create(buf, OWRITE, 0600); + if(fd < 0) + sysfatal("couldn't open tmp file: %r"); + writeimage(fd, cimg, 0); + close(fd); + + if(fork() == 0){ + close(1); + dup(p[0], 1); + + if(idims.x < idims.y || (idims.x == idims.y && sdims.x > sdims.y)){ + sprint(buf2, "%d", sdims.x); + execl("/bin/resize", "resize", "-x", buf2, buf, nil); + }else{ + sprint(buf2, "%d", sdims.y); + execl("/bin/resize", "resize", "-y", buf2, buf, nil); + } + } + *nextimg = readimage(display, p[1], 0); + if(*nextimg == nil) + sysfatal("couldn't scale '%s': %r", s->lines[i]); + + nextimg++; + } + + close(p[0]); + close(p[1]); +} +void +freeimages(void){ + const Slide *s; + Image **p; + int i; + + if(images == nil) + return; + + s = slides[cslide]; + p = images; + + for(i = 0; i < s->nlines; i++){ + if(*(s->lines[i]) == '\0') + continue; + + freeimage(*p); + p++; + } + + free(images); + images = nil; +} +void +rmtmp(void) +{ + char buf[64]; + + sprint(buf, "/tmp/%s.%d.img", argv0, getpid()); + remove(buf); +} + void render(void) { @@ -263,7 +425,11 @@ render(void) string(screen, Pt(center.x - (width / 2), voff), fg, Pt(0,0), tfont, s->lines[i]); voff += tfont->height; } - + + }else if(strcmp(s->cmd, "gallery") == 0){ + loadimages(); + p = divpt(subpt(subpt(screen->r.max, screen->r.min), subpt(images[0]->r.max, images[0]->r.min)), -2); + draw(screen, screen->r, images[0], nil, p); } } @@ -272,6 +438,7 @@ eresized(int new) { if(new && getwindow(display, Refnone) < 0) fprint(2,"can't reattach to window\n"); + freeimages(); render(); } @@ -348,6 +515,8 @@ main(int argc, char *argv[]) if(checkonly) exits(nil); + atexit(rmtmp); + slides = malloc(nslides*sizeof(Slide*)); for(i = 0; i < nslides; i++){ slides[i] = nextslide(&offset, &linum); @@ -394,10 +563,14 @@ main(int argc, char *argv[]) if(etype == Emouse){ m = e.mouse; - if(m.buttons & 1 && !(lastm.buttons & 1)) + if(m.buttons & 1 && !(lastm.buttons & 1)){ + freeimages(); cslide--; - if(m.buttons & 4 && !(lastm.buttons & 4)) + } + if(m.buttons & 4 && !(lastm.buttons & 4)){ + freeimages(); cslide++; + } menu.lasthit = -1; if(m.buttons & 2) @@ -405,9 +578,11 @@ main(int argc, char *argv[]) switch(menu.lasthit){ case MenuNext: + freeimages(); cslide++; break; case MenuPrev: + freeimages(); cslide--; break; case MenuExit: