Introduction
Introduction Statistics Contact Development Disclaimer Help
Add primitive support for multiple images - lel - Farbfeld image viewer
git clone git://git.codemadness.org/lel
Log
Files
Refs
README
LICENSE
---
commit 049c5f73a2b1174d54d033e10bd5d34373f77884
parent 0bcb47ab3451309490d3f4a856b755ea43ff282e
Author: sin <[email protected]>
Date: Fri, 1 Aug 2014 19:06:32 +0100
Add primitive support for multiple images
Signed-off-by: Hiltjo Posthuma <[email protected]>
Diffstat:
M LICENSE | 1 +
M TODO | 1 -
M lel.c | 264 ++++++++++++++++++++---------…
3 files changed, 176 insertions(+), 90 deletions(-)
---
diff --git a/LICENSE b/LICENSE
@@ -1,6 +1,7 @@
MIT/X Consortium License
(c) 2014 Hiltjo Posthuma <[email protected]>
+(c) 2014 sin <[email protected]>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
diff --git a/TODO b/TODO
@@ -5,7 +5,6 @@
[ ] enter key or some other key should print the current filename to stdout.
[ ] for pictures which use an alpha mask use a checked pattern, similar to:
http://www.modejong.com/blog/Media/Ghost_TransparentBG_400x300.jpg
-[ ] support multiple filenames as arguments, use hotkeys to switch image.
[ ] zooming
[ ] improve performance (cull only the visible part?), use XGetImage()…
[ ] improve zoomfact "steps".
diff --git a/lel.c b/lel.c
@@ -1,3 +1,4 @@
+/* See LICENSE file for copyright and license details. */
#include <unistd.h>
#include <stdarg.h>
#include <stdint.h>
@@ -24,6 +25,23 @@ enum { NONE = 0, LOADED = 1, SCALED = 2, DRAWN = 4 };
/* View mode. */
enum { ASPECT = 0, FULL_ASPECT, FULL_STRETCH };
+struct img {
+ char *filename;
+ FILE *fp;
+ int state;
+ int width;
+ int height;
+ uint8_t *buf;
+ struct view {
+ int panxoffset;
+ int panyoffset;
+ float zoomfact;
+ } view;
+};
+
+static struct img *imgs;
+static struct img *cimg;
+static size_t nimgs;
static int viewmode = ASPECT;
static char *wintitle = APP_NAME;
static XImage *ximg = NULL;
@@ -33,12 +51,11 @@ static Window win;
static GC gc;
static int screen, xfd;
static int running = 1;
-static int imgstate = NONE;
-static int imgwidth, imgheight;
-static uint8_t *imgbuf;
static int winx, winy, winwidth = 320, winheight = 240;
-static int panxoffset = 0, panyoffset = 0;
-static float zoomfact = 1.0, zoominc = 0.25;
+static float zoominc = 0.25;
+static int tflag;
+static int wflag;
+static int hflag;
void
die(const char *fmt, ...)
@@ -72,53 +89,70 @@ usage(void)
}
int
-if_open(FILE *f)
+if_open(struct img *img)
{
uint8_t hdr[17];
- if (fread(hdr, 1, strlen(HEADER_FORMAT), f) != strlen(HEADER_FORMAT))
+ if (img->state & LOADED)
+ return 0;
+
+ if (fread(hdr, 1, strlen(HEADER_FORMAT), img->fp) != strlen(HEADER_FOR…
return -1;
if(memcmp(hdr, "imagefile", 9))
return -1;
- imgwidth = ntohl((hdr[9] << 0) | (hdr[10] << 8) | (hdr[11] << 16) | (h…
- imgheight = ntohl((hdr[13] << 0) | (hdr[14] << 8) | (hdr[15] << 16) | …
- if(imgwidth <= 0 || imgheight <= 0)
+ img->width = ntohl((hdr[9] << 0) | (hdr[10] << 8) | (hdr[11] << 16) | …
+ img->height = ntohl((hdr[13] << 0) | (hdr[14] << 8) | (hdr[15] << 16) …
+ if(img->width <= 0 || img->height <= 0)
return -1;
+ if(!(img->buf = malloc(img->width * img->height * 4)))
+ die("can't malloc\n");
+
return 0;
}
int
-if_read(FILE *f)
+if_read(struct img *img)
{
int i, j, off, row_len;
uint8_t *row;
- row_len = imgwidth * strlen("RGBA");
+ if (img->state & LOADED)
+ return 0;
+
+ row_len = img->width * strlen("RGBA");
if(!(row = malloc(row_len)))
- return 1;
+ return -1;
- for(off = 0, i = 0; i < imgheight; ++i) {
- if(fread(row, 1, (size_t)row_len, f) != (size_t)row_len) {
+ for(off = 0, i = 0; i < img->height; ++i) {
+ if(fread(row, 1, (size_t)row_len, img->fp) != (size_t)row_len)…
free(row);
die("unexpected EOF or row-skew at %d\n", i);
}
for(j = 0; j < row_len; j += 4, off += 4) {
- imgbuf[off] = row[j];
- imgbuf[off + 1] = row[j + 1];
- imgbuf[off + 2] = row[j + 2];
- imgbuf[off + 3] = row[j + 3];
+ img->buf[off] = row[j];
+ img->buf[off + 1] = row[j + 1];
+ img->buf[off + 2] = row[j + 2];
+ img->buf[off + 3] = row[j + 3];
}
}
free(row);
- imgstate |= LOADED;
+ img->state |= LOADED;
return 0;
}
+void
+if_close(struct img *img)
+{
+ img->state &= ~LOADED;
+ rewind(img->fp);
+ free(img->buf);
+}
+
/* NOTE: will be removed later, for debugging alpha mask */
#if 0
void
@@ -137,6 +171,58 @@ normalsize(char *newbuf)
}
#endif
+void
+loadimg(void)
+{
+ if(if_open(cimg))
+ die("can't open image (invalid format?)\n");
+ if(if_read(cimg))
+ die("can't read image\n");
+ if(!wflag)
+ winwidth = cimg->width;
+ if(!hflag)
+ winheight = cimg->height;
+ if(!tflag)
+ wintitle = cimg->filename;
+}
+
+void
+reloadimg(void)
+{
+ loadimg();
+ XResizeWindow(dpy, win, winwidth, winheight);
+ XStoreName(dpy, win, wintitle);
+ XFlush(dpy);
+}
+
+void
+nextimg(void)
+{
+ struct img *tmp = cimg;
+
+ cimg++;
+ if (cimg >= &imgs[nimgs])
+ cimg = &imgs[0];
+ if (tmp != cimg) {
+ if_close(tmp);
+ reloadimg();
+ }
+}
+
+void
+previmg(void)
+{
+ struct img *tmp = cimg;
+
+ cimg--;
+ if (cimg < &imgs[0])
+ cimg = &imgs[nimgs - 1];
+ if (tmp != cimg) {
+ if_close(tmp);
+ reloadimg();
+ }
+}
+
/* scales imgbuf data to newbuf (ximg->data), nearest neighbour. */
void
scale(unsigned int width, unsigned int height, unsigned int bytesperline,
@@ -146,10 +232,10 @@ scale(unsigned int width, unsigned int height, unsigned i…
unsigned int jdy, dx, bufx, x, y;
jdy = bytesperline / 4 - width;
- dx = (imgwidth << 10) / width;
+ dx = (cimg->width << 10) / width;
for(y = 0; y < height; y++) {
- bufx = imgwidth / width;
- ibuf = &imgbuf[y * imgheight / height * imgwidth * 4];
+ bufx = cimg->width / width;
+ ibuf = &cimg->buf[y * cimg->height / height * cimg->width * 4];
for(x = 0; x < width; x++) {
*newbuf++ = (ibuf[(bufx >> 10)*4+2]);
@@ -195,17 +281,17 @@ scaleview(void)
ximage(winwidth, winheight);
break;
case FULL_ASPECT:
- if(winwidth * imgheight > winheight * imgwidth)
- ximage(imgwidth * winheight / imgheight, winheight);
+ if(winwidth * cimg->height > winheight * cimg->width)
+ ximage(cimg->width * winheight / cimg->height, winheig…
else
- ximage(winwidth, imgheight * winwidth / imgwidth);
+ ximage(winwidth, cimg->height * winwidth / cimg->width…
break;
case ASPECT:
default:
- ximage(imgwidth * zoomfact, imgheight * zoomfact);
+ ximage(cimg->width * cimg->view.zoomfact, cimg->height * cimg-…
break;
}
- imgstate |= SCALED;
+ cimg->state |= SCALED;
}
void
@@ -218,8 +304,8 @@ draw(void)
xoffset = (winwidth - ximg->width) / 2;
yoffset = (winheight - ximg->height) / 2;
/* pan offset */
- xoffset -= panxoffset;
- yoffset -= panyoffset;
+ xoffset -= cimg->view.panxoffset;
+ yoffset -= cimg->view.panyoffset;
}
XSetForeground(dpy, gc, BlackPixel(dpy, 0));
XFillRectangle(dpy, xpix, gc, 0, 0, winwidth, winheight);
@@ -227,17 +313,17 @@ draw(void)
XCopyArea(dpy, xpix, win, gc, 0, 0, winwidth, winheight, 0, 0);
XFlush(dpy);
- imgstate |= DRAWN;
+ cimg->state |= DRAWN;
}
void
update(void)
{
- if(!(imgstate & LOADED))
+ if(!(cimg->state & LOADED))
return;
- if(!(imgstate & SCALED))
+ if(!(cimg->state & SCALED))
scaleview();
- if(!(imgstate & DRAWN))
+ if(!(cimg->state & DRAWN))
draw();
}
@@ -247,36 +333,36 @@ setview(int mode)
if(viewmode == mode)
return;
viewmode = mode;
- imgstate &= ~(DRAWN | SCALED);
+ cimg->state &= ~(DRAWN | SCALED);
update();
}
void
pan(int x, int y)
{
- panxoffset -= x;
- panyoffset -= y;
- imgstate &= ~(DRAWN | SCALED);
+ cimg->view.panxoffset -= x;
+ cimg->view.panyoffset -= y;
+ cimg->state &= ~(DRAWN | SCALED);
update();
}
void
inczoom(float f)
{
- if((zoomfact + f) <= 0)
+ if((cimg->view.zoomfact + f) <= 0)
return;
- zoomfact += f;
- imgstate &= ~(DRAWN | SCALED);
+ cimg->view.zoomfact += f;
+ cimg->state &= ~(DRAWN | SCALED);
update();
}
void
zoom(float f)
{
- if(f == zoomfact)
+ if(f == cimg->view.zoomfact)
return;
- zoomfact = f;
- imgstate &= ~(DRAWN | SCALED);
+ cimg->view.zoomfact = f;
+ cimg->state &= ~(DRAWN | SCALED);
update();
}
@@ -352,9 +438,19 @@ keypress(XEvent *ev)
zoom(1.0);
setview(ASPECT); /* fallthrough */
case XK_r:
- panxoffset = 0;
- panyoffset = 0;
- imgstate &= ~(DRAWN | SCALED);
+ cimg->view.panxoffset = 0;
+ cimg->view.panyoffset = 0;
+ cimg->state &= ~(DRAWN | SCALED);
+ update();
+ break;
+ case XK_n:
+ nextimg();
+ cimg->state &= ~(DRAWN | SCALED);
+ update();
+ break;
+ case XK_p:
+ previmg();
+ cimg->state &= ~(DRAWN | SCALED);
update();
break;
}
@@ -377,11 +473,11 @@ handleevent(XEvent *ev)
if(winwidth != ev->xconfigure.width || winheight != ev->xconfi…
winwidth = ev->xconfigure.width;
winheight = ev->xconfigure.height;
- imgstate &= ~(SCALED);
+ cimg->state &= ~(SCALED);
}
break;
case Expose:
- imgstate &= ~(DRAWN);
+ cimg->state &= ~(DRAWN);
update();
break;
case KeyPress:
@@ -421,18 +517,14 @@ run(void)
{
XEvent ev;
- while(running && !XNextEvent(dpy, &ev)) {
+ while(running && !XNextEvent(dpy, &ev))
handleevent(&ev);
- }
}
int
main(int argc, char *argv[]) {
- char *filename = "";
- FILE *fp = NULL;
- int tflag = 0;
- int wflag = 0;
- int hflag = 0;
+ FILE *fp;
+ int i, j;
ARGBEGIN {
case 'a':
@@ -466,44 +558,38 @@ main(int argc, char *argv[]) {
break;
} ARGEND;
- if(argc >= 1) {
- filename = argv[0];
- if(!(fp = fopen(filename, "rb"))) {
- die("can't read %s:", filename);
- return EXIT_FAILURE;
- }
+ if(argc == 0) {
+ imgs = calloc(1, sizeof(*imgs));
+ if (!imgs)
+ die("can't calloc\n");
+ nimgs = 1;
+ imgs[0].filename = "<stdin>";
+ imgs[0].fp = stdin;
+ imgs[0].view.zoomfact = 1.0;
} else {
- filename = "<stdin>";
- fp = stdin;
+ imgs = calloc(argc, sizeof(*imgs));
+ if(!imgs)
+ die("can't calloc\n");
+ for(i = 0, j = 0; j < argc; j++) {
+ fp = fopen(argv[j], "rb");
+ if (!fp) {
+ fprintf(stderr, "can't open %s\n", argv[j]);
+ continue;
+ }
+ imgs[i].filename = argv[j];
+ imgs[i].fp = fp;
+ imgs[i].view.zoomfact = 1.0;
+ i++;
+ }
+ if (i == 0)
+ return EXIT_FAILURE;
+ nimgs = i;
}
- if(!tflag)
- wintitle = filename;
-
- if(if_open(fp))
- die("can't open image (invalid format?)\n");
- if(!(imgbuf = malloc((imgwidth) * (imgheight) * 4)))
- die("can't malloc\n");
- if_read(fp);
-
- if(!wflag)
- winwidth = imgwidth;
- if(!hflag)
- winheight = imgheight;
+ cimg = imgs;
+ loadimg();
setup();
run();
- if(fp && fp != stdin)
- fclose(fp);
-
- free(imgbuf);
-
- if(ximg)
- XDestroyImage(ximg);
- if(xpix)
- XFreePixmap(dpy, xpix);
- if(dpy)
- XCloseDisplay(dpy);
-
return EXIT_SUCCESS;
}
You are viewing proxied material from codemadness.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.