📄 graphics-gdkrgb.html
字号:
<HTML><HEAD><TITLE>GdkRGB</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="The GDK Wrapper"HREF="graphics-gdk.html"><LINKREL="NEXT"TITLE="Libart"HREF="graphics-libart.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-gdk.html">Prev</A></TD><TDWIDTH="80%"ALIGN="center"VALIGN="bottom">Chapter 10. Graphics</TD><TDWIDTH="10%"ALIGN="right"VALIGN="bottom"><AHREF="graphics-libart.html">Next</A></TD></TR></TABLE><HRALIGN="LEFT"WIDTH="100%"></DIV><DIVCLASS="SECT1"><H1CLASS="SECT1"><ANAME="GRAPHICS-GDKRGB">GdkRGB</A></H1><P> The next step up in the drawing hierarchy is the GdkRGB drawing API. Although technically this is still part of GDK, we consider it separately here because unlike most of GDK, which is a thin wrapper, GdkRGB is pure added value and doesn't wrap any specific part of Xlib. </P><P> The name "GdkRGB" sounds like it might refer to some sort of object or structure. This is not the case. GdkRGB is a unified set of functions for drawing on GdkDrawable surfaces-that is, GdkWindow or GdkPixmap. These functions help manage colors for you, behind the scenes. By drawing with GdkRGB, you won't have to deal with visuals and color maps. </P><DIVCLASS="SECT2"><H2CLASS="SECT2"><ANAME="AEN764">The RGB Buffer</A></H2><P> GdkRGB stores all of its pixel data in 24-bit color arrays, and then converts the colors and images to the target visual and color map when it renders them to the drawable. Thus it shields you from the hassle of dealing with color lookups and buffer management (remember that each color depth uses a different amount of memory to hold a single on-screen pixel). With GdkRGB, you always work with the same type of 24-bit color array, so you won't have to create special rendering routines for each type of visual. </P><P> As the name "GdkRGB" suggests, each pixel contains a red, a green, and a blue element, each one 8 bits in size, implying that each color can have an intensity value ranging from 0 to 255. The values of these three elements are packed consecutively into three guchar elements of the RGB buffer array. You might guess from this arrangement that the size of the RGB buffer is the number of pixels in the image, multiplied by 3. Thus a 25 40 image would correspond to a guchar array with 3,000 (25 40 3) elements. However, this is not the case. </P><P> The dimensions of the buffer's image affect the exact size allocated for the buffer. To help optimize access to the later parts of the image buffer, each full row of pixels in the buffer is aligned on a 4-byte (or 4-guchar) boundary. This design typically leads to slightly faster memory lookups at the hardware level, and since graphics rendering consists largely of memory copies in long, repeti- tive loops, any optimization within these innermost loops can make quite a difference. To keep things simple and customizable, each buffer is assigned a row stride, the exact length that each row takes up in the buffer array. The row stride is the sum of all the data bytes in a single row of pixels, plus any extra bytes needed to pad the row to 4-byte alignment. </P><P> Let's take our 25 40 image as an example. Each 25-pixel row uses 75 bytes of data. To make sure the next row starts on a 4-byte boundary, at 76 bytes, we have to add a single unused byte of padding to the end of each row. The result is that we can calculate the offset to any row by multiplying by 4 rather than by 3,1 so we have a buffer size of 3,040 (76 40) instead of 3,000. Figure 10.4 illustrates the concept of row strides. </P><DIVCLASS="FIGURE"><ANAME="AEN770"></A><P><B>Figure 10-4. RGB Row Strides</B></P><DIVCLASS="MEDIAOBJECT"><P><IMGSRC="figures/10f4.png"></IMG></P></DIV></DIV><P> It's not easy to aesthetically convert a 24-bit color buffer into a 16-bit color buffer, and it is even harder to convert it into an 8-bit (or lower) color buffer. The quality of your results will vary wildly, depending on the intricacies of the algorithms you use. For each pixel in your 24-bit image, you will have to search the target visual's color map for an appropriate color. The simplest, and probably fastest, approach is to find the nearest match. When going from 24-bit to 16-bit, you won't lose much quality because you still have 64K colors to choose from. </P><P> The real problems come when you try to degrade your 16-million-color image down to 256 colors. Simple closest-match algorithms can't do justice to the image and will lead to severe banding. This sharp line of transition between color hues shows up most often in conversions of a smooth color gradient to a lower color depth. </P><P> A more sophisticated color conversion algorithm can smooth out this abrupt transition by dithering colors. Dithering introduces an element of fuzziness to color conversions. Rather than taking into account only one pixel at a time, a dithering algorithm looks at surrounding pixels and tries to come up with a combination of adjacent pixel colors that the human eye will mistake for an intermediate color. A common application of dithering (especially in newspapers) is the fine-grained black-and-white checkerboard, which appears from a distance to be a flat gray. Sophisticated dithering techniques can do wonders to maintain image quality in conversions to a lower color depth. </P><P> This discussion about color conversions is intended to illustrate the amount of work that goes on behind the scenes in GdkRGB. If it weren't for GdkRGB, you would have to implement all these conversion routines yourself to produce consistent-looking images across the full range of color depths and visuals. By analogy, if you've never bicycled from Detroit to Albuquerque, you may not appreciate how much more convenient it is to fly there. GdkRGB makes the arduous journey from one color depth to another quick and easy. </P><P> If you wish to use GdkRGB in your application, you will need to initialize it, as shown here, before you call any of its functions: </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">void gdk_rgb_init( ); </PRE></TD></TR></TABLE><P> GdkRGB makes use of global variables that need to be loaded in order for it to function properly. Failure to initialize GdkRGB can result in application crashes, so don't forget this step! If you are using GdkRGB indirectly, through a wrapper such as GNOME or gdk-pixbuf (see Section 10.5), you shouldn't have to initialize it, because the wrapper will take care of that for you. </P><P> If you get into trouble and need help figuring out why your calls to GdkRGB aren't doing what you think they should be doing, you can turn on the verbose debugging mode by calling the following function with a value of TRUE: </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">void gdk_rgb_set_verbose(gboolean verbose); </PRE></TD></TR></TABLE><P> You can turn it back off by calling the function again with a FALSE. It may not tell you exactly what's going on, but if you're lucky, it will give you a hint or two. </P></DIV><DIVCLASS="SECT2"><H2CLASS="SECT2"><ANAME="AEN785">Drawing Functions</A></H2><P> The most impressive feature of the GdkRGB API is its set of drawing routines, each of which targets a GdkDrawable instance. The drawing routines are quite similar, differing primarily in the particular algorithms they use to transfer and downgrade the 24-bit colors into the target drawable. </P><P> In most cases you will be able to get by with using only the first drawing function, gdk_draw_rgb_image( ). This function, like the others, copies a rectangular block of pixels from anywhere inside the RGB buffer into the target drawable, automatically converting it to the proper visual. You must also supply the dithering style, a pointer to the RGB buffer, and your buffer's row stride so that GdkRGB knows exactly where to wrap the pixel rows: </P><TABLEBORDER="0"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -