However, I ran into an interesting problem when I was writing that script, not having written anything with imlib2 bindings before! As I was testing my photo album script, I found that I had a memory leak...The longer I left my script to run, the more and more my memory usage would ramp up until it topped out and I found I couldn't display any more photos. Eep! Not really what you want from a photo album.
So I thought I'd share with you a little bit about how imlib2 draws pictures, as opposed to the way Cairo does it, because having had a bit of experience with Cairo actually led me to think about image drawing in a way that made it difficult to work with imlib2, because the two are so different.
First of all, why use imlib2 at all when you can, to some extent, use Cairo to draw pictures? Well, the reason I turned my hand to it was because I wanted to be able to render .jpg images in my Conky, and the Cairo bindings we use can only interpret .png at the moment, through cairo_image_surface_create_from_png(...). By contrast, if you load an image using imlib2, it auto-detects the type and scans its own internal libraries to find a suitable decoder. So imlib2 has a much broader range of image type support, with no fiddling.
If you want to manipulate existing images in imlib2, first you need to load the image into memory with imlib_load_image(...). Eventually, if you want to then draw that image onto the Conky window, you'll use the imlib_render_image_on_drawable(...) function. However, if you want to manipulate that image first, you will need to do all your manipulation on a "buffer" image before you render it onto the surface.
Now, I'm not very good (yet!) at working with transformations in Cairo, so I'm used to thinking of things like a plotter...Move to (a, b), draw a line to (x, y) and stroke. So when I want to draw an image to a window, what I really want to do is load an image, select the rectangle to draw it into, and then "fill" it in...But that's not really the way to do it with imlib2. My example will be my photo album script...Essentially, I wanted to load an image and draw it onto the Conky window at a set (smaller) size. However, I found that if I just load the image and then draw the image at a smaller size using the following:
imlib_blend_image_onto_image(image, 0, 0, 0, w_img, h_img, 0, 0, width, height)I wound up with a horrific memory leak...Basically, I was loading the images into memory and LEAVING THEM THERE. AT FULL SIZE. Ouch.
imlib_render_image_on_drawable(xc - width/2, yc - height/2)
(For those of you who are wondering, the lines above shrink the image from w_img x h_img down to a specified width x height, then draw it on the Conky window at the coordinates in the second line...)
What you need to do to avoid the memory leak is to very carefully manage your memory usage by freeing your images after you're done with them. The good way, then, to draw my reduced images onto the Conky window is to use the following method:
image = imlib_load_image(album_dir .. filename)This code does the following:
if image == nil then return end
imlib_context_set_image(image)
w_img, h_img = imlib_image_get_width(), imlib_image_get_height()
buffer = imlib_create_image(width, height)
imlib_context_set_image(buffer)
imlib_blend_image_onto_image(image, 0, 0, 0, w_img, h_img, 0, 0, width, height)
imlib_context_set_image(image)
imlib_free_image()
imlib_context_set_image(buffer)
imlib_render_image_on_drawable(xc - width/2, yc - height/2)
imlib_free_image()
- loads the given image into memory, in a variable called "image"
- checks to see if the image has loaded successfully; if not, breaks out of the function
- sets the imlib2 context to be "image"
- grabs the dimensions of the loaded image
- creates a "buffer" image
- sets the context to be "buffer", so we can blend onto it
- draws a scaled-down version of the image onto "buffer"
- sets the context back to "image", so we can release it
- releases the original loaded image, so we are then just left with the scaled down version, still held in memory
- sets the context back to "buffer", so we can draw what's on it onto the drawable window
- draws whatever's in "buffer" onto the Conky window
- releases the buffer image
For more information on the functions available to you in imlib2, check out their documentation.
In the meantime, here, have a screenie :)
From Screenshots |
Have try out photo_album widget and other widgets together? I added photo_album widget on conky_widgets.lua script and set all the options, but I had error message regarding "album_dir" and all the other widgets not display either. If you know anything about this, Would you post a solution?
ReplyDeleteThank you so much.