graphics-gdk-pixbuf.html
来自「linux下gnome编程」· HTML 代码 · 共 1,729 行 · 第 1/4 页
HTML
1,729 行
<HTML><HEAD><TITLE>Gdk-pixbuf</TITLE><METANAME="GENERATOR"CONTENT="Modular DocBook HTML Stylesheet Version 1.61"><LINKREL="HOME"TITLE="Writing GNOME Applications"HREF="index.html"><LINKREL="UP"TITLE="Graphics"HREF="graphics.html"><LINKREL="PREVIOUS"TITLE="Libart"HREF="graphics-libart.html"><LINKREL="NEXT"TITLE="The GNOME Canvas"HREF="gnome-canvas.html"></HEAD><BODYCLASS="SECT1"><DIVCLASS="NAVHEADER"><TABLEWIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><THCOLSPAN="3"ALIGN="center">Writing GNOME Applications</TH></TR><TR><TDWIDTH="10%"ALIGN="left"VALIGN="bottom"><AHREF="graphics-libart.html">Prev</A></TD><TDWIDTH="80%"ALIGN="center"VALIGN="bottom">Chapter 10. Graphics</TD><TDWIDTH="10%"ALIGN="right"VALIGN="bottom"><AHREF="gnome-canvas.html">Next</A></TD></TR></TABLE><HRALIGN="LEFT"WIDTH="100%"></DIV><DIVCLASS="SECT1"><H1CLASS="SECT1"><ANAME="GRAPHICS-GDK-PIXBUF">Gdk-pixbuf</A></H1><P> Libart is designed to manipulate graphics buffers, but it contains no functions to help load existing images into those buffers. It leaves the buffer creation and loading up to you. The gdk-pixbuf library is a toolkit for image loading and pixel buffer manipulation that you can use in conjunction with libart. Gdk-pixbuf also provides convenience functions for progressive image loading, animation (which we won't cover here), and rendering the libart image buffer to a GdkDrawable instance. </P><P> Gdk-pixbuf has a fairly large API. We'll discuss it briefly as we go, and then we'll wrap up the chapter with a sample application. The fundamental currency in the gdk-pixbuf library is the GdkPixbuf structure, a private, opaque data structure that mirrors many of the same concepts that ArtPixBuf supports. In fact, most of GdkPixbuf's private data fields have the same names and data types as the corresponding ones in ArtPixBuf. This similarity dates back to the earlier days when gdk-pixbuf was a wrapper around libart. Since that time, the libart dependency has been stripped out, and gdk-pixbuf is now scheduled to be merged into the GTK+ 2.0 code base. As such, gdk-pixbuf's days as a standalone library are limited to the GNOME 1.x release. </P><DIVCLASS="SECT2"><H2CLASS="SECT2"><ANAME="AEN891">Creating</A></H2><P> To get started, you will have to create a new GdkPixbuf instance. If you're planning on populating the RGB buffer from scratch, or if you want to load several smaller pixel buffers into a larger one, you may want to use gdk_pixbuf_new( ), which creates an uninitialized pixel buffer of guchar elements: </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">GdkPixbuf *gdk_pixbuf_new(GdkColorspace colorspace, gboolean has_alpha, int bits_per_sample, int width, int height); </PRE></TD></TR></TABLE><P> The guchar type is essentially the same data type as libart's art_u8 type, so you can use libart to manipulate the raw pixel buffers in gdk-pixbuf. Given gdk-pixbuf's history with libart, this should come as no surprise. </P><P> The first parameter is a value in the GdkColorspace enumeration, analogous to libart's ArtPixFormat enumeration. For now, you can specify only the value GDK_COLORSPACE_RGB, but other types of color spaces may be supported in the future: </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">typedef enum{ GDK_COLORSPACE_RGB} GdkColorspace; </PRE></TD></TR></TABLE><P> You can request an optional alpha channel for determining image opacity with the has_alpha parameter. The bits_per_sample parameter behaves just like the bits_per_sample field in the ArtPixBuf structure. For the time being, you should always pass in an 8. In the future, gdk-pixbuf might support additional channel depths, but currently it supports only 8-bit channels (just like libart). Finally, you must pass in the width and height of your desired buffer; gdk-pixbuf uses these parameters to calculate the best possible row stride for the new buffer. </P><P> After you've created and initialized your GdkPixbuf structure, you can retrieve information about it with the following set of accessor functions: </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">GdkColorspace gdk_pixbuf_get_colorspace( const GdkPixbuf *pixbuf);int gdk_pixbuf_get_n_channels(const GdkPixbuf *pixbuf);gboolean gdk_pixbuf_get_has_alpha(const GdkPixbuf *pixbuf);int gdk_pixbuf_get_bits_per_sample(const GdkPixbuf *pixbuf);guchar *gdk_pixbuf_get_pixels(const GdkPixbuf *pixbuf);int gdk_pixbuf_get_width(const GdkPixbuf *pixbuf);int gdk_pixbuf_get_height(const GdkPixbuf *pixbuf);int gdk_pixbuf_get_rowstride(const GdkPixbuf *pixbuf); </PRE></TD></TR></TABLE><P> You can also create a GdkPixbuf structure from an existing image or buffer. One approach is to load it up with a graphics file. You can give the gdk_pixbuf_new_from_file( ) function the path to a graphics file. Gdk-pixbuf will automatically invoke one of a handful of its image format loaders to convert the graphics file into an RGB buffer. A second function, gdk_pixbuf_new_from_xpm_data( ), loads inline XPM data: </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">GdkPixbuf *gdk_pixbuf_new_from_file(const char *filename);GdkPixbuf *gdk_pixbuf_new_from_xpm_data(const char **data); </PRE></TD></TR></TABLE><P> Gdk-pixbuf currently supports PNG, XPM, JPEG, TIFF, PNM, RAS, BMP, and even the patented GIF format. The loaders are easy to write and very modular, so gdk-pixbuf is well equipped to keep pace with new and old image formats alike. </P><P> Gdk-pixbuf even lets you create a pixel buffer from an existing raw data buffer. The gdk_pixbuf_new_from_data( ) function is similar to gdk_pixbuf_new( ), except it has four extra parameters: data to pass in your RGB buffer, destroy_fn and destroy_fn_data to register a callback function to clean up the data buffer when the GdkPixbuf is destroyed, and rowstride: </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">typedef void (* GdkPixbufDestroyNotify) (guchar *pixels, gpointer data);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); </PRE></TD></TR></TABLE><P> You must calculate and pass in a rational row stride for the pixel buffer you've created. The pixel buffer is really only a one-dimensional array of guchar elements, so gdk-pixbuf can't guess from the height and width parameters what your intended row stride should be. In the case of gdk_pixbuf_new( ), gdk-pixbuf creates its own pixel buffer and can make its own decision about the row stride. </P><P> You should use this function only if you know what you're doing. Gdk-pixbuf does very little safety checking on the imported buffer, so if your rowstride value doesn't properly match the rows of pixels in your buffer, your image will end up scrambled. Gdk-pixbuf unquestioningly accepts your values, trusting you not to make any mistakes. </P><P> Sometimes you end up with a three-channel RGB pixel buffer that you later need to convert into a four-channel RGBA buffer. The most common example of such a situation occurs when you load a three-channel image from a file but need to use the alpha channel for masking. The file-loading modules create whichever style of GdkPixbuf best matches the image file. You can't tell it ahead of time that you need four-channel pixel buffers, so you're forced to convert it to RGBA after the fact. </P><P> Although it may seem simple at first to tack the extra channel onto each pixel, you'll find that things are a little more complicated if you try this by hand. First you have to create a new GdkPixbuf and copy the pixels into it one by one, adding the extra alpha channel byte to each one as you go. An added twist is the fact that your row stride will always change, so the number of unused padding bytes at the end of each row will change as well. You can't just do a simple byte-by-byte transfer. </P><P> Recall our row stride example from Section 10.3.1, in which an image with a width of 25 pixels had a row stride of 76 (25 3 = 75), which amounts to a single byte of padding per row. Adding an alpha channel to this image will result in a row stride of 100 (25 4), which means that the new buffer will have no padding bytes. Every time you copy over a row of pixels, you will have to drop a byte. </P><P> To save you the effort of reimplementing this algorithm in each application that needs it, gdk-pixbuf offers the gdk_pixbuf_add_alpha( ) convenience function. Simply pass in your three-channel pixel buffer, and this function will generate a new four-channel copy. If you want, you can preload the new alpha channel on the basis of the contents of the image. Set the substitute_color parameter to TRUE and fill the r, g, and b parameters with target color values. The function will turn on the corresponding pixels in the alpha channel each time it finds the target color. This feature is great for transparency, when the backgrounds of your three-channel images have been set to a special masking color. Conversely, if you set substitute_color to FALSE, the function will ignore the three color parameters and initialize the alpha channel to show the full image: </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">GdkPixbuf *gdk_pixbuf_add_alpha(const GdkPixbuf *pixbuf, gboolean substitute_color, guchar r, guchar g, guchar b); </PRE></TD></TR></TABLE><P> To make it easier to share and manage RGB buffers, gdk-pixbuf implements the familiar reference-counting scheme (see Section 2.2.5). All newly created pixbufs start out with a reference count of 1, so you should need to call gdk_pixbuf_ref( ) for only the second and later owners. When you're done with the pixbuf, always call gdk_pixbuf_unref( ), which automatically destroys the pixbuf when the reference count reaches 0, but not before. For this reason gdk-pixbuf doesn't have an explicit destroy function. </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">void gdk_pixbuf_ref(GdkPixbuf *pixbuf);void gdk_pixbuf_unref(GdkPixbuf *pixbuf); </PRE></TD></TR></TABLE><P> If you need a physically separate copy of a pixel buffer, and not just a shared reference to an existing one, you can use gdk_pixbuf_copy( ) to create a new pixbuf identical to the one you pass in: </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">GdkPixbuf* gdk_pixbuf_copy(const GdkPixbuf *pixbuf); </PRE></TD></TR></TABLE></DIV><DIVCLASS="SECT2"><H2CLASS="SECT2"><ANAME="AEN917">Rendering</A></H2><P> After you have tweaked your image buffer and loaded it into a GdkPixbuf structure, you'll probably want to display it on the screen. GNOME offers various ways to do this, particularly within the GnomeCanvas widget (see Section 11.4.6). In this chapter we'll focus on displaying the buffer in a GdkDrawable instance. </P><P> One of the most frustrating limitations of the current incarnation of the X Window System is its lack of support for a full-fledged alpha channel. In X you cannot perform all the alpha blending that libart and gdk-pixbuf support. You can only use alpha blending and anti-aliasing on local image buffers, and then transfer those buffers as a whole to the X drawables. There are tentative plans for an alpha channel extension to X, but those hopes are off in the future. </P><P> The basic rendering tools of X support only binary masks: Either copy a pixel in its original color, or don't copy it at all. X does not allow you to perform color blending during an image copy. You can render shaped images to a drawable by specifying a 1-bit mask (a GdkBitmap), but those images will have sharp edges. You won't be able to smoothly blend your new image into the old image residing in the GdkDrawable. Thus if you want anti-aliased drop shadows, you must take care of them within the RGB buffer, before you render the image to the X drawable. Internally, gdk-pixbuf uses GdkRGB to handle the complexities of color maps, visuals, and dithering. </P><P> To express the nature of the mask it will use when rendering to a drawable, gdk-pixbuf declares the GdkPixbufAlphaMode enumeration: </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">typedef enum{
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?