GFXprim
2D bitmap graphics library with emphasis on speed and correctness

Typedefs  
typedef enum gp_correction_type  gp_correction_type 
A list of supported correction types.  
Enumerations  
enum  gp_correction_type { GP_CORRECTION_TYPE_GAMMA , GP_CORRECTION_TYPE_SRGB } 
A list of supported correction types. More...  
First of all gamma is a function, or better there is a gamma function and it's inverse function. Both gamma function and it's inverse are defined on interval [0,1] and are defined as out = in^(gamma) and it's inverse as out = in^(1/gamma).
The purpose of this function is to compensate nonlinearity of human eye perception. The human eye is more sensitive to dark tones than the light ones so without gamma correction storage and manipulation with image data would either be less efficient in space (in case you decided to use more bits and encode the image linearly) or quantization in darker tones would be more visible resulting in "pixelated" images (aliasing).
So there is a gamma, the Internet seems to suggest that usual values for gamma are 2.5 for old CRT monitors and about 2.2 for LCD ones, ideally you should have color profile for your device (you need special hardware to measure it). So if you are trying to draw linear gradient on the screen you need to generate sequence of numbers accordingly to gamma function (the 50% intensity is around 186 for gamma = 2.2 and 8bit grayscale pixel).
For pixel types with transparency only the color channels are nonlinear, the alpha channel is always linear and defines fractions of the channel values that should be used to get the desired transparency.
Moreover image formats tend to save data in nonlinear fashion (some formats include gamma value used to for the image) so before you apply filter that manipulates with pixel values, you need to convert it to linear space (adding some more bits to compensate for rounding errors).
Also it's important to take gamma, into an account, when drawing antialiased shapes, you can't get right results otherwise.
This code implements management functions for easy, per pixmap, per channel, gamma tables.
The tables for particular gamma are reference counted. There is only one table for particular gamma value and bit depth in memory at a time.
The pointers to gamma tables are storied in gp_gamma structure and are organized in the same order as channels. The lin tables linearize pixel values and use at least two more bits than the input size. The enc tables encode the linear values back into the original nonlinear space.
E.g. if we have RGB888 pixel and gamma 2.2 there are two lookup tables in the memory, one for gamma=2.2 8bit > 10bit that's an array of 256 x u16 values and its inverse gamma=0.4545... 10bit > 8bit that's an array 1024 x u8 values. The gp_gamma lin[] first three pointers point to the first table and the first three pointers in enc[] points to the second table.
To get a linear value for a RGB888 pixel channel:
And to get the value back:
When doing more than one conversion it's better to save pointers to individual table:
enum gp_correction_type 
A list of supported correction types.
Enumerator  

GP_CORRECTION_TYPE_GAMMA  Classical gamma correction. 
GP_CORRECTION_TYPE_SRGB  Standard RGB. 
Definition at line 97 of file gp_gamma_correction.h.