xscreenshot

suckless screen capture tool
git clone git://git.2f30.org/xscreenshot.git
Log | Files | Refs | README | LICENSE

commit d027bcf68df72a92e3b0f6d2b7b97e73e736f4ed
parent 82ccf27dff05c70fe7c0bcde466edb9a36aa0314
Author: Hiltjo Posthuma <hiltjo@codemadness.org>
Date:   Mon Jul 28 15:21:28 +0000

xscreenshot improvements, thanks sin and frign!

- use imagefile tools for conversion, don't depend on libpng anymore
  directly.
- use XGetPixel to get pixel values.
- update documentation accordingly.

Signed-off-by: Hiltjo Posthuma <hiltjo@codemadness.org>

Diffstat:
LICENSE | 2++
README | 15++++++++++-----
TODO | 2--
config.mk | 2+-
xscreenshot.c | 105+++++++++++++++++++------------------------------------------------------------
5 files changed, 38 insertions(+), 88 deletions(-)
diff --git a/LICENSE b/LICENSE @@ -1,6 +1,8 @@ MIT/X Consortium License (c) 2014 Hiltjo Posthuma <hiltjo@codemadness.org> +(c) 2014 sin <sin@2f30.org> +(c) 2014 Laslo Hunhold <dev@frign.de> 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/README b/README @@ -7,22 +7,27 @@ xscreenshot is a simple screenshot utility. It writes image data to stdout. Dependencies ------------ -- libpng - libX11 +Optional dependencies +--------------------- + +- To convert imagefile data you can use if2png from: + http://git.2f30.org/imagefile + Compile ------- -run make or: - -cc xscreenshot.c -o xscreenshot -lX11 -lpng +$ make +# make install Usage ----- -xscreenshot [winid] > file.png +xscreenshot [winid] > file.if +if2png < file.if > file.png Known issues diff --git a/TODO b/TODO @@ -1,3 +1 @@ -[ ] I might have missed a few cases of color conversion (convertrow_*). [ ] better multi-monitor support. -[ ] write a "if" output: http://git.2f30.org/imagefile/. diff --git a/config.mk b/config.mk @@ -8,7 +8,7 @@ MANPREFIX = ${PREFIX}/share/man # includes and libs INCS = -LIBS = -lc -lpng -lX11 +LIBS = -lc -lX11 # debug CFLAGS = -O0 -g -std=c99 -Wall -Wextra -pedantic \ diff --git a/xscreenshot.c b/xscreenshot.c @@ -8,8 +8,7 @@ #include <X11/X.h> #include <X11/Xlib.h> #include <X11/Xutil.h> - -#include <png.h> +#include <arpa/inet.h> static void die(const char *s) { @@ -17,82 +16,6 @@ die(const char *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, NULL, - 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); -} - static void usage(void) { @@ -108,12 +31,15 @@ main(int argc, char *argv[]) Display *dpy; Window win; XWindowAttributes attr; + uint32_t tmp, pix; + uint8_t rgba[4] = {0, 0, 0, 255}; + int w, h; dpy = XOpenDisplay(NULL); if(!dpy) die("Can't XOpenDisplay"); - /* win */ + /* identify window */ if(argc > 1) { if(strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "-v") == 0) usage(); @@ -133,7 +59,26 @@ main(int argc, char *argv[]) XCloseDisplay(dpy); if(!img) die("Can't XGetImage"); - pngstdout(img); + + /* write header with big endian width and height-values */ + fprintf(stdout, "imagefile"); + tmp = htonl(img->width); + fwrite(&tmp, sizeof(uint32_t), 1, stdout); + tmp = htonl(img->height); + fwrite(&tmp, sizeof(uint32_t), 1, stdout); + + /* write pixels */ + for(h = 0; h < img->height; ++h) { + for(w = 0; w < img->width; ++w) { + pix = XGetPixel(img, w, h); + rgba[0] = (pix & img->red_mask) >> 16; + rgba[1] = (pix & img->green_mask) >> 8; + rgba[2] = (pix & img->blue_mask) >> 0; + if(fwrite(&rgba, sizeof(uint8_t), 4, stdout) != 4) + die("fwrite() failed"); + } + } + XDestroyImage(img); return EXIT_SUCCESS;