python:使用 windows api 使用 ttf 字体呈现文本 [英] python: use windows api to render text using a ttf font
问题描述
一个完整的例子是什么,从无到在内存中得到一个位图,打开一个特定的 .ttf
文件并使用该字体渲染一些文本,使用本地 Windows API?我目前正在通过 windows API 苦苦挣扎,所以这是我和 stackoverflow 其他人之间的一场竞赛.
完成并完成渲染字体(需要 PyWin32):
import ctypes导入结构导入 win32con导入 win32gui导入 win32ui从 PIL 导入图像def RGB(r, g, b):返回 r |(g<<8) |(b<<16)def native_bmp_to_pil(hdc, bitmap_handle, width, height):bmpheader = struct.pack(LHHHH", struct.calcsize(LHHHH"),宽度,高度,1, 24) #w,h, 平面=1, 位数)c_bmpheader = ctypes.c_buffer(bmpheader)#3 字节/像素,填充线为 4 字节c_bits = ctypes.c_buffer(" " * (height * ((width*3 + 3) & -4)))res = ctypes.windll.gdi32.GetDIBits(hdc, bitmap_handle, 0, 高度,c_bits, c_bmpheader,win32con.DIB_RGB_COLORS)如果不是资源:引发 IOError(native_bmp_to_pil 失败:GetDIBits")im = Image.frombuffer(RGB", (width, height), c_bits,原始",BGR",(宽度* 3 + 3)&-4, -1)返回我Win32Font 类:def __init__(self, name, height, weight=win32con.FW_NORMAL,斜体=假,下划线=假):self.font = win32ui.CreateFont({名称":名称,高度":高度,重量":重量,斜体":斜体,下划线":下划线})#创建一个我们可以用来绘制的兼容 DC:self.desktopHwnd = win32gui.GetDesktopWindow()self.desktopDC = win32gui.GetWindowDC(self.desktopHwnd)self.mfcDC = win32ui.CreateDCFromHandle(self.desktopDC)self.drawDC = self.mfcDC.CreateCompatibleDC()#初始化self.drawDC.SelectObject(self.font)def renderText(self, text):"使用windows API 将文本渲染为PIL 图像.""self.drawDC.SetTextColor(RGB(255,0,0))#创建兼容位图:w,h = self.drawDC.GetTextExtent(text)saveBitMap = win32ui.CreateBitmap()saveBitMap.CreateCompatibleBitmap(self.mfcDC, w, h)self.drawDC.SelectObject(saveBitMap)#画出来self.drawDC.DrawText(text, (0, 0, w, h), win32con.DT_LEFT)#转换为PIL图像im = native_bmp_to_pil(self.drawDC.GetSafeHdc(), saveBitMap.GetHandle(), w, h)#清理win32gui.DeleteObject(saveBitMap.GetHandle())返回我def __del__(self):self.mfcDC.DeleteDC()self.drawDC.DeleteDC()win32gui.ReleaseDC(self.desktopHwnd, self.desktopDC)win32gui.DeleteObject(self.font.GetSafeHandle())def __del__(self):win32gui.DeleteObject(self.font.GetSafeHandle())
用法:
<预><代码>>>>f = Win32Font("Arial", 15)>>>im = f.renderText(这只是一个测试")>>>im.save("c:/hope.png")结果:
太棒了!!!
要呈现特定的 .ttf
文件,我需要深入研究.
更新:更新以计算 bmp 大小:
What would be a full example, going from nothing to ending up with a bitmap in memory, of opening a particular .ttf
file and rendering some text using that font, using the native Windows API? I'm currently slogging through the windows API, so it's a race between me and the rest of stackoverflow.
Done and done for rendering a font (requires PyWin32):
import ctypes
import struct
import win32con
import win32gui
import win32ui
from PIL import Image
def RGB(r, g, b):
return r | (g << 8) | (b << 16)
def native_bmp_to_pil(hdc, bitmap_handle, width, height):
bmpheader = struct.pack("LHHHH", struct.calcsize("LHHHH"),
width, height, 1, 24) #w,h, planes=1, bitcount)
c_bmpheader = ctypes.c_buffer(bmpheader)
#3 bytes per pixel, pad lines to 4 bytes
c_bits = ctypes.c_buffer(" " * (height * ((width*3 + 3) & -4)))
res = ctypes.windll.gdi32.GetDIBits(
hdc, bitmap_handle, 0, height,
c_bits, c_bmpheader,
win32con.DIB_RGB_COLORS)
if not res:
raise IOError("native_bmp_to_pil failed: GetDIBits")
im = Image.frombuffer(
"RGB", (width, height), c_bits,
"raw", "BGR", (width*3 + 3) & -4, -1)
return im
class Win32Font:
def __init__(self, name, height, weight=win32con.FW_NORMAL,
italic=False, underline=False):
self.font = win32ui.CreateFont({
'name': name, 'height': height,
'weight': weight, 'italic': italic, 'underline': underline})
#create a compatible DC we can use to draw:
self.desktopHwnd = win32gui.GetDesktopWindow()
self.desktopDC = win32gui.GetWindowDC(self.desktopHwnd)
self.mfcDC = win32ui.CreateDCFromHandle(self.desktopDC)
self.drawDC = self.mfcDC.CreateCompatibleDC()
#initialize it
self.drawDC.SelectObject(self.font)
def renderText(self, text):
"""render text to a PIL image using the windows API."""
self.drawDC.SetTextColor(RGB(255,0,0))
#create the compatible bitmap:
w,h = self.drawDC.GetTextExtent(text)
saveBitMap = win32ui.CreateBitmap()
saveBitMap.CreateCompatibleBitmap(self.mfcDC, w, h)
self.drawDC.SelectObject(saveBitMap)
#draw it
self.drawDC.DrawText(text, (0, 0, w, h), win32con.DT_LEFT)
#convert to PIL image
im = native_bmp_to_pil(self.drawDC.GetSafeHdc(), saveBitMap.GetHandle(), w, h)
#clean-up
win32gui.DeleteObject(saveBitMap.GetHandle())
return im
def __del__(self):
self.mfcDC.DeleteDC()
self.drawDC.DeleteDC()
win32gui.ReleaseDC(self.desktopHwnd, self.desktopDC)
win32gui.DeleteObject(self.font.GetSafeHandle())
def __del__(self):
win32gui.DeleteObject(self.font.GetSafeHandle())
usage:
>>> f = Win32Font("Arial", 15)
>>> im = f.renderText("this is just a test")
>>> im.save("c:/hope.png")
result:
brilliant!!!
To render a particular .ttf
file I'll need to dig around more.
UPDATE: Updated to calculate the bmp size:
这篇关于python:使用 windows api 使用 ttf 字体呈现文本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!