diff
Makefile | 12 +++++++
ss.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 120 insertions(+)
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..46b2951
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,12 @@
+CFLAGS = -std=c89 -Wall -Wextra -Werror -pedantic
+CPPFLAGS = -I/usr/X11R6/include
+LDFLAGS = -L/usr/X11R6/lib
+LDLIBS = -lX11
+
+all: ss
+
+ss: ss.c
+ cc $(CPPFLAGS) $(CFLAGS) -o ss ss.c $(LDFLAGS) $(LDLIBS)
+
+clean:
+ rm -f ss
diff --git a/ss.c b/ss.c
new file mode 100644
index 0000000..04940bf
--- /dev/null
+++ b/ss.c
@@ -0,0 +1,108 @@
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+static unsigned long
+lowbit(unsigned long x)
+{
+ return x & (~x + 1UL);
+}
+
+static unsigned char
+chan(unsigned long pixel, unsigned long mask)
+{
+ unsigned long base;
+ unsigned long max;
+ unsigned long v;
+
+ if (mask == 0)
+ return 0;
+ base = lowbit(mask);
+ max = mask / base;
+ v = (pixel & mask) / base;
+ if (max == 0)
+ return 0;
+ return (unsigned char)((v * 255UL + (max / 2UL)) / max);
+}
+
+int
+main(int argc, char **argv)
+{
+ Display *dpy;
+ Window root;
+ XImage *img;
+ FILE *f;
+ unsigned int w;
+ unsigned int h;
+ int x;
+ int y;
+ int sw;
+ int sh;
+ int ix;
+ int iy;
+ char tail;
+
+ if (argc != 3) {
+ fprintf(stderr, "usage: ss WIDTHxHEIGHT+X+Y file.ppm\n");
+ return 1;
+ }
+ if (sscanf(argv[1], "%ux%u+%d+%d%c", &w, &h, &x, &y, &tail) != 4 || w == 0 || h == 0) {
+ fprintf(stderr, "invalid geometry: %s\n", argv[1]);
+ return 1;
+ }
+ if ((dpy = XOpenDisplay(NULL)) == NULL) {
+ fprintf(stderr, "failed to open X display\n");
+ return 1;
+ }
+
+ sw = DisplayWidth(dpy, DefaultScreen(dpy));
+ sh = DisplayHeight(dpy, DefaultScreen(dpy));
+ if (x < 0 || y < 0 || x + (int)w > sw || y + (int)h > sh) {
+ fprintf(stderr, "geometry out of bounds (%dx%d screen)\n", sw, sh);
+ XCloseDisplay(dpy);
+ return 1;
+ }
+
+ root = DefaultRootWindow(dpy);
+ img = XGetImage(dpy, root, x, y, w, h, AllPlanes, ZPixmap);
+ if (img == NULL) {
+ fprintf(stderr, "XGetImage failed\n");
+ XCloseDisplay(dpy);
+ return 1;
+ }
+
+ f = fopen(argv[2], "wb");
+ if (f == NULL) {
+ fprintf(stderr, "failed to open output: %s\n", argv[2]);
+ XDestroyImage(img);
+ XCloseDisplay(dpy);
+ return 1;
+ }
+
+ fprintf(f, "P6\n%u %u\n255\n", w, h);
+ for (iy = 0; iy < (int)h; iy++) {
+ for (ix = 0; ix < (int)w; ix++) {
+ unsigned long p;
+ unsigned char rgb[3];
+
+ p = XGetPixel(img, ix, iy);
+ rgb[0] = chan(p, img->red_mask);
+ rgb[1] = chan(p, img->green_mask);
+ rgb[2] = chan(p, img->blue_mask);
+ if (fwrite(rgb, 1, 3, f) != 3) {
+ fprintf(stderr, "write failed: %s\n", argv[2]);
+ fclose(f);
+ XDestroyImage(img);
+ XCloseDisplay(dpy);
+ return 1;
+ }
+ }
+ }
+
+ fclose(f);
+ XDestroyImage(img);
+ XCloseDisplay(dpy);
+ return 0;
+}