graphics-gdk-pixbuf.html
来自「linux下gnome编程」· HTML 代码 · 共 1,729 行 · 第 1/4 页
HTML
1,729 行
GDK_PIXBUF_ALPHA_BILEVEL, GDK_PIXBUF_ALPHA_FULL} GdkPixbufAlphaMode; </PRE></TD></TR></TABLE><P> For the time being, for the reasons already stated, you must always use GDK_PIXBUF_ALPHA_BILEVEL. This value tells gdk-pixbuf to convert the pixel buffer's alpha channel (if any) into a 1-bit bilevel mask. When full alpha blending finally becomes part of the X Window System, you can start using GDK_PIXBUF_ALPHA_FULL. </P><P> So, to render a nonrectangular shape to a drawable, you need to pass X11 a GdkBitmap instance in addition to your pixel buffer. If your RGB buffer has an alpha channel, gdk-pixbuf can take care of the bitmask creation itself, behind the scenes, using the contents of the alpha channel as a guide. Sometimes, however, you might want to create the bitmap yourself, from scratch; perhaps your pixbuf doesn't have an alpha channel, or you need to do some special postprocessing to the mask before you render it to a drawable. If you leave the bitmask creation up to gdk-pixbuf, you won't be able to step in and alter it be- fore gdk-pixbuf passes it to X11. </P><P> The gdk_pixbuf_render_threshold_alpha( ) function converts a portion of the pixel buffer's alpha channel into a GdkBitmap mask provided by you (see Figure 10.8 for a visual representation of this function): </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">void gdk_pixbuf_render_threshold_alpha(GdkPixbuf *pixbuf, GdkBitmap *bitmap, int src_x, int src_y, int dest_x, int dest_y, int width, int height, int alpha_threshold); </PRE></TD></TR></TABLE><DIVCLASS="FIGURE"><ANAME="AEN928"></A><P><B>Figure 10-8. Rendering an Alpha Channel to a Bitmap</B></P><DIVCLASS="MEDIAOBJECT"><P><IMGSRC="figures/10f8.png"></IMG></P></DIV></DIV><P> The src_x and src_y parameters determine where to start in the source GdkPixbuf; width and height determine the size of the area to transfer. The dest_x and dest_y parameters describe where in the destination GdkBitmap to render the chosen region. If the src coordinates do not match the dest coordinates, the bitmask will be offset within GdkBitmap. The GdkBitmap mask can be a different size from the original pixel buffer, but it must be large enough to contain the complete mask, including any offsets. </P><P> With a little juggling of coordinates, you can take any rectangular area from the pixel buffer and translate it into a 1-bit mask of the same size, and then store it anywhere within GdkBitmap. However, make sure that the bitmap you pass in is at least (dest_x + width) pixels wide and (dest_y + height) pixels tall. </P><P> The alpha_threshold parameter gives you the critical control over which pixels to turn on in the bitmask and which to turn off. As gdk-pixbuf scans through pixels in your alpha channel, it compares each value to alpha_threshold. If the alpha channel value is greater than or equal to alpha_threshold, gdk-pixbuf turns on (sets to 1) the corresponding bit in the GdkBitmap; any values less than alpha_threshold are turned off (set to 0). When the time comes to render an image with that bitmask, X11 copies only pixels that are masked to a 1 and ignores the rest. In a manner of speaking, all areas of the alpha channel that meet or exceed the threshold are rendered. The higher you set the alpha_threshold, the less of the image will be rendered. </P><P> When your pixel buffer does not contain an alpha channel, gdk_pixbuf_render_threshold_alpha( ) pretends that the entire alpha channel is set to 254. Thus if the alpha_threshold parameter is 0 to 254, the mask will consist of only 1's, since the alpha channel will be equal to or above the threshold; everything under that mask will be visible. If you set alpha_threshold to 255, the mask will be all 0's, which will hide the entire masked area from view. </P><P> When you are done creating your bitmask-which could conceivably amount to multiple calls to gdk_pixbuf_render_threshold_alpha( )-you should register it with the GDK graphics context as a clipping mask, using the gdk_gc_set_clip_mask( ) function. Later, when GdkRGB renders the image to the target drawable, it will pull your mask from the GdkGC structure and use it as a stencil for the image. </P><P> Now that you have a GdkPixbuf structure and a 1-bit mask, you are ready to transfer the image to a drawable. Gdk-pixbuf has two functions for rendering to drawables. The first one, gdk_pixbuf_render_to_drawable( ), requires that you place the bitmask into a GdkGC structure beforehand, as already described. The second rendering function, gdk_pixbuf_render_to_drawable_alpha( ), creates the bitmask from the alpha channel in the pixel buffer, internally using gdk_pixbuf_render_threshold_alpha( ): </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">void gdk_pixbuf_render_to_drawable(GdkPixbuf *pixbuf, GdkDrawable *drawable, GdkGC *gc, int src_x, int src_y, int dest_x, int dest_y, int width, int height, GdkRgbDither dither, int x_dither, int y_dither);void gdk_pixbuf_render_to_drawable_alpha(GdkPixbuf *pixbuf, GdkDrawable *drawable, int src_x, int src_y, int dest_x, int dest_y, int width, int height, GdkPixbufAlphaMode alpha_mode, int alpha_threshold, GdkRgbDither dither, int x_dither, int y_dither); </PRE></TD></TR></TABLE><P> The former function gives you more flexibility at the risk of greater complexity. You must know how to set up your bitmask and how to set up a GdkGC structure. The second function is easier to use but requires a four-channel RGBA buffer. </P><P> For completeness, gdk-pixbuf can transfer images both ways. Not only can it push a pixel buffer out to a drawable, but it can also pull a drawable image into a pixel buffer. This reciprocal capability is perfect for making screen shots or managing special effects such as zooming in on another window. The parameters are fairly straightforward, except for cmap, which is needed only when the drawable is a GdkPixmap instance, since unlike GdkWindow structures, pixmaps don't carry their own color maps: </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">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); </PRE></TD></TR></TABLE></DIV><DIVCLASS="SECT2"><H2CLASS="SECT2"><ANAME="AEN943">Scaling</A></H2><P> If you're lucky, the images you load from graphics files will be exactly the correct size for what you need. In the real world, however, you will eventually have to shrink or enlarge some of your images to a more manageable size. Per- haps you need a thumbnail of a graphics file or want to stretch a background to fill a window. Or maybe you just want to display a collection of images all at the same size and need to tweak a few of them to fit. Whatever the reason, image scaling is not something you'll want to tackle from scratch, unless you are very well versed in graphics programming. A poorly designed algorithm is guaranteed to produce noticeable scaling artifacts. Image scaling is a highly mathematical, deeply researched field of study, and we are fortunate to have the algorithms for it already coded and easily accessible in gdk-pixbuf. </P><P> The primary scaling function in gdk-pixbuf is gdk_pixbuf_scale( ), an extremely flexible function that should cover most, if not all, of your scaling needs. It has quite a few parameters and can be confusing at first to use: </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">void gdk_pixbuf_scale(const GdkPixbuf *src, GdkPixbuf *dest, int dest_x, int dest_y, int dest_width, int dest_height, double offset_x, double offset_y, double scale_x, double scale_y, GdkInterpType interp_type); </PRE></TD></TR></TABLE><P> See Figure 10.9 for a visual representation of what the parameters control. </P><DIVCLASS="FIGURE"><ANAME="AEN949"></A><P><B>Figure 10-9. Scaling Parameters</B></P><DIVCLASS="MEDIAOBJECT"><P><IMGSRC="figures/10f9.png"></IMG></P></DIV></DIV><P> The src pixbuf is the base unscaled image-for example, the graphics file you just loaded into memory. The dest pixbuf is the preexisting target for rendering the scaled image. The scale_x and scale_y parameters are the scaling multipliers; a value less than 1.0 will shrink the image, and a value greater than 1.0 will enlarge it. A (scale_x, scale_y) value of (2.0, 0.5) will make the src pixel buffer twice as wide and only half as tall. Gdk-pixbuf will scale the entire src pixbuf by these multipliers. You can then use offset_x and offset_y to move the scaled image in relation to the destination origin at (dest_x, dest_y). </P><P> In its final step, gdk_pixbuf_scale( ) copies the area defined by the four dest_* parameters to the dest pixbuf. In other words, gdk_pixbuf_scale( ) scales src by (scale_x, scale_y), moves it to (offset_x, offset_y), and takes a snapshot of it using the rectangle defined by (dest_x, dest_y, dest_width, dest_height). By cleverly manipulating the size and position parameters, you can selectively copy any portion of the scaled src pixbuf. In Figure 10.9 we pass in an offset_x of -10.0 to shift the image 10 pixels to the left so that it's centered in the 30-pixel-wide clipping region in the destination pixbuf. </P><P> You must create the dest pixbuf beforehand. You should be careful to create one large enough to hold the scaled image. Always make dest at least (dest_x + dest_width) pixels wide and (dest_y + dest_height) pixels tall. </P><P> The last parameter, interp_type, determines which scaling algorithm you want to use. Each of the four algorithms varies in quality, speed, and appearance, so you should pick the filtering style that best suits your needs. GdkIn- terpType is an enumeration of the available algorithms: </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">typedef enum{ GDK_INTERP_NEAREST, GDK_INTERP_TILES, GDK_INTERP_BILINEAR, GDK_INTERP_HYPER} GdkInterpType; </PRE></TD></TR></TABLE><P> The enumeration represents the order of increasing quality (and increased rendering time) of the filter operations. GDK_INTERP_NEAREST is by far the quickest, but it ends up rather pixelated for enlargements. GDK_INTERP_BILINEAR uses bilinear interpolation to produce smooth, antialiased scaled images, even when you magnify the image to many times its original size. Between NEAREST and BILINEAR is GDK_INTERP_TILES, which looks pixelated like NEAREST when you enlarge but is smoother when you shrink the image, like BILINEAR. GDK_INTERP_HYPER is the highest-quality filter, and of course the slowest. In most cases, TILES and BILINEAR will be good enough. </P><P> Often you won't need to use all the various parameters in gdk_pixbuf_scale( ), and they will just get in the way. Fortunately, gdk-pixbuf also has a streamlined version: gdk_pixbuf_scale_simple( ). Gone are the offsets and scaling factors, which are either set to 0 or calculated from the size of the src pixbuf. This function will scale the entire src image to the new size of dest_width dest_height and create a GdkPixbuf instance containing the scaled image, saving you from creating a properly sized dest pixbuf yourself: </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">GdkPixbuf *gdk_pixbuf_scale_simple(const GdkPixbuf *src, int dest_width, int dest_height, GdkInterpType interp_type); </PRE></TD></TR></TABLE><P> The two scaling functions we've covered so far will erase the previous contents of the destination pixel buffer (although technically the internally created destination pixel buffer in gdk_pixbuf_scale_simple( ) will always be initially empty, making this a moot point). Sometimes you'll need to overlay the scaled image on top of an existing image without entirely overwriting it, a process known as compositing. The gdk-pixbuf function to do alpha blending like this is gdk_pixbuf_composite( ). It is similar to gdk_pixbuf_scale( ) except for the extra parameter, overall_alpha, which it uses to determine the opacity of the scaled image: </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">void gdk_pixbuf_composite(const GdkPixbuf *src, GdkPixbuf *dest, int dest_x, int dest_y, int dest_width, int dest_height, double offset_x, double offset_y, double scale_x, double scale_y, GdkInterpType interp_type, int overall_alpha); </PRE></TD></TR></TABLE><P> The dest pixbuf should already have image data in it; otherwise, what's the point of compositing the scaled src image on top of it? </P><P> Incidentally, gdk-pixbuf has a couple of other more specialized scaling and compositing functions: gdk_pixbuf_composite_color( ) and the slimmer version, gdk_pixbuf_composite_color_simple( ). Rather than compositing the scaled image onto another image, these functions will composite it onto a generated checkerboard pattern. This functionality is probably not useful to you unless you are writing an application for viewing or editing anti-aliased images. The checkerboard pattern helps emphasize the anti-aliasing. Figure 10.10 shows testpixbuf-scale, one of the test programs that comes with gdk-pixbuf, using gdk_pixbuf_composite_color( ) to display gnome-globe.png, an icon packaged with gnome-libs. </P><DIVCLASS="FIGURE"><ANAME="AEN966"></A><P><B>Figure 10-10. Image Composition with testpixbuf-scale</B></P><DIVCLASS="MEDIAOBJECT"><P><IMGSRC="figures/10f10.png"></IMG></P></DIV></DIV><P> A specialization of the scaling operation is the copy operation, in which the scaling multipliers are both 1.0. Rather than forcing you to call gdk_pixbuf_scale( ) with a one-to-one scaling ratio, gdk-pixbuf offers a con- venience function to do it in a more rational way: gdk_pixbuf_copy_area( ). This function copies the region
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?