[Image-SIG] On Controlling TrueType Font Antialiasing

nickg nickg at modp.com
Wed Aug 31 17:11:45 CEST 2005


Hello all.

I assume this is mailing list for the python imaging library: http:// 
www.pythonware.com/products/pil/index.htm

If so, let me say that I love PIL!

But, I bumped into a problem. For an RGB image I wanted to use a  
small TrueType  "pixel" font without antialiasing.  (for instance  
Courier at 8 pt) I didn't see anything in the documentation on how to  
control this.

However I found that setting "fontmode" on an ImageDraw instance  
seems to work

The by commented out the draw.fontmode="1" one will get antialiasing  
or not.

import sys
import Image, ImageFont, ImageDraw
font = ImageFont.truetype("/System/Library/Fonts/Monaco.dfont", 8)
im = Image.new("RGB", (100, 100), "White")
draw = ImageDraw.Draw(im)
#
draw.fontmode = "1"
#
draw.text((10,10), "hello", fill="Black", font=font)
im.save(sys.stdout, "png")

I assume this is a hack.  It would be great if "fontmode" were  
formally exposed in ImageDraw.text as an option such as  
"antialias=true/false"

I'm happy to work on a patch if so desired.

thanks all,

--nickg


Here's the relevant code trace:

ImageDraw: ctor:  sets fontmode

   def __init__(self, im, mode=None):
         im.load()
         if im.readonly:
             im._copy() # make it writable
         blend = 0
         if mode is None:
             mode = im.mode
         if mode != im.mode:
             if mode == "RGBA" and im.mode == "RGB":
                 blend = 1
             else:
                 raise ValueError("mode mismatch")
         if mode == "P":
             self.palette = im.palette
         else:

             self.palette = None
         self.im = im.im
         self.draw = Image.core.draw(self.im, blend)
         self.mode = mode
         if mode in ("I", "F"):
             self.ink = self.draw.draw_ink(1, mode)
         else:
             self.ink = self.draw.draw_ink(-1, mode)
         if mode in ("1", "P", "I", "F"):
             # FIXME: fix Fill2 to properly support matte for I+F images
             self.fontmode = "1"
         else:
             self.fontmode = "L" # aliasing is okay for other modes
         self.fill = 0
         self.font = None


ImageDraw.text:
    passes fontmode to ImageFont.getmask

     def text(self, xy, text, fill=None, font=None, anchor=None):
         ink, fill = self._getink(fill)
         if font is None:
             font = self.getfont()
         if ink is None:
             ink = fill
         if ink is not None:
             try:
                 mask = font.getmask(text, self.fontmode)
             except TypeError:
                 mask = font.getmask(text)
             self.draw.draw_bitmap(xy, mask, ink)


ImageFont.getmask

calls fontrender with mode == "1", i.e. mode==1 -> 1, mode != 1 -> 0

     def getmask(self, text, mode="", fill=Image.core.fill):
         size = self.font.getsize(text)
         im = fill("L", size, 0)
         self.font.render(text, im.id, mode=="1")
         return im


For Freetype fonts, this goes to _imagingft.c, font_render and here

mask = 1, no antialias
mask = 0, antialias

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.python.org/pipermail/image-sig/attachments/20050831/b50c35ff/attachment.htm


More information about the Image-SIG mailing list