用百万文字拼出一张照片, 快去给你的心上人表白吧!

提示:想偷懒?我都给你准备好了->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多个这样的画板就可以像拼图一样,拼成一幅画(你の臭宝的照片).啊, 实在是不想写了, 还望见谅, 看官去看视频吧.如果有什么建议, 可以在评论区提出来, 非常感谢!!!

                

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值