您的位置:首页 > 大数据 > 人工智能

Cairo 图形指南 (11) —— 图像

2010-04-30 17:04 309 查看
在这一篇里,要讲述图像的处理。先是演示如何在 GTK+ 窗口中显示一幅图像,然后再制造一些特效。

在第一个例子里,显示了一幅图像。



01.

#

include

<cairo.h>


02.

#

include

<gtk/gtk.h>


03.


04.

cairo_surface_t *image;


05.


06.

static

gboolean


07.

on_expose_event(GtkWidget *widget,


08.


GdkEventExpose *event,


09.


gpointer data)


10.

{


11.


cairo_t *cr;


12.


13.


cr = gdk_cairo_create (widget->window);


14.


15.


cairo_set_source_surface(cr,image,

10

,

10

);


16.


cairo_paint(cr);


17.


18.


cairo_destroy(cr);


19.


20.


return

FALSE;


21.

}


22.


23.


24.

int

main(

int

argc,char *argv[])


25.

{


26.


GtkWidget *window;


27.


28.


image = cairo_image_surface_create_from_png(

"plaveckycastle.png"

);


29.


30.


gtk_init(&argc,&argv);


31.


32.


window = gtk_window_new(GTK_WINDOW_TOPLEVEL);


33.


34.


g_signal_connect(window,

"expose-event"

,


35.


G_CALLBACK (on_expose_event),NULL);


36.


g_signal_connect(window,

"destroy"

,


37.


G_CALLBACK (gtk_main_quit),NULL);


38.


39.


gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER);


40.


gtk_window_set_default_size(GTK_WINDOW(window),

320

,

250

);


41.


gtk_widget_set_app_paintable(window,TRUE);


42.


43.


gtk_widget_show_all(window);


44.


45.


gtk_main();


46.


47.


cairo_surface_destroy(image);


48.


49.


return

0

;


50.

}


这个示例显示了一幅图片,其尺寸为 300x225,可从这里

下载。这是斯洛伐克西部一个什么地方(Plavecke Podhradie)的中世纪城堡的废墟的一幅照片。

view source

print
?

1.

image = cairo_image_surface_create_from_png(

"plaveckycastle.png"

);


用一幅 png 图片来创建一份图像外观。出于效率的考虑,应在主函数中调用这个函数。

view source

print
?

1.

cairo_set_source_surface(cr,image,10,10);


基于前面构造的图像外观来创建源与外观,用于图像的绘制。

view source

print
?

1.

cairo_paint(cr);


绘制图片。



垂帘效果(Blind Down)

在下面的代码示例中,要垂帘显示图片,就像拉下窗帘的那种效果。

view source

print
?

01.

#include <cairo.h>


02.

#include <gtk/gtk.h>


03.


04.


05.

gboolean timer = TRUE;


06.

cairo_surface_t *image;


07.


08.


09.

static

gboolean


10.

on_expose_event(GtkWidget *widget,


11.


GdkEventExpose *event,


12.


gpointer data)


13.

{


14.


cairo_t *cr;


15.


cairo_t *ic;


16.


17.


cairo_surface_t *surface;


18.


19.


static

gdouble angle = 0;


20.


static

gint image_width = 0;


21.


static

gint image_height = 0;


22.


23.


static

gint w = 0;


24.


static

gint h = 0;


25.


26.


cr = gdk_cairo_create(widget->window);


27.


28.


gint width,height;


29.


gtk_window_get_size(GTK_WINDOW(widget),&width,&height);


30.


31.


image_width = cairo_image_surface_get_width(image);


32.


image_height = cairo_image_surface_get_height(image);


33.


w = image_width;


34.


35.


surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,image_width,image_height);


36.


ic = cairo_create(surface);


37.


38.


cairo_rectangle(ic,0,0,w,h);


39.


cairo_fill(ic);


40.


41.


h += 1;


42.


if

( h == image_height) timer = FALSE;


43.


44.


cairo_set_source_surface(cr,image,10,10);


45.


cairo_mask_surface(cr,surface,10,10);


46.


47.


cairo_surface_destroy(surface);


48.


49.


cairo_destroy(cr);


50.


cairo_destroy(ic);


51.


return

FALSE;


52.

}


53.


54.

static

gboolean


55.

time_handler(GtkWidget *widget)


56.

{


57.


if

(widget->window == NULL)

return

FALSE;


58.


59.


if

(!timer)

return

FALSE;


60.


61.


gtk_widget_queue_draw(widget);


62.


return

TRUE;


63.

}


64.


65.

int

main(

int

argc,

char

*argv[])


66.

{


67.


GtkWidget *window;


68.


69.


image = cairo_image_surface_create_from_png(

"plaveckycastle.png"

);


70.


71.


gtk_init(&argc,&argv);


72.


73.


window = gtk_window_new(GTK_WINDOW_TOPLEVEL);


74.


75.


g_signal_connect(G_OBJECT(window),

"expose-event"

,


76.


G_CALLBACK(on_expose_event),NULL);


77.


g_signal_connect(G_OBJECT(window),

"destroy"

,


78.


G_CALLBACK(gtk_main_quit),NULL);


79.


80.


gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER);


81.


gtk_window_set_default_size(GTK_WINDOW(window),325,250);


82.


gtk_window_set_title(GTK_WINDOW(window),

"blind down"

);


83.


84.


gtk_widget_set_app_paintable(window,TRUE);


85.


g_timeout_add(15,(GSourceFunc) time_handler,(gpointer) window);


86.


87.


gtk_widget_show_all(window);


88.


89.


gtk_main();


90.


91.


cairo_surface_destroy(image);


92.


93.


return

0;


94.

}


这个垂帘效果幕后的思想相当简单。图片的高度是 h 个像素,则可对其逐行进行绘制,直至图片完全显示。

view source

print
?

1.

cairo_t *cr;


2.

cairo_t *ic;


声明两个 cairo 环境,一个与 GtkWindow 相关联,另一个与图片相关联。

view source

print
?

1.

surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,image_width,image_height);


2.

ic = cairo_create(surface);


创建一个图像外观,并通过它构造那个与图像相关联的 cairo 环境。

view source

print
?

1.

cairo_rectangle(ic,0,0,w,h);


2.

cairo_fill(ic);


在初始的空图像中绘制一个矩形,它在循环显示中会增加 1 个像素的高度。采用这种方式创建的图像在后面要作为蒙板来用。

view source

print
?

1.

h += 1;


2.

if

( h == image_height) timer = FALSE;


整幅图像绘制完毕后,停止计时器。

view source

print
?

1.

cairo_set_source_surface(cr,image,10,10);


2.

cairo_mask_surface(cr,surface,10,10);


城堡图像被设置为要被绘制的源,并采用 surface 的 alpha 通道作为蒙板来绘制这个源。



光谱效果

将这种效果称为光谱效果,因为作者不知道怎么称呼才好(我感觉叫百叶窗效果更好)。可能你还记得从前的 ZX 光谱计算机,在这种计算机上载入图像时,它就逐渐的被显示出来,下面的示例大致是模仿这种方式。

view source

print
?

001.

#include <cairo.h>


002.

#include <gtk/gtk.h>


003.


004.


005.

gboolean timer = TRUE;


006.

cairo_surface_t *image;


007.


008.

static

gboolean


009.

on_expose_event(GtkWidget *widget,


010.


GdkEventExpose *event,


011.


gpointer data)


012.

{


013.


cairo_t *cr;


014.


cairo_t *ic;


015.


016.


cairo_surface_t *surface;


017.


018.


static

gdouble angle = 0;


019.


static

gint w = 0;


020.


static

gint h = 0;


021.


022.


static

gint image_width = 0;


023.


static

gint image_height = 0;


024.


025.


static

gint count = 0;


026.


027.


cr = gdk_cairo_create(widget->window);


028.


029.


gint width,height;


030.


gtk_window_get_size(GTK_WINDOW(widget),&width,&height);


031.


032.


surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,image_width,image_height);


033.


034.


image_width = cairo_image_surface_get_width(image);


035.


image_height = cairo_image_surface_get_height(image);


036.


w = image_width;


037.


038.


ic = cairo_create(surface);


039.


040.


gint i,j;


041.


for

(i = 0; i <= image_height; i+=7) {


042.


for

(j=0 ; j < count; j++) {


043.


cairo_move_to(ic,0,i+j);


044.


cairo_line_to(ic,w,i+j);


045.


}


046.


}


047.


048.


count++;


049.


if

( count == 8) timer = FALSE;


050.


051.


cairo_stroke(ic);


052.


053.


cairo_set_source_surface(cr,image,10,10);


054.


cairo_mask_surface(cr,surface,10,10);


055.


056.


cairo_surface_destroy(surface);


057.


058.


cairo_destroy(cr);


059.


cairo_destroy(ic);


060.


return

FALSE;


061.

}


062.


063.

static

gboolean


064.

time_handler (GtkWidget *widget)


065.

{


066.


if

(widget->window == NULL)

return

FALSE;


067.


068.


if

(!timer)

return

FALSE;


069.


070.


gtk_widget_queue_draw(widget);


071.


return

TRUE;


072.

}


073.


074.

int

main(

int

argc,

char

*argv[])


075.

{


076.


GtkWidget *window;


077.


078.


image = cairo_image_surface_create_from_png(

"plaveckycastle.png"

);


079.


080.


gtk_init(&argc,&argv);


081.


082.


window = gtk_window_new(GTK_WINDOW_TOPLEVEL);


083.


084.


g_signal_connect(G_OBJECT(window),

"expose-event"

,


085.


G_CALLBACK(on_expose_event),NULL);


086.


g_signal_connect(G_OBJECT(window),

"destroy"

,


087.


G_CALLBACK(gtk_main_quit),NULL);


088.


089.


gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER);


090.


gtk_window_set_default_size(GTK_WINDOW(window),325,250);


091.


092.


gtk_widget_set_app_paintable(window,TRUE);


093.


g_timeout_add(400,(GSourceFunc) time_handler,(gpointer) window);


094.


095.


gtk_widget_show_all(window);


096.


097.


gtk_main();


098.


099.


cairo_surface_destroy(image);


100.


101.


return

0;


102.

}


这个示例的许多细节与上一个示例相似。这次,是将图像分为每 8 行为一个区域。在每次循环中,8 个部分中每个区域增加一个像素高度。通过这种方式创建的图像将再一次作为模板来显示城堡图像。

view source

print
?

1.

gint i,j;


2.

for

(i = 0; i <= image_height; i+=7) {


3.


for

(j=0 ; j < count; j++) {


4.


cairo_move_to(ic,0,i+j);


5.


cairo_line_to(ic,w,i+j);


6.


}


7.

}


这是该示例的主要逻辑,我们逐渐的将线绘制到各区域。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: