-
Notifications
You must be signed in to change notification settings - Fork 87
/
glyph-lcd-cairo.py
executable file
·120 lines (111 loc) · 4.43 KB
/
glyph-lcd-cairo.py
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# -----------------------------------------------------------------------------
#
# pycairo/cairocffi-based glyph-lcd example - Copyright 2017 Hin-Tak Leung
# Distributed under the terms of the new BSD license.
#
# rewrite of the numply,matplotlib-based example from Nicolas P. Rougier
# - Not immitating the upside-downness
# - Do LCD_V side by side also
#
# Limitation: Suface.get_data() is not in the "python 3, pycairo < 1.11" combo.
#
# -----------------------------------------------------------------------------
'''
Glyph bitmap LCD display (sub-pixel) rendering
'''
from freetype import *
# use Matrix() from Cairo instead of from Freetype
from cairo import Context, ImageSurface, FORMAT_ARGB32, SurfacePattern, FILTER_BEST, Matrix
if __name__ == '__main__':
from PIL import Image
from numpy import ndarray, ubyte, uint32
face = Face('./Vera.ttf')
face.set_char_size( 48*64 )
face.load_char('S', FT_LOAD_RENDER |
FT_LOAD_TARGET_LCD )
bitmap = face.glyph.bitmap
width = face.glyph.bitmap.width//3
rows = face.glyph.bitmap.rows
pitch = face.glyph.bitmap.pitch
copybuffer = (c_ubyte * (pitch * rows))()
memmove(pointer(copybuffer), bitmap._FT_Bitmap.buffer,
pitch * rows)
I = ImageSurface(FORMAT_ARGB32, width, rows)
ndR = ndarray(shape=(rows,width), buffer=copybuffer,
dtype=ubyte, order='C',
offset=0,
strides=[pitch, 3])
ndG = ndarray(shape=(rows,width), buffer=copybuffer,
dtype=ubyte, order='C',
offset=1,
strides=[pitch, 3])
ndB = ndarray(shape=(rows,width), buffer=copybuffer,
dtype=ubyte, order='C',
offset=2,
strides=[pitch, 3])
try:
ndI = ndarray(shape=(rows,width), buffer=I.get_data(),
dtype=uint32, order='C',
strides=[I.get_stride(), 4])
except NotImplementedError:
raise SystemExit("For python 3.x, you need pycairo >= 1.11+ (from https://github.com/pygobject/pycairo)")
# 255 * 2**24 = opaque
ndI[:,:] = 255 * 2**24 + ndR[:,:] * 2**16 + ndG[:,:] * 2**8 + ndB[:,:]
I.mark_dirty()
surface = ImageSurface(FORMAT_ARGB32, 800, 600)
ctx = Context(surface)
ctx.set_source_surface(I, 0, 0)
pattern = ctx.get_source()
SurfacePattern.set_filter(pattern, FILTER_BEST)
scale = 480.0 / rows
scalematrix = Matrix()
scalematrix.scale(1.0/scale,1.0/scale)
scalematrix.translate(-(400.0 - width *scale /2.0 )+200, -60)
pattern.set_matrix(scalematrix)
ctx.paint()
# we need this later for shifting the taller LCD_V glyph up.
rows_old = rows
# LCD_V
face.load_char('S', FT_LOAD_RENDER |
FT_LOAD_TARGET_LCD_V )
bitmap = face.glyph.bitmap
width = face.glyph.bitmap.width
rows = face.glyph.bitmap.rows//3
pitch = face.glyph.bitmap.pitch
copybuffer = (c_ubyte * (pitch * face.glyph.bitmap.rows))()
memmove(pointer(copybuffer), bitmap._FT_Bitmap.buffer,
pitch * face.glyph.bitmap.rows)
I = ImageSurface(FORMAT_ARGB32, width, rows)
ndR = ndarray(shape=(rows,width), buffer=copybuffer,
dtype=ubyte, order='C',
offset=0,
strides=[pitch*3, 1])
ndG = ndarray(shape=(rows,width), buffer=copybuffer,
dtype=ubyte, order='C',
offset=pitch,
strides=[pitch*3, 1])
ndB = ndarray(shape=(rows,width), buffer=copybuffer,
dtype=ubyte, order='C',
offset=2*pitch,
strides=[pitch*3, 1])
ndI = ndarray(shape=(rows,width), buffer=I.get_data(),
dtype=uint32, order='C',
strides=[I.get_stride(), 4])
# 255 * 2**24 = opaque
ndI[:,:] = 255 * 2**24 + ndR[:,:] * 2**16 + ndG[:,:] * 2**8 + ndB[:,:]
I.mark_dirty()
ctx.set_source_surface(I, 0, 0)
pattern = ctx.get_source()
SurfacePattern.set_filter(pattern, FILTER_BEST)
# Re-use the sane scale (LVD_V taller than LCD),
# but adjust vertical position to line up mid-height of glyphs
adjust = (rows - rows_old) * 240.0 /rows
scalematrix.translate(-400, adjust)
pattern.set_matrix(scalematrix)
ctx.paint()
#
surface.flush()
surface.write_to_png("glyph-lcd-cairo.png")
Image.open("glyph-lcd-cairo.png").show()