python: Brug windows api til at gengive tekst ved hjælp af en ttf skrifttype

Indlæg af Hanne Mølgaard Plasc

Problem



Hvad ville være et fuldt eksempel, gå fra intet til at ende med en bitmap i hukommelsen, at åbne en bestemt .ttf fil og gøre noget tekst ved hjælp af den skrifttype ved hjælp af det native Windows API? Jeg er i øjeblikket slogging gennem Windows API, så det er et løb mellem mig og resten af ​​stackoverflow.

Bedste reference


Udført og gjort for at gøre en skrifttype (kræver 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())


brug:


>>> f = Win32Font("Arial", 15)
>>> im = f.renderText("this is just a test")
>>> im.save("c:/hope.png")


resultat:


GLORY http://i53.tinypic.com/2qvxf2u.png[5]


strålende!!!


For at lave en bestemt .ttf fil skal jeg grave mere.


UPDATE: Opdateret til at beregne bmp størrelse:


woot http://i51.tinypic.com/s4rq7s.png[6]