graphics-gdk-pixbuf.html
来自「linux下gnome编程」· HTML 代码 · 共 1,729 行 · 第 1/4 页
HTML
1,729 行
defined by src_x, src_y, width, and height in the source pixel buffer, into the destination pixel buffer at (dest_x, dest_y): </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">void gdk_pixbuf_copy_area(const GdkPixbuf *src_pixbuf, int src_x, int src_y, int width, int height, GdkPixbuf *dest_pixbuf, int dest_x, int dest_y); </PRE></TD></TR></TABLE></DIV><DIVCLASS="SECT2"><H2CLASS="SECT2"><ANAME="AEN973">Progressive Loading</A></H2><P> Gdk-pixbuf's image-loading facilities make it very easy for you to load a variety of graphics file formats without doing any extra work. All you have to do is supply the file name, and gdk-pixbuf will handle the rest. However, the file- loading system has one potentially limiting flaw: It blocks until it's finished. With icons and smaller images, this temporary stall is not noticeable enough to matter, but when the file is particularly large, or is loading from a remote site with a slow connection, your application may flounder in an input/output loop, unable to update itself. The resulting slowness gives your application a buggy, unresponsive appearance, even though it has a good reason for stalling. </P><P> To address this problem, the gdk-pixbuf library offers the GdkPixbufLoader API. GdkPixbufLoader is a derivative of GtkObject that allows the loading process to be controlled by your application rather than by gdk-pixbuf's image-loading code. Because it's derived from GtkObject, GdkPixbufLoader can notify you through GTK+ signals when something interesting happens. </P><P> The interface is simple and straightforward. You create a loader object, write chunks of raw image data to it, and then close it when you're done. As soon as the loader receives enough of the graphics file to determine what sort of image it's loading, it creates a GdkPixbuf structure in which to store the image data. When you close the loader, it unreferences that GdkPixbuf, so if you want the pixbuf still to exist after you're done with the loader, your appli- cation will need to explicitly call gdk_pixbuf_ref( ) on it (and of course release it when you're done). The best place to reference the pixbuf is inside an area_prepared signal callback, which we'll discuss in a moment. </P><P> The loader uses the same code to load images into GdkPixbufLoader that gdk-pixbuf uses inside gdk_pixbuf_new_from_file( ). Here's the basic GdkPixbufLoader API: </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">GdkPixbufLoader* gdk_pixbuf_loader_new( );gboolean gdk_pixbuf_loader_write(GdkPixbufLoader *loader, const guchar *buf, size_t count);GdkPixbuf* gdk_pixbuf_loader_get_pixbuf( GdkPixbufLoader *loader);void gdk_pixbuf_loader_close(GdkPixbufLoader *loader); </PRE></TD></TR></TABLE><P> The loader has three signals of interest to us here.3 Here are the prototypes for these signals, from the GdkPixbufLoaderClass structure: </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">void (* area_prepared) (GdkPixbufLoader *loader);void (* area_updated) (GdkPixbufLoader *loader, guint x, guint y, guint width, guint height);void (* closed) (GdkPixbufLoader *loader); </PRE></TD></TR></TABLE><P> The aforementioned area_prepared signal indicates that the loader has read enough of the file to calculate the size and color depth of the image. Until the loader has this information, it makes no sense to create the target GdkPixbuf. This first milestone is important enough to merit a special signal emission because it means that your application can allocate space in the display for the image. If you connect to the area_prepared signal, you should take the opportunity in your callback to call gdk_pixbuf_ref( ) on the supplied pixbuf. Also, you are guaranteed at this point that the loader has not started writing into the new pixel buffer, so you can fill it with whatever background you want, whether it's a solid color or a placeholder image. As image data continues to pour into the loader, your background image will slowly be written over, line by line, until the full image arrives. </P><P> You'll receive only one area_prepared signal per loader, but altogether you'll end up receiving several area_updated signals. In fact, each time you call gdk_pixbuf_loader_write( ), the loader will fire off another area_updated signal. If you're displaying the progressive image to a drawable-which, after all, is largely the point of using GdkPixbufLoader- you should use this opportunity to update the display. In the sample application at the end of this chapter, we do this by copying the currently loaded portion of the image to a GdkPixmap drawable with gdk_pixbuf_render_to_drawable_alpha( ) and then triggering a refresh with gtk_widget_draw( ). </P><P> The final signal, closed, is useful if you want to know when the image is completely loaded. If other parts of your application, such as a Web browser window, need to be notified when the image is complete, you can connect them to the loader's closed signal, rather than blocking until then. </P></DIV><DIVCLASS="SECT2"><H2CLASS="SECT2"><ANAME="AEN985">Autoconf Support</A></H2><P> To facilitate its integration with the GNOME build system, the gdk-pixbuf package contains an autoconf macro, a gdk-pixbuf-config tool, and a drop-in extension for gnome-config. </P><P> You can use the macro AM_PATH_GDK_PIXBUF in your configure.in file to run a series of checks for gdk-pixbuf. It works just as you would expect: You give it the minimum version of gdk-pixbuf your application requires, followed by an optional shell-scripted action to perform if the target system has a valid gdk-pixbuf installation, and a second action to perform if the target system fails the test: </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">AM_PATH_GDK_PIXBUF([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) </PRE></TD></TR></TABLE><P> The macro will call AC_SUBST on the GDK_PIXBUF_CFLAGS and GDK_PIXBUF_LIBS variables, which you can then reference from your Makefile.am file. It also runs some safety checks to alert the administrator of any strange behavior in the current gdk-pixbuf installation. Finally, it adds the options --with-gdk-pixbuf-prefix and --with-gdk-pixbuf-exec-prefix to the configure script to handle cases in which gdk-pixbuf is installed in a nonstandard place on the target system. </P><P> Gdk-pixbuf supplies its own version of gnome-config, called gdk-pixbuf-config, for retrieving path and version information at the command line. It also installs a plug-in extension so that you can get the same information from gnome-config. You can run either one of these commands to obtain the necessary CFLAGS parameters for gdk-pixbuf: </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">gnome-config gdk_pixbuf --cflagsgdk-pixbuf-config --cflags </PRE></TD></TR></TABLE></DIV><DIVCLASS="SECT2"><H2CLASS="SECT2"><ANAME="AEN993">Gdk-pixbuf Application Example</A></H2><P> In our sample graphics application, we will touch on many points related to what we've just been discussing. We will see how to create a GdkPixbuf structure from a file and from an existing raw buffer. We will see how to copy image data from buffer to buffer, and from buffer to GDK drawable. We'll dip into image scaling and compositing, event handling, and even progressive image loading. To top things off, we'll include double buffering with a GdkPixmap. </P><P> Although this example is technically a GNOME application, most of it consists of calls to GDK and gdk-pixbuf. You can click on two of the icons (see Figure 10.11). Clicking on the feather will change the alpha blending level and make the feather fade in and out of view; clicking on the icon for gnome-error.png will load an image of a globe, a few scan lines at a time. Figure 10.11 shows a screen shot of the sample application. Listings 10.1 and 10.2 contain the makefile and the source code. </P><DIVCLASS="FIGURE"><ANAME="AEN997"></A><P><B>Figure 10-11. Screen Shot of Sample Gdk-pixbuf Application</B></P><DIVCLASS="MEDIAOBJECT"><P><IMGSRC="figures/10f11.png"></IMG></P></DIV></DIV><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">Listing 10.1 Makefile for Sample Gdk-pixbuf ApplicationCC = gcc CFLAGS = `gnome-config --cflags gnomeui gdk_pixbuf`LDFLAGS = `gnome-config --libs gnomeui gdk_pixbuf`rgbtest: rgbtest.c $(CC) rgbtest.c -o rgbtest $(CFLAGS) $(LDFLAGS) </PRE></TD></TR></TABLE><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">Listing 10.2 Source Code for Sample Gdk-pixbuf Application/* rgbtest.c - Sample gdk-pixbuf Application */#include <gnome.h>#include <gdk-pixbuf/gdk-pixbuf.h>#include <gdk-pixbuf/gdk-pixbuf-loader.h>#include <unistd.h>#include <sys/stat.h>#define PACKAGE "rgbtest"#define VERSION "0.0.1"/* Size of drawing area */#define WIDTH 250#define HEIGHT 200/* Coordinates of progressive loader image */#define LOADER_X 100#define LOADER_Y 140/* Visible drawing surface */GtkWidget *drawing_area;/* Raw pixel buffer */static guchar drawbuf[WIDTH * HEIGHT * 6];/* Double-buffer pixmap */GdkPixmap *dbuf_pixmap = NULL;/* Feather opacity */static gint opacity = 127;/* Loader stuff */GdkPixbufLoader *loader = NULL;GdkPixbuf *loader_pixbuf = NULL;guchar *filebuf = NULL;guint filesize = 0;guint curpos = 0;/* Create a colorful background gradient */static void init_drawing_buffer( ){ gint x, y; gint pixel_offset; gint rowstride = WIDTH * 3; for (y = 0; y < HEIGHT; y++) { for (x = 0; x < WIDTH; x++) { pixel_offset = y * rowstride + x * 3; drawbuf[pixel_offset] = y * 255 / HEIGHT; drawbuf[pixel_offset + 1] = 128 - (x + y) * 255 / (WIDTH * HEIGHT); drawbuf[pixel_offset + 2] = x * 255 / WIDTH; } }}/* Render our images to the double-buffered pixmap */static void render_apples( ){ gint width; gint height; GdkPixbuf *pixbuf1, *pixbuf2, *pixbuf3; gchar *applefile = gnome_pixmap_file ("apple-red.png"); if(applefile) { g_message ("Rendering apple: %s", applefile); pixbuf1 = gdk_pixbuf_new_from_file(applefile); width = gdk_pixbuf_get_width(pixbuf1); height = gdk_pixbuf_get_height(pixbuf1); /* Scale second apple to double size */ pixbuf2 = gdk_pixbuf_scale_simple(pixbuf1, width * 2, height * 2, GDK_INTERP_BILINEAR); /* Create a 50 x 180 GdkPixbuf to display our distorted * apple. Set the dest parameters to copy into the full * area of pixbuf3. Offset the chunk of pixbuf1 that we're * scaling by (-50.0, -60.0) so that we see an interesting * bit of the stem, and not just the upper left-hand corner * of the apple. Finally, stretch the apple by 4 in the * horizontal and 12 in the vertical. */ pixbuf3 = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, 50, 180); gdk_pixbuf_scale(pixbuf1, pixbuf3, 0, 0, 50, 180, -50.0, -60.0, 4.0, 12.0, GDK_INTERP_BILINEAR); gdk_pixbuf_render_to_drawable_alpha(pixbuf1, dbuf_pixmap, 0, 0, 50, 0, width, height, GDK_PIXBUF_ALPHA_BILEVEL, 128, GDK_RGB_DITHER_NORMAL, 0, 0); gdk_pixbuf_render_to_drawable_alpha(pixbuf2, dbuf_pixmap, 0, 0, 70, 20, width * 2, height * 2, GDK_PIXBUF_ALPHA_BILEVEL, 128, GDK_RGB_DITHER_NORMAL, 0, 0); gdk_pixbuf_render_to_drawable_alpha(pixbuf3, dbuf_pixmap, 0, 0, WIDTH - 70, 0, 50, 180, GDK_PIXBUF_ALPHA_BILEVEL, 128, GDK_RGB_DITHER_NORMAL, 0, 0); gdk_pixbuf_unref(pixbuf1); gdk_pixbuf_unref(pixbuf2); gdk_pixbuf_unref(pixbuf3); g_free(applefile); }}static void render_feathers( ){ gint width; gint height; GdkPixbuf *pixbuf1, *pixbuf2; gchar *featherfile = gnome_pixmap_file ("gnome-word.png"); if(featherfile) { g_message ("Rendering feather: %s", featherfile); pixbuf1 = gdk_pixbuf_new_from_file(featherfile); width = gdk_pixbuf_get_width(pixbuf1); height = gdk_pixbuf_get_height(pixbuf1); /* Create a feather composited onto a checkerboard */ pixbuf2 = gdk_pixbuf_composite_color_simple(pixbuf1,
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?