Corrupted XImage retrieved from a Window area

Fabien Lelaquais Fabien.Lelaquais at roguewave.com
Sat Jul 30 08:34:20 UTC 2016


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;
              }
    }
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.x.org/archives/xorg/attachments/20160730/8e9c3677/attachment-0001.html>


More information about the xorg mailing list