4. Image
在 GUI 介面下, 常会需要将一张图片直接 show 在视窗上, 像是 show 照片. Xlib 提供一些可以直接在 client 和 server 间传送影像(image)的函数, 以直接处理一张张的影像, 例如, 图形档. 在这提到的 image 相关函数, 都会使用 XImage 结构做为函数的输入参数. Xlib 在 client 端使用 XImage 描述影像资料, 当你要使用 Xlib 的函数处理影像资料时, 必需透过 XImage 进行操作. XImage 提供一个物件化的介面, 透过物件提供的函数, 我们可以相同的方式, 处理不同的影像资料.
--------------------------------------------------------------------------------
/*
* Data structure for "image" data, used by image manipulation routines.
*/
typedef struct _XImage {
int width, height; /* size of image */
int xoffset; /* number of pixels offset in X direction */
int format; /* XYBitmap, XYPixmap, ZPixmap */
char *data; /* pointer to image data */
int byte_order; /* data byte order, LSBFirst, MSBFirst */
int bitmap_unit; /* quant. of scanline 8, 16, 32 */
int bitmap_bit_order; /* LSBFirst, MSBFirst */
int bitmap_pad; /* 8, 16, 32 either XY or ZPixmap */
int depth; /* depth of image */
int bytes_per_line; /* accelarator to next line */
int bits_per_pixel; /* bits per pixel (ZPixmap) */
unsigned long red_mask; /* bits in z arrangment */
unsigned long green_mask;
unsigned long blue_mask;
XPointer obdata; /* hook for the object routines to hang on */
struct funcs { /* image manipulation routines */
struct _XImage *(*create_image)();
#if NeedFunctionPrototypes
int (*destroy_image) (struct _XImage *);
unsigned long (*get_pixel) (struct _XImage *, int, int);
int (*put_pixel) (struct _XImage *, int, int, unsigned long);
struct _XImage *(*sub_image)(struct _XImage *, int, int, unsigned int, unsigned int);
int (*add_pixel) (struct _XImage *, long);
#else
int (*destroy_image)();
unsigned long (*get_pixel)();
int (*put_pixel)();
struct _XImage *(*sub_image)();
int (*add_pixel)();
#endif
} f;
} XImage;
--------------------------------------------------------------------------------
XImage 可以建过 XInitImage 和 XCreateImage 建立. 建立之後的 object, 可以使用 XGetPixel, XPutPixel, XSubImage 和 XAddPixel 读取和修改内容. 使用 XPutImage 输出到 drawable (视窗或 pixmap), 使用 XGetImage 从 drawable 读取. object 最後必需使用 XDestroyImage 释放.
--------------------------------------------------------------------------------
Status XInitImage(image)
XImage *image;
--------------------------------------------------------------------------------
XImage 在使用之前, 必需先经过 XInitImage 进行 initialize. 在呼叫 XInitImage 之前, 除了 manipulate functions 之外, 其它的栏位都必需 先设定好. 成功的话, 传回非0值, 否则传回 0.
--------------------------------------------------------------------------------
XImage *XCreateImage(display, visual, depth, format, off-
set, data, width, height, bitmap_pad,
bytes_per_line)
Display *display;
Visual *visual;
unsigned int depth;
int format;
int offset;
char *data;
unsigned int width;
unsigned int height;
int bitmap_pad;
int bytes_per_line;
--------------------------------------------------------------------------------
XCreateImage 会为输入之影像资料产生一个 XImage 结构, 并传回结构. 是一个包装 XInitImage 的函数. 'format' 指定影像储存的形式, 有 ZPixmap, XYPixmap 和 XYBitmap. ZPixmap 的储存方式是一个 pixel 接 着一个 pixel 存放. XYPixmap 则是 plane 接着 plane, 将所有 pixel 特定 plane 的内容集成 bitmap, 然後依 plane 的顺序储存各 plane 形式的 bitmap. XYBitmap 和 XYPixmap 一样, 但是 XYBitmap只有一个 plane. 而, 影像的内容则存在 data 所指定的 memory block . 使用者必需指定一块记忆(data)以储存影像, XCreateImage 并不会主动为您配置. data 的大小和 image 的大小和深度(depth)有关, format 也会影响. 下面是 data 大小和 bytes_per_line 的计算公式.
format size of data bytes_per_line
ZPixmap width * height * ((depth + 7) / 8) width * ((depth + 7) / 8)
XYPixmap ((width + 7) / 8) * height * depth (width + 7) / 8
XYBitmap ((width + 7) / 8) * height * 1 (width + 7) / 8
--------------------------------------------------------------------------------
unsigned long XGetPixel(ximage, x, y)
XImage *ximage;
int x;
int y;
--------------------------------------------------------------------------------
取得影像内的一个图点.
--------------------------------------------------------------------------------
XPutPixel(ximage, x, y, pixel)
XImage *ximage;
int x;
int y;
unsigned long pixel;
--------------------------------------------------------------------------------
在影像上放上一个点.
--------------------------------------------------------------------------------
XImage *XSubImage(ximage, x, y, subimage_width,
subimage_height)
XImage *ximage;
int x;
int y;
unsigned int subimage_width;
unsigned int subimage_height;
--------------------------------------------------------------------------------
读取影像的一部分内容, 并传回 XImage. x, y, subimage_width, 和 subimage_height 指定 image 内的一个方框的位置和大小, 读 取方框内的资料.
--------------------------------------------------------------------------------
XAddPixel(ximage, value)
XImage *ximage;
long value;
--------------------------------------------------------------------------------
把 image 内每个点的 pixel 值都加上指定的 valuex.
--------------------------------------------------------------------------------
XDestroyImage(ximage)
XImage *ximage;
--------------------------------------------------------------------------------
由上面和下面各函数所产生的 XImage 物件, 最後不用时, 都要使用 XDestroyImage 释放掉。注意, XDestroyImage 会主动将 data 释放
--------------------------------------------------------------------------------
XPutImage(display, d, gc, image, src_x, src_y, dest_x,
dest_y, width, height)
Display *display;
Drawable d;
GC gc;
XImage *image;
int src_x, src_y;
int dest_x, dest_y;
unsigned int width, height;
--------------------------------------------------------------------------------
将 image 输出 'd' 所指定的 drawable.
--------------------------------------------------------------------------------
XImage *XGetImage(display, d, x, y, width, height,
plane_mask, format)
Display *display;
Drawable d;
int x, y;
unsigned int width, height;
unsigned long plane_mask;
int format;
--------------------------------------------------------------------------------
读取 'd' 所指定之 drawable 的影像. 'plane_mask' 指定要读取的 planes. 若指定的 planes, 为 drawable 所有 planes 的 subset, 那麽传回的 image 的 depth 将和指定的 planes 数目相同.
--------------------------------------------------------------------------------
XImage *XGetSubImage(display, d, x, y, width, height,
plane_mask, format, dest_image, dest_x,
dest_y)
Display *display;
Drawable d;
int x, y;
unsigned int width, height;
unsigned long plane_mask;
int format;
XImage *dest_image;
int dest_x, dest_y;
--------------------------------------------------------------------------------
下面是处理影像的例.
--------------------------------------------------------------------------------
/* -- Image-test.c -- */
#include
#include
#include
#include
#include
#include
#include "gnu.xpm"
#include "doomface.xpm"
#include "Boss2.xpm"
struct ColorElm {
char *tag;
unsigned long pixel;
};
unsigned long
get_pixel(Display *display, Colormap colormap, char *str)
{
char *cp = str;
XColor color, excolor;
if(*cp == '#') {
int j, k;
int t;
int rgbl;
unsigned short rgb[3];
cp++;
if(strlen(cp) == 6)
rgbl = 2;
else
rgbl = 4;
for(k = 0; k < 3; k++) {
t = 0;
for(j = 0; j < rgbl; j++) {
char c = *(cp++);
t <<= 4;
if(c >= 'A' && c <= 'F')
t += c - 'A' + 10;
else if(c >= 'a' && c <= 'f')
t += c - 'a' + 10;
else
t += c - '0';
}
rgb[k] = t;
}
color.red = rgb[0];
color.green = rgb[1];
color.blue = rgb[2];
color.flags = DoRed | DoGreen | DoBlue;
XAllocColor(display, colormap, &color);
} else {
char *cp;
if(strcasecmp(str, "None") == 0)
cp = "black";
else
cp = str;
XAllocNamedColor(display, colormap, cp, &color, &excolor);
}
return color.pixel;
}
/*
* 从 *.xpm 转换成 Xlib 能处理的 image 资料形式 (ZPixmap)
*/
char *
xpm_to_data(char **xpm, Display *display,
Colormap colormap, int depth, int *width, int *height)
{
int nc, el; /* # of color, and element length */
int i;
int bpp; /* byte per pixel */
struct ColorElm *ce, *cep;
unsigned short rgb[3];
XColor color;
char *data, *dp;
sscanf(*(xpm++), "%d %d %d %d", width, height, &nc, &el);
bpp = (depth + 7) / 8;
data = (char *)malloc(sizeof(char) * bpp *
*width * *height);
ce = (struct ColorElm *)malloc(sizeof(struct ColorElm) * nc);
cep = ce;
for(i = 0; i < nc; i++) {
char *cp;
cep->tag = (char *)malloc(sizeof(char) * el);
memcpy(cep->tag, *xpm, el);
cp = *xpm + el;
/*
* skip redundant character
*/
while(isspace(*cp)) cp++;
while(*(cp++) != 'c') {
while(isspace(*cp)) cp++;
while(!isspace(*cp)) cp++;
while(isspace(*cp)) cp++;
}
/*
* get pixel of color
*/
while(isspace(*cp)) cp++;
cep->pixel = get_pixel(display, colormap, cp);
cep++;
xpm++;
}
/*
* generate image data
*/
dp = data;
for(i = 0; i < *height; i++) {
int j;
char *p;
p = *(xpm++);
for(j = 0; j < *width; j++) {
int idx;
unsigned long pixel;
/*
* find pixel of point
*/
for(idx = 0; idx < nc; idx++)
if(!memcmp(p, ce[idx].tag, el)) {
memcpy(dp, &ce[idx].pixel, bpp);
break;
}
dp += bpp;
p += el;
}
}
free(ce);
return data;
}
main()
{
Display *display;
Window window;
XSetWindowAttributes attr;
Colormap colormap;
XColor color1, color2;
XGCValues gcvalue;
GC gc;
XSizeHints *sz;
XImage *img1, *img2, *img3;
int screen;
char *data; /* image data */
int w, h; /* width & height */
int bpp; /* byte per pixel */
display = XOpenDisplay("0:0");
colormap = DefaultColormap(display, screen = DefaultScreen(display));
color1.red = color1.blue = 0xffff;
color1.green = 0;
color2.red = color2.green = color2.blue = 0xff;
color1.flags = color2.flags = DoRed | DoGreen | DoBlue;
XAllocColor(display, colormap, &color1);
XAllocColor(display, colormap, &color2);
attr.background_pixel = color2.pixel;
window = XCreateWindow(display, XDefaultRootWindow(display),
100, 100, 500, 300, 2, XDefaultDepth(display, 0),
InputOutput, CopyFromParent, CWBackPixel, &attr);
XStoreName(display, window, "hello!! world!!");
sz = XAllocSizeHints();
sz->x = 100;
sz->y = 100;
sz->width = 300;
sz->height = 500;
sz->flags = USPosition | USSize;
XSetNormalHints(display, window, sz);
XMapWindow(display, window);
gc = XCreateGC(display, window, 0, &gcvalue);
XSetForeground(display, gc, color1.pixel);
XSetBackground(display, gc, color2.pixel);
XFlush(display);
printf("Show image!!\n");
bpp = (DefaultDepth(display, screen) + 7) / 8;
/*
* Create gnu.xpm
*/
data = xpm_to_data(image_name, display, colormap,
DefaultDepth(display, screen), &w, &h);
img1 = XCreateImage(display,
DefaultVisual(display, screen),
DefaultDepth(display, screen),
ZPixmap, 0, data,
w, h, 8, w * bpp);
/* (w, h) 是影像的宽和高 */
/*
* Create doomface.xpm
*/
data = xpm_to_data(xpm, display, colormap,
DefaultDepth(display, screen), &w, &h);
img2 = XCreateImage(display,
DefaultVisual(display, screen),
DefaultDepth(display, screen),
ZPixmap, 0, data,
w, h, 8, w * bpp);
/* (w, h) 是影像的宽和高 */
/*
* Create Boss2.xpm
*/
data = xpm_to_data(Boss2_xpm, display, colormap,
DefaultDepth(display, screen), &w, &h);
img3 = XCreateImage(display,
DefaultVisual(display, screen),
DefaultDepth(display, screen),
ZPixmap, 0, data,
w, h, 8, w * bpp);
/* (w, h) 是影像的宽和高 */
/*
* Show images
*/
XPutImage(display, window, gc, img1, 0, 0, 10, 10, w, h);
XPutImage(display, window, gc, img2, 0, 0, 10, 100, w, h);
XPutImage(display, window, gc, img3, 0, 0, 200, 50, w, h);
XFlush(display);
/*
* Destroy images
*/
XDestroyImage(img1);
XDestroyImage(img2);
XDestroyImage(img3);
sleep(3);
XDestroyWindow(display, window);
XFlush(display);
XCloseDisplay(display);
}
--------------------------------------------------------------------------------
执行结果
颜色和原图有些不同, 主要原因是使用 default 的 colormap. 上面的程式 在视窗显示三张 .xpm 的图形档, 分别是 gnu.xpm, doomface.xpm 和 Boss2.xpm.
5. 例
--------------------------------------------------------------------------------
/* ---- XGraph.c ---- */
#include
#include
#include
#include
main() {
Display *display;
Window window;
XSetWindowAttributes attr;
Colormap colormap;
XColor color1, color2;
XGCValues gcvalue;
GC gc;
XSizeHints *sz;
display = XOpenDisplay("0:0");
/* 取得预设之 colormap */
colormap = DefaultColormap(display,
DefaultScreen(display));
/* 取得 colorcell */
color1.red = color1.blue = 0xffff;
color1.green = 0;
color2.red = color2.green = color2.blue = 0xff;
color1.flags = color2.flags = DoRed | DoGreen | DoBlue;
XAllocColor(display, colormap, &color1);
XAllocColor(display, colormap, &color2);
/* 设定视窗的 attribute 和建设 */
attr.background_pixel = color2.pixel; /* 背景颜色 */
window = XCreateWindow(display,
XDefaultRootWindow(display), 100, 100, 300, 300,
2, XDefaultDepth(display, 0), InputOutput,
CopyFromParent, CWBackPixel, &attr);
/* 设定和 window manager 进行沟通 */
XStoreName(display, window, "hello!! world!!");
sz = XAllocSizeHints();
sz->x = 100;
sz->y = 100;
sz->width = 300;
sz->height = 300;
sz->flags = USPosition | USSize;
XSetNormalHints(display, window, sz);
/* 显示视窗 */
printf("Map window\n");
XMapWindow(display, window);
XFlush(display);
getchar();
/* 建立并设定 GC */
gc = XCreateGC(display, window, 0, &gcvalue);
XSetForeground(display, gc, color1.pixel);
XSetBackground(display, gc, color2.pixel);
/* 画一个矩形 */
printf("Draw rectangle\n");
XDrawRectangle(display, window, gc, 10, 10, 100, 100);
XFlush(display);
getchar();
/* 清除视窗 */
XClearWindow(display, window);
/* 设定 GC 内,线的形式 */
XSetLineAttributes(display, gc, 5, LineOnOffDash,
CapButt, JoinRound);
/* 画线 (200, 10) - (200, 290) */
printf("Draw line\n");
XDrawLine(display, window, gc, 200, 10, 200, 290);
XFlush(display);
getchar();
/* 关闭视窗 */
printf("Destory Window\n");
XDestroyWindow(display, window);
XFlush(display);
getchar();
printf("close display\n");
XCloseDisplay(display);
getchar();
}
--------------------------------------------------------------------------------
gcc -o XGraph XGraph.c -L/usr/X11R6/lib -lX11
--------------------------------------------------------------------------------
上面是一个简单的例程式和 compile 的方法。
在 GUI 介面下, 常会需要将一张图片直接 show 在视窗上, 像是 show 照片. Xlib 提供一些可以直接在 client 和 server 间传送影像(image)的函数, 以直接处理一张张的影像, 例如, 图形档. 在这提到的 image 相关函数, 都会使用 XImage 结构做为函数的输入参数. Xlib 在 client 端使用 XImage 描述影像资料, 当你要使用 Xlib 的函数处理影像资料时, 必需透过 XImage 进行操作. XImage 提供一个物件化的介面, 透过物件提供的函数, 我们可以相同的方式, 处理不同的影像资料.
--------------------------------------------------------------------------------
/*
* Data structure for "image" data, used by image manipulation routines.
*/
typedef struct _XImage {
int width, height; /* size of image */
int xoffset; /* number of pixels offset in X direction */
int format; /* XYBitmap, XYPixmap, ZPixmap */
char *data; /* pointer to image data */
int byte_order; /* data byte order, LSBFirst, MSBFirst */
int bitmap_unit; /* quant. of scanline 8, 16, 32 */
int bitmap_bit_order; /* LSBFirst, MSBFirst */
int bitmap_pad; /* 8, 16, 32 either XY or ZPixmap */
int depth; /* depth of image */
int bytes_per_line; /* accelarator to next line */
int bits_per_pixel; /* bits per pixel (ZPixmap) */
unsigned long red_mask; /* bits in z arrangment */
unsigned long green_mask;
unsigned long blue_mask;
XPointer obdata; /* hook for the object routines to hang on */
struct funcs { /* image manipulation routines */
struct _XImage *(*create_image)();
#if NeedFunctionPrototypes
int (*destroy_image) (struct _XImage *);
unsigned long (*get_pixel) (struct _XImage *, int, int);
int (*put_pixel) (struct _XImage *, int, int, unsigned long);
struct _XImage *(*sub_image)(struct _XImage *, int, int, unsigned int, unsigned int);
int (*add_pixel) (struct _XImage *, long);
#else
int (*destroy_image)();
unsigned long (*get_pixel)();
int (*put_pixel)();
struct _XImage *(*sub_image)();
int (*add_pixel)();
#endif
} f;
} XImage;
--------------------------------------------------------------------------------
XImage 可以建过 XInitImage 和 XCreateImage 建立. 建立之後的 object, 可以使用 XGetPixel, XPutPixel, XSubImage 和 XAddPixel 读取和修改内容. 使用 XPutImage 输出到 drawable (视窗或 pixmap), 使用 XGetImage 从 drawable 读取. object 最後必需使用 XDestroyImage 释放.
--------------------------------------------------------------------------------
Status XInitImage(image)
XImage *image;
--------------------------------------------------------------------------------
XImage 在使用之前, 必需先经过 XInitImage 进行 initialize. 在呼叫 XInitImage 之前, 除了 manipulate functions 之外, 其它的栏位都必需 先设定好. 成功的话, 传回非0值, 否则传回 0.
--------------------------------------------------------------------------------
XImage *XCreateImage(display, visual, depth, format, off-
set, data, width, height, bitmap_pad,
bytes_per_line)
Display *display;
Visual *visual;
unsigned int depth;
int format;
int offset;
char *data;
unsigned int width;
unsigned int height;
int bitmap_pad;
int bytes_per_line;
--------------------------------------------------------------------------------
XCreateImage 会为输入之影像资料产生一个 XImage 结构, 并传回结构. 是一个包装 XInitImage 的函数. 'format' 指定影像储存的形式, 有 ZPixmap, XYPixmap 和 XYBitmap. ZPixmap 的储存方式是一个 pixel 接 着一个 pixel 存放. XYPixmap 则是 plane 接着 plane, 将所有 pixel 特定 plane 的内容集成 bitmap, 然後依 plane 的顺序储存各 plane 形式的 bitmap. XYBitmap 和 XYPixmap 一样, 但是 XYBitmap只有一个 plane. 而, 影像的内容则存在 data 所指定的 memory block . 使用者必需指定一块记忆(data)以储存影像, XCreateImage 并不会主动为您配置. data 的大小和 image 的大小和深度(depth)有关, format 也会影响. 下面是 data 大小和 bytes_per_line 的计算公式.
format size of data bytes_per_line
ZPixmap width * height * ((depth + 7) / 8) width * ((depth + 7) / 8)
XYPixmap ((width + 7) / 8) * height * depth (width + 7) / 8
XYBitmap ((width + 7) / 8) * height * 1 (width + 7) / 8
--------------------------------------------------------------------------------
unsigned long XGetPixel(ximage, x, y)
XImage *ximage;
int x;
int y;
--------------------------------------------------------------------------------
取得影像内的一个图点.
--------------------------------------------------------------------------------
XPutPixel(ximage, x, y, pixel)
XImage *ximage;
int x;
int y;
unsigned long pixel;
--------------------------------------------------------------------------------
在影像上放上一个点.
--------------------------------------------------------------------------------
XImage *XSubImage(ximage, x, y, subimage_width,
subimage_height)
XImage *ximage;
int x;
int y;
unsigned int subimage_width;
unsigned int subimage_height;
--------------------------------------------------------------------------------
读取影像的一部分内容, 并传回 XImage. x, y, subimage_width, 和 subimage_height 指定 image 内的一个方框的位置和大小, 读 取方框内的资料.
--------------------------------------------------------------------------------
XAddPixel(ximage, value)
XImage *ximage;
long value;
--------------------------------------------------------------------------------
把 image 内每个点的 pixel 值都加上指定的 valuex.
--------------------------------------------------------------------------------
XDestroyImage(ximage)
XImage *ximage;
--------------------------------------------------------------------------------
由上面和下面各函数所产生的 XImage 物件, 最後不用时, 都要使用 XDestroyImage 释放掉。注意, XDestroyImage 会主动将 data 释放
--------------------------------------------------------------------------------
XPutImage(display, d, gc, image, src_x, src_y, dest_x,
dest_y, width, height)
Display *display;
Drawable d;
GC gc;
XImage *image;
int src_x, src_y;
int dest_x, dest_y;
unsigned int width, height;
--------------------------------------------------------------------------------
将 image 输出 'd' 所指定的 drawable.
--------------------------------------------------------------------------------
XImage *XGetImage(display, d, x, y, width, height,
plane_mask, format)
Display *display;
Drawable d;
int x, y;
unsigned int width, height;
unsigned long plane_mask;
int format;
--------------------------------------------------------------------------------
读取 'd' 所指定之 drawable 的影像. 'plane_mask' 指定要读取的 planes. 若指定的 planes, 为 drawable 所有 planes 的 subset, 那麽传回的 image 的 depth 将和指定的 planes 数目相同.
--------------------------------------------------------------------------------
XImage *XGetSubImage(display, d, x, y, width, height,
plane_mask, format, dest_image, dest_x,
dest_y)
Display *display;
Drawable d;
int x, y;
unsigned int width, height;
unsigned long plane_mask;
int format;
XImage *dest_image;
int dest_x, dest_y;
--------------------------------------------------------------------------------
下面是处理影像的例.
--------------------------------------------------------------------------------
/* -- Image-test.c -- */
#include
#include
#include
#include
#include
#include
#include "gnu.xpm"
#include "doomface.xpm"
#include "Boss2.xpm"
struct ColorElm {
char *tag;
unsigned long pixel;
};
unsigned long
get_pixel(Display *display, Colormap colormap, char *str)
{
char *cp = str;
XColor color, excolor;
if(*cp == '#') {
int j, k;
int t;
int rgbl;
unsigned short rgb[3];
cp++;
if(strlen(cp) == 6)
rgbl = 2;
else
rgbl = 4;
for(k = 0; k < 3; k++) {
t = 0;
for(j = 0; j < rgbl; j++) {
char c = *(cp++);
t <<= 4;
if(c >= 'A' && c <= 'F')
t += c - 'A' + 10;
else if(c >= 'a' && c <= 'f')
t += c - 'a' + 10;
else
t += c - '0';
}
rgb[k] = t;
}
color.red = rgb[0];
color.green = rgb[1];
color.blue = rgb[2];
color.flags = DoRed | DoGreen | DoBlue;
XAllocColor(display, colormap, &color);
} else {
char *cp;
if(strcasecmp(str, "None") == 0)
cp = "black";
else
cp = str;
XAllocNamedColor(display, colormap, cp, &color, &excolor);
}
return color.pixel;
}
/*
* 从 *.xpm 转换成 Xlib 能处理的 image 资料形式 (ZPixmap)
*/
char *
xpm_to_data(char **xpm, Display *display,
Colormap colormap, int depth, int *width, int *height)
{
int nc, el; /* # of color, and element length */
int i;
int bpp; /* byte per pixel */
struct ColorElm *ce, *cep;
unsigned short rgb[3];
XColor color;
char *data, *dp;
sscanf(*(xpm++), "%d %d %d %d", width, height, &nc, &el);
bpp = (depth + 7) / 8;
data = (char *)malloc(sizeof(char) * bpp *
*width * *height);
ce = (struct ColorElm *)malloc(sizeof(struct ColorElm) * nc);
cep = ce;
for(i = 0; i < nc; i++) {
char *cp;
cep->tag = (char *)malloc(sizeof(char) * el);
memcpy(cep->tag, *xpm, el);
cp = *xpm + el;
/*
* skip redundant character
*/
while(isspace(*cp)) cp++;
while(*(cp++) != 'c') {
while(isspace(*cp)) cp++;
while(!isspace(*cp)) cp++;
while(isspace(*cp)) cp++;
}
/*
* get pixel of color
*/
while(isspace(*cp)) cp++;
cep->pixel = get_pixel(display, colormap, cp);
cep++;
xpm++;
}
/*
* generate image data
*/
dp = data;
for(i = 0; i < *height; i++) {
int j;
char *p;
p = *(xpm++);
for(j = 0; j < *width; j++) {
int idx;
unsigned long pixel;
/*
* find pixel of point
*/
for(idx = 0; idx < nc; idx++)
if(!memcmp(p, ce[idx].tag, el)) {
memcpy(dp, &ce[idx].pixel, bpp);
break;
}
dp += bpp;
p += el;
}
}
free(ce);
return data;
}
main()
{
Display *display;
Window window;
XSetWindowAttributes attr;
Colormap colormap;
XColor color1, color2;
XGCValues gcvalue;
GC gc;
XSizeHints *sz;
XImage *img1, *img2, *img3;
int screen;
char *data; /* image data */
int w, h; /* width & height */
int bpp; /* byte per pixel */
display = XOpenDisplay("0:0");
colormap = DefaultColormap(display, screen = DefaultScreen(display));
color1.red = color1.blue = 0xffff;
color1.green = 0;
color2.red = color2.green = color2.blue = 0xff;
color1.flags = color2.flags = DoRed | DoGreen | DoBlue;
XAllocColor(display, colormap, &color1);
XAllocColor(display, colormap, &color2);
attr.background_pixel = color2.pixel;
window = XCreateWindow(display, XDefaultRootWindow(display),
100, 100, 500, 300, 2, XDefaultDepth(display, 0),
InputOutput, CopyFromParent, CWBackPixel, &attr);
XStoreName(display, window, "hello!! world!!");
sz = XAllocSizeHints();
sz->x = 100;
sz->y = 100;
sz->width = 300;
sz->height = 500;
sz->flags = USPosition | USSize;
XSetNormalHints(display, window, sz);
XMapWindow(display, window);
gc = XCreateGC(display, window, 0, &gcvalue);
XSetForeground(display, gc, color1.pixel);
XSetBackground(display, gc, color2.pixel);
XFlush(display);
printf("Show image!!\n");
bpp = (DefaultDepth(display, screen) + 7) / 8;
/*
* Create gnu.xpm
*/
data = xpm_to_data(image_name, display, colormap,
DefaultDepth(display, screen), &w, &h);
img1 = XCreateImage(display,
DefaultVisual(display, screen),
DefaultDepth(display, screen),
ZPixmap, 0, data,
w, h, 8, w * bpp);
/* (w, h) 是影像的宽和高 */
/*
* Create doomface.xpm
*/
data = xpm_to_data(xpm, display, colormap,
DefaultDepth(display, screen), &w, &h);
img2 = XCreateImage(display,
DefaultVisual(display, screen),
DefaultDepth(display, screen),
ZPixmap, 0, data,
w, h, 8, w * bpp);
/* (w, h) 是影像的宽和高 */
/*
* Create Boss2.xpm
*/
data = xpm_to_data(Boss2_xpm, display, colormap,
DefaultDepth(display, screen), &w, &h);
img3 = XCreateImage(display,
DefaultVisual(display, screen),
DefaultDepth(display, screen),
ZPixmap, 0, data,
w, h, 8, w * bpp);
/* (w, h) 是影像的宽和高 */
/*
* Show images
*/
XPutImage(display, window, gc, img1, 0, 0, 10, 10, w, h);
XPutImage(display, window, gc, img2, 0, 0, 10, 100, w, h);
XPutImage(display, window, gc, img3, 0, 0, 200, 50, w, h);
XFlush(display);
/*
* Destroy images
*/
XDestroyImage(img1);
XDestroyImage(img2);
XDestroyImage(img3);
sleep(3);
XDestroyWindow(display, window);
XFlush(display);
XCloseDisplay(display);
}
--------------------------------------------------------------------------------
执行结果
颜色和原图有些不同, 主要原因是使用 default 的 colormap. 上面的程式 在视窗显示三张 .xpm 的图形档, 分别是 gnu.xpm, doomface.xpm 和 Boss2.xpm.
5. 例
--------------------------------------------------------------------------------
/* ---- XGraph.c ---- */
#include
#include
#include
#include
main() {
Display *display;
Window window;
XSetWindowAttributes attr;
Colormap colormap;
XColor color1, color2;
XGCValues gcvalue;
GC gc;
XSizeHints *sz;
display = XOpenDisplay("0:0");
/* 取得预设之 colormap */
colormap = DefaultColormap(display,
DefaultScreen(display));
/* 取得 colorcell */
color1.red = color1.blue = 0xffff;
color1.green = 0;
color2.red = color2.green = color2.blue = 0xff;
color1.flags = color2.flags = DoRed | DoGreen | DoBlue;
XAllocColor(display, colormap, &color1);
XAllocColor(display, colormap, &color2);
/* 设定视窗的 attribute 和建设 */
attr.background_pixel = color2.pixel; /* 背景颜色 */
window = XCreateWindow(display,
XDefaultRootWindow(display), 100, 100, 300, 300,
2, XDefaultDepth(display, 0), InputOutput,
CopyFromParent, CWBackPixel, &attr);
/* 设定和 window manager 进行沟通 */
XStoreName(display, window, "hello!! world!!");
sz = XAllocSizeHints();
sz->x = 100;
sz->y = 100;
sz->width = 300;
sz->height = 300;
sz->flags = USPosition | USSize;
XSetNormalHints(display, window, sz);
/* 显示视窗 */
printf("Map window\n");
XMapWindow(display, window);
XFlush(display);
getchar();
/* 建立并设定 GC */
gc = XCreateGC(display, window, 0, &gcvalue);
XSetForeground(display, gc, color1.pixel);
XSetBackground(display, gc, color2.pixel);
/* 画一个矩形 */
printf("Draw rectangle\n");
XDrawRectangle(display, window, gc, 10, 10, 100, 100);
XFlush(display);
getchar();
/* 清除视窗 */
XClearWindow(display, window);
/* 设定 GC 内,线的形式 */
XSetLineAttributes(display, gc, 5, LineOnOffDash,
CapButt, JoinRound);
/* 画线 (200, 10) - (200, 290) */
printf("Draw line\n");
XDrawLine(display, window, gc, 200, 10, 200, 290);
XFlush(display);
getchar();
/* 关闭视窗 */
printf("Destory Window\n");
XDestroyWindow(display, window);
XFlush(display);
getchar();
printf("close display\n");
XCloseDisplay(display);
getchar();
}
--------------------------------------------------------------------------------
gcc -o XGraph XGraph.c -L/usr/X11R6/lib -lX11
--------------------------------------------------------------------------------
上面是一个简单的例程式和 compile 的方法。