How do I access an XImage directly?
I am trying to access the pixels of an XImage without using XGetPixel
and XSetPixel. I created an XImage with the following code:
XImage* img = XGetImage(display, window, 0, 0, 256, 256, AllPlanes,
XYPixmap);
I can't figure out how to access the pixels directly. This is what I
have so far (it doesn't work):
int get_pixel(XImage* img, int x, int y) {
int pos = y * img->bytes_per_line + x;
int color = rgb(img->data[pos], img->data[pos+1], img->data[pos+2]);
return color;
}
Re: How do I access an XImage directly?
[email]nate@nate879.org[/email] wrote:[color=blue]
> I am trying to access the pixels of an XImage without using XGetPixel
> and XSetPixel. I created an XImage with the following code:
>
> XImage* img = XGetImage(display, window, 0, 0, 256, 256, AllPlanes,
> XYPixmap);
>
> I can't figure out how to access the pixels directly. This is what I
> have so far (it doesn't work):
>
> int get_pixel(XImage* img, int x, int y) {
> int pos = y * img->bytes_per_line + x;
> int color = rgb(img->data[pos], img->data[pos+1], img->data[pos+2]);
> return color;
> }[/color]
A few things to note:
XGetImage returns the image format in the client's byte order.
XCreateImage by default creates an XImage with the Display's byte order,
which may not match the client.
XPutImage will translate with ReformatImage internally if say the byte
order of the XImage is LSBFirst and you want to display remotely on an
MSBFirst display.
So with the endian constraints, you then have the different display
depths to handle.
For sanity sake let's start with a 24/32-bit per-pixel image/drawable
that you're using with XGetImage.
bytes = octets.
As I understand it, the bytes of the image may be in BGR or RGB, and
that's dependent on:
Visual *visual = DefaultVisual(display, DefaultScreen(display));
Visual is layed out like this:
unsigned long red_mask;
unsigned long green_mask;
unsigned long blue_mask;
So for my display with a LSBFirst (least significant byte first)
x86/IA-32 the Visual masks are:
red, green, blue masks: 0xff0000, 0xff00, 0xff
unsigned char *ptr = img->data + (y * img->bytes_per_line + 4 * x);
unsigned char r, g, b;
b = ptr[0];
g = ptr[1];
r = ptr[2];
This unportable code may give you the idea:
assert(sizeof(int) == 4);
unsigned char bytes[4] = { 0xff, 0xee, 0xee, 0xdd};
int i;
memcpy (&i, bytes, 4);
printf("i:%x i & 0xff: %x\n", i, i & 0xff);
Which displays on my system:
i:ddeeeeff i & 0xff: ff
For a 16 bit image you generally have 6 bits for green, 5 bits for red,
and 5 for blue. Green is more visually significant to the human eye, so
they have devoted an extra bit to it.
A 15 bit image is stored in 2 bytes, but has only 5 bits for each
individual color channel.
The Visual masks can tell you which colors are which by ANDing with the
appropriate value, after you construct a single value from the 2 bytes
by ORing and shifting.
If I were you, I'd ignore the 8 bit displays/drawables/images. They
tend to look awful these days when you use XGetImage/XPutImage with
them. The color management (dithering) for such displays is also
horrendously complicated. Be glad we live in more modern times.
If you get stuck, I suggest looking at the libX11 sources.
George