文字图片制作

文字图片制作

现在是2021年12月30日23:37,线代啥的真的是🐶都不学...于是突然想到这个点子,希望借此放松一下。

首先我们需要掌握以下知识:

1
2
3
4
5
6
#PIL(Python Image Library)为python的第三方图像库
#ImageFont可存储bitmap字体
#拓展:字体
# 分为OpenType和TrueType两种
# OpenType:后缀名OTF,由微软和Adobe公司开发
# TrueType:后缀名TTF,由微软和苹果公司开发

我们知道,图片是由一个一个像素组成的,那么这一个一个像素也可以由文字图片构成,因此,只要文字足够小,从远处看,也可以看做成普通图片的效果。为此,我们引入python的第三方PIL库

实现过程

首先我们设定子图和新图的大小

1
2
3
4
5
6
img_chile_size = 15  # 子图的大小(新像素点)
x, y = image.size # 旧图的长和宽
# 有了旧图的长和宽,我们就可以得到新图的大小
canvas = Image.new('RGB', (x * img_chile_size, y * img_chile_size)) # 创# 建新画布,后来的子图都要按顺序放在上面
canvas_child = Image.new('RGB', (img_chile_size, img_chile_size))
# 当然也要创建小画布,让文字画在上面,然后再把小画布贴#在新的大画布上

然后我们创建好画布之后,要开始考虑字体怎么画在小画布上,以及画的位置

1
2
3
4
5
6
7
8
9
10
font_img = ImageFont.truetype("_font.ttf", img_chile_size)
# 这里_font.ttf是我从字体网站上下载下来的,img_chile_size是我们设置的字体大小,也就# 是小画布的大小嘛
# truetype是在文章开头提到的一种字体类型
x_font, y_font = font_img.getsize("嗨")
# 这里是x_font,y_font是字体的大小
offset_x = (img_chile_size - x_font) / 2
offset_y = (img_chile_size - y_font) / 2
# 这里就是定义字体开始画的位置,方便居中显示
draw = ImageDraw.Draw(canvas_child)
# 当然,这里需要定义在哪画

接下来就到了最核心的步骤,利用两层循环画出文字图片,PIL中坐标系与我们普通的坐标系不同,x轴朝右,y轴朝下

image-20211231125844972
1
2
3
4
5
6
7
for i in range(y):
for j in range(x):
draw.rectangle((0, 0, img_chile_size, img_chile_size), fill='lightgray') # 画一个淡灰色的长方形作为背景
draw.text((offset_x, offset_y), text[char_index], font=font_img, fill=image.getpixel((j, i))) # 画文字
canvas.paste(canvas_child, (j * img_chile_size, i * img_chile_size)) # 把小画布粘贴到大画布上
char_index = (char_index + 1) % len(text) # 更改文字索引
canvas.save("finished.jpg") # 最后要保存

运行起来内存直接爆满...

image-20211231133216489

当我们打开图片,效果是这样的

image-20211231140326240

但是图片和原来的图片相比,美观性降低了很多,首先那个白茫茫的效果就很不好,作为一个完美主义者,我们当然不能止步于此。我们发现,之所以出现白茫茫的效果,是因为我们在画小画布时填充的时lightgray,所有的图片效果都是由文字实现的,而要解决这个问题,我们首先要把填充背景改为彩色(随位置变换),并且与文字颜色相比,只能是亮度变暗或者变亮。而我们默认使用的颜色模型是RGB模式,不能改变亮度,而另一种颜色模型HSV(Hue色调, Saturation饱和度, Value明度)就可以改变亮度(哈哈哈哈说实话咱也只知道改亮度可以,不知道改饱和度和色调的效果怎么样,时间太紧,就不试了)

colorsys模块是python的一个库,支持进行颜色转换

在转换过后,程序出现了报错,提示下面的fill接受的存放rgb参数的元组只能是整形,于是我们进行了修改,自定义函数

draw.rectangle((0, 0, img_chile_size, img_chile_size), fill=temp_color2)

1
2
3
4
5
6
7
8
9
10
def color_change(temp, rate):
_rgb_temp = list(temp) # temp是临时的元组类型的rgb,把旧的RGB转为列表
_hsv = colorsys.rgb_to_hsv(_rgb_temp[0], _rgb_temp[1], _rgb_temp[2]) # 把RGB转为HSV
_hsv_temp = list(_hsv) # 把hsv转为列表
_hsv_temp[2] *= rate # 修改hsv
_rgb_new = colorsys.hsv_to_rgb(_hsv_temp[0], _hsv_temp[1], _hsv_temp[2]) # 将修改的hsv再转换为rgb
_rgb_new_int = list(_rgb_new)
for i in range(3):
_rgb_new_int[i] = int(_rgb_new[i]) # 这里强制把float类型转换为int型
return tuple(_rgb_new_int)

运行效果

最终运行效果是这样的:

image-20211231135539580

放大

image-20211231135600656

需要注意的问题

首先那个小画布不能太大或太小,稍微增加或者减小都会导致图片效果和大小发生很大的变化

另外要注意区分PIL和pillow的区别,下面代码不能直接运行,可能需要安装PIL,运行pip install PIL(好像是安装PIL,也可能是pillow,哎呀,自己百度一下,我是很久之前安装的,早就忘记了,不想百度,我已经懒到了一种境界you know ⸜(๑'ᵕ'๑)⸝⋆*

最后,这个由于这个程序只是临时使用,可能有许多不完善是地方,日后有空的时候可能会加入一些GUI界面以及个性化设置,还有解决最大的img_chile_size更改问题

代码展示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
from PIL import ImageFont, Image, ImageDraw
import colorsys


def color_change(temp, rate):
_rgb_temp = list(temp) # ,temp是临时的元组类型的rgb,把旧的RGB转为列表
_hsv = colorsys.rgb_to_hsv(_rgb_temp[0], _rgb_temp[1], _rgb_temp[2]) # 把RGB转为HSV
_hsv_temp = list(_hsv) # 把hsv转为列表
_hsv_temp[2] *= rate # 修改hsv
_rgb_new = colorsys.hsv_to_rgb(_hsv_temp[0], _hsv_temp[1], _hsv_temp[2])#将修改的hsv再转换为rgb
_rgb_new_int = list(_rgb_new)
for i in range(3):
_rgb_new_int[i] = int(_rgb_new[i])
return tuple(_rgb_new_int)


with Image.open("img.jpg") as image:
text = "happy new year"
img_chile_size = 15 # 子图的大小(新像素)
x, y = image.size # 旧图的长和宽
canvas = Image.new('RGB', (x * img_chile_size, y * img_chile_size)) # 创建新画布
canvas_child = Image.new('RGB', (img_chile_size, img_chile_size)) # 创建小画布
font_img = ImageFont.truetype("_font.ttf", img_chile_size) # 字体初始化
x_font, y_font = font_img.getsize("A")
offset_x = (img_chile_size - x_font) / 2
offset_y = (img_chile_size - y_font) / 2
draw = ImageDraw.Draw(canvas_child)
char_index = 0

for i in range(y):
for j in range(x):
temp_color = image.getpixel((j, i))
temp_color2 = color_change(temp_color,0.5)
draw.rectangle((0, 0, img_chile_size, img_chile_size), fill=temp_color2)
draw.text((offset_x, offset_y), text[char_index], font=font_img, fill=image.getpixel((j, i)))
canvas.paste(canvas_child, (j * img_chile_size, i * img_chile_size))
char_index = (char_index + 1) % len(text)
canvas.save("gift.jpg")

文字图片制作
https://d4wnnn.github.io/2022/01/27/Others/文字图片制作/
作者
D4wn
发布于
2022年1月27日
许可协议