Navigation C API Pages Python bindings Applications

Templating Engine

The GFXprim uses python templating engine to generate code for different pixel types. This is documentation to the engine internals.

GFXprim Config

The configuration which describes pixel layout could be found in root GFXprim directory under name which is used to create objects described below.

Main Objects

Pixel Size

class PixelSize(object):
    self.size = size

    self.suffix = suffix

    self.bit_endian = bit_endian

    def needs_bit_endian(self):


The Pixel Size object represents pixel as a continous block of data.

The size is size in bits and is sometimes called bpp which stands for "bits per pixel". This number includes padding bits, if any.

The suffix is a string used as a suffix for functions, macros and other identifiers that operate with this pixel size.

The bit_endian determines the ordering of pixel bits within a byte in bitmaps and graymaps. This is significant in pixel types with pixel boundaries within a byte, i.e. 1 bpp, 4 bpp or 17 bpp.

The function needs_bit_endian() returns true for pixel sizes that are not aligned to the whole bytes.

The bit endian can be either BE or LE (i.e. most significant bit left or right in the bitmap). Usually, the bitmap is ordered with left bits earlier in the memory, but the earlier/later relationship is important. This is defined in terms of natural pixel ordering within the memory.

BE means that the earlier (usually left-most) pixels use the higher ("big") bits of the byte. I.e. in 1 bpp, the first pixel would have value 128, the second 64 and so on.

LE means that the earlier (usually left-most) pixels use the lower ("little") bits of the byte. I.e. in 1 bpp, the first pixel would have value 1, the second 2, the eight’th 128 and so on.

The following two figures describe bit layout in 1 bpp and 2 bpp grayscale bitmaps. The rectangles in the figures represents bytes as they are in the bitmap memory. The start of the image (i.e. topleft corner and coodinates (0,0)) is on the left side. The numbers describe position of the bit in the byte, i representing value 1<<i, that is 7-th bit representing value 128 and 0-th bit value 1.

Note Different pixel types (i.e. RGB888 and BGR888) can share the same pixel size, since certain types of operations do not depend on the actual arrangement of the color channels in a pixel (i.e. get/put pixel, rotate buffer 90 degrees, etc.).

TODO: Rename size to bpp?

Pixel Type

class PixelType(object): = name
    self.chanslist = chanslist
    self.chans = dict() # { chan_name: (offset, size) }
    self.pixelsize = pixelsize # bits per pixel

    def is_palette(self):

    def is_unknown(self):

    def is_rgb(self):

    def is_cmyk(self):

    def is_gray(self):

    def is_alpha(self):

This object represents pixel type which describes the sizes and arrangements of channels in a pixel. Note that it carries an instance of pixel size described above.

The chanslist is a list of triplets describing individual channels as [(chan_name, bit_offset, bit_size) ] where chan_name is usually one of R, G, B, V (value, used for grayscale), A (opacity).

Templating language

GFXprim uses Jinja templating engine with a few objects added into the environment.

Added are python buildins:

  • int

  • float

  • round

  • len

And most importantly objects generated from the configuration files:

  • pixelsizes list of all pixel size objects

  • pixeltypes list of all pixel type objects

Quick Syntax Help

Jinja2 basics:

  • Each written line is reproduces as it is unless it contains template variable or expression

  • Variable is text enclosed between {{ and }}

    • {{ ps.size }} or {{ ps.suffix }}

    • {{ 2 ** i }}

    • {{ int(2 ** (7 - i)) }} >> {{ 8 - i }}

  • Expression is either line that starts with %% or a text enclosed between {% and %}

    • %% for ps in pixel_size

    • %% endfor

    • {% if ps.needs_bit_endian() %} … {% endif %}

  • Comments are enclosed in {# and #}

More complete documentation could be found in Jinja official documentation