>お楽しみコーナー>Linux>X11プログラミング サイトマップ 最終更新日:2005/07/22

センリュウのホームページへ ようこそ!

 X11プログラミング   

ここでは簡単なX11プログラミングについて取り上げてみた。

汎用Makefile プログラムソースはtest.cで保存して、Makefileを以下の内容で準備し、makeを実行する。
INCLUDE = /usr/X11R6/include/X11
LIB = /usr/X11R6/lib
CC = gcc
CFLAGS = -lX11 -lpthread
TARGETS = test
OBJ = ${SRC:.c=.o}
SRC = test.c

$(TARGETS):${OBJ}
    ${CC} -I ${INCLUDE} -L ${LIB} ${CFLAGS} ${OBJ} -o ${TARGETS}

${OBJ}:${SRC}
    ${CC} ${SRC} -c -o ${OBJ}

clean: 
    rm -f *.o $(TARGETS)

ウィンドマネージャーの介入なし



#include <X11/Xlib.h>
#include <X11/Xutil.h>

int main(void)
{
Display *d;
Window wr, w1, w2;   wrを親ウィンド、w1、w2をサブウィンドとする
GC gc, gc1, gc2;
XSetWindowAttributes attr;
unsigned long black,white;

d=XOpenDisplay(NULL);

black=BlackPixel(d,0);
white=WhitePixel(d,0);

wr=XCreateSimpleWindow(d,RootWindow(d,0),100,50,800,530,1,black,white);  親ウィンドの生成
w1=XCreateSimpleWindow(d,wr,10,10,780,400,1,black,white);  子ウィンドの生成
w2=XCreateSimpleWindow(d,wr,10,410,780,80,1,black,white);

attr.override_redirect=True;
XChangeWindowAttributes(d,wr,CWOverrideRedirect,&attr);

XMapWindow(d,wr);  親ウィンドのマップ(ディスプレイ上に写像して可視状態にする)
XMapSubwindows(d,wr);  子ウィンド(w1、w2)のマップ

gc=XCreateGC(d,wr,0,0);  各ウィンドに対するGC(このあとここに描画色や描画フォントなどの設定を行っていく)の生成
gc1=XCreateGC(d,w1,0,0);
gc2=XCreateGC(d,w2,0,0);

……………
XDrawString(d,wr,gc,500,515,"test",4);
XFlush(d);
sleep(10);
return(0);
}


ウィンドマネージャー付き 



上(mainの中)を手直しする

Display *d;
Window wr, w1, w2;
GC gc, gc1, gc2;
XEvent event;
unsigned long black,white;

d=XOpenDisplay(NULL);

black=BlackPixel(d,0);
white=WhitePixel(d,0);

wr=XCreateSimpleWindow(d,RootWindow(d,0),100,50,800,530,1,black,white);
w1=XCreateSimpleWindow(d,wr,10,10,780,400,1,black,white);
w2=XCreateSimpleWindow(d,wr,10,410,780,80,1,black,white);

XSelectInput(d,wr,ExposureMask);  Exposeイベントを設定

XMapWindow(d,wr);
XMapSubwindows(d,wr);

gc=XCreateGC(d,wr,0,0);
gc1=XCreateGC(d,p1,0,0);
gc2=XCreateGC(d,w2,0,0);

while(1)
{
XNextEvent(d,&event);
switch(event.type)
{
case Expose:
XDrawString(d,wr,gc,500,515,"test",4);
XFlush(d);
……………  その他のイベント
}
}


GCへのフォントや色の設定
GC gc1, gc2;
Font f1,f2;
unsigned long black,white;  白と黒の設定は簡単な方法で行えるので別に定義
Colormap cmap;
XColor c0,red,green;

……………
gc1=XCreateGC(d,w1,0,0);
gc2=XCreateGC(d,w2,0,0);

f1=XLoadFont(d,"variable");  ………………………フォントの読み込み
f2=XLoadFont(d,"-urw-helvetica-bold-r-normal--42-401-75-75-p-234-iso8859-1");
XSetFont(d,gc1,f1);  …………………………………各GCにフォントの設定
XSetFont(d,gc2,f2);

black=BlackPixel(d,0);  ………………………………白と黒
white=WhitePixel(d,0);
cmap=DefaultColormap(d,0);  …………………………その他の色
XAllocNamedColor(d,cmap,"red",&red,&c0);
XAllocNamedColor(d,cmap,"green",&green,&c0);
XSetForeground(d,gc1,white);  ………………………各GCに前面色の設定
XSetForeground(d,gc2,green.pixel);

XDrawString(d,w1,gc1,500,515,"test",4);
……………
XFlush(d);

ピクセルマップを使った表示(ちらつきをなくす)
Display *d;
Window w1, w2;
GC gc1, gc2;
Pixmap p1, p2;

……………
p1=XCreatePixmap(d,w1,780,400,DefaultDepth(d,0));
p2=XCreatePixmap(d,w2,780,80,DefaultDepth(d,0));

……………
XDrawLine(d,p1,gc1,0,0,100,100);  ピクセルマップp1に描画していく
……………
XCopyArea(d,p1,w1,gc1,0,0,780,400,0,0);  それをウィンドw1にコピー

XFillRectangle(d,p2,gc2,0,0,780,80);
XDrawString(d,p2,gc2,100,60,s,strlen(s));
XCopyArea(d,p2,w2,gc2,0,0,780,80,0,0);

XFlush(d);

XCopyAreaの代わりに、XSetWindowBackgroundPixmapでピクセルマップをウィンド本体の背景として設定してもよい。
XSetWindowBackgroundPixmap(d,w1,p1);
XClearWindow(d,w1);

また、ピクセルマップにはウィンドのように初期化やクリアの機能がないため、これらはXSetForgroundやXFillRectangle関数によって行う。
XSetForground(d,gc2,white);
XFillRectangle(d,p2,gc2,0,0,780,80);
XCopyArea(d,p2,w2,gc2,0,0,780,80,0,0);



モノクロ(ビットマップ)画像を表示する。

@1プレーン・ビットマップで表示
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdio.h>

main()
{
Display *d;
Window wr;
GC gc;
Pixmap px;
XSetWindowAttributes attr;
int width,height,x_hot,y_hot;

d=XOpenDisplay(NULL);

wr=XCreateSimpleWindow(d,RootWindow(d,0),50,100,340,130,1,BlackPixel(d,0),WhitePixel(d,0));

attr.override_redirect=True;
XChangeWindowAttributes(d,wr,CWOverrideRedirect,&attr);

XMapWindow(d,wr);
gc=XCreateGC(d,wr,0,0);

XSetForeground(d,gc,BlackPixel(d,0));  モノクロ2色の設定
XSetBackground(d,gc,WhitePixel(d,0));

XReadBitmapFile(d,wr,"./test.bmp",&width,&height,&px,&x_hot,&y_hot);  画像ファイルの読み込み
XCopyPlane(d,px,wr,gc,0,0,width,height,0,0,1);

XFlush(d);
sleep(10);
}

Aピックスマップで表示
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdio.h>

main()
{
Display *d;
Window wr;
GC gc;
Pixmap px;
XSetWindowAttributes attr;
int width,height,x_hot,y_hot;
static unsigned char data[]=……………;  画像ファイルの当該部分(data部分)をそのままもってくればよい。

d=XOpenDisplay(NULL);

wr=XCreateSimpleWindow(d,RootWindow(d,0),50,100,340,130,1,BlackPixel(d,0),WhitePixel(d,0));

attr.override_redirect=True;
XChangeWindowAttributes(d,wr,CWOverrideRedirect,&attr);

XMapWindow(d,wr);
px=XCreatePixmap(d,wr,width,height,DefaultDepth(d,0));
gc=XCreateGC(d,wr,0,0);

px=XCreatePixmapFromBitmapData(d,wr,data,width,height,BlackPixel(d,0),WhitePixel(d,0),DefaultDepth(d,0)); 
XCopyArea(d,px,wr,gc,0,0,width,height,0,0);

XFlush(d);
sleep(10);
}

BXImageによる表示方法


ビットマップファイルを作成するには
# bitmap -size 50x50
この中身を見るには、 # cat test.bmp



GIMPで作成したVWDフォーマット画像の表示(XImage構造体を使う)

ディスプレイの色深度を、数千または数百万にして試して下さい。



#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/XWDFile.h>
#include <stdio.h>

typedef struct struct_imElement{ XImage *im; int width; int height; } imElement;

main(void)
{
Display *d;
Window wr;
GC gc;
Pixmap pr;
XEvent event;
void XWDView(Display *d, char name[], imElement *im);
imElement im1;

d=XOpenDisplay(NULL);

wr=XCreateSimpleWindow(d,RootWindow(d,0),0,0,800,600,0,0,0);
XStoreName(d, wr, “test”);
XSelectInput(d,wr,ExposureMask);
XMapWindow(d,wr);
gc=XCreateGC(d,wr,0,0);
pr=XCreatePixmap(d,wr,800,600,DefaultDepth(d,0));

XSetForeground(d,gc,BlackPixel(d,0));
XFillRectangle(d,pr,gc,0,0,800,600);

XWDView(d, “test.xwd”, &im1);  ←サブ関数で画像ファイルを読み込みimにセットする
XPutImage(d,pr,gc,im1.im,0,0,100,50,im1.width,im1.height);  ←XImage構造体imの(prへの)描画

while(1)
{
XNextEvent(d,&event);
switch(event.type)
{
case Expose:
XCopyArea(d,pr,wr,gc,0,0,800,600,0,0);
XFlush(d);
}
}
}

/////////////////////////////////////////////////////

void XWDView(Display *d, char name[], imElement *im)
{
XWDFileHeader fh;  ←XWDファイルのヘッダー部の構造体
int change(unsigned int val);

FILE *fp;
unsigned char buff[3*800*600];
int i, flg;
int r0,r1,r2;  ←ディスプレイ設定が16ビットの時使う

if((fp=fopen(name,”r”)) == NULL)
{
printf(“can not open file!”);
exit(0);
}
flg=fread(&fh,sizeof(fh),1,fp);  ←VWDファイルのヘッダー部の読み込み
fh.window_width=change(fh.window_width);  ←fh.****の値は32ビットデータが8ビットずつの単位で逆になっているので元に戻す。
fh.window_height=change(fh.window_height);
fh.bits_per_pixel=change(fh.bits_per_pixel);
fh.bytes_per_line=change(fh.bytes_per_line);
flg=fread(buff,fh.bits_per_pixel/8,fh.window_width*fh.window_height,fp);  ←VWDファイルの画像データ部の読み込み
fclose(fp);

im->width=fh.window_width;
im->height=fh.window_height;

im->im=XCreateImage(d,DefaultVisual(d,0),DefaultDepth(d,0),ZPixmap,0,0,im->width,im->height,32,0);  ←XImage構造体の生成

if(DefaultDepth(d,0) == 16)     ←ディスプレイ設定が16ビットの時、画像データの変換
{
for(i=0;i<im->width*im->height;i++)
{
r0=31*buff[3*i+0]/255;
r1=31*buff[3*i+1]/255;
r2=31*buff[3*i+2]/255;
buff[3*i+0]=0x00;
buff[3*i+1]=r0<<3 | r1>>2;
buff[3*i+2]=(r1 & 0x07)<<6 | r2;
}
}

im->im->data=(char *)buff;  ←XImage構造体に画像データを代入
im->im->xoffset=0;
im->im->byte_order=MSBFirst;
im->im->bitmap_unit=32;
im->im->bitmap_bit_order=MSBFirst;
im->im->bytes_per_line=fh.bytes_per_line;
im->im->bits_per_pixel=fh.bits_per_pixel;
}

//////////////////////////////////////////////////////////////////////////////////

int change(unsigned int val)
{
val=(val<<24)+(val<<8 & 0xff0000)+(val>>8 & 0xff00)+(val>>24);
return val;
}