initial import - xscreenshot - screen capture tool | |
git clone git://git.codemadness.org/xscreenshot | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 1cf03c53b280d3fe21dac843504dd54e9b64e4b6 | |
Author: Hiltjo Posthuma <[email protected]> | |
Date: Sun, 27 Jul 2014 21:22:39 +0000 | |
initial import | |
Signed-off-by: Hiltjo Posthuma <[email protected]> | |
Diffstat: | |
A .gitignore | 2 ++ | |
A LICENSE | 21 +++++++++++++++++++++ | |
A Makefile | 9 +++++++++ | |
A README | 31 +++++++++++++++++++++++++++++… | |
A TODO | 5 +++++ | |
A xscreenshot.c | 133 +++++++++++++++++++++++++++++… | |
6 files changed, 201 insertions(+), 0 deletions(-) | |
--- | |
diff --git a/.gitignore b/.gitignore | |
@@ -0,0 +1,2 @@ | |
+xscreenshot | |
+*.o | |
diff --git a/LICENSE b/LICENSE | |
@@ -0,0 +1,21 @@ | |
+MIT/X Consortium License | |
+ | |
+(c) 2014 Hiltjo Posthuma <[email protected]> | |
+ | |
+Permission is hereby granted, free of charge, to any person obtaining a | |
+copy of this software and associated documentation files (the "Software"), | |
+to deal in the Software without restriction, including without limitation | |
+the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
+and/or sell copies of the Software, and to permit persons to whom the | |
+Software is furnished to do so, subject to the following conditions: | |
+ | |
+The above copyright notice and this permission notice shall be included in | |
+all copies or substantial portions of the Software. | |
+ | |
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
+DEALINGS IN THE SOFTWARE. | |
diff --git a/Makefile b/Makefile | |
@@ -0,0 +1,9 @@ | |
+build: clean | |
+ cc xscreenshot.c -o xscreenshot -lX11 -lpng -Wall -Wextra -pedantic -s… | |
+ | |
+test: build | |
+ ./xscreenshot > screen.png | |
+ meh screen.png | |
+ | |
+clean: | |
+ rm -f xscreenshot | |
diff --git a/README b/README | |
@@ -0,0 +1,31 @@ | |
+xscreenshot - make screenshot | |
+============================= | |
+ | |
+xscreenshot is a simple screenshot utility. It writes image data to stdout. | |
+ | |
+ | |
+Dependencies | |
+------------ | |
+ | |
+- libpng | |
+- libX11 | |
+ | |
+ | |
+Compile | |
+------- | |
+ | |
+run make or: | |
+ | |
+cc xscreenshot.c -o xscreenshot -lX11 -lpng | |
+ | |
+ | |
+Usage | |
+----- | |
+ | |
+xscreenshot [winid] > file.png | |
+ | |
+ | |
+Known issues | |
+------------ | |
+ | |
+A specified windowid has to be visible on the screen. | |
diff --git a/TODO b/TODO | |
@@ -0,0 +1,5 @@ | |
+- I might have missed a few cases of color conversion (convertrow_*). | |
+- write a man page. | |
+- write a Makefile (suckless-style). | |
+- better multi-monitor support. | |
+- write a "if" output: http://git.2f30.org/imagefile/. | |
diff --git a/xscreenshot.c b/xscreenshot.c | |
@@ -0,0 +1,133 @@ | |
+/* see LICENSE / README for more info */ | |
+#include <stdio.h> | |
+#include <stdint.h> | |
+#include <string.h> | |
+#include <stdlib.h> | |
+#include <errno.h> | |
+ | |
+/* X11 */ | |
+#include <X11/X.h> | |
+#include <X11/Xlib.h> | |
+#include <X11/Xutil.h> | |
+ | |
+/* png */ | |
+#include <png.h> | |
+ | |
+static void | |
+die(const char *s) { | |
+ fprintf(stderr, "xscreenshot: %s\n", s); | |
+ exit(EXIT_FAILURE); | |
+} | |
+ | |
+/* LSBFirst: BGRA -> RGBA */ | |
+static void | |
+convertrow_lsb(unsigned char *drow, unsigned char *srow, XImage *img) { | |
+ int sx, dx; | |
+ | |
+ for(sx = 0, dx = 0; dx < img->bytes_per_line - 4; sx += 4) { | |
+ drow[dx++] = srow[sx + 2]; /* B -> R */ | |
+ drow[dx++] = srow[sx + 1]; /* G -> G */ | |
+ drow[dx++] = srow[sx]; /* R -> B */ | |
+ if(img->depth == 32) | |
+ drow[dx++] = srow[sx + 3]; /* A -> A */ | |
+ else | |
+ drow[dx++] = 255; | |
+ } | |
+} | |
+ | |
+/* MSBFirst: ARGB -> RGBA */ | |
+static void | |
+convertrow_msb(unsigned char *drow, unsigned char *srow, XImage *img) { | |
+ int sx, dx; | |
+ | |
+ for(sx = 0, dx = 0; dx < img->bytes_per_line - 4; sx += 4) { | |
+ drow[dx++] = srow[sx + 1]; /* G -> R */ | |
+ drow[dx++] = srow[sx + 2]; /* B -> G */ | |
+ drow[dx++] = srow[sx + 3]; /* A -> B */ | |
+ if(img->depth == 32) | |
+ drow[dx++] = srow[sx]; /* R -> A */ | |
+ else | |
+ drow[dx++] = 255; | |
+ } | |
+} | |
+ | |
+static void | |
+pngstdout(XImage *img) | |
+{ | |
+ png_structp png_struct_p; | |
+ png_infop png_info_p; | |
+ void (*convert)(unsigned char *, unsigned char *, XImage *); | |
+ unsigned char *drow = NULL, *srow; | |
+ int h; | |
+ | |
+ png_struct_p = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NU… | |
+ NULL); | |
+ png_info_p = png_create_info_struct(png_struct_p); | |
+ | |
+ if(!png_struct_p || !png_info_p || setjmp(png_jmpbuf(png_struct_p))) | |
+ die("failed to initialize libpng"); | |
+ | |
+ png_init_io(png_struct_p, stdout); | |
+ png_set_IHDR(png_struct_p, png_info_p, img->width, img->height, 8, | |
+ PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, | |
+ PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); | |
+ png_write_info(png_struct_p, png_info_p); | |
+ | |
+ srow = (unsigned char *)img->data; | |
+ drow = calloc(1, img->width * 4); /* output RGBA */ | |
+ if(!drow) | |
+ die("Can't calloc"); | |
+ | |
+ if(img->byte_order == LSBFirst) | |
+ convert = convertrow_lsb; | |
+ else | |
+ convert = convertrow_msb; | |
+ | |
+ for(h = 0; h < img->height; h++) { | |
+ convert(drow, srow, img); | |
+ srow += img->bytes_per_line; | |
+ png_write_row(png_struct_p, drow); | |
+ } | |
+ png_write_end(png_struct_p, NULL); | |
+ | |
+ free(drow); | |
+ png_free_data(png_struct_p, png_info_p, PNG_FREE_ALL, -1); | |
+ png_destroy_write_struct(&png_struct_p, NULL); | |
+} | |
+ | |
+int | |
+main(int argc, char *argv[]) | |
+{ | |
+ XImage *img; | |
+ Display *dpy; | |
+ Window win; | |
+ XWindowAttributes attr; | |
+ | |
+ dpy = XOpenDisplay(NULL); | |
+ if(!dpy) | |
+ die("Can't XOpenDisplay"); | |
+ | |
+ /* win */ | |
+ if(argc > 1) { | |
+ errno = 0; | |
+ win = (Window)strtol(argv[1], NULL, 0); | |
+ if(errno != 0) | |
+ die("input not a number"); | |
+ } else { | |
+ win = RootWindow(dpy, 0); | |
+ } | |
+ | |
+ XGrabServer(dpy); | |
+ XGetWindowAttributes(dpy, win, &attr); | |
+ | |
+ img = XGetImage(dpy, win, 0, 0, attr.width, attr.height, 0xffffffff, | |
+ ZPixmap); | |
+ if(!img) | |
+ die("Can't XGetImage"); | |
+ pngstdout(img); | |
+ XDestroyImage(img); | |
+ XUngrabServer(dpy); | |
+ XCloseDisplay(dpy); | |
+ | |
+ return EXIT_SUCCESS; | |
+} |