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