文字图片制作
现在是2021年12月30日23:37,线代啥的真的是🐶都不学...于是突然想到这个点子,希望借此放松一下。
首先我们需要掌握以下知识:
我们知道,图片是由一个一个像素组成的,那么这一个一个像素也可以由文字图片构成,因此,只要文字足够小,从远处看,也可以看做成普通图片的效果。为此,我们引入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)
x_font, y_font = font_img.getsize("嗨")
offset_x = (img_chile_size - x_font) / 2 offset_y = (img_chile_size - y_font) / 2
draw = ImageDraw.Draw(canvas_child)
|
接下来就到了最核心的步骤,利用两层循环画出文字图片,PIL中坐标系与我们普通的坐标系不同,x轴朝右,y轴朝下
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")
|
运行起来内存直接爆满...
当我们打开图片,效果是这样的
但是图片和原来的图片相比,美观性降低了很多,首先那个白茫茫的效果就很不好,作为一个完美主义者,我们当然不能止步于此。我们发现,之所以出现白茫茫的效果,是因为我们在画小画布时填充的时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) _hsv = colorsys.rgb_to_hsv(_rgb_temp[0], _rgb_temp[1], _rgb_temp[2]) _hsv_temp = list(_hsv) _hsv_temp[2] *= rate _rgb_new = colorsys.hsv_to_rgb(_hsv_temp[0], _hsv_temp[1], _hsv_temp[2]) _rgb_new_int = list(_rgb_new) for i in range(3): _rgb_new_int[i] = int(_rgb_new[i]) return tuple(_rgb_new_int)
|
运行效果
最终运行效果是这样的:
放大
需要注意的问题
首先那个小画布不能太大或太小,稍微增加或者减小都会导致图片效果和大小发生很大的变化
另外要注意区分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) _hsv = colorsys.rgb_to_hsv(_rgb_temp[0], _rgb_temp[1], _rgb_temp[2]) _hsv_temp = list(_hsv) _hsv_temp[2] *= rate _rgb_new = colorsys.hsv_to_rgb(_hsv_temp[0], _hsv_temp[1], _hsv_temp[2]) _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")
|