Image Management In Gambas

The pixel format problem

Image management on Linux is a tricky beast that can easily turn into nightmare because of the many different way images store their pixel data into memory.

The different pixel formats

Here is a non-exhaustive list of different pixel formats:

Name Description Pixel in memory (little-endian CPU)
BGR Each pixel is three bytes (24 bits). Each byte is a colour component, blue being the lowest byte. RGBRGBRGB...
BGRX Each pixel is four bytes (32 bits). Three bytes are for the colour components, one byte is ignored. Blue is the lowest byte. -RGB-RGB-RGB...
BGRA Each pixel is four bytes (32 bits). Three bytes are for the colour components, one byte for the alpha value. Blue is the lowest byte. ARGBARGBARGB...
RGBA Each pixel is four bytes (32 bits). Three bytes are for the colour components, one byte for the alpha value. Red is the lowest byte. ABGRABGRABGR...
BGRP Each pixel is four bytes (32 bits). Three bytes are for the colour components, one byte for the alpha value. Blue is the lowest byte. The colour values are pre-multiplied by the alpha value, for performance reasons. PRGBPRGBPRGB...

The name of the pixel format comes from the convention internally used by Gambas.

Pixel formats and libraries

The problem comes when you start using all these nifty toolkits and libraries: each library want to use one or more specific pixel formats that are usually not the same as the other library.

Let's see:

Entity Gambas component Preferred pixel format
QT4 image gb.qt4 BGRP. QT4 usually uses BGRA, but explicitly urges to use BGRP for performance reasons.
GTK+ pixbuf gb.gtk, gb.gtk3 RGB or RGBA
Cairo gb.gtk, gb.gtk3, gb.cairo BGRP
JPEG image loader gb.image.io RGB
Video device gb.media, gb.v4l RGB, usually internally translated from one of the many possible video device format (YUV, RGB on 16 bits...)
OpenGL gb.opengl RGB, BGR, RGBA or BGRA.
Poppler gb.pdf RGB
Gambas gb.image Gambas colours use BGRA, but the alpha component is inverted! (255 for full transparency, and 0 for full opacity).

How Gambas deals with these pixel formats

Hopefully, Gambas manages the different pixel formats for you, thanks to the gb.image component.

Automatic format conversion

The gb.image component automatically converts image from one pixel format to the other, according to the needs of the component that wants to use the image.

Consequently, when programming in Gambas, you can freely take an image from a video device, draw it inside a DrawingArea control, use it as an OpenGL texture, or whatever you want. You will never see the pixel formats.

To get the pixel format of an image, use the Image.Format property.

Conversion costs

Each image conversion has a performance cost, which is proportional to the image size.

The conversion routines are optimized (but do not use assembly at all, so maybe they could be faster), but that cost cannot be neglected if the image is huge.

Especially with gb.gtk, that uses two different pixel formats (one for its images, another one when drawing with them): for example, if you load an image from the disk and draw it on the screen, a conversion will occur.

The Image.Debug property

To check that you don't cause too many conversions, you can set the Image.Debug static property.

Then a message will be printed on the standard error output each time an image conversion occurs.

Image processing methods

All methods of the Image class can deal with any pixel formats, with the exception of the Image.PaintImage method that only supports RGBA and BGRA formats.

But do not worry: you normally encounter pre-multiplied formats with GUI components, and so you will use the Paint.Image method instead.