aboutsummaryrefslogtreecommitdiff
path: root/circuitpython/frozen/circuitpython-stage/font/genfont2.py
blob: 158d5e90ed78a026786d8ce224dc77cad59e2b90 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import array
import pprint


def color565(r, g, b):
    return (r & 0xf8) << 8 | (g & 0xfc) << 3 | b >> 3


class BMP16:
    """Read 16-color BMP files."""

    def __init__(self, filename):
        self.filename = filename
        self.colors = 0

    def read_header(self):
        """Read the file's header information."""

        if self.colors:
            return
        with open(self.filename, 'rb') as f:
            f.seek(10)
            self.data = int.from_bytes(f.read(4), 'little')
            f.seek(18)
            self.width = int.from_bytes(f.read(4), 'little')
            self.height = int.from_bytes(f.read(4), 'little')
            f.seek(46)
            self.colors = int.from_bytes(f.read(4), 'little')

    def read_palette(self):
        """Read the color palette information."""

        palette = array.array('H', (0 for i in range(16)))
        with open(self.filename, 'rb') as f:
            f.seek(self.data - self.colors * 4)
            for color in range(self.colors):
                buffer = f.read(4)
                c = color565(buffer[2], buffer[1], buffer[0])
                palette[color] = ((c & 0xff) << 8) | (c >> 8)
        return palette

    def read_data(self, offset=0, size=-1):
        """Read the image data."""

        with open(self.filename, 'rb') as f:
            f.seek(self.data + offset)
            return f.read(size)


class Font:
    def __init__(self, buffer):
        self.buffer = buffer

    @classmethod
    def from_bmp16(cls, filename):
        bmp = BMP16(filename)
        bmp.read_header()
        if bmp.width != 8 or bmp.height != 1024:
            raise ValueError("A 8x1024 16-color BMP expected!")
        data = bmp.read_data()
        self = cls(bytearray(2048))
        c = 0
        x = 0
        y = 7
        for b in data:
            self.pixel(c, x, y, b >> 4)
            x += 1
            self.pixel(c, x, y, b & 0x0f)
            x += 1
            if x >= 8:
                x = 0
                y -= 1
                if y < 0:
                    y = 7
                    c += 1
        del data
        self.palette = bmp.read_palette()
        return self

    def pixel(self, c, x, y, color):
        index = (127 - c) * 16 + 2 * y + x // 4
        bit = (x % 4) * 2
        color = color & 0x03
        self.buffer[index] |= color << bit


font = Font.from_bmp16("font2.bmp")
pprint.pprint(font.buffer)
pprint.pprint(font.palette.tobytes())