在网上看到了很多由文字构成的图片,感觉挺厉害的,so自己也来亲自上手试试。
先上个图叭,让大家康康什么是文字图(底色是白色,可能有点模糊)
放大看,可以按住Ctrl键用鼠标滑轮(全图是由love组成)
首先要理解将图片转换成文字图的原理,才能更好的理解代码。
我们要做的就是先构造一块画布,将原图片取出每一像素的颜色,然后用相同颜色的文字取代该处的像素,最后将这些文字布局在画布上。
知道了原理,现在开始开工!!!
先用tkinter将界面布局好
因为需要用到pack和grid定位,所以需要生成两个frame
root = Tk()
root.title("making love image")
root.resizable(1,1)
root.geometry("400x600")
frame1 = Frame(root)
frame2 = Frame(root)
frame1.pack()
frame2.pack()
read_var = StringVar()
save_var = StringVar()
Label3 = Label(frame1,text = "文件路径:")
Label3.grid(row = 0,column = 0,pady = 10)
Label1 = Label(frame1,textvariable = read_var)
Label1.grid(row = 0,column = 1,pady = 30)
Label4 = Label(frame1,text = "保存路径:")
Label4.grid(row = 1,column = 0,pady = 10)
Label2 = Label(frame1,textvariable = save_var)
Label2.grid(row = 1,column = 1,pady = 30)
Button1 = Button(frame2,text = "选择图片",font = ("楷体",22),command = get_image)
Button2 = Button(frame2,text = "选择路径",font = ("楷体",22),command = save_image)
Button3 = Button(frame2,text = "开始生成",font = ("楷体",22),command = make_image)
Button1.pack(pady = 20)
Button2.pack(pady = 20)
Button3.pack(pady = 20)
接着是设置如何选取文件(一般选取文件路径都是这样的代码)
**注:**文件可以选取的类型只有以下代码提到的三种(jpg/png/gif)
文件类型是可以自己改的
def get_image():
global IMGPATH # 全局变量
filenames = askopenfilenames(filetypes = (("jpg img","*.jpg"),("png img","*.png"),("gif img","*.gif"))) # 文件可选类型(jpg\png\gif)
if len(filenames) > 0:
fnlist = [fn for fn in filenames]
fnstr = '\n'.join(fnlist)
read_var.set(fnstr)
IMGPATH = fnlist
else:
read_var.set("目前没有选择任何图片文件")
设置保存路径(利用asksavesfilename方法选取路径)
**注:**选取保存路径时需自己写文件名及后缀名
def save_image():
global savepath # 全局变量savepath
savepath = tkinter.filedialog.asksaveasfilename() # 返回保存路径
save_var.set(savepath)
设置生成图片过程
def make_image():
global IMGPATH
global savepath
for imgpath in IMGPATH: #IMGPATH是一个包含路径的字符串,imgpath才是真正的路径
produce_image(imgpath,savepath)
showinfo(title = '完成生成',message = f'保存路径为:{savepath}') # 弹出消息框
以下才是本章的重点(如何转换):
首先打开所需文件,取出该图的像素组
img_raw = Image.open(img_path) # 打开图片
img_array = img_raw.load() # 加载图像的像素数组
生成一块画布,选取字体类型及文字大小
注:
将画布设置为可涂鸦,该画布的底色可以改变,不同的图用不同颜色的底色,会使转换后的图更为清晰
选择的文字字体类型(即’arial.ttf’)需在windows-font中存在----->不了解的可以看这里
img_new = Image.new("RGB", img_raw.size, (255, 255, 255)) # 生成新画布
draw = ImageDraw.Draw(img_new) # 在新画布上可以画画
font = ImageFont.truetype('arial.ttf', font_size) # 选择字体类型和大小
设置文字生成器(即可以一直循环生成文字)
最好是去了解一下yield的用法
def character_generator(text):
while True:
for i in range(len(text)):
yield text[i]
将文字按图片像素组分布在新的画布上
for y in range(0, img_raw.size[1], font_size):
for x in range(0, img_raw.size[0], font_size):
draw.text((x, y), next(ch_gen), font=font, fill=img_array[x, y], direction=None)
# coding=utf-8
from tkinter import *
from tkinter.filedialog import askopenfilenames
import tkinter.filedialog
from tkinter.messagebox import showinfo
from PIL import Image,ImageDraw,ImageFont
root = Tk()
root.title("making love image")
root.resizable(1,1)
root.geometry("400x600")
frame1 = Frame(root)
frame2 = Frame(root)
frame1.pack()
frame2.pack()
read_var = StringVar()
save_var = StringVar()
IMGPATH = ""
savepath = ""
def get_image():
global IMGPATH # 全局变量
filenames = askopenfilenames(filetypes = (("jpg img","*.jpg"),("png img","*.png"),("gif img","*.gif"))) # 文件可选类型
if len(filenames) > 0:
fnlist = [fn for fn in filenames]
fnstr = '\n'.join(fnlist)
read_var.set(fnstr)
IMGPATH = fnlist
else:
read_var.set("目前没有选择任何图片文件")
def save_image():
global savepath # 全局变量savepath
savepath = tkinter.filedialog.asksaveasfilename() # 返回保存路径
save_var.set(savepath)
def make_image():
global IMGPATH
global savepath
for imgpath in IMGPATH:
produce_image(imgpath,savepath)
showinfo(title = '完成生成',message = f'保存路径为:{savepath}') # 弹出消息框
def produce_image(img_path, savepath):
font_size = 7 # 设置文字大小
text = "love" # 设置文字内容
img_raw = Image.open(img_path)
img_array = img_raw.load()
img_new = Image.new("RGB", img_raw.size, (255, 255, 255))
draw = ImageDraw.Draw(img_new)
font = ImageFont.truetype('arial.ttf', font_size)
ch_gen = character_generator(text)
for y in range(0, img_raw.size[1], font_size):
for x in range(0, img_raw.size[0], font_size):
draw.text((x, y), next(ch_gen), font=font, fill=img_array[x, y], direction=None)
img_new.convert('RGB').save(savepath) # 保存图片
def character_generator(text):
while True:
for i in range(len(text)):
yield text[i]
Label3 = Label(frame1,text = "文件路径:")
Label3.grid(row = 0,column = 0,pady = 10)
Label1 = Label(frame1,textvariable = read_var)
Label1.grid(row = 0,column = 1,pady = 30)
Label4 = Label(frame1,text = "保存路径:")
Label4.grid(row = 1,column = 0,pady = 10)
Label2 = Label(frame1,textvariable = save_var)
Label2.grid(row = 1,column = 1,pady = 30)
Button1 = Button(frame2,text = "选择图片",font = ("楷体",22),command = get_image)
Button2 = Button(frame2,text = "选择路径",font = ("楷体",22),command = save_image)
Button3 = Button(frame2,text = "开始生成",font = ("楷体",22),command = make_image)
Button1.pack(pady = 20)
Button2.pack(pady = 20)
Button3.pack(pady = 20)
mainloop()