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 + -
显示快捷键?