In the beginning, there was Wilber, Wilber the gimp. The graphic was without form and void, and darkness was upon the face of the desktop, and the Spirit of Wilber was moving over the face of the bitstream. And Wilber said, "<Toolbox>/File/New" and there was an image. And Wilber saw that the image was good, and Wilber separated the image into drawables. And Wilber looked down at what he had wrought, and Wilber said, "Oh golly." For Wilber had made the drawables of the layer according to their kinds, and the drawables of the channel according to their kinds, and the drawables of the mask according to their kinds... | |
Book of Wilber, Kt 1:1-12 |
The GIMP stores the image data simply as an array of unsigned chars (guchar): One byte each for red, green, blue, and, if necessary, one for alpha. But the image data is fragmented in small parts to make the access more efficient - when you work on a fragment of the image it would be very inefficient to copy entire rows into the memory, while you may just need the first half.
Images are a collection of drawables that are either layers or channels. Channels contain only grayscale information. Drawables are subdivided into tiles that are typically 64x64 pixels, but may be arbitrary sizes in future. The access to raw pixel data (in C Plugins) is managed via PixelRegions. To be able to use them you have to access the drawable:
GimpDrawable* gimp_drawable_get (gint32 drawable_ID);(the drawable_ID is what you typically get per GUI or PDB-Call). You can then initialize the PixelRegion:
void gimp_pixel_rgn_init (GimpPixelRgn *pr, GimpDrawable *drawable, int x, int y, int width, int height, int dirty, int shadow);
whereby you announce that you want to access the drawable drawable in the area specified by x, y, width and height. The dirty flag specifies that you want to write to the area and the image data has to be written back to The GIMP. If shadow is specified, The GIMP provides you with a set of freshly allocated tiles, where you can write your modified data into. When you are done The GIMP cares about merging the new image data into the image (respecting the current selection and handling undo stuff – basically it does all the hard stuff for you...). So usually these flags are either FALSE, FALSE when you just need read-access or TRUE, TRUE when you want to modify the image data.
C-plug-ins can use the following PDB functions to get or set rectangular areas, rows or columns of an image:
void gimp_pixel_rgn_get_[pixel | row | col | rect] (GimpPixelRgn *pr, guchar *buf, gint x, gint y, gint width, gint height);
void gimp_pixel_rgn_set_[pixel | row | col | rect] (GimpPixelRgn *pr, guchar *buf, gint x, gint y, gint width, gint height);
You have to keep in mind that these functions are relatively slow, because The GIMP has to copy image data around. But sometimes the advantage of having an easy API outweights the performance impact.
When you are done with manipulating the image you have to clean up:
gimp_drawable_flush (drawable); gimp_drawable_merge_shadow (drawable->id, TRUE); gimp_drawable_update (drawable->id, x1, y1, width, height); gimp_displays_flush(); gimp_drawable_detach(drawable);