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 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
|
# Copyright 1997 by Corporation for National Research Initiatives.
# See the file LICENSE for details.
"""Interface for using t1lib-generated bitmaps with Fredrik Lundh's
Python Imaging Library.
This module provides alternate classes for FontSetter and Glyph from the
t1lib module. These classes, ImagingSetter and ImagingGlyph, are used by
instantiating an ImagingSetter instead of a FontSetter object. This works
by overriding the FontSetter.newGlyph() method so that it creates
ImagingGlyph objects instead of Glyph objects. The ImagingGlyphs have
additional methods which support the creation of PIL images. The PIL images
available via the additional interface can be used anywhere PIL images can
be used.
"""
import Image
import string
import t1lib
class ConversionError(t1lib.T1Error):
"""Raised when a glyph cannot be converted to a PIL image."""
pass
class DepthError(ConversionError):
"""Raised when a particular bitmap depth is required but not present."""
def __init__(self, required, found):
self.required = required
self.found = found
def __str__(self):
return "bit depth of %d is required; found %d" \
% (self.required, self.found)
class ImagingSetter(t1lib.FontSetter):
"""FontSetter extension which can be used to derive PIL images."""
__32bitmode = "RGB"
def __init__(self, font, size, angle=0.0, spaceoff=0.0, kerning=0, bpp=1):
"""Ensure that we don't have to deal with 16-bit bitmaps later."""
if bpp == 16:
raise ValueError("setter object does not support 16-bit bitmaps")
t1lib.FontSetter.__init__(
self, font, size, angle, spaceoff, kerning, bpp)
def newGlyph(self, bits, metrics, bpp):
"""Create a glyph which can be converted to a PIL image.
The arguments match those of t1lib.FontSetter.newGlyph().
"""
height = metrics[0] + metrics[1]
width = metrics[3] - metrics[2]
if bpp == 1:
mode = "1"
rawmode = "1;IR" # XXX: undocumented rawmode, but works
elif bpp == 8:
mode = rawmode = "L"
elif bpp == 24:
mode = "RGB"
rawmode = "RGBX" # account for padding
elif bpp == 32:
mode = self.__32bitmode
rawmode = (mode == "RGBA") and "RGBA" or "RGBX"
im = Image.fromstring(mode, (width, height), bits, "raw", rawmode)
im.__class__ = ImagingGlyph
t1lib.Glyph.__init__(im, bits, metrics, bpp)
return im
def get32BitMode(self):
"""Return the conversion mode for 32-bit images."""
return self.__32bitmode
def set32BitMode(self, mode):
"""Set the conversion mode for 32-bit images.
mode -- mode indicator; must be 'RGB' or 'RGBA'
Glyphs 32 bits deep can be converted to RGB or RGBA images.
"""
mode = string.upper(mode)
if mode not in ("RGB", "RGBA"):
raise ValueError("illegal 32-bit mode; must be 'RGB' or 'RGBA'")
self.__32bitmode = mode
def getmask(self, string):
"""Rasterize a string.
string -- the string to be rendered
This is provided to support the ImageDraw class from the Python
Imaging Library. This interface allows ImageSetter instances which
generate glyphs of 1 bit per pixel to be passed to the
ImageDraw.setfont() method.
If the bits-per-pixel for generated glyphs is not 1, DepthError is
raised.
"""
if self.bpp != 1:
raise DepthError(1, self.bpp)
return self.setString(string)
class ImagingGlyph(Image.Image, t1lib.Glyph):
"""A rasterized image which is also a PIL image."""
pass
def test():
"""Run a stand-alone test.
This function parses the command line. It provides a limited self-test
for this module.
"""
import getopt
import sys
#
fontname = "CharterBT-Roman"
depth = 1
fontsize = 120.0
text = "abc"
#
opts, args = getopt.getopt(sys.argv[1:], "d:f:s:")
for opt, val in opts:
if opt == "-d":
depth = string.atoi(val)
elif opt == "-f":
fontname = val
elif opt == "-s":
fontsize = string.atof(val)
if args:
text = string.join(args)
#
font = t1lib.getFont(fontname)
setter = ImagingSetter(font, fontsize, bpp=depth)
glyph = setter.setString(text)
glyph.show()
if __name__ == "__main__":
test()
|