写在前面:
好久没有更新了,本来想着在2月14号发这篇随笔的,但是仔细想想,还是过两天再发比较合适,毕竟2月14号这个日期并不适合自己。
时针拨回两年前,那年我竟然要写一篇关于情人节的推送,内容涉及到情人节礼物等等,这对我来说简直就是 “难于上青天” 。结果可想而知,最后还是你亲自动手改我的推送,内容简直就是焕然一新,完全变了一个样。
再后来,你不再是我的 “上司”,见面的机会几乎没有。你依然躺在我的VX置顶,但是这又能说明什么呢。如果你要问有哪些英文单词让我记忆深刻,那么 bookstall 这个单词一定在其中。
上面的内容就当我是在胡扯吧,其实写这篇文章,可以说纯粹就是娱乐一下。在看了情人节来了,教你个用 Python 表白的技巧 & 这段 Python 代码,可以让你脱单 这两篇文章之后,感觉挺有意思的,自己也跟着试了一下。
1. 引入
PS:此小节的内容来源于 情人节来了,教你个用 Python 表白的技巧 。
前段时间,在微博上刷到了一条推荐。内容是这样的
出于好奇,我点开了,放大再放大,emmm,有点意思吖…(此处说明:需要 在手机上 查看才能看到效果)
2. 原理
PS:此小节的内容来源于 情人节来了,教你个用 Python 表白的技巧 。
接下来我们就来聊聊 情人节该怎么向ta表白 图片背后的原理。
事实上,每一张图片都是由一个一个的像素点所组成的。而每个像素点,都有自己的颜色,其颜色可以用一个数组来表示:,其中每位数的取值范围都是
。
比如 代表白色,
代表黑色。
当像素点足够多的时候,这张照片就是我们所说的高清照片;而如果当像素点太少,我们的肉眼就能感知到明显的锯齿感(也就是我们所说的糊掉了)。
用 Excel 画了个图,每一方格代表一个像素,其中若我的字体的大小设置 (非字号
,而是每个字占用
个像素),效果大概就是如下这样子。
我只要 每个像素取出一个像素值,并使用这个像素做为该字的颜色即可,在像素量够多的情况下,从远处看,是能看到我们原来图像的轮廓的。
3. 实现
说完了原理,接下来我们尝试用 python 来实现。
PS:本小节的内容来源于 情人节来了,教你个用 Python 表白的技巧 & 这段 Python 代码,可以让你脱单
- 首先,使用 pillow.Image 读取图像,并使用 load函数 获取图片的每一个像素值。
img_raw = Image.open(img_path)
img_array = img_raw.load()
-
然后新建一张画布,并选好你要使用的字体和字体大小。
-
我还增加了一个参数叫做
,原来的代码 生成的字可能有点紧凑,这里我增加这个参数可以控制字和字的距离,比如
,字间距就是字的大小,就是紧密排布的,如果改大一点,比如
,字间距就会变成字的
倍,就留有字大小的
倍的空隙。(来源于 这段 Python 代码,可以让你脱单 )
# 字体大小
font_size = 7
# 字体间距,1 即间距正好为字体大小,紧凑排布,1.2 为字体大小的 1.2 倍
font_space = 1.2
# 字体文件的路径
font_file = 'C:/Windows/Fonts/Alibaba-PuHuiTi-Regular.ttf'
img_new = Image.new('RGB', img_raw.size, (0, 0, 0))
draw = ImageDraw.Draw(img_new)
font = ImageFont.truetype(font_file, size=font_size)
- 由于需要不断循环 “情人节快乐”,这五个字符。所以这里可以
循环
来实现一个生成器。(关于yield的用法,可以参见这篇文章:python中yield的用法详解——最简单,最清晰的解释)
# 绘制的文本
text = '情人节快乐'
def character_generator(text):
while True:
for i in range(len(text)):
yield text[i]
- 接着,要给这些字加上相应的颜色,写入新创建的画布中( 从左到右,从上到下 写入这些字)。
ch_gen = character_generator(text)
for y in range(0, img_raw.size[1], int(font_size * font_space)):
for x in range(0, img_raw.size[0], int(font_size * font_space)):
draw.text((x, y), next(ch_gen), font=font, fill=img_array[x, y], direction=None)
- 最后进行保存。
img_new.convert('RGB').save(join(outputs_folder, basename(path)))
完整代码如下:
from PIL import Image, ImageDraw, ImageFont
from glob import glob
from os.path import basename, join
# 字体大小
font_size = 7
# 字体间距,1 即间距正好为字体大小,紧凑排布,1.2 为字体大小的 1.2 倍
font_space = 1.2
# 绘制的文本
text = '情人节快乐'
# 字体文件的路径
font_file = 'C:/Windows/Fonts/Alibaba-PuHuiTi-Regular.ttf'
# 输入图片路径
inputs_folder = 'C:/Users/admin/Desktop/inputs'
# 输出图片路径
outputs_folder = 'C:/Users/admin/Desktop/outputs'
def process(path):
img_raw = Image.open(path)
img_array = img_raw.load()
img_new = Image.new('RGB', img_raw.size, (0, 0, 0))
draw = ImageDraw.Draw(img_new)
font = ImageFont.truetype(font_file, size=font_size)
def character_generator(text):
while True:
for i in range(len(text)):
yield text[i]
ch_gen = character_generator(text)
for y in range(0, img_raw.size[1], int(font_size * font_space)):
for x in range(0, img_raw.size[0], int(font_size * font_space)):
draw.text((x, y), next(ch_gen), font=font, fill=img_array[x, y], direction=None)
img_new.convert('RGB').save(join(outputs_folder, basename(path)))
if __name__ == '__main__':
for path in glob(join(inputs_folder, '*')):
print('starting processing', path)
process(path)
print('finished processing', path)
注意:
4. 效果
PS:以下图片来源网络
随便从网上找了几张 Hebe(田馥甄)的图片,作为代码测试的对象。
![](https://img.haomeiwen.com/i15175892/d005a364a516e6d3.jpeg)
![](https://img.haomeiwen.com/i15175892/93069fa924f7058e.jpeg)
![](https://img.haomeiwen.com/i15175892/3daff1dc05131631.jpg)
![](https://img.haomeiwen.com/i15175892/38c14a00848d33d8.jpg)
结果如下所示,看起来还是不错的。
![](https://img.haomeiwen.com/i15175892/fdad5da39c6bf3e0.jpeg)
![](https://img.haomeiwen.com/i15175892/9de139dfcdf49337.jpeg)
![](https://img.haomeiwen.com/i15175892/7fe0b57e681a40b5.jpg)
![](https://img.haomeiwen.com/i15175892/0072d296ed4e369b.jpg)
写在最后:
参考资料:
更多资料:
- 阿里巴巴普惠体R 的下载地址:Github or 字体下载网
- 博客:python中yield的用法详解——最简单,最清晰的解释
- 关于 PIL 的 ImageFont:博客:ImageFont与PIL & Python图像处理库PIL的ImageFont模块介绍
- python中PIL模块
如果此文章涉及侵权,还请私信作者删除,谢谢。
网友评论