I’m using 2.9.4 on Windows. I can try to make a minimal program, but I can’t do it right now because I’ll be gone for the rest of the day. The following function is the heart of the matter, but there is some post-processing in C++ to convert to RGBA, with the opacity for all background pixels set to zero and for all other pixels set to 255.
def text_to_bitmap(text, color=(1,1,1), background=(0,0,0), opacity=1,
height=13, font=‘sans’,
style=‘normal’, weight=‘normal’):
Algorithm provided by Chris Barker in the wxPython forum
global _dc
if font == ‘sans’:
wfont = _wx.FONTFAMILY_SWISS
fudge = 12.0/13.0 # fudge factor for backwards compatibility
elif font == ‘serif’:
wfont = _wx.FONTFAMILY_ROMAN
fudge = 10.0/13.0 # fudge factor for backwards compatibility
elif font == ‘monospace’:
wfont = _wx.FONTFAMILY_MODERN
fudge = 10.0/13.0 # fudge factor for backwards compatibility
else:
raise ValueError(“font should be ‘serif’, ‘sans’, or ‘monospace’”)
if style == ‘normal’:
wstyle = _wx.FONTSTYLE_NORMAL
elif style == ‘italic’:
wstyle = _wx.FONTSTYLE_ITALIC
else:
raise ValueError(“font style should be ‘normal’ or ‘italic’”)
if weight == ‘normal’:
wweight = _wx.FONTWEIGHT_NORMAL
elif weight == ‘bold’:
wweight = _wx.FONTWEIGHT_BOLD
else:
raise ValueError(“font weight should be ‘normal’ or ‘bold’”)
if _dc == None:
_dc = _wx.MemoryDC()
height = int(fudge*height + 0.5)
_dc.SetFont(_wx.Font(height, wfont, wstyle, wweight))
while text[0] == ‘\n’: text = text[1:]
while text[-1] == ‘\n’: text = text[:-1]
lines = text.split(’\n’)
maxwidth = 0
totalheight = 0
heights = []
for line in lines:
if line == ‘’: line = ’ ’
w,h = _dc.GetTextExtent(line)
h += 1
w += 2
if w > maxwidth: maxwidth = w
heights.append(totalheight)
totalheight += h
bmp = _wx.EmptyBitmap(maxwidth,totalheight)
_dc.SelectObject(bmp)
fore = (int(255*color[0]),
int(255*color[1]),
int(255*color[2]))
_dc.SetTextForeground(fore)
Make background only slightly different from foreground
so that antialiasing doesn’t create pixels with colors
very different from the foreground color:
back = [0,0,0]
for i in range(3):
if fore[i] == 0: back[i]=1
else: back[i] = fore[i]-1
brush = _wx.Brush(back)
_dc.SetBackground(brush)
_dc.Clear()
for n, line in enumerate(lines):
_dc.DrawText(line, 1, heights[n])
_dc.SelectObject( _wx.NullBitmap )
img = _wx.ImageFromBitmap(bmp)
data = fromstring(img.GetData(), dtype=uint8)
return maxwidth, totalheight, back, data