第 5 章 GdkPixbuf を使った画像アプリケーションの作成 65
5.3 画像の表示
これまで紹介した関数を使用すれば,画像データを簡単にメモリ上に読み込んで扱うことができます.では,画像データをメ モリ上で扱うだけではなく,ウィンドウ上に表示するにはどうすればいいでしょうか.この節では,画像をウィンドウ上に表示 する方法をいくつか紹介します.
5.3.1 GtkImage ウィジェットによる画像の表示
チュートリアルの2.4節(p.15)でも紹介したように,画像を表示する一番簡単な方法はイメージウィジェット(GtkImage) を使用する方法です.GtkImageウィジェットは名前の通り画像を扱うウィジェットです.GtkImageウィジェットを使用した 画像の表示の例を,ソース5–1に示します.
ソース5–1 GtkImageウィジェットによる画像の表示: display1.c
1 # i n c l u d e <g t k / g t k . h >
2 # i n c l u d e <s t d l i b . h >
3 4 i n t
5 m a i n (i n t a r g c , c h a r * a r g v [ ] )
6 {
7 G t k W i d g e t * w i n d o w ;
8 G t k W i d g e t * i m a g e ;
9
10 i f ( a r g c < 2 )
11 {
12 g _ p r i n t ( " U s a g e : . / d i s p l a y 1 i m a g e f i l e \ n " ) ;
13 e x i t ( 0 ) ;
14 }
15 g t k _ i n i t ( & a r g c , & a r g v ) ;
16
17 w i n d o w = g t k _ w i n d o w _ n e w ( G T K _ W I N D O W _ T O P L E V E L ) ;
18 g t k _ w i n d o w _ s e t _ t i t l e ( G T K _ W I N D O W ( w i n d o w ) , " D i s p l a y I m a g e 1 " ) ;
19 g _ s i g n a l _ c o n n e c t ( G _ O B J E C T ( w i n d o w ) , " d e s t r o y " ,
20 G _ C A L L B A C K ( g t k _ m a i n _ q u i t ) , N U L L ) ;
21 i m a g e = g t k _ i m a g e _ n e w _ f r o m _ f i l e ( a r g v [ 1 ] ) ;
22 g t k _ c o n t a i n e r _ a d d ( G T K _ C O N T A I N E R ( w i n d o w ) , i m a g e ) ;
23
24 g t k _ w i d g e t _ s h o w _ a l l ( w i n d o w ) ;
25 g t k _ m a i n ( ) ;
26
27 r e t u r n 0 ;
28 }
ソース 5–1を見てもわかるように,GtkImagウィジェットをGtkWindowウィジェットにパックするだけで,画像を表示 できます.この例ではGdkPixbufを使用せずに,関数gtk image new from file を使用することで,画像ファイルから直接
GtkImageウィジェットを作成できます.
G t k W i d g e t* g t k _ i m a g e _ n e w _ f r o m _ f i l e (c o n s t g c h a r * f i l e n a m e ) ;
次の関数を使用することで,GdkPixbufやGdkPixmapからGtkImageウィジェットを作成することも可能です.
図5.1 GdkImageウィジェットによる画像の表示
G t k W i d g e t* g t k _ i m a g e _ n e w _ f r o m _ p i x b u f (G d k P i x b u f * p i x b u f ) ; G t k W i d g e t* g t k _ i m a g e _ n e w _ f r o m _ p i x m a p (G d k P i x m a p * p i x m a p ,
G d k B i t m a p * m a s k ) ;
逆に次の関数を使用することで,GtkImageウィジェットからGdkPixbufやGdkPixmap形式のデータを取得することもで きます.
G d k P i x b u f* g t k _ i m a g e _ g e t _ p i x b u f (G t k I m a g e * i m a g e ) ; v o i d g t k _ i m a g e _ g e t _ p i x m a p (G t k I m a g e * i m a g e ,
G d k P i x m a p * * p i x m a p , G d k B i t m a p * * m a s k ) ;
5.3.2 GtkDrawingArea ウィジェットによる画像の表示
画像の表示には,GtkDrawingAreaウィジェットを利用することもできます.このウィジェットは図形や画像を描画するウィ ジェットで,GDKライブラリで定義されたGdkDrawable(これ以降はドローアブルと呼ぶことにします)という描画領域を 持ちます.なお,ウィンドウウィジェットもドローアブルを持つため,ウィンドウ上に直接描画することも可能です.
GtkDrawingAreaウィジェットはGtkImageウィジェットに比べて扱いが多少面倒ですが,表示した画像の上にさらに図
形を描画するといったことが可能になります.GtkDrawingAreaウィジェットを使った画像描画のソースコードをソース5–2
(p.72)に示します.
画像の読み込み(45行目)
ウィンドウに表示する画像を,関数gdk pixbuf new from fileを使ってファイルから読み込みます.
GtkDrawingAreaウィジェットの設定(52–55行目)
GtkImageウィジェットは,画像の大きさに応じて自動的に最適な大きさに伸縮しますが,GtkDrawingAreaウィジェットを
用いて画像を表示する場合には,ユーザが最適な大きさを指定する必要があります.関数gtk widget set size requestは,ウィ ジェットの大きさを設定します.
v o i d g t k _ w i d g e t _ s e t _ s i z e _ r e q u e s t (G t k W i d g e t * w i d g e t ,
g i n t w i d t h , g i n t h e i g h t ) ; コールバック関数の設定(56–57行目)
GtkDrawingAreaウィジェットで画像を描画する場合には,expose-eventシグナルのコールバック関数に画像描画のコー
ドを記述するか,画像を描画する関数を呼び出す記述をします.ユーザがドローアブル上に図形を描画する場合,図形を描画し ているウィンドウが他のウィンドウで隠れると,図形を再描画しない限り,隠された領域が自動的に描画されることはありませ ん.このような再描画が必要になったときに発生するシグナルが,expose-eventシグナルです.そのため,一般的にはこのシグ ナルに対するコールバック関数で描画処理を行います.
画像の描画(16–23行目)
ここでは画像を描画するために,GdkPixbuf型のデータからGdkPixmap型のデータ(ピックスマップ)を作成し,作成し たピックスマップをドローアブルに描画しています.
GdkPixbuf型のデータからピックスマップを生成するには,関数gdk pixbuf render pixmap and maskを使います.
v o i d g d k _ p i x b u f _ r e n d e r _ p i x m a p _ a n d _ m a s k (G d k P i x b u f * p i x b u f ,
G d k P i x m a p * * p i x m a p _ r e t u r n , G d k B i t m a p * * m a s k _ r e t u r n , i n t a l p h a _ t h r e s h o l d ) ;
第1引数 GdkPixbuf型の画像データ.
第2引数 生成されるピックスマップ.
第3引数 生成されるビットマップ(マスクデータ).
第4引数 画像データがアルファチャネルを持つ場合の透明度のしきい値.0から255の範 囲で指定する.
画像データにアルファチャネルがある場合には,第3引数に与えた変数に,第4引数に与えたしきい値でアルファチャネルを 2値化したマスク情報が返ります.
この方法を使っていったん画像データを背景に登録すると,画像の再描画は関数gdk window clearを呼び出すのみで済むと いう利点があります.
gdk pixbuf composite color
ソース5–2では,関数gdk pixbuf composite colorを使って,透明部分にタイル柄を描画して,透明部分を演出しています.
この関数の最後の3つの引数(第15–17引数)で,タイルの大きさ,1つ目のタイルの色,2つ目のタイルの色を指定していま す.
v o i d g d k _ p i x b u f _ c o m p o s i t e _ c o l o r (c o n s t G d k P i x b u f * src , G d k P i x b u f * d e s t ,
i n t d e s t _ x ,
i n t d e s t _ y ,
i n t d e s t _ w i d t h ,
i n t d e s t _ h e i g h t ,
d o u b l e o f f s e t _ x ,
d o u b l e o f f s e t _ y ,
d o u b l e s c a l e _ x ,
d o u b l e s c a l e _ y ,
G d k I n t e r p T y p e i n t e r p _ t y p e ,
i n t o v e r a l l _ a l p h a ,
i n t c h e c k _ x ,
i n t c h e c k _ y ,
i n t c h e c k _ s i z e ,
g u i n t 3 2 c o l o r 1 ,
g u i n t 3 2 c o l o r 2 ) ; 第1引数: 入力画像.
第2引数: 出力画像.
第3引数: 入力画像の描画を開始するX座標.
第4引数: 入力画像の描画を開始するY座標.
第5引数: 描画する幅.
第6引数: 描画する高さ.
第7引数: 入力画像のオフセットのX座標.
第8引数: 入力画像のオフセットのY座標.
第9引数: 入力画像のX方向の拡大率.
第10引数: 入力画像のY方向の拡大率.
第11引数: 画素値の内挿方法.
第12引数: 透明度の設定.0から255の範囲で指定する.
第13引数: チェッカーボードのオフセットのX座標.
第14引数: チェッカーボードのオフセットのY座標.
第15引数: チェッカーボードの大きさ(2のべき乗でなければならない). 第16引数: チェッカーボードの色1.
第17引数: チェッカーボードの色2.
これは,入力画像をscale x,scale yだけ拡大して,(offset x, offset y)だけ平行移動した画像を,出力画像の(dest x, dest y)
から幅dest width,高さdest heightの矩形領域に描画する関数です.透明領域は指定したチェッカーボードで塗りつぶされま
す.GdkInterpTypeは表5.3のように定義されています.
表5.3 画像補間の種類
値 説明
GDK INTERP NEAREST 最近傍補間.
GDK INTERP TILES 各点を平行四辺形として扱い,各点間の輪郭をアンチエイリアシングする.
GDK INTERP BILINEAR 線形補間.
GDK INTERP HYPER 2次補間.
最後に,関数gdk window set back pixmapで生成したピックスマップをドローアブル(ここではGtkDrawingAreaウィ
ジェットのメンバwindowがドローアブルになる)にセットし,関数gdk window clearで描画領域の更新処理を行っています.
v o i d g d k _ w i n d o w _ s e t _ b a c k _ p i x m a p (G d k W i n d o w * w i n d o w , G d k P i x m a p * p i x m a p ,
g b o o l e a n p a r e n t _ r e l a t i v e ) ; v o i d g d k _ w i n d o w _ c l e a r (G d k W i n d o w * w i n d o w ) ;
ソース5–2 GtkDrawingAreaウィジェットによる画像の表示: display2.c
1 # i n c l u d e <g t k / g t k . h >
2 # i n c l u d e <s t d l i b . h >
3
4 s t a t i c g i n t
5 c b _ e x p o s e (G t k W i d g e t * w i d g e t ,
6 G d k E v e n t E x p o s e * e v e n t ,
7 g p o i n t e r u s e r _ d a t a )
8 {
9 G d k P i x b u f * p i x b u f = (G d k P i x b u f * ) u s e r _ d a t a ;
10 G d k P i x b u f * b a c k g r o u n d ;
11 G d k P i x m a p * p i x m a p ;
12 i n t w , h ;
13
14 w = g d k _ p i x b u f _ g e t _ w i d t h ( p i x b u f ) ;
15 h = g d k _ p i x b u f _ g e t _ h e i g h t ( p i x b u f ) ;
16 b a c k g r o u n d = g d k _ p i x b u f _ n e w ( G D K _ C O L O R S P A C E _ R G B , F A L S E , 8 , w , h ) ;
17 g d k _ p i x b u f _ c o m p o s i t e _ c o l o r ( p i x b u f , b a c k g r o u n d ,
18 0 , 0 , w , h , 0 , 0 , 1 . 0 , 1 . 0 ,
19 G D K _ I N T E R P _ B I L I N E A R , 2 5 5 , 0 , 0 , 16 ,
20 0 x a a a a a a , 0 x 5 5 5 5 5 5 ) ;
21 g d k _ p i x b u f _ r e n d e r _ p i x m a p _ a n d _ m a s k ( b a c k g r o u n d , & p i x m a p , N U L L , 2 5 5 ) ;
22 g d k _ w i n d o w _ s e t _ b a c k _ p i x m a p ( w i d g e t - >w i n d o w , p i x m a p , F A L S E ) ;
23 g d k _ w i n d o w _ c l e a r ( w i d g e t - >w i n d o w ) ;
24
25 g _ o b j e c t _ u n r e f ( b a c k g r o u n d ) ;
26 g _ o b j e c t _ u n r e f ( p i x m a p ) ;
27
28 r e t u r n T R U E ;
29 }
30 31 i n t
32 m a i n (i n t ar g c , c h a r * a r g v [ ] )
33 {
34 G t k W i d g e t * w i n d o w ;
35 G t k W i d g e t * c a n v a s ;
36 G d k P i x b u f * p i x b u f ;
37
38 i f ( a r g c < 2 )
39 {
40 g _ p r i n t ( " U s a g e : . / d i s p l a y 2 i m a g e f i l e \ n " ) ;
41 e x i t ( 0 ) ;
42 }
43 g t k _ i n i t ( & a r g c , & a r g v ) ;
図5.2 GtkDrawingAreaウィジェットによる画像の表示
44
45 p i x b u f = g d k _ p i x b u f _ n e w _ f r o m _ f i l e ( a r g v [ 1 ] , N U L L ) ;
46
47 w i n d o w = g t k _ w i n d o w _ n e w ( G T K _ W I N D O W _ T O P L E V E L ) ;
48 g t k _ w i n d o w _ s e t _ t i t l e ( G T K _ W I N D O W ( w i n d o w ) , " D i s p l a y I m a g e 2 " ) ;
49 g _ s i g n a l _ c o n n e c t ( G _ O B J E C T ( w i n d o w ) , " d e s t r o y " ,
50 G _ C A L L B A C K ( g t k _ m a i n _ q u i t ) , N U L L ) ;
51
52 c a n v a s = g t k _ d r a w i n g _ a r e a _ n e w ( ) ;
53 g t k _ w i d g e t _ s e t _ s i z e _ r e q u e s t ( c a n v a s ,
54 g d k _ p i x b u f _ g e t _ w i d t h ( p i x b u f ) ,
55 g d k _ p i x b u f _ g e t _ h e i g h t ( p i x b u f ) ) ;
56 g _ s i g n a l _ c o n n e c t ( G _ O B J E C T ( c a n v a s ) , " e x p o s e - e v e n t " ,
57 G _ C A L L B A C K ( c b _ e x p o s e ) , p i x b u f ) ;
58 g t k _ c o n t a i n e r _ a d d ( G T K _ C O N T A I N E R ( w i n d o w ) , c a n v a s ) ;
59
60 g t k _ w i d g e t _ s h o w _ a l l ( w i n d o w ) ;
61 g t k _ m a i n ( ) ;
62
63 r e t u r n 0 ;
64 }