[Image-SIG] PIL 1.1; Compiling Fonts

kcazabon kcazabon" <kcazabon@home.com
Tue, 18 Jul 2000 22:42:31 -0700


I produced a bunch of PIL fonts a while back, which Piers Lauder (spelling?
sorry!) kindly posted to his FTP site.  The address is:

http://www.cs.usyd.edu.au/~piers/python/pilfonts.html


Additionally, I've attached a script that you can use to add rotated and/or
colored text to images with.  It's a little memory hungry, but it works
well.  I submitted this to Fred as well, and I 'think' he's planning on
putting it in an upcoming release of PIL.

Kevin.

(email me offline if you want this in a complete .py file, there's a bunch
more tools in it too.)

##########################
import Image, Imagefont, Imagedraw
from numeric import pi, cos, sin

anchorPoints = {"NW":(0.0, 0.0),
                "N":(0.5, 0.0),
                "NE":(1.0, 0.0),
                "W":(0.0, 0.5),
                "C":(0.5, 0.5),
                "E":(1.0, 0.5),
                "SW":(1.0, 0.0),
                "S":(1.0, 0.5),
                "SE":(1.0, 1.0),
                "nw":(0.0, 0.0),
                "n":(0.5, 0.0),
                "ne":(1.0, 0.0),
                "w":(0.0, 0.5),
                "c":(0.5, 0.5),
                "e":(1.0, 0.5),
                "sw":(1.0, 0.0),
                "s":(1.0, 0.5),
                "se":(1.0, 1.0)}

def addRotatedText(im, text, where, rotation, font, color = (0,0,0), anchor
= "NW", maxSize = None):
    anchor = anchorPoints[anchor]
    font = Imagefont.load(font)
    draw = Imagedraw.Draw(im)
    draw.setfont(font)
    draw.setink(color)

    textsize = draw.textsize(text)

    #print "Textsize: %s x %s pixels" %(textsize[0], textsize[1])

    del(draw)

    # do the math to figure out how big the text box will be after rotation
    rotationRadians = ((2.0*pi)/360.0) * rotation
    rotatedWidth = int(float(textsize[0]) * abs(cos(rotationRadians)) +
float(textsize[1]) * abs(sin(rotationRadians)) + 0.5)
    rotatedHeight = int(float(textsize[0]) * abs(sin(rotationRadians)) +
float(textsize[1]) * abs(cos(rotationRadians)) + 0.5)

    rotatedtextsize = (rotatedWidth, rotatedHeight)

    # make the text box big enough for the original text in any rotation
    if textsize[0] > textsize[1]:
        largetextsize = (textsize[0], textsize[0])
    else:
        largetextsize = (textsize[1], textsize[1])

    xOffset = int((float(largetextsize[0] - textsize[0])/2.0)+0.5)

    textIm = Image.new("L", largetextsize, (0))

    # draw a mask of the text unrotated
    draw = Imagedraw.Draw(textIm)
    draw.setfont(font)
    draw.setink((255))
    draw.text((xOffset, (textIm.size[1]/2) - (textsize[1]/2)), text)

    # rotate the text mask
    textIm = textIm.rotate(rotation)

    # crop it down to the real used area
    xOffset = int((float(textIm.size[0] - rotatedtextsize[0])/2.0) + 0.5)
    yOffset = int((float(textIm.size[1] - rotatedtextsize[1])/2.0) + 0.5)
    textIm = textIm.crop((xOffset, yOffset, xOffset + rotatedtextsize[0],
yOffset + rotatedtextsize[1]))

    # fit it in MaxSize if specified and valid
    if maxSize != None and type(maxSize) == type(("tuple", "tuple")) and
len(maxSize) == 2:
        if textIm.size[0] > maxSize[0] or textIm.size[1] > maxSize[1]:
            textIm.thumbnail(maxSize)

    # create an image mask the size of the whole image that you're putting
the text on
    mask = Image.new("L", im.size, (0))

    # place the text mask in the proper place
    where = (where[0] - int(float(textIm.size[0])*anchor[0] + 0.5),
where[1] - int(float(textIm.size[1])*anchor[1] + 0.5))
    mask.paste(textIm, where)

    del(textIm)

    # create an image the full size of the supplied image, in the color of
the text you want to apply
    colorIm = Image.new(im.mode, im.size, color)

    # paste the color onto the image, using the text mask as a mask
    im.paste(colorIm, (0,0), mask)

    del(colorIm)
    del(mask)

    return im