GTK+中文社区(gtk.awaysoft.com)

 找回密码
 马上加入

QQ登录

只需一步,快速开始

查看: 6727|回复: 2

GTK编程——绘图

[复制链接]

该用户从未签到

发表于 2011-4-25 17:17:46 | 显示全部楼层 |阅读模式
1.GtkImage


GtkWidget*  gtk_image_new_from_animation(GdkPixbufAnimation *animation);
Returns :a new GtkImage widget(下同)

GtkWidget*  gtk_image_new_from_file(const gchar *filename);     Returns :a new GtkImage

GtkWidget*  gtk_image_new_from_gicon(GIcon *icon,  GtkIconSize size);

GtkWidget*  gtk_image_new_from_icon_name(const gchar *icon_name,  GtkIconSize size);

GtkWidget*  gtk_image_new_from_icon_set(GtkIconSet *icon_set,   GtkIconSize size);

GtkWidget*  gtk_image_new_from_image(GdkImage *image, GdkBitmap *mask);

GtkWidget*  gtk_image_new_from_pixbuf(GdkPixbuf *pixbuf);

GtkWidget*  gtk_image_new_from_pixmap(GdkPixmap *pixmap, GdkBitmap *mask);

GtkWidget*  gtk_image_new_from_stock(const gchar *stock_id, GtkIconSize size);
2.Bitmaps and Pixmaps


GdkPixmap是GdkDrawable的子类。GdkDrawable和Win32下的DC(DeviceContext)有点类似,你可以在上面画直线、画圆或者在上面贴图片。DC有很多不同的子类,最常见的有内存DC,打印机DC,屏幕DC。同样,GdkDrawable也有很多子类,非要和Win32对应起来的话,GdkPixmap的地位和内存DC差不多。

GdkPixbuf的功能近似于位图(bitmap),但一般仅限于在内存使用中,没有定义特定的存储格式。可以把任意格式的图片文件加裁到一个GdkPixbuf中; 可以把GdkPixbuf贴到GdkDrawable任意子类的对象上; 也可以把GdkDrawable任意子类的对象转换成GdkPixbuf对象,然后把GdkPixbuf对象存为指定格式的图片文件。
GTK+提供了几个函数在这两者之间转换:
gdk_draw_pixbuf 把GdkPixbuf对象贴到GdkDrawable对象上。
gdk_pixbuf_get_from_drawable 从GdkDrawable对象中得到GdkPixbuf对象。

GdkPixbuf是GdkDrawable的子类,这两个函数自然也适用于GdkPixmap。

GdkPixmap*  gdk_pixmap_new(GdkDrawable *drawable,gint width,gint height,gint depth);

GdkBitmap* gdk_bitmap_create_from_data(GdkDrawable *drawable,const gchar *data,gint width,gint height);

GdkPixmap* gdk_pixmap_create_from_data(GdkDrawable *drawable,const gchar *data,gint width,gint height,gint depth,
                                       const GdkColor *fg,const GdkColor *bg);

GdkPixmap* gdk_pixmap_create_from_xpm(GdkDrawable *drawable,GdkBitmap **mask,const GdkColor *transparent_color,
                                      const gchar *filename);

GdkPixmap* gdk_pixmap_colormap_create_from_xpm (GdkDrawable *drawable,GdkColormap *colormap, GdkBitmap **mask,
                                                const GdkColor *transparent_color,const gchar *filename);

GdkPixmap* gdk_pixmap_create_from_xpm_d(GdkDrawable *drawable,GdkBitmap **mask,const GdkColor *transparent_color,
                                        gchar **data);

GdkPixmap* gdk_pixmap_colormap_create_from_xpm_d(GdkDrawable *drawable, GdkColormap *colormap, GdkBitmap **mask,
                                                 const GdkColor *transparent_color, gchar **data);

GdkPixmap* gtk_widget_get_snapshot(GtkWidget *widget,GdkRectangle *clip_rect);

GdkPixmap* gtk_widget_get_snapshot(GtkWidget *widget,GdkRectangle *clip_rect);

typedef struct {
  gint x;
  gint y;
  gint width;
  gint height;
} GdkRectangle;
3.GdkPixbuf


GdkPixbuf * gdk_pixbuf_new(GdkColorspace colorspace,gboolean has_alpha,int bits_per_sample,int width,int height);

GdkPixbuf * gdk_pixbuf_new_from_data(const guchar *data, GdkColorspace colorspace, gboolean has_alpha,
                                     int bits_per_sample, int width, int height, int rowstride,
                                     GdkPixbufDestroyNotify destroy_fn, gpointer destroy_fn_data);

GdkPixbuf * gdk_pixbuf_new_from_xpm_data(const char **data);

GdkPixbuf*  gdk_pixbuf_new_from_inline(gint data_length,const guint8 *data,gboolean copy_pixels, GError **error);

GdkPixbuf * gdk_pixbuf_new_subpixbuf(GdkPixbuf *src_pixbuf,int src_x,int src_y,int width,int height);

GdkPixbuf * gdk_pixbuf_copy(const GdkPixbuf *pixbuf);

GdkPixbuf * gtk_widget_render_icon(GtkWidget *widget,const gchar *stock_id,GtkIconSize size,const gchar *detail);

GdkPixbuf * gdk_pixbuf_get_from_drawable(GdkPixbuf *dest,GdkDrawable *src,GdkColormap *cmap,int src_x,int src_y,
                                         int dest_x,int dest_y,int width,int height);

GdkPixbuf * gdk_pixbuf_get_from_image(GdkPixbuf *dest,GdkImage *src,GdkColormap *cmap,int src_x,int src_y,
                                      int dest_x,int dest_y,int width,int height);

GdkPixbuf*          gtk_image_get_pixbuf                (GtkImage *image);
GTK 绘图

一旦理解了绘图区、颜色、视件、图形上下文和字体,绘图就会变得很简单了。本节简要介绍了Gdk的相关绘图函数。要注意的是绘图是一种服务器端的操作,例如,如果要画一条线,Xlib会将线的端点传给服务器,服务器用特定的GC(GC也是一种服务器端资源)做实际的绘图操作。创建绘图应用程序时通常要考虑程序的性能。

16.9.1画点

可以用gdk_draw_point()函数画一个点,或用gdk_draw_points()函数画多个点。点是用当前的前景颜色画的。多个点是由一个GdkPoint数组给出的。GdkPoint结构如下所示:

typedefstruct_GdkPointGdkPoint;
struct_GdkPoint
{
gint16x;
gint16y;
};

注意,X坐标是从绘图区的左上角开始的,是一个有符号的16位整数。函数列表:画点

#include<gdk/gdk.h>
void  gdk_draw_point(GdkDrawable*drawable, GdkGC*gc, gintx,ginty)
void gdk_draw_points(GdkDrawable*drawable, GdkGC*gc, GdkPoint*points, gintnpoints)

16.9.2画线

用gdk_draw_line()函数画一条线,将线的端点作为它的参数。要画几条连接着的线,可调用gdk_draw_lines()函数,并将点的列表作为参数传到函数中。Gdk会将点连接起来。要画多条不必连接起来的线,可调用gdk_draw_segments()函数,将线段列表作为参数传到函数中。

GdkSegment结构是这样定义的:

typedefstruct_GdkSegmentGdkSegment;
struct_GdkSegment
{
gint16x1;
gint16y1;
gint16x2;
gint16y2;
};

如果在同一个绘画请求中画出的线或者线段的端点是相交的,它们会以GC中的“连接风格”连接起来。
函数列表:画线

#include<gdk/gdk.h>
void gdk_draw_line(GdkDrawable*drawable, GdkGC*gc, gintx1, ginty1, gintx2, ginty2)
void gdk_draw_lines(GdkDrawable*drawable, GdkGC*gc, GdkPoint*points, gintnpoints)
voidgdk_draw_segments(GdkDrawable*drawable, GdkGC*gc, GdkSegment*segments, gintnsegments)

16.9.3矩形

用gdk_draw_rectangle()函数画矩形。其中filled参数指明是否填充矩形,设为TRUE意味着填充它,FALSE则不填充。

函数列表:画矩形

#include<gdk/gdk.h>
voidgdk_draw_rectangle(GdkDrawable*drawable, GdkGC*gc, gintfilled, gintx, ginty, gintwidth, gintheight)

16.9.4画弧

gdk_draw_arc()函数画一个椭圆或椭圆弧。弧可以是填充的,也可以是不填充的,第3个参数切换填充状态。第4到第7个参数描绘了一个矩形,椭圆内切于这个矩形;angle1参数是画弧的起始角,它以时钟三点钟位置为0°;angle2是绕圆弧旋转的角度,如果值是正的,逆时针旋转,否则顺时针旋转。参数angle1和angle2都是以1/64度来指定的,所以360°就是360×64。这样可以更精确地指定弧形的尺寸和形状,而不需使用浮点数。参数angle2不要超过360°,因为对椭圆来说旋转角度超过360°没有什么意义。

要画一个圆,在正方形内从0到360×64画一个弧:

gdk_draw_arc(drawable,gc,TRUE,0,0,50,50,0,360*64);

要画一个半椭圆,改变长轴和短轴的比例,角度从0到180×64:

gdk_draw_arc(drawable,gc,TRUE,0,0,100,50,0,180*64);

有许多X服务器在用来画填充圆弧的边缘时是很难看的,特别是很小的圆看起来会不太圆。要解决这个问题,可以在画圆时把圆的轮廓也画出来。

函数列表:画弧

#include<gdk/gdk.h>
void gdk_draw_arc(GdkDrawable* drawable, GdkGC* gc, gint filled, gint x, gint y, gint width, gint height,

                                   gint   angle1, gint angle2)

16.9.5多边形

gdk_draw_polygon()函数用来画一个填充或不填充的多边形。注意,也可以用gdk_draw_lines()函数画一个不填充的多边形。这那种方法并没有什么实质区别。

gdk_draw_polygon()函数的参数与gdk_draw_lines()中的参数完全一样。多边形不一定必须是凸多边形。它的边可以是交叉的(自交)。自交的多边形用一种“奇-偶规则”来填充,规则是重叠奇数次的多边形区域是不填充的。也就是,如果多边形不是重叠的,它就是完全填充的;如果一个区域重叠了一次,它不会被填充;如果它重叠了两次,它会被填充等等。

函数列表:画多边形

#include<gdk/gdk.h>
voidgdk_draw_polygon(GdkDrawable* drawable, GdkGC* gc, gint filled, GdkPoint* points,  gint npoints)

16.9.6文本

有两个函数可用于绘制字符串:gdk_draw_text()和gdk_draw_string()。其中gdk_draw_text()是最好的方法。gdk_draw_text()用字符串的长度作为参数,而gdk_draw_string()函数用strlen()函数计算字符串的长度。函数中的x和y坐标指定要绘制的文本基线的左边位置。文本是用前景颜色绘出的。

在Gdk中没有方法画出缩放的或旋转的文本。GnomeCanvasText构件提供了一个较慢的、质量较低的方法来渲染缩放的和旋转的文本。如果需要高质量的按比例缩放的和旋转的文本,则需要使用额外的库函数,比如说对Type1fonts字体使用t1lib库函数,或对TrueTypefonts 字体使用FreeType库函数,或者使用DisplayPostscript的X扩展(XDPS)。GNU项目组正致力于开发一个免费的XDPS的 Linux版本。作为gnome-print库的一部分,Gnome项目组也正在开发一个文本绘图方案。

函数列表:画文本

#include<gdk/gdk.h>
voidgdk_draw_string(GdkDrawable* drawable, GdkFont* font, GdkGC* gc, gint x, gint y, const gchar* text)
voidgdk_draw_text(GdkDrawable* drawable, GdkFont* font, GdkGC* gc, gint x, gint y, const gchar* text,  gint text_length)

16.9.7        pixmap像素映射图形

gdk_draw_pixmap()从一个像素映射图形中复制一个区域到另一个绘图区(像素映射或窗口)。绘图区的源和目的必须有相同的深度和视件(visual)。如果给width或height参数传递-1值,会将源pixmap图片全部复制过去。源图片可以是任何绘图区,包括窗口,但是如果源是一个窗口,使用gdk_window_copy_area()函数将使代码更清晰。下面是gdk_draw_pixmap()函数的声明形式。

函数列表:画pixmaps图形

#include<gdk/gdk.h>
voidgdk_draw_pixmap(GdkDrawable*  drawable,
                                     GdkGC*  gc,
                                     GdkDrawable*  src,
                                     gint  xsrc,
                                     gint  ysrc,
                                     gint  xdest,
                                     gint  ydest,
                                     gint  width,
                                     gint  height)

16.9.8RGB缓冲

Gdk的GdkRGB模块允许将一个图像数据的客户端缓冲复制到一个绘图区。如果要大量操作图像,或将图像数据复制到服务器,最好使用这种方法。因为 pixmap是一种服务器端对象,不能直接操纵GdkPixmap。用gdk_draw_point()函数复制图像数据到服务器中是非常慢的,因为每一个点都要求一个服务器请求(也许还不止一个,因为还需要为每个点更改其GC)。

本质上来说,GdkRGB用一个称为GdkImage的对象在一个请求内将图象数据复制到服务器。这样还是有点慢(大量的数据需要复制),但是 GdkRGB是已经对此进行了优化,并且如果客户和服务器碰巧是在同一台机器上,它还会使用共享内存。所以在X结构中,这是完成这个任务最快的方法。它还会处理一些微妙的问题(比如说适应给定X服务器上的颜色表和视件)。

GdkRGB函数是在一个单独的头文件gdk/gdkrgb.h.里面定义的。在使用任何GdkRGB函数前,必须用gdk_rgb_init()函数初始化GdkRGB模块,它设置一些要用到的视件和颜色表,以及一些内部的数据结构。
要将RGB缓冲复制进去的绘图区必须使用GdkRGB的视件和颜色表。如果绘图区是构件的一部分,保证这一点最简单的方法就是在创建构件时将GdkRGB视件和颜色表压入构件的视件和颜色表栈中:

GtkWidget*widget;
gtk_widget_push_visual(gdk_rgb_get_visual());
gtk_widget_push_colormap(gdk_rgb_get_cmap());
widget=gtk_whatever_new();
gtk_widget_pop_visual();
gtk_widget_pop_colormap();

如果创建包含绘图区的顶级窗口时像上面那么做,而不是在只在创建绘图区时做,当前的Gtk+版本表现还是较好的。不过,原则上可以只对绘图区做这样的工作。

GdkRGB能理解几种类型的图像数据,包括24位和32位RGB数据、8位灰度级,以及8位的按RGB值数组索引的数据(一种客户端 GdkRgbCmap)。本节只介绍最简单的24位RGB数据,这种缓冲数据是用gdk_draw_rgb_image()函数渲染的。有一些单独的函数用于渲染其他缓冲类型,但是所有其他函数本质上的工作原理都是一样的。

24位RGB缓冲是一个一维的字节数组,每个字节三个一组组成像素值(0位是红色,1位是绿色,2位是蓝色)。三个数字描述了数组的大小和字节的位置:width是图像每行的像素数(三个字节)。

height是图像的行数。

Rowstride(行跨距)是行之间的字节数。也就是说,对一个rowstride为r的缓冲,如果第n行从数组索引i开始,那么第n+1行从数组索引i+r开始。rowstride不一定是缓冲宽度的三倍;如果源指针和rowstride都与4字节边界对齐,GdkRGB会较块。指定一个 rowstride允许用填充量来达到这个效果。

gdk_rgb_draw_image()中的x、y、width和height参数定义了目标可绘区中的一个区域,RGB缓冲就复制到这个区域。RGB缓冲至少要有width列、height行。RGB缓冲的第0行第0列将复制到可绘区的(x,y)。
gdk_draw_rgb_image函数中的dither(抖动)参数在有限调色板的显示器上模拟很多颜色。

dither只在8位和16位的显示器上管用,24位的显示器的调色板没有什么限制。dither参数是一个枚举类型,有下列几种可能取值:

GDK_RGB_DITHER_NONE规定没有抖动。它对画文本或用较少的颜色画线很合适,但是对处理照片不合适。

GDK_RGB_DITHER_NORMAL规定在8位的显示器上抖动。但在16位的显示器上不抖动。这通常是质量/性能的一个折衷。

GDK_RGB_DITHER_MAX规定在8位和16位的显示器上都抖动。在16位显示器上使用GDK_RGB_DITHER_MAX能够使绘图质量获得提高,但是与性能损失相比可能不值得这么做。gdk_draw_rgb_image()的gc参数被简单地传递到gdk_draw_image() 函数中(GdkRGB在内部使用GdkImage)。最好使用有意义的gc值(比如剪裁屏蔽值、绘图函数,以及subwindow模式)。

函数列表:GdkRGB

#include<gdk/gdkrgb.h>
void   gdk_rgb_init()
GdkColormap*   gdk_rgb_get_cmap()
GdkVisual*   gdk_rgb_get_visual()
voidgdk_draw_rgb_image(GdkDrawable*  drawable,
                                          GdkGC*  gc,
                                          gint  x,
                                          gint  y,
                                          gint  width,
                                          gint  height,
                                          GdkRGBDither  dither,
                                          guchar*  rgb_buf,
                                          gint  rowstride)

评分

参与人数 1 +10 收起 理由
Tom + 10 优秀文章

查看全部评分

该用户从未签到

发表于 2011-4-26 07:21:08 | 显示全部楼层
lz介绍的东西有些过时了,在gtk3中都被抛弃了(除了 GtkImage和 GdkPixbuf,不过GdkPixbuf的去留也是个问题了,有可能在3.2中被GdkPicture取代)
盛洋科技 该用户已被删除
发表于 2012-12-2 10:49:27 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
*滑块验证:
您需要登录后才可以回帖 登录 | 马上加入

本版积分规则

申请友链|Archiver|小黑屋|手机版|GTK+中文社区 ( 粤ICP备13080851号 )

我要啦免费统计

GMT+8, 2024-3-29 09:57 , Processed in 0.049134 second(s), 9 queries , Redis On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表