Rename GP_Context -> GP_Pixmap
[gfxprim.git] / include / core / GP_Gamma.h
blob1d4918dcf36796692cd253c09a73685fd6e29385
1 /*****************************************************************************
2 * This file is part of gfxprim library. *
3 * *
4 * Gfxprim is free software; you can redistribute it and/or *
5 * modify it under the terms of the GNU Lesser General Public *
6 * License as published by the Free Software Foundation; either *
7 * version 2.1 of the License, or (at your option) any later version. *
8 * *
9 * Gfxprim is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
12 * Lesser General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU Lesser General Public *
15 * License along with gfxprim; if not, write to the Free Software *
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
17 * Boston, MA 02110-1301 USA *
18 * *
19 * Copyright (C) 2009-2013 Cyril Hrubis <metan@ucw.cz> *
20 * *
21 *****************************************************************************/
25 Gamma correction.
27 What is gamma and what is it doing in my computer?
28 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
30 First of all gamma is a function, or better there is a gamma function and
31 it's inverse function. Both gamma function and it's inverse are defined on
32 interval [0,1] and are defined as out = in^(gamma) and it's inverse as
33 out = in^(1/gamma).
35 The purpose of this function is to compensate nonlinearity of human eye
36 perception. The human eye is more sensitive to dark tones than the light ones
37 so without gamma correction storage and manipulation with image data would
38 either be less efficient in space (in case you decided to use more bits and
39 encode the image linearly) or quantization in darker tones would be more
40 visible resulting in "pixelated" images (aliasing).
42 So there is a gamma, the Internet seems to suggest that usual values for
43 gamma are 2.5 for old CRT monitors and about 2.2 for LCD ones, ideally you
44 should have color profile for your device (you need special hardware to
45 measure it). So if you are trying to draw linear gradient on the screen
46 you need to generate sequence of numbers accordingly to gamma function
47 (the 50% intensity is around 186 for gamma = 2.2 and 8bit grayscale pixel).
49 Moreover image formats tend to save data in nonlinear fashion (some formats
50 include gamma value used to for the image) so before you apply filter that
51 manipulates with pixel values, you need to convert it to linear space (adding
52 some more bits to compensate for rounding errors).
54 Also it's important to take gamma, into an account, when drawing anti-aliased
55 shapes, you can't get right results otherwise.
61 This code implements management functions for easy, per pixmap, per
62 channel, gamma tables.
64 The tables for particular gamma are reference counted. There is only one
65 table for particular gamma value and bit depth in memory at a time.
67 Also the table output, for linear values, has two more bits than original in
68 order not to loose precision.
70 The pointers to gamma tables are storied in GP_Gamma structure and are
71 organized in the same order as channels. First N tables for each channel and
72 gamma value gamma, then N tables for inverse 1/gamma function.
74 So when we have RGB888 pixel and gamma 2.2 there are two tables in the
75 memory, one for gamma 2.2 input 8bit output 10bit and it's inverse input
76 10bit output 8bit. The GP_Gamma contains six pointers. First three points to
77 the gamma table for gamma 2.2 with 8bit input (256 array members) and the
78 output format is 10bits so each array member is uint16_t. The other three
79 are for inverse gamma function (gamma = 0.454545...) with 10bit input (1024
80 array members) and 8bit output so each member is uint8_t.
82 The whole interface is designed for speed, so that conversion to linear
83 space or from linear space is just a matter of indexing arrays. Imagine you
84 need to get gamma-corrected pixel value. First you take individual pixel
85 channels then use the GP_Gamma structure as follows:
87 gamma->tables[chan_number].u16[chan_val]
89 or when result has no more than 8bits
91 gamma->tables[chan_number].u8[chan_val]
93 The inverse transformation is done as:
95 gamma->tables[chan_count + chan_number].u8[chan_val]
97 or when original pixel channel had more than 8bits
99 gamma->tables[chan_count + chan_number].u16[chan_val]
101 When doing more than one conversion it's better to save pointers to
102 individual table (example for RGB888):
104 uint16_t *R_2_LIN = gamma->tables[0].u16;
106 uint8_t *R_2_GAMMA = gamma->tables[3].u8;
111 #ifndef CORE_GP_GAMMA_H
112 #define CORE_GP_GAMMA_H
114 #include <stdint.h>
116 #include "GP_Pixmap.h"
118 typedef enum GP_CorrectionType {
120 * Classical gamma correction
122 GP_CORRECTION_GAMMA,
124 * Standard RGB
126 GP_CORRECTION_sRGB,
127 } GP_CorrectionType;
131 * Gamma table.
133 typedef struct GP_GammaTable {
134 /* Table description */
135 enum GP_CorrectionType type;
136 float gamma;
137 uint8_t in_bits;
138 uint8_t out_bits;
140 /* Used for internal purpose */
141 unsigned int ref_count;
142 struct GP_GammaTable *next;
144 /* The table itself */
145 union {
146 uint8_t u8[0];
147 uint16_t u16[0];
149 } GP_GammaTable;
152 * Gamma structure for general pixel type.
154 * The GP_Gamma structure contains pointers to tables for each pixel
155 * channel and for gamma and it's inverse transformation.
157 * The interface is specially designed so that getting Gamma corrected value is
158 * a matter of indexing two arrays.
160 typedef struct GP_Gamma {
161 GP_PixelType pixel_type;
163 unsigned int ref_count;
165 GP_GammaTable *tables[];
166 } GP_Gamma;
169 * Returns pointer to a gamma translation table, the same gamma is used for all
170 * channels.
172 * May fail, in case malloc() has failed.
174 GP_Gamma *GP_GammaAcquire(GP_PixelType pixel_type, float gamma);
177 * Returns pointer to the sRGB translation table.
179 GP_Gamma *GP_sRGBAcquire(GP_PixelType pixel_type);
182 * Copies Gamma table (actually increases ref_count) so it's fast and can't
183 * fail.
185 GP_Gamma *GP_GammaCopy(GP_Gamma *gamma);
188 * Releases gamma table.
190 void GP_GammaRelease(GP_Gamma *self);
193 * Prints info about gamma table into the stdout.
195 void GP_GammaPrint(const GP_Gamma *self);
197 #endif /* CORE_GP_GAMMA_H */