12 Replies - 6117 Views - Last Post: 15 January 2011 - 09:11 AM Rate Topic: -----

#1 LivingNightmare  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 21
  • View blog
  • Posts: 129
  • Joined: 07-July 10

XLib Image/Pixmap Problems

Posted 13 January 2011 - 08:35 AM

Hello all,

This is my first time using a graphics library and not just making command-line programs, and I'm having a bit of difficulty trying to use an image as a sprite. First of all, I made this picture with GIMP, and then I saved it as a XWindow Pixmap. Then, when I was looking into using that file as a sprite, I found that (from here: http://www.kerguelen...utorial-4.html) "Reading pixmaps from files and writing them to files is not possible with standard X libraries. For that, you need the Xpm library, which is installed by default on many systems." So I got stuck...

So then, I looked into the XImage structure (http://tronche.com/gui/x/xlib/utilities/XCreateImage.html) - I got that working... somewhat, but when I put the image on the screen, the color is all messed up. (I tried this saving my image as both a .h file or a pixmap file with GIMP). At first I thought it's because my image was fairly complex, so I tried using a basic 16x16 simple triangle with a few different colors, but again, the color was all messed up with using XPutImage. (By 'color all messed up', I mean that all of the pixels were the wrong color, and that the image didn't really appear well in the window).

I'm having a hard time finding resources about this online, and I was wondering if anyone could provide me a snippet that shows me how to take an image and place it on the screen (with proper color), and explain how it works.

I've attached the original image I was trying to get up on the screen (for testing purposes... wasn't going to use this as a sprite).

On a different note, I had another question. For the assignment I'm working on, we're working on this type of tower defense game. So I was thinking that when the using clicks on one of their towers, that it would show them it's radius in this somewhat transparent color... but I have no idea how to apply transparency with Xlib. (The same goes for the enemies life bar). Could somewhat tell me which functions I have to look at in order to accomplish this?

Thanks!

L.N

Attached image(s)

  • Attached Image

This post has been edited by LivingNightmare: 13 January 2011 - 08:37 AM


Is This A Good Question/Topic? 0
  • +

Replies To: XLib Image/Pixmap Problems

#2 anonymous26  Icon User is offline

  • D.I.C Lover

Reputation: 0
  • View blog
  • Posts: 3,638
  • Joined: 26-November 10

Re: XLib Image/Pixmap Problems

Posted 13 January 2011 - 10:15 AM

I don't know Xlib, but regarding your image it would appear that you have saved it with different attributes. Have you saved as 32-bit RGBA for instance when something else was expected?
Was This Post Helpful? 0
  • +
  • -

#3 LivingNightmare  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 21
  • View blog
  • Posts: 129
  • Joined: 07-July 10

Re: XLib Image/Pixmap Problems

Posted 13 January 2011 - 12:52 PM

I don't remember reading a specific requirement of the sort, so I'll say no... but I'm not 100% sure. I've tried exporting it as a few different file formats, but I get garbage colors either way.

L.N
Was This Post Helpful? 0
  • +
  • -

#4 anonymous26  Icon User is offline

  • D.I.C Lover

Reputation: 0
  • View blog
  • Posts: 3,638
  • Joined: 26-November 10

Re: XLib Image/Pixmap Problems

Posted 13 January 2011 - 12:58 PM

Have a double-check. You won't know if that is the problem until you are sure. :)
Was This Post Helpful? 0
  • +
  • -

#5 LivingNightmare  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 21
  • View blog
  • Posts: 129
  • Joined: 07-July 10

Re: XLib Image/Pixmap Problems

Posted 13 January 2011 - 01:07 PM

Do you know how I can check that in GIMP? - I don't see an option like it anywhere... just a file format (like pixmap for example). One's thing for sure is that I can't find a requirement like that in the documentation I have for Xlib. I just know that I need a pixmap file, or an exported .h file with the pixels in a character array. GIMP does that automatically if you export the file into a .h file.

L.N

This post has been edited by LivingNightmare: 13 January 2011 - 01:16 PM

Was This Post Helpful? 0
  • +
  • -

#6 anonymous26  Icon User is offline

  • D.I.C Lover

Reputation: 0
  • View blog
  • Posts: 3,638
  • Joined: 26-November 10

Re: XLib Image/Pixmap Problems

Posted 13 January 2011 - 01:19 PM

I don't have GIMP installed, but the usual method is to load the image and check its properties in the 'file' menu.
Was This Post Helpful? 0
  • +
  • -

#7 skyhawk133  Icon User is offline

  • Head DIC Head
  • member icon

Reputation: 1868
  • View blog
  • Posts: 20,280
  • Joined: 17-March 01

Re: XLib Image/Pixmap Problems

Posted 13 January 2011 - 02:01 PM

Post your Gimp question in the Graphic Design forum. The XLib question is still a valid one for Game Programming, so I don't want to move your whole thread.
Was This Post Helpful? 0
  • +
  • -

#8 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon

Reputation: 5800
  • View blog
  • Posts: 12,635
  • Joined: 16-October 07

Re: XLib Image/Pixmap Problems

Posted 13 January 2011 - 02:09 PM

Open it up in gimp, save as .xpm. If you were too look in the file with a text editor, you'd see something like:
/* XPM */
static char * foo_xpm[] = {
"720 720 47301 3",
"   	c #060C0C",
".  	c #0A1010",



Yes, it's actually C code. It's probably the easiest graphic resource to embed in a program. Of course, XLib is a bloody nightmare...


Here's some quick sample code that worked for me:
// compile with
// gcc -lX11 -lXpm t.c

#include <stdlib.h>
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/xpm.h>
#include "foo.xpm"
// yes, really, just throw the file in

#define W_WIDTH 800
#define W_HEIGHT 800

int showImage(Display *dis, Window win, char *xpm[]) {
	XImage *img;
	if (XpmCreateImageFromData (dis, xpm, &img, NULL, NULL)) {
		fprintf(stderr, "Can't read image.\n");
		return 0;
	} else {
		int x = (W_WIDTH - img->width)/2;
		int y = (W_HEIGHT - img->height)/2;
		GC gc = XCreateGC(dis, win, 0, NULL);
		XPutImage(dis, win, gc, img, 0, 0, x, y, img->width, img->height );
		XFreeGC(dis, gc);
		return 1;
	}
}

int main() {
	Display *dis = XOpenDisplay(NULL);
	int blackColor = BlackPixel(dis, DefaultScreen(dis));

	Window win = XCreateSimpleWindow(dis, DefaultRootWindow(dis), 0, 0, W_WIDTH, W_HEIGHT, 0, blackColor, blackColor);
	XSelectInput(dis, win, StructureNotifyMask);
	XMapWindow(dis, win);

	for(;;)/> {
		XEvent e;
		XNextEvent(dis, &e);
		if (e.type == MapNotify) { break; }
	}

	if (showImage(dis, win, foo_xpm)) {
		XFlush(dis);
		getchar();
	}
	return 0;
}



Hope this helps.
Was This Post Helpful? 2
  • +
  • -

#9 LivingNightmare  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 21
  • View blog
  • Posts: 129
  • Joined: 07-July 10

Re: XLib Image/Pixmap Problems

Posted 13 January 2011 - 02:56 PM

Sadly, I don't have the X11/xpm.h file since it's not part of our programming environment. I was hoping it would be possible to do this with just the standard X11 files? I keep getting the error: "user@AndroidDevVM:~/CS349/A1/Project$ gcc -lX11 -lXpm test.c test.c:7: fatal error: X11/xpm.h: No such file or directory - compilation terminated."

Which is why I started looking at the XImage structure, hoping that there would be a way around this. So what I did was use GIMP to export the file as follows (see attached), hoping I would be able too at least use XCreateImage and XPutImage. But this is where I got the colour related issues. I was also hoping to use a pixmap as a way to use the double buffer technique to draw things on the screen, but it looks like I'll have to adapt it to an XImage.

Any advice?

Also: To ButchDean, I checked the image file properties, and it says that the colour space is "RGB Colour".

L.N

EDIT: Attached a different .h file, since the one for the image above was too big. So this is just a quick picture I made for testing purposes. Right now, I have something like this for the attached image:

        int screen, depth;
        XImage* xi;
        Visual* v;

        GC gc = XCreateGC(display, window, 0, 0);
        screen = DefaultScreen(display);
        v = DefaultVisual(display, screen);
        depth = DefaultDepth(display, screen);
        xi = XCreateImage(display, v, depth, ZPixmap, 0, header_data, 16, 16, 16, 0);
        XPutImage(display, window, gc, xi, 0, 0, 0, 0, 16, 16);

Attached File(s)

  • Attached File  Ship.txt (1.56K)
    Number of downloads: 149

This post has been edited by LivingNightmare: 13 January 2011 - 03:13 PM

Was This Post Helpful? 0
  • +
  • -

#10 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon

Reputation: 5800
  • View blog
  • Posts: 12,635
  • Joined: 16-October 07

Re: XLib Image/Pixmap Problems

Posted 14 January 2011 - 05:58 AM

Unfortunate.

The problem with your file is that is really only offers the ability to include once. There are a few ways to tinker with it. But for an example, we'll stick to one file.

Perhaps:
// compile with
// gcc -lX11 t2.c

#include <stdlib.h>
#include <stdio.h>
#include <X11/Xlib.h>

#define W_WIDTH 200
#define W_HEIGHT 200

typedef struct {
	unsigned int width, height;
	unsigned char *pixel_data;
} RawImage;

const RawImage Ship = {
	16,16,
	"!!!!!!!!!!!!!!!!!!!!````!!!!!!!!!!!!!!!!````!!!!!!!!!!!!!!!!!!!!"
	"!!!!`Q!!`Q!!`Q!!`Q!!!!!!!!!!``]!``]!!!!!!!!!`Q!!`Q!!`Q!!`Q!!!!!!"
	"````!!!!!!!!`Q!!`Q!!`Q!!!!!!!!!!!!!!!!!!`Q!!`Q!!`Q!!!!!!!!!!````"
	"````!!!!`Q!!!!!!`Q!!`Q!!!!!!!!!!!!!!!!!!`Q!!`Q!!!!!!`Q!!!!!!````"
	"````````!!!!`Q!!!!!!`Q!!`Q!!!!!!!!!!`Q!!`Q!!!!!!`Q!!!!!!````````"
	"````````!!!!`Q!!`Q!!!!!!`Q!!!!!!!!!!`Q!!!!!!`Q!!`Q!!!!!!````````"
	"````````````!!!!!!$``Q!!!!!!Q-$!Q-$!!!!!`Q!!!!$`!!!!````````````"
	"````````````!!!!!!$`!!!!Q-$!!!!!!!!!Q-$!!!!!!!$`!!!!````````````"
	"````````````````!!!!!!!!Q-$!!!!!!!!!Q-$!!!!!!!!!````````````````"
	"````````````````!!!!!!$`!!!!Q-$!Q-$!!!!!!!$`!!!!````````````````"
	"````````````````````!!!!!!$`!!!!!!!!!!$`!!!!````````````````````"
	"````````````````````!!!!Q-$!!!$`!!$`Q-$!!!!!````````````````````"
	"````````````````````````!!!!Q-$!Q-$!!!!!````````````````````````"
	"````````````````````````!!!!Q-$!Q-$!!!!!````````````````````````"
	"````````````````````````````!!!!!!!!````````````````````````````"
	"````````````````````````````!!!!!!!!````````````````````````````"
	""
};

XImage *CreateImageFromRawImage(Display *dis, Window win, const RawImage *ri) {
	int screen_number = XDefaultScreen(dis);
	return XCreateImage (dis, 
		XDefaultVisual(dis, screen_number),
		XDefaultDepth(dis, screen_number), 
		ZPixmap, 0, ri->pixel_data, ri->width, ri->height,
		32, 0);
}

int showImageFromRaw(Display *dis, Window win, const RawImage *ri) {
	XImage *img = CreateImageFromRawImage(dis, win, ri);
	if (img==NULL) {
		fprintf(stderr, "Can't create image.\n");
		return 0;
	} else {
		int x = (W_WIDTH - img->width)/2;
		int y = (W_HEIGHT - img->height)/2;
		GC gc = XCreateGC(dis, win, 0, NULL);
		XPutImage(dis, win, gc, img, 0, 0, x, y, img->width, img->height );
		XFreeGC(dis, gc);
		return 1;
	}
}

int main() {
	Display *dis = XOpenDisplay(NULL);
	int blackColor = BlackPixel(dis, DefaultScreen(dis));

	Window win = XCreateSimpleWindow(dis, DefaultRootWindow(dis), 0, 0, W_WIDTH, W_HEIGHT, 0, blackColor, blackColor);
	XSelectInput(dis, win, StructureNotifyMask);
	XMapWindow(dis, win);

	for(;;)/> {
		XEvent e;
		XNextEvent(dis, &e);
		if (e.type == MapNotify) { break; }
	}

	if (showImageFromRaw(dis, win, &Ship)) {
		XFlush(dis);
		getchar();
	}
	return 0;
}


Was This Post Helpful? 1
  • +
  • -

#11 LivingNightmare  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 21
  • View blog
  • Posts: 129
  • Joined: 07-July 10

Re: XLib Image/Pixmap Problems

Posted 14 January 2011 - 03:48 PM

Hmm, I think I understand what's happening somewhat - but I'm still a bit confused about color. Say I had a depth of 32, meaning 32 bits per pixel right? How would I pass that to XCreateImage? Since XCreateImage takes a char* ... meaning that there can only be 8 bits per pixel... so 0x00 to 0xff. But that only represents 256 colors right?

I'm a bit confused, because the colors of my ship look different when I open it up on GIMP, then they do when I try it with your code. And from my understanding (which must be incorrect), XCreateImage can only create images using 256 colors. :\ -

I looked at the xpm file format, and i noticed that it mapped a character (or multiple characters), to a 0x???????? color code (or even colors with more bits than that). So all of this makes it very hard for me to understand what's happening here :(

Do you think that you could explain this to me? - It's really appreciated :)

EDIT: I realized after that to set a mask, that XClipMask requires a Pixmap and not an Image.... so now I'm really confused :(

L.N

This post has been edited by LivingNightmare: 14 January 2011 - 04:51 PM

Was This Post Helpful? 0
  • +
  • -

#12 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon

Reputation: 5800
  • View blog
  • Posts: 12,635
  • Joined: 16-October 07

Re: XLib Image/Pixmap Problems

Posted 15 January 2011 - 08:31 AM

Ok, I messed with this, probably way too much.

I exported my own image. Figured out how you did it; save as with .h extension.

I couldn't figure out exactly what was up. I ultimately got an image, but the colors were off. In annoyance, I wrote this:
#include <stdlib.h>
#include <stdio.h>
#include <X11/Xlib.h>

#define IMG_FROM_HEAD

#ifdef IMG_FROM_HEAD
// compile with
// gcc -lX11 test.c

XImage *getTestImage(Display *dis) {
#include "hagrid.h"
	int i, screen_number = XDefaultScreen(dis);
	
	char *src, *dst, *buff = malloc(width * height * 4 + 1);
	dst = buff;
	src = header_data;
	for(i=width * height; i>0; i--) {
		int temp;
		HEADER_PIXEL(src,dst);
		// they're in the wrong bloody order!
		temp = dst[0]; dst[0] = dst[2]; dst[2] = temp;
		
		// last is 0
		dst[3] = 0;
		dst += 4;
		// dst += 3;
	}
	
	XImage *img = XCreateImage (dis, 
		XDefaultVisual(dis, screen_number),
		XDefaultDepth(dis, screen_number), 
		ZPixmap, 0, buff, width, height,
		32, 0);
	
	//free(buff);
	return img;
}

#endif

#ifdef IMG_FROM_XPM
// compile with
// gcc -lX11 -lXpm test.c
#include <X11/xpm.h>
#include "hagrid.xpm"

XImage *getTestImage(Display *dis) {
	XImage *img;
	if (XpmCreateImageFromData (dis, hagrid_xpm, &img, NULL, NULL)) {
		return NULL;
	}
	return img;
}
#endif



int main() {
	showImage(300, 300);
}


void dumpXImageInfo(XImage *img) {
	int i, sampleSize = 10;
	printf("XImage img = {\n");
	printf("%d, %d, /* size of image */\n", img->width, img->height);
	printf("%d, /* number of pixels offset in X direction */\n", img->xoffset);
	printf("%d, /* XYBitmap, XYPixmap, ZPixmap */\n", img->format);
	printf("\"");
	
	for(i=0; i<sampleSize; i++) {
		printf("\\x%x", img->data[i]);
	}
	printf("...\", /* pointer to image data */\n", img->format);
	
	printf("%d, /* data byte order, LSBFirst, MSBFirst */\n", img->byte_order);
	printf("%d, /* quant. of scanline 8, 16, 32 */\n", img->bitmap_unit);
	printf("%d, /* LSBFirst, MSBFirst */\n", img->bitmap_bit_order);
	printf("%d, /* 8, 16, 32 either XY or ZPixmap */\n", img->bitmap_pad);
	printf("%d, /* depth of image */\n", img->depth);
	printf("%d, /* accelerator to next scanline */\n", img->bytes_per_line);
	printf("%d, /* bits per pixel (ZPixmap) */\n", img->bits_per_pixel);
	printf("%lu, /* bits in z arrangement */\n", img->red_mask);
	printf("%lu,\n", img->green_mask);
	printf("%lu,\n", img->blue_mask);
	printf("};\n\n");
}

void waitForEvent(Display *d, Window win, long eventMask, long eventType) {
	XSelectInput(d, win, eventMask);
	for(;;)/> {
		XEvent e;
		XNextEvent(d, &e);
		if (e.type == eventType) { break; }
	}
}




int showImage(int winWidth, int winHeight) {
	Display *dis = XOpenDisplay(NULL);
	int color1 = BlackPixel(dis, DefaultScreen(dis));
	int retVal = 1;
	XImage *img;

	Window win = XCreateSimpleWindow(dis, DefaultRootWindow(dis), 0, 0, winWidth, winHeight, 0, color1, color1);
	XMapWindow(dis, win);
	
	waitForEvent(dis, win, StructureNotifyMask, MapNotify);

	img = getTestImage(dis);
	if (img==NULL) {
		fprintf(stderr, "Can't create image.\n");
	} else {
		int x = (winWidth - img->width)/2;
		int y = (winHeight - img->height)/2;
		GC gc = XCreateGC(dis, win, 0, NULL);
		XPutImage(dis, win, gc, img, 0, 0, x, y, img->width, img->height );
		XFreeGC(dis, gc);
		XFlush(dis);
		dumpXImageInfo(img);
		waitForEvent(dis, win, ButtonPressMask|ButtonReleaseMask, ButtonRelease);
		retVal = 0;
	}
	XDestroyWindow( dis, win );
	XCloseDisplay( dis );
	
	return retVal;
}



The lead me to the discovery, commented in code, that the byte order on the pixels was different! Now I have working code.

Step two is how in elegantly integrate that format into my code. It will work with one file, but what if I have more. My solution was some macro play an embedded includes.

Final test looks like so:
#include <stdlib.h>
#include <stdio.h>
#include <X11/Xlib.h>

XImage *getImageFromImageHeader(Display *dis, int width, int height, char *header_data, char **processed_data) {
	int screen_number = XDefaultScreen(dis);
	if (*processed_data==NULL) {
		char *pixel, *data = header_data;
		int i = width * height;
		*processed_data = pixel = malloc(i * 4 + 1);
		while(i-- > 0) {
			pixel[0] = ((((data[2] - 33) & 0x3) << 6) | ((data[3] - 33)));
			pixel[1] = ((((data[1] - 33) & 0xF) << 4) | ((data[2] - 33) >> 2));
			pixel[2] = (((data[0] - 33) << 2) | ((data[1] - 33) >> 4));
			pixel[3] = 0;
			data += 4;
			pixel += 4;
		}
	}
	return XCreateImage (dis, 
		XDefaultVisual(dis, screen_number), 
		XDefaultDepth(dis, screen_number),  
		ZPixmap, 0, 
		*processed_data, width, height, 
		32, 0);
}


#define IMG_HEAD_BEGIN(name) XImage * get_image_##name (Display *d) { \
	static char *processed_data = NULL;
#define IMG_HEAD_END return getImageFromImageHeader(d, width, height, header_data, &processed_data); }

IMG_HEAD_BEGIN(img1)
#include "hagrid.h"
IMG_HEAD_END

IMG_HEAD_BEGIN(img2)
#include "Ship.h"
IMG_HEAD_END


void waitForEvent(Display *d, Window win, long eventMask, long eventType) {
	XSelectInput(d, win, eventMask);
	for(;;)/> {
		XEvent e;
		XNextEvent(d, &e);
		if (e.type == eventType) { break; }
	}
}


int main() {
	const int winWidth = 300, winHeight = 300;
	
	Display *dis = XOpenDisplay(NULL);
	int color1 = BlackPixel(dis, DefaultScreen(dis));
	int retVal = 1;
	XImage *img1, *img2;

	Window win = XCreateSimpleWindow(dis, DefaultRootWindow(dis), 0, 0, winWidth, winHeight, 0, color1, color1);
	XMapWindow(dis, win);
	
	waitForEvent(dis, win, StructureNotifyMask, MapNotify);

	img1 = get_image_img1(dis);
	img2 = get_image_img2(dis);
	if (img1==NULL || img2==NULL) {
		fprintf(stderr, "Can't create image.\n");
	} else {
		GC gc = XCreateGC(dis, win, 0, NULL);
		XPutImage(dis, win, gc, img1, 0, 0, 0, (winHeight - img1->height), img1->width, img1->height );
		XPutImage(dis, win, gc, img2, 0, 0, 0, 0, img1->width, img1->height );
		XFreeGC(dis, gc);
		XFlush(dis);
		waitForEvent(dis, win, ButtonPressMask|ButtonReleaseMask, ButtonRelease);
		retVal = 0;
	}
	XDestroyWindow( dis, win );
	XCloseDisplay( dis );
	
	return retVal;
}



Hope that helps.

As to other adventures in XLib; you're on your own. As you've noted, available documentation is sad to non existent. I would recommend using a friendlier abstraction, Gtk, Qt, something with a support community.

Good luck.
Was This Post Helpful? 1
  • +
  • -

#13 LivingNightmare  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 21
  • View blog
  • Posts: 129
  • Joined: 07-July 10

Re: XLib Image/Pixmap Problems

Posted 15 January 2011 - 09:11 AM

Thank you so much for your help! :) - You have no idea how much it is appreciated. I would of never figured that out =( - And yes, I know that the documentation is beyond crap... but this is what we have to use for the assignment.

Thanks again! If I could +100 your posts, I would :D
L.N
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1