Adapt gen/ for bit-endianness
[gfxprim.git] / core / gen / pixeltype.py
blob3e85dfefa398c2e783f2c25875dcbb38b881948f
1 # Module with PixelType descrition class
2 # 2011 - Tomas Gavenciak <gavento@ucw.cz>
4 # pixel format:
5 # type
6 # - PAL
7 # - HSVRGBA
8 # per chan
9 # name, pos, size
10 # bitwidth
11 # name
13 import re
16 ## *Global* dictionary of all pixeltypes { name : PixelType }
17 pixeltypes = {}
19 ## *Global* set of all encountered channel names
20 channels = set()
22 ## Allowed bit-sizes of pixels
23 bitsizes = [1,2,4,8,16,24,32]
25 ## bit_endian values
26 bit_endians = ['LE', 'BE']
28 ## Create pixel-size suffix (16BPP or 4BPP_LE)
29 def get_size_suffix(bpp, bit_endian):
30 assert bpp in bitsizes
31 assert bit_endian in bit_endians
32 size_suffix = '%dBPP' % (bpp)
33 if bpp < 8:
34 size_suffix += '_' + bit_endian
35 return size_suffix
38 class PixelType(object):
39 """Representation of one GP_PixelType"""
40 def __init__(self, name, size, chanslist, number=None, bit_endian=None):
41 """`name` must be a valid C identifier
42 `size` is in bits, allowed are 1, 2, 4, 8, 16, 24, 32
43 `bit_endian` is order of 1,2,4BPP pixels in a byte, either 'BE' or 'LE'
44 `chanslist` is a list of triplets describing individual channels as
45 [ (`chan_name`, `bit_offset`, `bit_size`) ]
46 `chan_name` is usually one of: R, G, B, V (value, used for grayscale), A (opacity)
47 `number` is auto-assigned (internal use only)
48 """
49 assert re.match('\A[A-Za-z][A-Za-z0-9_]*\Z', name)
50 self.name = name
51 self.chanslist = chanslist
52 self.chans = dict() # { chan_name: (offset, size) }
53 # all types except UNKNOWN=0 must have one of these sizes
54 if number is not 0:
55 assert(size in bitsizes)
56 self.size = size
58 # bit_endian matters only for 1,2,4bpp
59 if size>=8 and bit_endian is None:
60 bit_endian = bit_endians[0]
61 assert bit_endian in bit_endians
62 self.bit_endian = bit_endian
64 if self.size == 0:
65 self.size_suffix = "INVALID"
66 else:
67 self.size_suffix = get_size_suffix(self.size, self.bit_endian)
69 # Numbering from 1
70 if number is not None:
71 self.number = number
72 else:
73 self.number = max([ptype.number for ptype in pixeltypes.values()] + [0]) + 1
75 # Verify channel bits for overlaps
76 # also builds a bit-map of the PixelType
77 self.bits = ['x']*size
78 for c in chanslist:
79 assert c[0] not in self.chans.keys()
80 self.chans[c[0]] = c
81 for i in range(c[1],c[1]+c[2]):
82 assert(i<self.size)
83 assert(self.bits[i]=='x')
84 self.bits[i] = c[0]
86 assert self.name not in pixeltypes.keys()
87 pixeltypes[self.name] = self
88 channels.update(set(self.chans.keys()))
90 def __str__(self):
91 return "<PixelType " + self.name + ">"
93 if 0 not in pixeltypes:
94 PixelType("UNKNOWN", 0, [], bit_endian=bit_endians[0], number=0)