[Image-SIG] Here is code for wrapping draw.text to fit within given pixel width

Caleb Hattingh caleb.hattingh at gmail.com
Tue Dec 7 20:27:50 CET 2004


Hi

I wrote the code below for the purpose of wrapping text to fit within
a given pixel width:

Args:
  drawer: Instance of "ImageDraw.Draw()"
  text: string of long text to be wrapped
  font: instance of ImageFont (I use .truetype)
  containerWidth: number of pixels text lines have to fit into.

Outputs described after code below:

***code***
def IntelliDraw(drawer,text,font,containerWidth):
    words = text.split()  
    lines = [] # prepare a return argument
    lines.append(words) 
    finished = False
    line = 0
    while not finished:
        thistext = lines[line]
        newline = []
        innerFinished = False
        while not innerFinished:
            #print 'thistext: '+str(thistext)
            if drawer.textsize(' '.join(thistext),font)[0] > containerWidth:
                # this is the heart of the algorithm: we pop words off
the current
                # sentence until the width is ok, then in the next outer loop
                # we move on to the next sentence. 
                newline.insert(0,thistext.pop(-1))
            else:
                innerFinished = True
        if len(newline) > 0:
            lines.append(newline)
            line = line + 1
        else:
            finished = True
    tmp = []        
    for i in lines:
        tmp.append( ' '.join(i) )
    lines = tmp
    (width,height) = drawer.textsize(lines[0],font)            
    return (lines,width,height)

***endcode***

Outputs of function:
  lines: list of strings which corresponds to the given "text"
argument, but broken up into list elements.
  width: pixel width of the first line (should be less than containerWidth)
  height: pixel height of first line (used for spacing successive lines)

An example of how this is used is given below:

***code***
text = 'One very extremely long string that cannot possibly fit \
into a small number of pixels of horizontal width, and the idea \
is to break this text up into multiple lines that can be placed like \
a paragraph into our image'

draw = ImageDraw.Draw(OurImagePreviouslyDefined)
font = fontpath = ImageFont.truetype('/usr/local/share/fonts/ttf/times.ttf',26)
pixelWidth = 500 # pixels

lines,tmp,h = IntelliDraw(draw,text,font,pixelWidth)
j = 0
for i in lines:
    draw.text( (0,0+j*h), i , font=font16, fill='black')
    j = j + 1
***endcode***

Hopefully this code works for you.  As you may observe, the algorithm
is *extremely* simple and not optimal in any way.  I would have loved
to have found something like this on the net, but couldn't, so maybe
someone else on this list is also looking.

Thanks
Caleb


More information about the Image-SIG mailing list