user13523677
user13523677

Reputation:

How can I rotate an emoji, printed as text, on an image?

This is what I'm doing right now:

from PIL import Image, ImageDraw, ImageFont, ImageFilter

fnt = ImageFont.truetype(font="NotoColorEmoji.ttf", size=109, layout_engine=ImageFont.LAYOUT_RAQM)
im = Image.open('1.png')
im = im.filter(ImageFilter.GaussianBlur(100))
draw = ImageDraw.Draw(im)
draw.text((66, 232), "😀" ,fill="#faa", embedded_color=True, font=fnt)
im.show()

Upvotes: 2

Views: 500

Answers (1)

HansHirse
HansHirse

Reputation: 18925

You'll need to

  1. determine the size of the rendered emoji w.r.t. the set up font,
  2. derive a rotation center w.r.t. the location of the rendered text and the determined size,
  3. print the text on some transparent image with the same size of your input image,
  4. rotate that image w.r.t. the desired angle and the derived rotation center, and
  5. paste that text image onto your actual input image.

Here's the code including some visualization overhead:

from PIL import Image, ImageDraw, ImageFont

# Load image
im = Image.open('path/to/your/image.png')

# Set up font, text, location, and rotation angle
fnt = ImageFont.truetype(font="NotoColorEmoji.ttf", size=109,
                         layout_engine=ImageFont.LAYOUT_RAQM)
txt = '😀'
loc = (50, 50)
ang = 123.45

# Get dimensions of rendered text using the specified font
fnt_dim = fnt.getsize(txt)

# Calculate rotation center, i.e. the center of the emoji, w.r.t. the
# text's location
rot_cnt = (loc[0] + fnt_dim[0] // 2, loc[1] + fnt_dim[1] // 2)

# Generate transparent image of the same size as the input, and print
# the text there
im_txt = Image.new('RGBA', im.size, (0, 0, 0, 0))
draw = ImageDraw.Draw(im_txt)
draw.text(loc, txt, fill="#faa", embedded_color=True, font=fnt)

# Rotate text image w.r.t. the calculated rotation center
im_txt = im_txt.rotate(ang, center=rot_cnt)

# Paste text image onto actual image
im.paste(im_txt, mask=im_txt)

# Just for comparison: Print text upright directly on input image
im2 = im.copy()
draw = ImageDraw.Draw(im2)
draw.text(loc, txt, fill="#faa", embedded_color=True, font=fnt)

# Just for visualization
import matplotlib.pyplot as plt

plt.figure(figsize=(18, 6))
plt.subplot(1, 3, 1), plt.imshow(im)
plt.subplot(1, 3, 2), plt.imshow(im2)
plt.subplot(1, 3, 3), plt.imshow(Image.blend(im, im2, 0.5))
plt.tight_layout(), plt.show()

That'd be the output:

Output

Looking at the blended image of both versions, the location of the rotated emoji is quite perfect. Some distortions are due to the non-square size of the emoji (136, 128).

----------------------------------------
System information
----------------------------------------
Platform:      Windows-10-10.0.19041-SP0
Python:        3.9.1
PyCharm:       2021.1.2
Matplotlib:    3.4.2
Pillow:        8.2.0
----------------------------------------

Upvotes: 3

Related Questions