commit d027bcf68df72a92e3b0f6d2b7b97e73e736f4ed
parent 82ccf27dff05c70fe7c0bcde466edb9a36aa0314
Author: Hiltjo Posthuma <hiltjo@codemadness.org>
Date: Mon, 28 Jul 2014 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:
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;