Hi all, I'm trying to create an XImage that represents a rectangular portion of a Window (because I need to be able to access the actual pixel values). My experimentations show that if the source window has an hidden region (overlapping window) and if the origin of the rectangle I query is not (0, 0), then the data is corrupted, resulting in pixels set to 0 in the image data (and a black area in the XImage).
I use a raw XGetImage. The XImage data is indeed corrupted. And if, as it is demonstrated in the following code, I draw the image on a Drawable, there is an invalid black area. I'm attaching a sample code at this end of this message. It clearly reproduces my problem. Can someone spot what I'm doing wrong? I'm quite sure I'm not using the X lib properly. The useful part of my xdpyinfo indicates: name of display: localhost:10.0 version number: 11.0 vendor string: The X.Org Foundation vendor release number: 11500000 X.Org version: 1.15.0 maximum request size: 16777212 bytes motion buffer size: 256 bitmap unit, bit order, padding: 32, LSBFirst, 32 image byte order: LSBFirst number of supported pixmap formats: 6 supported pixmap formats: depth 1, bits_per_pixel 1, scanline_pad 32 depth 4, bits_per_pixel 8, scanline_pad 32 depth 8, bits_per_pixel 8, scanline_pad 32 depth 16, bits_per_pixel 16, scanline_pad 32 depth 24, bits_per_pixel 32, scanline_pad 32 depth 32, bits_per_pixel 32, scanline_pad 32 keycode range: minimum 8, maximum 255 focus: window 0x800022, revert to PointerRoot number of extensions: 22 BIG-REQUESTS DAMAGE DOUBLE-BUFFER DPMS GLX Generic Event Extension MIT-SCREEN-SAVER MIT-SHM RANDR RECORD RENDER SGI-GLX SHAPE SYNC VNC-EXTENSION X-Resource XC-MISC XFIXES XInputExtension XKEYBOARD XTEST XVideo default screen number: 0 number of screens: 1 screen #0: dimensions: 1280x640 pixels (339x169 millimeters) resolution: 96x96 dots per inch depths (7): 1, 4, 8, 16, 24, 32, 24 root window id: 0xdc depth of root window: 24 planes number of colormaps: minimum 1, maximum 1 default colormap: 0x20 default number of colormap cells: 256 preallocated pixels: black 0, white 16777215 options: backing-store NO, save-unders NO largest cursor: 1280x640 current input event mask: 0x520004 ButtonPressMask StructureNotifyMask SubstructureRedirectMask PropertyChangeMask number of visuals: 64 default visual id: 0x21 ... visual: visual id: 0x21 class: TrueColor depth: 24 planes available colormap entries: 256 per subfield red, green, blue masks: 0xff0000, 0xff00, 0xff significant bits in color specification: 8 bits Thanks a lot for your help! Fabien --------- Sample code follows --------- /* * Compilation: * gcc -o xcopy xcopy.c -I/usr/include/X11 -L/usr/X11/lib -lX11 * * Usage: * This app displays three top windows: * - "XCopy": the mainWindow, with a white background * - "Image": the imageWindow, where images are displayed * - "Overlap": transient for mainWindow, and meant to create * a covered area on mainWindow. * * Press the left mouse button in "Image". This will copy the center * area of mainWindow (with a margin of 'margin') into imageWindow. * Note that there is a black stripe, that looks as large as 'margin', * to the right side of the generated image. * 'mainWindow' and 'imageWindow' are aligned to it is easier to * see the problem (the image is larger than it should be). * * Press 'q' in any window to quit. */ #include <X11/Xlib.h> #include <X11/Xutil.h> #include <stdio.h> #include <stdlib.h> /* Global variables */ Display* display; Window mainWindow; Window imageWindow; Window overlapWindow; static const unsigned int windowSize = 200; /* If margin is 0 (the whole source window is copied) then the problem disappears */ static const int margin = 15; /* ---------------------------------------------------------------------- */ void OnCopyWindow() { /* Erase the entire image window */ XClearWindow(display, imageWindow); /* * Copy the center of the mainWindow area into * imageWindow, using an XImage. */ unsigned int imageSize = windowSize-2*margin; XImage* image = XGetImage(display, mainWindow, margin, margin, imageSize, imageSize, AllPlanes, ZPixmap); GC gc = XCreateGC(display, imageWindow, 0, 0); XPutImage(display, imageWindow, gc, image, 0, 0, 0, 0, imageSize, imageSize); XFreeGC(display, gc); XDestroyImage(image); } /* ====================================================================== */ main() { /* Initialize everything */ display = XOpenDisplay((char*)0); int screen = DefaultScreen(display); XSetWindowAttributes setwinattr; XSizeHints* hints = XAllocSizeHints(); /* * Main window */ setwinattr.background_pixel = WhitePixel(display, screen); setwinattr.border_pixel = BlackPixel(display, screen); mainWindow = XCreateWindow(display, XRootWindow(display, screen), 0, 0, windowSize, windowSize, 0, DefaultDepth(display, screen), InputOutput, DefaultVisual(display, screen), CWBackPixel | CWBorderPixel, &setwinattr); XSetStandardProperties(display, mainWindow, "XCopy", "", None, NULL, 0, NULL); XSelectInput(display, mainWindow, KeyReleaseMask); hints->x = 0; hints->y = 0; hints->width = windowSize; hints->height = windowSize; hints->flags = USPosition | PSize; XSetWMNormalHints(display, mainWindow, hints); XMapWindow(display, mainWindow); /* * Target 'image' window (moved to the bottom of mainWindow) */ setwinattr.background_pixel = 0x808080; setwinattr.border_pixel = BlackPixel(display, screen); imageWindow = XCreateWindow(display, XRootWindow(display, screen), margin, windowSize+30, windowSize-2*margin, windowSize-2*margin, 0, DefaultDepth(display, screen), InputOutput, DefaultVisual(display, screen), CWBackPixel | CWBorderPixel, &setwinattr); XSetStandardProperties(display, imageWindow, "Image", "", None, NULL, 0, NULL); XSelectInput(display, imageWindow, ButtonPressMask|ButtonReleaseMask|KeyReleaseMask); hints->x = margin; hints->y = windowSize+30; hints->width = windowSize-2*margin; hints->height = windowSize-2*margin; hints->flags = USPosition | PSize; XSetWMNormalHints(display, imageWindow, hints); XMapWindow(display, imageWindow); /* * Overlapping window, on top of mainWindow */ setwinattr.background_pixel = 0xFF0000; setwinattr.border_pixel = BlackPixel(display, screen); overlapWindow = XCreateWindow(display, XRootWindow(display, screen), windowSize>>2, windowSize>>2, windowSize>>1, windowSize>>1, 0, DefaultDepth(display, screen), InputOutput, DefaultVisual(display, screen), CWBackPixel|CWBorderPixel, &setwinattr); XSetStandardProperties(display, overlapWindow, "Overlap", "", None, NULL, 0, NULL); XSelectInput(display, overlapWindow, KeyReleaseMask); hints->x = windowSize>>2; hints->y = windowSize>>2; hints->width = windowSize>>1; hints->height = windowSize>>1; hints->flags = USPosition | PSize; XSetWMNormalHints(display, overlapWindow, hints); /* Make it transient for mainWindow */ XSetTransientForHint(display, overlapWindow, mainWindow); /* If overlapWindow is NOT mapped, the problem disappears */ XMapWindow(display, overlapWindow); XFree(hints); /* * Main loop */ while(1) { XEvent event; XNextEvent(display, &event); switch (event.type) { case KeyRelease: { KeySym keysym; char key[64]; int keyCount = XLookupString(&event.xkey, key, 64, &keysym, 0); if (keyCount > 0) { if ((keyCount == 1) && (key[0] == 'q')) { XDestroyWindow(display, overlapWindow); XDestroyWindow(display, imageWindow); XDestroyWindow(display, mainWindow); XCloseDisplay(display); exit(0); } } } break; case ButtonRelease: if (event.xbutton.window == imageWindow) { OnCopyWindow(); } break; } } }
_______________________________________________ xorg@lists.x.org: X.Org support Archives: http://lists.freedesktop.org/archives/xorg Info: https://lists.x.org/mailman/listinfo/xorg Your subscription address: %(user_address)s