44

I started to learn python a week ago and want to write a small program that converts a email to a image (.png) so that it can be shared on forums without risking to get lots of spam mails.

It seems like the python standard library doesn't contain a module that can do that but I've found out that there's a PIL module for it (PIL.ImageDraw).

My problem is that I can't seem to get it working.

So basically my questions are:

  1. How to draw a text onto a image.
  2. How to create a blank (white) image
  3. Is there a way to do this without actually creating a file so that I can show it in a GUI before saving it?

Current Code:

import Image
import ImageDraw
import ImageFont

def getSize(txt, font):
    testImg = Image.new('RGB', (1, 1))
    testDraw = ImageDraw.Draw(testImg)
    return testDraw.textsize(txt, font)

if __name__ == '__main__':

    fontname = "Arial.ttf"
    fontsize = 11   
    text = "example@gmail.com"
    
    colorText = "black"
    colorOutline = "red"
    colorBackground = "white"


    font = ImageFont.truetype(fontname, fontsize)
    width, height = getSize(text, font)
    img = Image.new('RGB', (width+4, height+4), colorBackground)
    d = ImageDraw.Draw(img)
    d.text((2, height/2), text, fill=colorText, font=font)
    d.rectangle((0, 0, width+3, height+3), outline=colorOutline)
    
    img.save("D:/image.png")
martineau
  • 119,623
  • 25
  • 170
  • 301
Marco-
  • 543
  • 2
  • 5
  • 8
  • 2
    Could you show us what you have already tried and where it is going wrong? – robjohncox Jul 25 '13 at 11:08
  • i don't really have anything yet. The problem is that i can't find a real doc for the ImageDraw module so i don't know how to use it – Marco- Jul 25 '13 at 11:18
  • related: [python PIL draw multiline text on image](http://stackoverflow.com/q/7698231/4279) – jfs Jul 25 '13 at 11:20
  • @user1743130 it seems that PIL documentation from pythonware.com got removed. You could use the documentation which comes with python-imaging module though. – Jan Spurny Jul 25 '13 at 11:25
  • The latest documentation for the pillow fork of PIL can be found [here](https://pillow.readthedocs.io/en/latest/index.html). pillow supports Python 3, unlike PIL itself. – martineau Sep 19 '20 at 22:20

2 Answers2

51
  1. use ImageDraw.text - but it doesn't do any formating, it just prints string at the given location

    img = Image.new('RGB', (200, 100))
    d = ImageDraw.Draw(img)
    d.text((20, 20), 'Hello', fill=(255, 0, 0))
    

    to find out the text size:

    text_width, text_height = d.textsize('Hello')
    
  2. When creating image, add an aditional argument with the required color (white):

    img = Image.new('RGB', (200, 100), (255, 255, 255))
    
  3. until you save the image with Image.save method, there would be no file. Then it's only a matter of a proper transformation to put it into your GUI's format for display. This can be done by encoding the image into an in-memory image file:

    import cStringIO
    s = cStringIO.StringIO()
    img.save(s, 'png')
    in_memory_file = s.getvalue()
    

    or if you use python3:

    import io
    s = io.BytesIO()
    img.save(s, 'png')
    in_memory_file = s.getvalue()
    

    this can be then send to GUI. Or you can send direct raw bitmap data:

    raw_img_data = img.tostring()
    
Jan Spurny
  • 5,219
  • 1
  • 33
  • 47
  • is there a way to find out wich size the image has to be? – Marco- Jul 25 '13 at 11:41
  • @user1743130 edited - but try to look for the documentation. Or you can just run python, write `import ImageDraw` and then `help(ImageDraw)`, `help(ImageDraw.textsize)`, etc. – Jan Spurny Jul 25 '13 at 11:48
  • textsize only seems to change the size of the text but i want to know how big the image has to be so that the text fits in (in pixels) – Marco- Jul 25 '13 at 12:02
  • @user1743130 `textsize` doesn't *change* anything, it tells you how big the text will be. So you can just create one "scrap" image to test for needed size and based on that, you'll create the real image – Jan Spurny Jul 25 '13 at 12:15
  • why does the code in my question works fine for fontsize = 400 but if fontsize is set to 11 the text isn't centered and the image height is too high? – Marco- Jul 25 '13 at 13:28
  • It didn't work for me. Now, with Python 3.7, it needs to use `from io import BytesIO` and replace `cStringIO.StringIO()` with `BytesIO` – mathfux Feb 11 '20 at 22:38
  • @mathfux - well, it's from 2013 - but you're right, I'll add it to the answer, thanks – Jan Spurny Feb 12 '20 at 09:39
10

The first 3 lines are not complete, when I'm not wrong. The correct code would be:

from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
Uwe_98
  • 697
  • 1
  • 8
  • 21