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.