loaders: BMP: Add sanity check for palette size
[gfxprim.git] / doc / gen.txt
blob44aed77c39bb0b2ffd8eb01aad89439deb86a3dd
1 Templating Engine
2 -----------------
4 The GFXprim uses python templating engine to generate code for different pixel
5 types. This is documentation to the engine internals.
7 GFXprim Config
8 ~~~~~~~~~~~~~~
10 The configuration which describes pixel layout could be found in root GFXprim
11 directory under name 'gfxprim_config.py' which is used to create objects
12 described below.
14 Main Objects
15 ~~~~~~~~~~~~
17 Pixel Size
18 ^^^^^^^^^^
20 [source,python]
21 -------------------------------------------------------------------------------
22 class PixelSize(object):
23     self.size = size
25     self.suffix = suffix
27     self.bit_endian = bit_endian
29     def needs_bit_endian(self):
30        ...
32     ...
34 -------------------------------------------------------------------------------
36 The Pixel Size object represents pixel as a continous block of data.
38 The 'size' is size in bits and is sometimes called bpp which stands for "bits
39 per pixel". This number includes padding bits, if any.
41 The 'suffix' is a string used as a suffix for functions, macros and other
42 identifiers that operate with this pixel size.
44 The 'bit_endian' determines the ordering of pixel bits within a byte in bitmaps
45 and graymaps. This is significant in pixel types with pixel boundaries
46 within a byte, i.e. 1 bpp, 4 bpp or 17 bpp.
48 The function 'needs_bit_endian()' returns true for pixel sizes that are not
49 aligned to the whole bytes.
51 The bit endian can be either 'BE' or 'LE' (i.e. most significant bit left or
52 right in the bitmap).  Usually, the bitmap is ordered with left bits earlier
53 in the memory, but the earlier/later relationship is important.  This is
54 defined in terms of natural pixel ordering within the memory.
56 'BE' means that the earlier (usually left-most) pixels use the higher ("big")
57 bits of the byte. I.e. in 1 bpp, the first pixel would have value 128, the second 64
58 and so on.
60 'LE' means that the earlier (usually left-most) pixels use the lower ("little")
61 bits of the byte. I.e. in 1 bpp, the first pixel would have value 1, the second 2,
62 the eight'th 128 and so on.
64 The following two figures describe bit layout in 1 bpp and 2 bpp
65 grayscale bitmaps. The rectangles in the figures represents bytes as they are
66 in the bitmap memory. The start of the image (i.e. topleft corner
67 and coodinates (0,0)) is on the left side.
68 The numbers describe position of the bit in the byte, 'i' representing
69 value '1<<i', that is 7-th bit representing value 128 and 0-th bit value 1.
74 ["graphviz", "bit-endian-be-1bit.png"]
75 ------------------------------------------------------------------------------
76 digraph bit_endian {
77         graph [ dpi = 70 ];
78         node [shape = record];
79         rankdir = LR;
81         node0 [label = "{<e> ...}"];
82         node1 [label = "{7 | 6 | 5 | 4 | 3 | 2 | 1 | <e> 0}"];
83         node2 [label = "{<b> 7 | 6 | 5 | 4 | 3 | 2 | 1 | <e> 0}"];
84         node3 [label = "{<b> 7 | 6 | 5 | 4 | 3 | 2 | 1 | <e> 0}"];
85         node4 [label = "{<b> ...}"];
87         node0:e -> node1:b;
88         node1:e -> node2:b;
89         node2:e -> node3:b;
90         node3:e -> node4:b;
92 ------------------------------------------------------------------------------
94 ["graphviz", "bit-endian-be-2bits.png"]
95 ------------------------------------------------------------------------------
96 digraph bit_endian {
97         graph [ dpi = 70 ];
98         node [shape = record];
99         rankdir = LR;
101         node0 [label = "{<e> ...}"];
102         node1 [label = "{7 6 | 5 4 | 3 2 | <e> 1 0}"];
103         node2 [label = "{<b> 7 6 | 5 4 | 3 2 | <e> 1 0}"];
104         node3 [label = "{<b> 7 6 | 5 4 | 3 2 | <e> 1 0}"];
105         node4 [label = "{<b> ...}"];
107         node0:e -> node1:b;
108         node1:e -> node2:b;
109         node2:e -> node3:b;
110         node3:e -> node4:b;
112 ------------------------------------------------------------------------------
117 ["graphviz", "bit-endian-le-1bit.png"]
118 ------------------------------------------------------------------------------
119 digraph bit_endian {
120         graph [ dpi = 70 ];
121         node [shape = record];
122         rankdir = LR;
124         node0 [label = "{<e> ...}"];
125         node1 [label = "{0 | 1 | 2 | 3 | 4 | 5 | 6 | <e> 7}"];
126         node2 [label = "{<b> 0 | 1 | 2 | 3 | 4 | 5 | 6 | <e> 7}"];
127         node3 [label = "{<b> 0 | 1 | 2 | 3 | 4 | 5 | 6 | <e> 7}"];
128         node4 [label = "{<b> ...}"];
130         node0:e -> node1:b;
131         node1:e -> node2:b;
132         node2:e -> node3:b;
133         node3:e -> node4:b;
135 ------------------------------------------------------------------------------
137 ["graphviz", "bit-endian-le-2bits.png"]
138 ------------------------------------------------------------------------------
139 digraph bit_endian {
140         graph [ dpi = 70 ];
141         node [shape = record];
142         rankdir = LR;
144         node0 [label = "<e> ..."];
145         node1 [label = "{1 0 | 3 2 | 5 4 | <e> 7 6}"];
146         node2 [label = "{<b> 1 0 | 3 2 | 5 4 | <e> 7 6}"];
147         node3 [label = "{<b> 1 0 | 3 2 | 5 4 | <e> 7 6}"];
148         node4 [label = "{<b> ...}"];
150         node0:e -> node1:b;
151         node1:e -> node2:b;
152         node2:e -> node3:b;
153         node3:e -> node4:b;
155 ------------------------------------------------------------------------------
157 NOTE: Different pixel types (i.e. RGB888 and BGR888) can share the same pixel
158       size, since certain types of operations do not depend on the actual
159       arrangement of the color channels in a pixel
160       (i.e. get/put pixel, rotate buffer 90 degrees, etc.).
162 TODO: Rename size to bpp?
164 Pixel Type
165 ^^^^^^^^^^
167 [source,python]
168 -------------------------------------------------------------------------------
169 class PixelType(object):
170     self.name = name
171     self.chanslist = chanslist
172     self.chans = dict() # { chan_name: (offset, size) }
173     self.pixelsize = pixelsize # bits per pixel
175     def is_palette(self):
176         ...
178     def is_unknown(self):
179         ...
181     def is_rgb(self):
182         ...
184     def is_cmyk(self):
185         ...
187     def is_gray(self):
188         ...
190     def is_alpha(self):
191         ...
193 -------------------------------------------------------------------------------
195 This object represents pixel type which describes the sizes and arrangements of
196 channels in a pixel. Note that it carries an instance of pixel size described
197 above.
199 [source,python]
200 -------------------------------------------------------------------------------
201 class PixelChannel():
202     # Index (position in pixel from left)
203     self.idx = idx
204     # Pixel channel name such as R, G, B, A, ...
205     self.name = name
206     # Bit offset in pixel
207     self.off = offset
208     # Channel bit size
209     self.size = size
210     # Maximal channel value
211     self.max = 2 ** size - 1
212     ...
213 -------------------------------------------------------------------------------
215 The chanslist describes pixel channel. There are some convenient members to be
216 used directly from C code whose value is a hexadecimal string, i.e. 'C_mask',
217 'C_max', 'C_shift'.
219 Templating language
220 ~~~~~~~~~~~~~~~~~~~
222 GFXprim uses https://github.com/metan-ucw/cct[CCT] templating engine which is
223 crafted especially for generating source code. CCT is a Python based language
224 that contains global variables with objects described in gfxprim config.
226 Quick Syntax Help
227 ^^^^^^^^^^^^^^^^^
229 CCT basics:
231 - Each written line is verbatim (reproduced as it is) unless it starts with
232   +@\s+
234 - Lines starting with +@\s+ are interpreted as a Python code
236 - Comments are lines starting with +@ #+
238 - Verbatim lines may also contain 'Expressions' or 'Function call'
240 - 'Expression' is a Python code that yields a value which is included in the
241    output and is enclosed between curly braces +{{ expression }}+.
243 - 'Function call' is a Python function whose output is included in the output.
244    It is called as {@ func() @}.
246 More complete documentation could be found in
247 https://github.com/metan-ucw/cct/blob/master/HOWTO[CCT howto].