提示:想偷懒?我都给你准备好了->Github传送门
前言
啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊,
怎么水文章啊.今天刚被大学录取(2024/8/1),求赞, 求收藏, 求关注.阿里嘎多!!!
一、你要准备什么?
宝子, 我已经把代码和其他文件准备好了, 你只需要准备好Python就行了!!!
奈何我语文不好, 我这小小标题有点抽象.不太懂的话可以去看看这个视频(但是他这个视频的代码有问题运行不了, 看我哒, 看我哒!)【『整活』用百万汉字拼一张彩色照片】@偶尔有点小迷糊偶尔有点小迷糊 这是Bilibili的一个宝藏博主, 力推!!!
二、亮个相吧,小宝贝!
来看看代码, 宝子!
"""
@Auther:Noah Miller
@Date: 2024/8/1
@Blog: https://blog.csdn.net/weixin_54444518
@灵感来源:
- @Author: 偶尔有点小迷糊(Bilibili)
- @link:【『整活』用百万汉字拼一张彩色照片】 https://www.bilibili.com/video/BV1mq4y1n7aE/?share_source=copy_web&vd_source=136849b7b9a5d8445987a371deb2fbf9
"""
# 保Pillow, Click导入
import os
try:
from PIL import Image, ImageDraw, ImageFont
import click
except:
print("缺失关键库, 正在安装(但一定要有Pip)...")
os.system("'pip install pillow click -i https://pypi.mirrors.ustc.edu.cn/simple/")
print("安转完成")
from PIL import Image, ImageDraw, ImageFont
import click
# 参数设置
class Setting:
"""
该类用于存储程序的各种参数设置
"""
chunkHeight = chunkWidth = 16 # 拼图块尺寸
fontSize = 16 # 字体大小
imageMode = "RGBA" # 图像模式
fontRelPath = "./AliPuHui-Bold.ttf" # 字体文件相对路径
chunkFill = "lightgrey" # 拼图块背景填充颜色, 亮灰色效果可以
chunkOutline = None # 拼图块边框, 一般测试的时候用, 可以把拼图框架网格化
chunkOutlineWidth = 1 # 拼图块边框宽度
setting = Setting()
# 用(已经绑定拼图块图片对象的)ImageDraw对象绘制拼图块
def drawChar2ChunkByImageDrawObj(char, draw:ImageDraw.ImageDraw, offsetX:int, offsetY:int, fill, outline, color):
"""
该函数用于在指定的 ImageDraw 对象上绘制带有指定字符的拼图块
:param char: 要绘制的字符
:param draw: 已绑定拼图块图片对象的 ImageDraw 对象
:param offsetX: 字符在 X 轴的偏移量
:param offsetY: 字符在 Y 轴的偏移量
:param fill: 填充颜色
:param outline: 边框颜色
:param color: 字符颜色
"""
draw.rectangle(
(0, 0, setting.chunkWidth, setting.chunkHeight),
fill=color,
outline=outline,
width=setting.chunkOutlineWidth,
)
# 渲染文字, anchor 特别重要, 它指定了对齐方式|anchor 文档传送门: https://pillow.readthedocs.io/en/stable/handbook/text-anchors.html#text-anchors
draw.text((offsetX, offsetY), char, font=setting.font, fill=fill, anchor="mm")
# 组织各函数进行图片文字化的函数
@click.command()
@click.argument("fp",type=click.Path(exists=True))
@click.argument("text")
@click.option("-c", "--color", default=setting.chunkFill, help="指定拼图块背景颜色")
@click.option("-l", "--outline", default=setting.chunkOutline, help="指定拼图块边框颜色.")
@click.option("-o", "--output",default="output.png", help="指定文件输出路径")
@click.option("-h", "--height", default=setting.chunkHeight, help="指定拼图块高度")
@click.option("-w", "--width", default=setting.chunkWidth, help="指定拼图块宽度")
@click.option("-f", "--mode", default=setting.imageMode, help="指定图片模式")
def process(text, fp, mode, width, height,output, outline, color):
"""
该函数是主处理函数,用于根据输入的图片路径和文本,生成带有文本的拼图
:param text: 要绘制的文本
:param fp: 输入图片的路径
:param mode: 图片模式
:param width: 拼图块宽度
:param height: 拼图块高度
:param output: 输出图片路径
:param outline: 拼图块边框颜色
:param color: 拼图块背景颜色
"""
imgSrc = Image.open(fp) # 加载原图
w, h = imgSrc.size # 原图尺寸
# 创建拼图块的图片对象
chunk = Image.new(mode, (width, height))
# 创建拼图框架的图片对象
picFrame = Image.new(mode, (width*w, height*h))
# 创建 ImageDraw 对象并绑定拼图块图片对象
draw = ImageDraw.Draw(chunk, mode)
f = open(setting.fontRelPath, "rb") # 下面连着三步是为了能正常创建字体对象, 如果这样依旧报错, 把字体路径改成绝对路径
font = ImageFont.truetype(f, fontSize)
f.close()
charIndex = 0 # 待渲染的字符在 text 序列里的索引
for y in range(h):
print(f"正在处理第{y+1}行, 还剩{h-y-1}行未处理.")
for x in range(w):
# 绘制拼图块
drawChar2ChunkByImageDrawObj(
text[charIndex],
draw,
width/2,
height/2,
fill=imgSrc.getpixel((x,y)),
color=color,
outline=outline,
)
# 拼图块拼到拼图框架的合适位置 (粘贴到指定位置)
picFrame.paste(chunk, (x*setting.chunkWidth, y*setting.chunkHeight))
charIndex+=1
if charIndex == len(text):
charIndex = 0
print("图片处理完成, 正在保存...")
picFrame.save(output)
print(f"图片已保存至 '{os.path.abspath(output)}'")
if __name__ == "__main__":
process()
三. 重要的事!
不要光把代码"Ctrl+C, Ctrl+V"了哦, 还有个字体文件哈!这个也需要!不然运行不了哦!或者, 你自己换个字体.把Setting里的FontRelPath改成你的字体文件路径也可以(有的字体会乱码)
算了, 懒得写那啥变量的解释了, 你看视频吧, 宝子, 看视频效率高一点.
算了, 还是简单写一下原理吧.怕被骂.嘤嘤嘤.
四. 原理(苦瓜脸, 疲惫)
我们知道, 照片是n多个像素点组成的.每个像素点对应一个颜色.我们获取每个像素点的颜色,
我们可以把同色的文字绘制在一个空的画板上, n多个这样的画板就可以像拼图一样,拼成一幅画(你の臭宝的照片).啊, 实在是不想写了, 还望见谅, 看官去看视频吧.如果有什么建议, 可以在评论区提出来, 非常感谢!!!