如何使用python的PIL以角度绘制文本?

时间:2021-02-03 00:26:02

Using Python I want to be able to draw text at different angles using PIL.

使用Python,我希望能够使用PIL以不同的角度绘制文本。

For example, imagine you were drawing the number around the face of a clock. The number 3 would appear as expected whereas 12 would we drawn rotated counter-clockwise 90 degrees.

例如,假设你在一个时钟的表面上绘制数字。数字3会像预期的那样出现,而我们画的12会逆时针旋转90度。

Therefore, I need to be able to draw many different strings at many different angles.

因此,我需要能够画出许多不同角度的不同弦。

4 个解决方案

#1


30  

Draw text into a temporary blank image, rotate that, then paste that onto the original image. You could wrap up the steps in a function. Good luck figuring out the exact coordinates to use - my cold-fogged brain isn't up to it right now.

将文本绘制到一个临时的空白图像中,旋转该图像,然后将其粘贴到原始图像上。你可以在函数中结束这些步骤。祝你好运,算出确切的坐标来使用——我的大脑现在还不能正常工作。

This demo writes yellow text on a slant over an image:

这个演示程序将黄色文本写在一个倾斜的图像上:

# Demo to add rotated text to an image using PIL

import Image
import ImageFont, ImageDraw, ImageOps

im=Image.open("stormy100.jpg")

f = ImageFont.load_default()
txt=Image.new('L', (500,50))
d = ImageDraw.Draw(txt)
d.text( (0, 0), "Someplace Near Boulder",  font=f, fill=255)
w=txt.rotate(17.5,  expand=1)

im.paste( ImageOps.colorize(w, (0,0,0), (255,255,84)), (242,60),  w)

#2


7  

It's also usefull to know our text's size in pixels before we create an Image object. I used such code when drawing graphs. Then I got no problems e.g. with alignment of data labels (the image is exactly as big as the text).

在创建图像对象之前,最好先知道文本的大小(以像素为单位)。我在绘制图形时使用了这样的代码。然后我没有遇到任何问题,例如数据标签的对齐(图像和文本一样大)。

(...)
img_main = Image.new("RGB", (200, 200))
font = ImageFont.load_default()

# Text to be rotated...
rotate_text = u'This text should be rotated.'

# Image for text to be rotated
img_txt = Image.new('L', font.getsize(rotate_text))
draw_txt = ImageDraw.Draw(img_txt)
draw_txt.text((0,0), rotate_text, font=font, fill=255)
t = img_value_axis.rotate(90, expand=1)

The rest of joining the two images together is already described on this page. When you rotate by an "unregular" angle, you have to improve this code a little bit. It actually works for 90, 180, 270...

将这两个图像连接在一起的其余部分已经在这个页面上进行了描述。当你以一个“不规则”的角度旋转时,你必须稍微改进一下这段代码。它实际上适用于90,180,270。

#3


3  

I'm not saying this is going to be easy, or that this solution will necessarily be perfect for you, but look at the documentation here:

我并不是说这很容易,或者这个解决方案对你来说一定是完美的,但是看看这里的文档:

http://effbot.org/imagingbook/pil-index.htm

http://effbot.org/imagingbook/pil-index.htm

and especially pay attention to the Image, ImageDraw, and ImageFont modules.

尤其要注意图像、ImageDraw和ImageFont模块。

Here's an example to help you out:

这里有一个例子可以帮助你:


import Image
im = Image.new("RGB", (100, 100))
import ImageDraw
draw = ImageDraw.Draw(im)
draw.text((50, 50), "hey")
im.rotate(45).show()

To do what you really want you may need to make a bunch of separate correctly rotated text images and then compose them all together with some more fancy manipulation. And after all that it still may not look great. I'm not sure how antialiasing and such is handled for instance, but it might not be good. Good luck, and if anyone has an easier way, I'd be interested to know as well.

为了实现您真正想要的效果,您可能需要创建一组独立的、正确旋转的文本图像,然后使用一些更花哨的操作将它们组合在一起。尽管如此,它看起来还是不太好。例如,我不确定如何处理反锯齿之类的问题,但这可能并不好。祝你好运,如果有人有更简单的方法,我也很想知道。

#4


2  

Here is a working version, inspired by the answer, but it works without opening or saving images.

这里有一个工作版本,灵感来自于答案,但是它不需要打开或保存图片。

The two images have colored background and alpha channel different from zero to show what's going on. Changing the two alpha channels from 92 to 0 will make them completely transparent.

这两张图片都有不同于0的彩色背景和alpha通道来显示正在发生的事情。将两个alpha通道从92改为0将使它们完全透明。

from PIL import Image, ImageFont, ImageDraw

text = 'TEST'
font = ImageFont.truetype(r'C:\Windows\Fonts\Arial.ttf', 50)
width, height = font.getsize(text)

image1 = Image.new('RGBA', (200, 150), (0, 128, 0, 92))
draw1 = ImageDraw.Draw(image1)
draw1.text((0, 0), text=text, font=font, fill=(255, 128, 0))

image2 = Image.new('RGBA', (width, height), (0, 0, 128, 92))
draw2 = ImageDraw.Draw(image2)
draw2.text((0, 0), text=text, font=font, fill=(0, 255, 128))

image2 = image2.rotate(30, expand=1)

px, py = 10, 10
sx, sy = image2.size
image1.paste(image2, (px, py, px + sx, py + sy), image2)

image1.show()

#1


30  

Draw text into a temporary blank image, rotate that, then paste that onto the original image. You could wrap up the steps in a function. Good luck figuring out the exact coordinates to use - my cold-fogged brain isn't up to it right now.

将文本绘制到一个临时的空白图像中,旋转该图像,然后将其粘贴到原始图像上。你可以在函数中结束这些步骤。祝你好运,算出确切的坐标来使用——我的大脑现在还不能正常工作。

This demo writes yellow text on a slant over an image:

这个演示程序将黄色文本写在一个倾斜的图像上:

# Demo to add rotated text to an image using PIL

import Image
import ImageFont, ImageDraw, ImageOps

im=Image.open("stormy100.jpg")

f = ImageFont.load_default()
txt=Image.new('L', (500,50))
d = ImageDraw.Draw(txt)
d.text( (0, 0), "Someplace Near Boulder",  font=f, fill=255)
w=txt.rotate(17.5,  expand=1)

im.paste( ImageOps.colorize(w, (0,0,0), (255,255,84)), (242,60),  w)

#2


7  

It's also usefull to know our text's size in pixels before we create an Image object. I used such code when drawing graphs. Then I got no problems e.g. with alignment of data labels (the image is exactly as big as the text).

在创建图像对象之前,最好先知道文本的大小(以像素为单位)。我在绘制图形时使用了这样的代码。然后我没有遇到任何问题,例如数据标签的对齐(图像和文本一样大)。

(...)
img_main = Image.new("RGB", (200, 200))
font = ImageFont.load_default()

# Text to be rotated...
rotate_text = u'This text should be rotated.'

# Image for text to be rotated
img_txt = Image.new('L', font.getsize(rotate_text))
draw_txt = ImageDraw.Draw(img_txt)
draw_txt.text((0,0), rotate_text, font=font, fill=255)
t = img_value_axis.rotate(90, expand=1)

The rest of joining the two images together is already described on this page. When you rotate by an "unregular" angle, you have to improve this code a little bit. It actually works for 90, 180, 270...

将这两个图像连接在一起的其余部分已经在这个页面上进行了描述。当你以一个“不规则”的角度旋转时,你必须稍微改进一下这段代码。它实际上适用于90,180,270。

#3


3  

I'm not saying this is going to be easy, or that this solution will necessarily be perfect for you, but look at the documentation here:

我并不是说这很容易,或者这个解决方案对你来说一定是完美的,但是看看这里的文档:

http://effbot.org/imagingbook/pil-index.htm

http://effbot.org/imagingbook/pil-index.htm

and especially pay attention to the Image, ImageDraw, and ImageFont modules.

尤其要注意图像、ImageDraw和ImageFont模块。

Here's an example to help you out:

这里有一个例子可以帮助你:


import Image
im = Image.new("RGB", (100, 100))
import ImageDraw
draw = ImageDraw.Draw(im)
draw.text((50, 50), "hey")
im.rotate(45).show()

To do what you really want you may need to make a bunch of separate correctly rotated text images and then compose them all together with some more fancy manipulation. And after all that it still may not look great. I'm not sure how antialiasing and such is handled for instance, but it might not be good. Good luck, and if anyone has an easier way, I'd be interested to know as well.

为了实现您真正想要的效果,您可能需要创建一组独立的、正确旋转的文本图像,然后使用一些更花哨的操作将它们组合在一起。尽管如此,它看起来还是不太好。例如,我不确定如何处理反锯齿之类的问题,但这可能并不好。祝你好运,如果有人有更简单的方法,我也很想知道。

#4


2  

Here is a working version, inspired by the answer, but it works without opening or saving images.

这里有一个工作版本,灵感来自于答案,但是它不需要打开或保存图片。

The two images have colored background and alpha channel different from zero to show what's going on. Changing the two alpha channels from 92 to 0 will make them completely transparent.

这两张图片都有不同于0的彩色背景和alpha通道来显示正在发生的事情。将两个alpha通道从92改为0将使它们完全透明。

from PIL import Image, ImageFont, ImageDraw

text = 'TEST'
font = ImageFont.truetype(r'C:\Windows\Fonts\Arial.ttf', 50)
width, height = font.getsize(text)

image1 = Image.new('RGBA', (200, 150), (0, 128, 0, 92))
draw1 = ImageDraw.Draw(image1)
draw1.text((0, 0), text=text, font=font, fill=(255, 128, 0))

image2 = Image.new('RGBA', (width, height), (0, 0, 128, 92))
draw2 = ImageDraw.Draw(image2)
draw2.text((0, 0), text=text, font=font, fill=(0, 255, 128))

image2 = image2.rotate(30, expand=1)

px, py = 10, 10
sx, sy = image2.size
image1.paste(image2, (px, py, px + sx, py + sy), image2)

image1.show()