62

I want to draw a rectangle and a text in it, here's a part of my code and it's a bit obfuscated:

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

  source_img = Image.open(file_name).convert("RGB")

  img1 = Image.new("RGBA", img.size, (0,0,0,0))
  draw1 = ImageDraw.Draw(watermark, "RGBA")
  draw1.rectangle(((0, 00), (100, 100)), fill="black")
  img_rectangle = Image.composite(img1, source_img, img1)

  draw2 = ImageDraw.Draw(img1, "RGBA")
  draw2.text((20, 70), "something123", font=ImageFont.truetype("font_path123"))

  Image.composite(img1, source_img, img1).save(out_file, "JPEG")

This draws them both, but they're separate: the text is under the rectangle. Whereas I want a text to be drawn inside the rectangle. How can I do that? Should I necessarily compose them or what?

ako25
  • 889
  • 1
  • 8
  • 11

1 Answers1

106

You can do it without composite()

from PIL import Image, ImageFont, ImageDraw, ImageEnhance

source_img = Image.open(file_name).convert("RGBA")

draw = ImageDraw.Draw(source_img)
draw.rectangle(((0, 00), (100, 100)), fill="black")
draw.text((20, 70), "something123", font=ImageFont.truetype("font_path123"))

source_img.save(out_file, "JPEG")

You can create empty image with size of button and put text on it and later put this image on source_img. This way long text will be cut to size of button.

from PIL import Image, ImageFont, ImageDraw, ImageEnhance

source_img = Image.open("source.jpg").convert("RGBA")

# create image with size (100,100) and black background
button_img = Image.new('RGBA', (100,100), "black")

# put text on image
button_draw = ImageDraw.Draw(button_img)
button_draw.text((20, 70), "very loooooooooooooooooong text", font=ImageFont.truetype("arial"))

# put button on source image in position (0, 0)
source_img.paste(button_img, (0, 0))

# save in new file
source_img.save("output.jpg", "JPEG")

EDIT: I use ImageFont.getsize(text) to get text size and create button with correct size.

from PIL import Image, ImageFont, ImageDraw, ImageEnhance

source_img = Image.open("input.jpg").convert("RGBA")


font = ImageFont.truetype("arial")

text = "very loooooooooooooooooong text"

# get text size
text_size = font.getsize(text)

# set button size + 10px margins
button_size = (text_size[0]+20, text_size[1]+20)

# create image with correct size and black background
button_img = Image.new('RGBA', button_size, "black")

# put text on button with 10px margins
button_draw = ImageDraw.Draw(button_img)
button_draw.text((10, 10), text, font=font)

# put button on source image in position (0, 0)
source_img.paste(button_img, (0, 0))

# save in new file
source_img.save("output.jpg", "JPEG")
Shaun
  • 4,057
  • 7
  • 38
  • 48
furas
  • 134,197
  • 12
  • 106
  • 148
  • it doesn't draw the text inside the rectangle. – ako25 Dec 31 '16 at 06:58
  • it works for me - I get text inside rectangle. Maybe you check wrong image - delete all old image and run again. – furas Dec 31 '16 at 07:02
  • no, the image is correct. how does it know that (20, 70) are the coordinates inside the rectangle and not inside the whole image? – ako25 Dec 31 '16 at 07:25
  • (20, 70) are the coordinates inside image. But (20, 70) is inside rectangle ((0, 00), (100, 100)) so it puts text inside rectangle. – furas Dec 31 '16 at 07:27
  • how can I get draw.text() to consider that (20, 70) are the coordinates relative to the rectangle? – ako25 Dec 31 '16 at 07:29
  • use variables ie. `x=0 y=0` and then `rectangle(((x, y), (x+100, y+100))` and `text((x+20, y+70)` – furas Dec 31 '16 at 07:30
  • yes, but that might draw the text outside of the rectangle if the text is too big. I want to lock the text inside the rectangle -- make the text assume that the rectangle is the whole image. – ako25 Dec 31 '16 at 07:35
  • so you have to do it in different way - you have to create empty image with size of `rectangle`, not wit size of `source_image` (and `black` color so you don't need draw rectangle), then use `text()` on it, and finally put it on `source_img`. I put example soon. – furas Dec 31 '16 at 07:56
  • see new example – furas Dec 31 '16 at 08:08
  • works. do you know how can I measure the size, width and height, of ""very loooooooooooooooooong text"" so that I can create a rectangle with the appropriate size? – ako25 Dec 31 '16 at 08:27
  • I know only how to do with `PyGame` because it first generates image only with text (so you can check it size) and later you put this image on rectangle/button. `PyGame` has even method to easily put one image (rendered text) in center of other image (button rectangle). – furas Dec 31 '16 at 08:38
  • Check [PIL.ImageFont.ImageFont.getsize(text)](http://pillow.readthedocs.io/en/3.1.x/reference/ImageFont.html#PIL.ImageFont.PIL.ImageFont.ImageFont.getsize) - maybe it gives you size of text – furas Dec 31 '16 at 08:41
  • see new example with `getsize(text)` – furas Dec 31 '16 at 08:47
  • This code does not work on all image formats, such as some standard test PNG images, like this one: http://r0k.us/graphics/kodak/kodim16.html Is there a limitation on supported images? It works on some other photos taken on iPhone though. – kakyo Dec 03 '18 at 02:22