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

_______________________________________________
Image-SIG maillist  -  [email protected]
http://mail.python.org/mailman/listinfo/image-sig

Reply via email to