Re: Correct use of pixbuf, pixmap, and image?




On Mar 14, 2006, at 3:25 PM, Ari Jolma wrote:

I've got a derivative (subclass in Perl sense) of Gtk2::Gdk::Pixbuf. I create it using gdk_pixbuf_new_from_data. The data is created in C using my own draw routines. From this pixbuf I create a pixmap by calling render_pixmap_and_mask in Gtk-Perl. And in the last step I create an Gtk2::Image by calling set_from_pixmap.

The image is used in a subclass of Gtk2::ScrolledWindow. Everything works. But there is somewhere a problem of wasting memory.

Creating the initial pixbuf may take a long time (seconds) and it is not possible to draw on a pixbuf, only on a pixmap. In my code I want to be able to re-use once created pixbuf. For example there is a dialog box, where the user may select a graphical object and it is highlighted by drawing it (with Gtk-Perl) on the pixmap. So every time the user selects a new object, this procedure is executed:

1. create pixmap from the initial pixbuf and set the pixmap into the image
2. draw on the pixmap
3. hide the ScrolledWindow
4. show the ScrolledWindow

Why the hide and show?


I haven't seen a good documentation on some of the functions I use, so I've ended up to this procedure with some experimentation. I also don't understand well the client/server concept related to this (if the program is running over X, the pixmap is created on the client?). I just played with this and I believe the code is hogging memory when the above procedure is run multiple times. Does anybody have any ideas?

First, a little context:

The X Window System uses a client/server architecture in which the screen and windows on it are managed by a window server, which deals with the display and input hardware. This server provides windowing services to client applications. (Many people think X's client and server names are backwards, but when seen from the point of view that the server provides windowing services to client applications, it makes sense.)

The client and server are not only separate processes, but may be on different physical machines. Because of this, the latency for a round trip to the server can be quite large, and the X model for many operations is designed to minimize this. That's where graphics contexts and pixmaps come from. A graphics context ("GC") is a server-side resource that contains information on how to perform drawing operations. The client has a handle which refers to a particular GC, and passes the handle with drawing operations. This keeps the client from having to transmit all of that information with each drawing command.

Similarly, image data can be stored in "bitmaps" (1-bit images, or maps of bits) or "pixmaps" (maps of more-than-one-bit pixels, or pixel maps). These are stored on the server, at device bit resolution and bit depth, and this can be manipulated quite quickly. Operations like $drawable->draw_pixmap() involve copying only the command information from the client to the server, because all of the bits are already on the server. These are stored in the server's memory.

So where does a GdkPixbuf fit in? Recall that the pixmap is stored on the server at device resolution and bitdepth. This means that if you want to change just one pixel, you have to do a round trip, which is expensive. Also, you'll have to deal with the image data at the server's bit depth, which could be anything -- 888, 565, indexed pseudocolor, etc, maybe involving dithering. Because this is a royal PITA, the gnome guys came up with GdkPixbuf, which is a simple 24-bit RGB or 32-bit RGBA image buffer stored in the *client*, which can be dithered and transferred to the server as needed. (The RENDER extension includes features to make this more efficient.)

GtkImage provides a way for you to set the source data directly from a pixbuf --- $image->set_from_pixbuf($pixbuf) --- so you could avoid the pixmap/mask stage.

You can also place a GdkPixbuf into a GnomeCanvas, which gives you more efficient rendering of the changed portions. You could use GnomeCanvasItems for the selected objects text overlays and that sort of stuff, along with scaling and other fun tricks.

You'll probably want also check for reference leaks in your code to make sure you're not piling up pixbufs.


If using a Canvas is not practical, you can probably drop a few steps by writing some of the more compute-intensive display stuff in C --- if you already have custom C code, then binding your own C widgets to gtk2-perl should be no problem. You could do stuff like render much smaller pieces from the source data and blit them exactly where they need to go in the master pixbuf.


About documentation.. I just found the Havoc Pennington's book on developer.gnome.org and I have Warkus' book. Are there other good sources?

I find it very helpful to look at the code of applications that do similar things to what i want to do. The gimp is a bit complicated, but has lots of good stuff.


--
"that's it! you're a genius!" "yes. that's what i think. do you think i deserve a raise?"
    - dialogue from 'Godzilla versus Mothra', 1964




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]