XPM文件格式及XPM库函数
BG6RDF
随着Linux应用开发的普及,越来越多的开发者接触到了X Window系统。X Window 的开发又往往涉及图标等图像文件的操作。本文介绍了X Window系统中常用的XPM图像文件格式,及XPM函数库的使用。
XPM是X Window系统中常用的图像文件格式,特别适合于图标(ICON)等小图像的使用。而XPM函数库(Library)定义了读写和显示XPM文件的函数。
一.XPM的基本结构
一个XPM文件的基本结构如下:
/* XPM */
static char* <pixmap_name>[] = {
“Values-string”,
“Colors-strings”,
“Pixels-strings”,
“Extensions-strings”,
};
XPM文件遵守C语言语法,可包括C语言风格的注释。正因如此可在C/C++语言源程序中直接引用(include)XPM文件。XPM文件必须有一个如上所示的/* XPM */文件头。
其中“Values-string”的格式是:“width height ncolors cpp [x_hotspot y_hotspot] [XPMEXT]”。Width是图像宽度,height是图像高度(width和height的单位都是像素-pixel),ncolors是颜数,cpp(characters per pixel)是颜定义中每个像素的字符数。X_hotspot 和y_hotspot是可选的,它们指定热点的坐标。如果存在”Extensions-String”才需要XPMEXT。
“Colors-strings”的格式是”chars key value…”。Chars是代表颜的字符,它的大小由cpp指定。Key用以指定value的类型,包括下列几种:m-单,c-彩,g4-四级灰度,g-多于4级的灰度,s-标识符。value用以指定颜(颜名可在*****中查询),它可以是颜名或以“#”开头的RGB值或以“%”开头的HSV值(,其中None表示透明。
“Pixels-strings”包含了图像的实际定义,它包含的字符串数量由height指定,每个字符串的有width*cpp个字符,而每个cpp长度的字符必须在“Colors-strings”中已定义。
“Extensions-strings”存放由应用程序定义的扩展信息。
下面是一个非常简单的XPM文件的例子:
/* XPM */
static char * bullet_xpm[] = {
/* width height number_of_colors chars_per_pixel */
/* colors */
“25 25 2 1”,
“X c black”,
“. c red”,
/*“.”表示红,“X”表示黑。*/
/* pixels */
“XXXXXXXXXXXXXXXXXXXXXXXXX”,
“XXXXXXXXXXXXXXXXXXXXXXXXX”, “XXXXXXXXXX”, “.XXXXXXXX”, “XXXXXX”, “XXXXX”, “XXXXX”, “XXXX”, “XXXX”, “XXX”, “XXX”, “XXX”, “XXX”, “XXX”, “XXXX”, “XXXX”, “XXXXX”, “XXXXX”, “XXXXXX”, “.XXXXXXXX”, “XXXXXXXXXX”, “XXXXXXXXXXXXXXXXXXXXXXXXX”,
“XXXXXXXXXXXXXXXXXXXXXXXXX”};
这个XPM文件图形是:
但是这个图标在单显示器上显示成完全黑。因为红在单显上会被转换为黑。为避免这个问题,可通过修改“.”的颜定义强行将红转换为白,即:“. c red m white”。这里用到了多个key/value对,即彩显上是红,单显上是白。
在XPM文件中,也可以定义颜标识符名。例如我们把“.”的颜定义成“. c red s Foreground”,表示Foreground是这个颜的标识符名,就可以动态地将Foreground的颜定义为任何颜。如果我们把“X”的颜定义成“X c none”,那么上图中黑的部分就成为透明的。具体用法下面将讨论。
二.XPM库(library)
XPM库提供了Xlib级操作XPM文件的C语言函数和数据结构。使用这个库可以实现显示XPM文件中定义的图像、将图像保存到XPM文件中。使用XPM库编写程序时,应包含头文件xpm.h,在link时应指定-lXpm参数。
1. 显示XPM文件
Xlib中图像处理通过Pixmap,XPM库中提供了由XPM文件生成Pixmap的函数。常用的是int XpmReadFileToPixmap(display, d, filename, pixmap_return, shapemask_return, attribute s)。这个函数。Pixmap生成后就可以使用Xlib中所有处理Pixmap的函数进行图像处理了,如XcopyArea等。
2. P ixmap属性
XpmReadFileToPixmap函数的最后一个参数是struct XpmAttributes类型的Pixmap属性,我们可在创建前通过该参数设置Pixmap的一些属性,或在创建Pixmap后取得它的一些属性,如长宽等。如同Xlib中GC(Graphics Context图形上下文)一样,用该参数设置Pixmap 的属性,必须提供一个掩码,但区别是这个掩码不是一个参数,而是attributes参数中的成员变量valuemask。在调用XpmReadFileToPixmap函数时,如果最后一个参数是0或空指针,表示不使用attributes参数,但如果一旦使用该参数,那么valuemask成员必须初始化。
3. 颜的重载和透明
如果在XPM文件中定义了颜标识符名或透明,就可以通过XpmAttributes参数进行颜的重载或设置透明。方法是通过XpmColorSymbol结构设置颜标识符的实际彩,接着将这个结构赋予XpmAttributes结构的colorsymbol变量,设置valuemask后,调用XpmReadFileToPixmap函数。
4.更多的功能
XPM库除了上面提到的几个功能外,还有诸如定义不规则(非矩形)窗口,进行图像转换等功能,本文仅涉及上述几个基本的功能。如果需要进一步了解,文后的参考网站中有更详细的介绍。当然,对
能够对XPM文件进行处理的函数库也有很多,例如Imlib不仅能处理XPM文件,而且能够处理很多别的图像文件格式,但它们的使用都比XPM库复杂。三.举例
为演示XPM库对XPM文件的基本操作,本文列出了一个简单的例子。这个程序演示了
XPM文件的显示、颜重载、透明处理。首先通过XPM库将XPM文件装入第一个Pixmap 中,并根据返回的XpmAttributes确定图像和窗口的大小;将图像人物的肤换成棕后装入第二个Pixmap,完成颜的重载;将背景换成窗口用的背景白,再次装入第三个Pixmap。在绘制窗口时通过Xlib的XCopyArea函数将前面创建的三个Pixmap复制到窗口中。
如果在C语言源程序中用#include指令引用XPM文件,可以通过XpmCreatePixmapFromData函数根据图像数据生成Pixmap。Pixmap的释放应使用用Xlib 提供的XfreePixmap函数。
这个程序并完全基于Xlib和XPM库,在Redhat 6.2和Mandrake 8.1下调试通过。编译命令是:gcc -o xpmtest -L/usr/X11R6/lib -lX11 -lXpm xpmtest.c。输出结果见下图。fprintf格式
参考网站:koala.ilog.fr/ftp/pub/xpm/
程序源码:
/* XPM Library test program */
/* Written by Tony Zheng */
#include <X11/Xlib.h>
#include <X11/xpm.h>
#include <stdio.h>
#define filename "bart.xpm"
int main(int argc, char ** argv)
{
Display *display;
int screennum;
Window win;
XEvent report;
GC gc;
Pixmap color1pixmap, color2pixmap, transparentpixmap;
XpmAttributes attributes;
int status;
unsigned int pixmapwidth, pixmapheight, width, height;
XGCValues values;
XpmColorSymbol symbol;
XpmColorSymbol symbols[2];
/
* 连接X server */
display=XOpenDisplay("");
if (display==NULL) {
fprintf(stderr, "%s:cannot open display.\n", argv[0]);
exit(-1);
}
screennum=DefaultScreen(display);
/*生成第一个Pixmap */
attributes.valuemask=0;
status=XpmReadFileToPixmap(display, RootWindow(display, screennum), filename, &color1pixmap, 0, &attributes);
if (status!=XpmSuccess) {
fprintf(stderr, "Pixmap 1 XpmError:%s\n", XpmGetErrorString(status)); exit(-1);
}
/* 获得pixmap尺寸,计算窗口尺寸 */
pixmapwidth=attributes.width;
pixmapheight=attributes.height;
width=pixmapwidth*3+80;
height=pixmapheight+40;
/*替换肤,生成第二个pixmap */
symbol.name="Skin";
symbol.value="brown";
attributes.numsymbols=1;
attributes.valuemask=XpmColorSymbols;
status=XpmReadFileToPixmap(display, RootWindow(display, screennum), filename, &color2pixmap, 0, &attributes);
if (status!=XpmSuccess) {
fprintf(stderr, "Pixmap 2 XpmError:%s\n", XpmGetErrorString(status)); exit(-1);
}
/*替换肤和背景,生成第三个pixmap */
symbols[0].name="Skin";
symbols[0].value="brown";
symbols[1].name="None";
symbols[1].value="white";
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论