Add Text on Image using PIL

Apostolos picture Apostolos · May 4, 2013 · Viewed 161.1k times · Source

I have an application that loads an Image and when the user clicks it, a text area appears for this Image (using jquery), where user can write some text on the Image. Which should be added on Image.

After doing some research on it, I figured that PIL (Python Imaging Library ) can help me do this. So I tried couple of examples to see how it works and I managed to write text on an image. But I think there is some difference when I try it using Python Shell and in web environment. I mean the text on the textarea is very big in px. How can I achieve the same size of text when using PIL as the one on the textarea?

The text is Multiline. How can i make it multiline in image also, using PIL?

Is there a better way than using PIL? I am not entirely sure, If this is the best implementation.

html:

<img src="images/test.jpg"/>

its the image being edited

var count = 0;
$('textarea').autogrow();
$('img').click(function(){
    count = count + 1;
    if (count > 1){
        $(this).after('<textarea />');
        $('textarea').focus();
    }   
});

the jquery to add the textarea. Also the text area is position:absolute and fixed size.

Should i place it inside a form so i can get coordinates of textarea on image? I want to write text on image when user clicks and save it on the image.

Answer

lalit picture lalit · May 4, 2013

I think ImageFont module available in PIL should be helpful in solving text font size problem. Just check what font type and size is appropriate for you and use following function to change font values.

# font = ImageFont.truetype(<font-file>, <font-size>)
# font-file should be present in provided path.
font = ImageFont.truetype("sans-serif.ttf", 16)

So your code will look something similar to:

from PIL import Image
from PIL import ImageFont
from PIL import ImageDraw 

img = Image.open("sample_in.jpg")
draw = ImageDraw.Draw(img)
# font = ImageFont.truetype(<font-file>, <font-size>)
font = ImageFont.truetype("sans-serif.ttf", 16)
# draw.text((x, y),"Sample Text",(r,g,b))
draw.text((0, 0),"Sample Text",(255,255,255),font=font)
img.save('sample-out.jpg')

You might need to put some extra effort to calculate font size. In case you want to change it based on amount of text user has provided in TextArea.

To add text wrapping (Multiline thing) just take a rough idea of how many characters can come in one line, Then you can probably write a pre-pprocessing function for your Text, Which basically finds the character which will be last in each line and converts white space before this character to new-line.