taking x-window screen shot

jepler at unpythonic.net jepler at unpythonic.net
Mon Oct 31 07:50:17 EST 2005


I recommend using 'xwd' to actually get the screenshot, because xwd is
installed nearly everwhere X is.  xwd-format images are "documented" by the
header file X11/XWDFile.h.  This program works in a pipeline to convert certain
xwd-format images to postscript.  You can use it something like this:
	$ xwd | python xwdtops.py | lpr
.. it should print a greyscale rendition of the clicked window to the default
printer, if it accepts postscript.

It's been quite awhile since I wrote this program (and later re-wrote it
in C because it's a bit slow), so I'm not really familiar with this code
anymore.  However, I do believe that it works on common 16 and 32-bit X
displays.

One more thing --- if you have imagemagick installed, you may want to consider
using its command "import" instead.  Instead of the xwd format, it can write
the image in many formats, instead of just xwd.

Jeff

#-----------------------------------------------------------------------
import struct, sys

print "%!PS-Adobe-1.0"
def get_shift(n):
    for i in range(32):
        if n & (1<<i):
            return i

def struct_read(f, fmt):
    sz = struct.calcsize(fmt)
    return struct.unpack(fmt, f.read(sz))

header_format = "!25I"
color_format = "!IHHHBB"

header_size = struct.calcsize(header_format)

header = struct_read(sys.stdin, header_format)

(header_size1, file_version, pixmap_format, pixmap_depth, pixmap_width, 
 pixmap_height, xoffset, byte_order, bitmap_unit, bitmap_bit_order,
 bitmap_pad, bits_per_pixel, bytes_per_line, visual_class, red_mask,
 green_mask, blue_mask, bits_per_rgb, colormap_entries, ncolors,
 window_width, window_height, window_x, window_y, window_bdrwidth) = header

if file_version != 7:
    raise ValueError, "Cannot parse file version %d (only 7)" % file_version
if pixmap_format != 2:
    raise ValueError, "Cannot parse pixel format %d (only ZPixmap, 2)" % pixel_format

window_name = sys.stdin.read(header[0]-100)[:-1] # discard terminating NUL

print "% Undumping", window_name


colors = {}
for i in range(colormap_entries):
    color = struct_read(sys.stdin, color_format)
    colors[color[0]] = color

rest = sys.stdin.read()

rs = get_shift(red_mask)
gs = get_shift(green_mask)
bs = get_shift(blue_mask)

rsc = .299*256/(red_mask >> rs)
gsc = .587*256/(green_mask >> gs)
bsc = .114*256/(blue_mask >> bs)

print "%", red_mask, green_mask, blue_mask
print "%", rs, gs, bs
print "%", rsc, gsc, bsc
print "%", bits_per_pixel
wscale = 558./window_width
hscale = 720./window_height
scale = min(1, wscale, hscale)

rwscale = 558./window_height
rhscale = 720./window_width
rscale = min(1, rwscale, rhscale)
print "% scale -", scale, rscale

print "/Helvetica findfont 16 scalefont setfont"
print "18 756 moveto"
print "(%s) show" % " ".join(sys.argv[1:]) or window_name

if scale < rscale:
    scale = rscale
    #print "%d %d translate" % (window_height*scale+18, 36)
    print "%d %d translate" % (8.5*72, 0)
    print "90 rotate"
    print "18 %d translate" % (594-window_height*scale) # 8.25"
    sz = 8.5*72
else:
    print "18 %d translate" % (750-window_height*scale) # 10.5"
    sz = 11*72

print "%d %d scale" % (window_width*scale, window_height*scale)

print "/picstr %d string def" % window_width

bytes_per_pixel = (bits_per_pixel+7)/8
row_format = "%c%d%c" % ("<>"[byte_order],
                        window_width,
                        "HI"[bits_per_pixel > 16])
print "%", row_format, bytes_per_line, bytes_per_pixel*window_width
print "%", len(rest)

print "%d %d 8 [%d 0 0 %d 0 0] {currentfile picstr readhexstring pop } image" % (window_width, window_height, window_width, window_height)

if 0:
    print "00"* window_width
    for row in range(window_height-2):
        print "00" + "c0" * (window_width-2) + "00"
    print "00"* window_width
else:
    for row in range(window_height-1, -1, -1):
        a = row * bytes_per_line
        b = a + bytes_per_pixel*window_width
        for pixel in struct.unpack(row_format, rest[a:b]):
            r = (pixel & red_mask) >> rs
            g = (pixel & green_mask) >> gs
            b = (pixel & blue_mask) >> bs
            gray = int(rsc*r+gsc*g+bsc*b)
            sys.stdout.write("%02x" % gray)
        sys.stdout.write("\n")
print
print "showpage"
#-----------------------------------------------------------------------
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 196 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/python-list/attachments/20051031/0439bfb6/attachment.sig>


More information about the Python-list mailing list