Index: 顏色 Graphics Context Graphics Image 例
--------------------------------------------------------------------------------
1. 顏色 在 X Window 視窗系統,程式使用顏色都是透過配置 color cell。 color cell 存放著顏色的 RGB 色值,即繪圖時顯示器上所顯示出來 的色值。在我們使用某種顏色之前,必需先配置一個正確的 cell, 使用該 cell 做為繪圖時的參數。當 server 將圖形輸出到顯示器時 ,顯示器(顯示卡)會取出 cell 內所設定之 RGB 值,輸出到畫面。 RGB 即光學三元色紅、綠、藍,經由三元色的比例不同,可以得到不 同的顏色。
color cells 分成兩種,read-only cell 和 read/write cell。 read-only cell 只能被使用,不能被應用程式修改,但是由各個應用 程式之間一起分享,共同使用。read/write cell 被配置(allocate) 之後可以修改其 RGB 值,但一般是不在各應用程式之間分享,是私有 的。
colormap 是 color cell 的集合。每個 client 都可以有自己的 colormap,所以同時可能會有多個 colormap 存在。而系統在同一 時間內,只安裝一個 colormap 到顯示器上(有些硬容許同時安裝多 個 colormap),所以當一個視窗能顯示正確的顏色時,其它視窗的顏色 可能會不正確。這是因為不同的 colormap,其 cell 和 RGB 值的對 應可能不同,所以當 server 把某個視窗的 colormap 安裝到硬體上 時,其它視窗內的 cell 和 RGB 的對映,就變成新被安裝的 colormap 的對映方式,導至不正確的顏色顯示。也就是當 server 把某個視窗 的 colormap 安裝到顯示硬上時,該視窗的顏色顯示就會正確。反 之,則會顯示目前被安裝的 colormap 的對映狀況,顯示不正確的顏 色。為了避免這個問題,一般建議使用預定(default)共用的 colormap ,每個視窗都使用同一個 colormap。default 的 colormap 可由 函數 XDefaultColormap 取得。
顏色是以 R、G、B 三種元色光的量值來表示,當某元色的量值越大時 ,則顯示出來的顏色就越偏向該元色。Xlib 使用 XColor 記錄 RGB 值。 --------------------------------------------------------------------------------
typedef struct { unsigned long pixel; /* pixel value */ unsigned short red, green, blue; /* rgb values */ char flags; /* DoRed, DoGreen, DoBlue */ char pad; } XColor;
-------------------------------------------------------------------------------- red、green、blue 的圍從 0 到 65535。Black 用 (0,0,0) 表示, White 用 (65535,65535,65535) 表示。
每個 color cell 在 colormap 上都占有一個位子,為了分別不同的 color cell,我們為每個 color cell 指定一個編號,稱之為 pixel。 所以當我們需要指定一個 cell 時,我是指定其 pixel 值。pixel 是一個 long 整數,每一個 bit 我們稱之為一個 plane。因此,當我 們在 colormap 上分配 x 個 plane 時,我們就是分配 2^x^ 個 cell。
cell 有分 read-only 和 read/write:read-only cell的 RGB 值是由 server 設定的,不能更改。但是可由各 client 并同使用。每當有一 個 client 配置(allocate)read-only cell,則 server 會紀錄下來, 當所有配置該 cell 的 client 都釋放該 cell 後,該 cell 才算真正 被釋放。否則該 cell 就只能維持其原來的值不能改變,也不能被當成 read/write cell 配置。而同一個 client 多次配置同一個 cell 則視 為多次的配置,client 也必需釋放該 cell 相同次數。read/write cell 則不會有初值,但卻可以由 client 設定更改其 RGB 值。當 client 分 配到 read/write cell 後,雖然其它 client 也可以設定其內容 (RGB 值),但一般我們還是認為 read/write cell是屬私人的,不被分 享共用的。
--------------------------------------------------------------------------------
Status XAllocColor(display, colormap, screen_in_out) Display *display; Colormap colormap; XColor *screen_in_out;
colormap 指定使用的 colormap。 screen_in_out 指定和傳回 colormap 內,實際的值。
-------------------------------------------------------------------------------- 可配置一個 read-only cell。client 指定一個 RGB 值,XAllocColor 分配一個對映到硬體所能提供最接近該 RGB 值的 cell。RGB 值設定在 screen_in_out 的 red、green、blue,而 cell 的 pixel 值會將由 pixel 傳回。硬體實際提供的 RGB 值,則經由 red、green、blue 傳 回。
--------------------------------------------------------------------------------
Status XAllocColorCells(display, colormap, contig plane_masks_return, nplanes, pixels_return, npixels) Display *display; Colormap colormap; Bool contig; unsigned long plane_masks_return[]; unsigned int nplanes; unsigned long pixels_return[]; unsigned int npixels;
colormap 指定使用的 colormap contig 一個 Boolean 值,指示配置的 planes 是否必 需是連續的。 plane_mask_return 傳回 plane masks 的 array。 nplanes 指定在 plane_mask_return 要傳回多少個 plane masks。 pixels_return 傳回 pixel 陣列。 npixels 指定在 pixels_return 傳回多少個 pixel values。
-------------------------------------------------------------------------------- 分配多個 read/write cell。這些 cell 都未指定內容,分配之後, client 程式可以更改其 RGB 值。在這你必需在 nplanes 指定你要分 配幾個 plane,分配到的 plane,會經由 plane_mask_return 傳回。 plane_mask_return 這個陣列內的每個元素,指定了分配到的 plane 的 mask。npixels 則指定了要分配多少個 pixel,pixel 則由 pixels_return 這個陣列傳回。所有分配到的 cell 的數目為 npixels * 2^nplanes^,而 cell 的 pixel 值則為 pixels_return 傳回之 pixel 值和 plane mask 做 OR 運算所能產生 的所有值。如果 contig 設為 true,則所有分配到之 plane 會是相 鄰連續的,也就是所有傳回之 plane mask 做 OR 運算,會得到一群 設為 1 的連續 bits。
--------------------------------------------------------------------------------
XStoreColor(display, colormap, color) Display *display; Colormap colormap; XColor *color;
colormap 指定 colormap。 color 指定 pixel 和 RGB 值。
-------------------------------------------------------------------------------- 使用 XStoreColor 設定指定之 cell 的 RGB 值,但只限於 read/write cell。
--------------------------------------------------------------------------------
XStoreColors(display, colormap, color, ncolors) Display *display; Colormap colormap; XColor color[]; int ncolor;
colormap 指定 colormap。 color 指定要設定之顏色的結構陣列。 ncolor 指定 color 陣列中有多少個設定值。
-------------------------------------------------------------------------------- XStoreColors 可以同時設定多個 color cells 的 RGB 值,但只 限於 read/write cell,read-only cell 不能更改。
--------------------------------------------------------------------------------
XFreeColors(display, colormap, pixels, npixels, planes) Display *display; Colormap colormap; unsigned long pixels[]; int npixels; unsigned long planes;
colormap 指定使用之 colormap。 pixels 指定對映到 cells 的 pixels 值的陣列。 npixels 指定 pixels 陣列中有多少個 pixel 值。 planes 指定你要釋放的 planes。
-------------------------------------------------------------------------------- 當你所配置到的 color cell 不再被需要時,你可以使用 XFreeColors 釋放。XFreeColors 同一時間內可以釋放多個 cell ,pixels 是指定要釋放掉的 cell 的陣列,npixels 則指定 cell 的數目。planes 則是要釋放之 planes 的 plane mask,將要釋放 之所有 plane 的 mask OR 起來所得到的 mask。所釋放的 pixels 為,任一指定之 pixel 和 plane mask 之部分集合做 OR 運算後,所 有可能產生的 pixel 集合。
使用顏色名稱 除了使用 RGB 值之外,你可以使用顏色的名稱,并取得適當的 pixel 值。 --------------------------------------------------------------------------------
status XAllocNamedColor(display, colormap, color_name, screen_def_return, exact_def_return) Display *display; Colormap colormap; char *color_name; XColor *screen_def_return, *exact_def_return;
colormap 指定 colormap。 color_name 顏色之名稱。 screen_def_return 傳回硬所能提供最接近之 RGB 值。 screen_def_exact 傳回精確的 RGB 值。
-------------------------------------------------------------------------------- screen_def_exact 傳回的是原本正確顏色所該有的 RGB 色值,而 screen_def_return 傳回的則是目前硬所能提供顏色最接近之 RGB 色值。
操作 Colormaps 除了使用預定公用的 colormap (從 parent 視窗拷貝而來的) 分配我 們需要的顏色之外,我們也可以為每個個別的視窗建立獨立的 colormap,讓每個視窗能獨力擁有 colormap,或者是由一群視窗來 分享(share)一個 colormap。
--------------------------------------------------------------------------------
Colormap XCreateColormap(display, w, visual, alloc) Display *display; Window w; Visual *visual; int alloc;
w 指定視窗。 visual 指定一個該 screen 所提供之 visual。 alloc 指定是否要分配在 colormap 的所有 entry。 可以是 AllocNone 或 AllocAll。
-------------------------------------------------------------------------------- XCreateColormap 會傳回一個在指定視窗所在的 screen 上建立之新的 colormap。visual 指定該 colormap 所提供之 visual。
我們可以隨時為視窗設定新的 colormap,但是 colormap 的 visual 必需和視窗的 visual 相同。指定視窗的 colormap,我們可以透過 XSetWindowColormap: --------------------------------------------------------------------------------
XSetWindowColormap(display, w, colormap) Display *display; Window w; Colormap colormap;
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
XFreeColormap(display, colormap) Display *display; Colormap colormap;
colormap 要釋放之 colormap。
-------------------------------------------------------------------------------- 釋放一個 colormap,但對於預定之 colormap 沒有作用。如果要 釋放之 colormap 已被使用在某個視窗上時,則 XFreeColormap 會將該視窗之 colormap 設成 None,并對該視窗產生 ColormapNotify event ( event 在後面的章節會談到 )。
2. Graphics Context Graphics Context 簡稱 GC,是存在 server 上的一種資源。GC 是用來 存放繪圖時所需要的各項資訊(例如: 線的寬度和長度,前景和背景顏色 等等),在大部分的繪圖功能中,都需要使用 GC 做為參數。其實,我們 可以把 GC 看做是我們在做畫時的畫筆,不同的畫筆會產生不同的效果 。同樣的,我們也可以使用不同的 GC 內容的變化,來組合達成我們所 需要的畫面效果。同一個 GC 可以在不同的視窗使用,也可以在不同的 client 間使用,但是一般來說 ,并不鼓勵由不同的 client 使用,因為 Xlib 會對 GC 暫存,可能會造 成同步上的問題。GC 是和 screen 結合在一起的,同時也和 depth 有關 ,只有 screen 和 depth 和 GC 和同的視窗,才可以使用該 GC。也就是 該視窗必需和 GC 是在同一個 screen,并且要有相同的 depth。
Xlib 提供 XGCValues 這個結構, 以存放 GC 的相關資訊。我們將要 設定的值,存於這個結構,同時也經由這個結構傳回 GC 的內存值。 --------------------------------------------------------------------------------
/* GC attribute value mask bits */
#define GCFunction (1L<<0) #define GCPlaneMask (1L<<1) #define GCForeground (1L<<2) #define GCBackground (1L<<3) #define GCLineWidth (1L<<4) #define GCLineStyle (1L<<5) #define GCCapStyle (1L<<6) #define GCJoinStyle (1L<<7) #define GCFillStyle (1L<<8) #define GCFillRule (1L<<9) #define GCTile (1L<<10) #define GCStipple (1L<<11) #define GCTileStipXOrigin (1L<<12) #define GCTileStipYOrigin (1L<<13) #define GCFont (1L<<14) #define GCSubwindowMode (1L<<15) #define GraphicsExposures (1L<<16) #define GCClipXOrigin (1L<<17) #define GCClipYOrigin (1L<<18) #define GCClipMask (1L<<19) #define GCDashOffset (1L<<20) #define GCDashList (1L<<21) #define GCArcMode (1L<<22)
/* Values */
typedef struct { int function; unsigned long plane_mask; unsigned long foreground; unsigned long background; int line_width; int line_style; int cap_style; int join_style; int fill_style; int fill_rule; int arc_mode; Pixmap tile; Pixmap stipple; int ts_x_origin; int ts_y_origin; Font font; int subwindow_mode; Bool graphics_exposures; int clip_x_origin; int clip_y_origin; Pixmap clip_mask; int dash_offset; char dashes; } XGCValues;
-------------------------------------------------------------------------------- 下面是 XGCValues 的欄位說明。 欄位 預設值 說明 function GXcopy Xlib 定義了 16 種 function, 用以定義各種 X 所提供的繪圖形式. Xlib 提供了一些繪圖函數, 當我們在一個 drawable 上繪圖時, 新繪上的 圖該如何和在原本位置上的圖形配合呢? function 定義了 X 所提供的 16 種可能中的一種. 當我們為 GC 設好新的 function 之後, 下一次我們使用 GC 進行繪圖時, 新的 function 就開始發生了作用. 下面是 Xlib 定義的 16 種 function. GXclear 把輸出圖素清除為 0 GXand 把輸出之圖與原圖素做 and 運算 GXandReverse 先把原圖素反相, 然後和輸出圖素做 and 運算 GXcopy 直接用輸出圖素替代原圖素 GXandInverted 先將輸出圖素和原圖素做 and 運算後, 再將結果反相 GXnoop 維持原圖素 GXxor 輸出圖素和原圖素做 xor 運算 GXor 輸出圖素和原圖素做 or 運算 GXnor 先分別把輸出圖素和原圖素做反相, 再將反相後的兩圖做 and 運算 GXequiv 先反相輸出圖素,然後和原圖素做 xor 運算 GXinvert 把原圖素反相 GXorReverse 反相原圖素, 然後和輸出圖素做 xor 運算 GXcopyInverted 把輸出圖素反相當為最後結果 GXorInverted 把輸出圖素反相後和原圖素做 or 運算 GXnand 把輸出圖素和原圖素做反相, 然後兩圖做 or 運算 GXset 把輸出部分全設為 1 plane_mask AllPlanes 指定會被影的 planes, 會被影的 planes 設為 1。Xlib 中定義 AllPlanes 常數, 指定所有的 planes。繪圖的最後結果是: ((輸出圖素 function 原圖素) AND plane_mask)
foreground 1 指定圖形輸出時的前景所使用的圖素值(pixel) background 0 指定圖形輸出時的背景所使用的圖素值(pixel) line_width 0 如果輸出中有線條時, 線條的寬度. line_style LineSolid 線條的樣式, Xlib 定義三個常數, 代表三種樣式. LineSolid 實線 LineOnOffDash 虛線 LineDoubleDash 另一種虛線 cap_style CapButt 指定線條端線點(起點和終點)的樣式。 CapNotLast 和 CapButt 相似, 只是 line width 為 0 時, 不畫出端點. CapButt 方形長角的端點 CapRound 圓弧形的端點 CapProjecting 和 CapButt 相似, 但端點會再延伸 line width 的一半長度 join_style JoinMiter 折線的折點形式。 JoinMiter 角狀的折點 JoinRound 圖弧狀的折點 JoinBevel 像是兩個 CapButt 的端點重疊在一起 fill_style FillSolid 設定線段,文字,和填充畫面的來源。 FillSolid 前景填滿 foreground 顏色 FillTiled 以 tile 填滿 FillStippled 前景以填上 foreground 但以 stipple 遮罩起來. FillOpaqueStippled 和 FillStippled 相似, 但被遮罩的部分(stipple 內為 0 的部分) 填上 background。 fill_rule EvenOddRule 設定呼叫 XFillPolygon 時,如何定義出內部和外部。 EvenOddRule 以通過指定點的線為基準, 通過 path 奇數次的為 inside WindingRule 通過順時鐘方向的 path 和逆時鐘方向的 path 的次數如果不同 即為 inside。 arc_mode ArcPieSlice 控制 XFillArcs 如何填滿圓弧。 ArcChord 以琴弦般的填滿弧 ArcPieSlice 像被切開的 pie 一樣的填滿弧 tile 0 和 GC 有相同 root 和深度(depth)的 pixmap stipple 0 深度(depth)為 1 的 pixmap ts_x_origin 0 設定 tile/stipple 的原點的 x 座標 ts_y_origin 0 設定 tile/stipple 的原點的 y 座標 font Implementation dependent 字形,XLoadFont 的傳回值 subwindow_mode ClipByChildren ClipByChildren IncludeInferiors graphics_exposures True 控制 XCopyArea 和 XCopyPlane 的 GraphicsExpose 事件(event)的產生。 clip_x_origin 0 clip_mask 的原點相對於 drawable 的位置 clip_y_origin 0 clip_mask 的原點相對於 drawable 的位置 clip_mask None clip_mask 為深度(depth)為 1 并和 GC 相同 root 的 pixmap, 做為輸出的 mask dash_offset dashes
你可以透過 XCreateGC 建立一新的 GC: --------------------------------------------------------------------------------
GC XCreateGC(display, d, valuemask, values) Display *display; Drawable d; unsigned long valuemask; XGCValues *values;
d 指定 drawable。 valuemask 指定使用了那些 GC 元件。這個參數是把各元件之 mask OR 起來得到的 mask,用以指定設了那些元 件。 value 指定設定的 GC 內容。
-------------------------------------------------------------------------------- 呼叫 XCreateGC 後,建立一個新的 GC,并會傳回 GC。所謂的 drawable 指的是一個可以使用繪圖功能,在其上進行繪圖的視窗或是其它 X 上的 物件。
--------------------------------------------------------------------------------
XFreeGC(display, gc) Display *display; GC gc;
gc 指定要釋放之 GC。
-------------------------------------------------------------------------------- 釋放一個己建立之 GC。
下面我們介紹一些設定 GC 的方便函數,以方便我們做 GC 設定。
--------------------------------------------------------------------------------
XSetForeground(display, gc, foreground) Display *display; GC gc; usigned long foreground;
gc 指定作用對像之 GC。 foreground 指定前景顏色。
-------------------------------------------------------------------------------- 設定 GC 內容的前景。當你使用該 GC 繪圖時,前景顏色即為 GC 內所設的前景顏色。
--------------------------------------------------------------------------------
XSetBackground(display, gc, background) Display *display; GC gc; usigned long background;
gc 指定作用對像之 GC。 background 指定背景顏色。
-------------------------------------------------------------------------------- 設定 GC 的背景顏色。當你使用該 GC 繪圖時,前景顏色即為 GC 內所設的前景顏色。
--------------------------------------------------------------------------------
XSetLineAttributes(display, gc, line_width, line_style, cap_style, join_style) Display *display; GC gc; unsigned int line_width; int line_style; int cap_style; int join_style;
gc 指定作用對像之 GC。 line_width 線條之寬度。 line_style 線條型式,有 LineSolid、LineOnOffDash、 LineDoubleDash。 cap_style 指定線條端點之型式,有 CapNotLast、 CapButt、CapRound、CapProjecting。 join_style 指定線條轉折點的型式,有 JoinMiter、 JoinRound、JoinBevel。
-------------------------------------------------------------------------------- 設定線的形式。
--------------------------------------------------------------------------------
XSetFont(display, gc, font) Display *display; GC gc; Font font;
gc 指定作用對像之 GC。 font 指定字型。
-------------------------------------------------------------------------------- 設定字形。
--------------------------------------------------------------------------------
XSetArcMode(display, gc, arc_mode) Display *display; GC gc; int arc_mode;
gc 指定作用對像之 GC。 arc_mode 指定畫弧時,封口的型式,有 ArcChord、 ArcPieSlice。
-------------------------------------------------------------------------------- 設定畫弧時,封口的型式。 3. Graphics Xlib 提供大量的函數,處理圖形的輸出。 --------------------------------------------------------------------------------
XClearWindow(display, w) Display *display; Window w;
-------------------------------------------------------------------------------- 清除視窗。
--------------------------------------------------------------------------------
XDrawPoint(display, d, gc, x, y) Display *display; Drawable d; GC gc; int x, y;
d 指定 drawable。 gc 指定要使用之 GC。 x, y 指定畫點的座標。
-------------------------------------------------------------------------------- 在視窗上畫一點。
--------------------------------------------------------------------------------
XDrawLine(display, d, gc, x1, y1, x2, y2) Display *display; Drawable d; GC gc; int x1, y1, x2, y2;
d 指定目的 drawable。 gc 指定使用之 GC。 x1, y1, x2, y2 指定線的兩端點座標。
-------------------------------------------------------------------------------- 在視窗上畫一條線。
--------------------------------------------------------------------------------
XDrawRectangle(display, d, gc, x, y, width, height) Display *display; Drawable d; GC gc; int x, y; unsigned int width, height;
x, y 指定矩形的左上角座標。 width, height 指定矩形的大小。
-------------------------------------------------------------------------------- 在視窗上畫一個矩形。
--------------------------------------------------------------------------------
XDrawArc(display, d, gc, x, y, width, height, angle1, angle2) Display *display; Drawable d; GC gc; int x, y; unsigned int width, height; int angle1, angle2;
x, y 指定弧的中心點(原點)。 width, height 指定弧的 x 軸和 y 軸的比例。 angle1, angle2 弧的起始角度和結止角度。
-------------------------------------------------------------------------------- 在視窗上畫一個弧形。
--------------------------------------------------------------------------------
XFillRectangle(display, d, gc, x, y, width, height) Display *display; Drawable d; GC gc; int x, y; unsigned int width, height;
-------------------------------------------------------------------------------- 在視窗上畫一個填滿顏色的矩形。
--------------------------------------------------------------------------------
XFillArc(display, d, gc, x, y, width, height, angle1, angle2) Display *display; Drawable d; GC gc; int x, y; unsigned int width, height; int angle1, angle2;
-------------------------------------------------------------------------------- 在視窗上畫一個填滿顏色的弧形。
--------------------------------------------------------------------------------
Font XLoadFont(display, name) Display *display; char *name;
name 指定字形名稱。
-------------------------------------------------------------------------------- 載入字形,當我要在視窗上顯示某一字形時,我們必需先載入字形, 然後才能使用。使用這個函數之後,會傳回一個 Font 的 ID,這 就是我們在使用 XSetFont 函數設定 GC 所要傳入的參數之一。 當我們使用傳回來的 Font 設定 GC 後,就可以使用該 GC 當做 參數在螢幕上顯示該字形的字串。
--------------------------------------------------------------------------------
XUnloadFont(display, font) Display *display; Font font;
font 指定要 unload 的字形。
-------------------------------------------------------------------------------- 移除字形。當我們不再使用一字形時,我們必需將之移除。
--------------------------------------------------------------------------------
XDrawString(display, d, gc, x, y, string, lengtth) Display *display; Drawable d; GC gc; int x, y; char *string; int length;
gc 畫字時所要用的 GC。 x, y 指定字串顯示的座標。 string 要顯示的字串。 length 字串的長度。
-------------------------------------------------------------------------------- 在螢幕上顯示一字串。
--------------------------------------------------------------------------------
XDrawString16(display, d, gc, x, y, string, length) Display *display; Drawable d; GC gc; int x, y; XChar2b *string; int length;
gc 指定使用之 GC。 x, y 指定字串顯示的座標。 string 指定顯示之字串。 length 指定字串內有多少個字。
-------------------------------------------------------------------------------- 在螢幕上顯示一雙位元組(或 16bits)的字串。X Window 有支援雙位元組 字集,用以顯示雙位元組的語言(如中文等)。雙位元組的字元是以 XChar2b 這個 structure 來表示: typedef struct { unsigned char byte1; unsigned char byte2; } XChar2b;
byte1 存放的是雙位元組字元的高位元組(MSB:most significant byte) ,byte2 存放的則是低位元組(LSB:least significant byte)。一個雙 位元組的字串就是 XChar2b 的陣列。
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 的方法。 |
|