如何用Python写春联和编一个中国结

如何用Python写春联和编一个中国结

这两天冰敦敦火了,但也不要忘记我们中国人的春节,新年也需要写春联和挂上中国结。
操作系统自带的某些矢量字库,是可以作为毛笔字库使用的 ,虽然有很多方法可以帮你呈现出系统支持的所有字体文件,我建议最直接的方式是去查看操作系统的字体目录。以Windows为例,我直接在C:WindowsFonts这个路径下找到了“华文隶书”这个字库文件,查看属性可知,该文件名为STLITI.TTF ,Python写春联运行截图: Python写春联完整代码:
# -*- coding: utf-8 -*-

import os
import freetype
import numpy as np
from PIL import Image

FONT_FILE = r"C:WindowsFontsSTLITI.TTF"
BG_FILE = r"bg.jpeg"

def text2image(word, font_file, size=128, color=(0, 0, 0)):
"""使用指定字库将单个汉字转为图像

word - 单个汉字字符串
font_file - 矢量字库文件名
size - 字号,默认128
color - 颜色,默认黑色
"""

face = freetype.Face(font_file)
face.set_char_size(size * size)

face.load_char(word)
btm_obj = face.glyph.bitmap
w, h = btm_obj.width, btm_obj.rows
pixels = np.array(btm_obj.buffer, dtype=np.uint8).reshape(h, w)

dx = int(face.glyph.metrics.horiBearingX / 64)
if dx > 0:
patch = np.zeros((pixels.shape[0], dx), dtype=np.uint8)
pixels = np.hstack((patch, pixels))

r = np.ones(pixels.shape) * color[0] * 255
g = np.ones(pixels.shape) * color[1] * 255
b = np.ones(pixels.shape) * color[2] * 255
im = np.dstack((r, g, b, pixels)).astype(np.uint8)

return Image.fromarray(im)

def write_couplets(text, horv="V", quality="L", out_file=None, bg=BG_FILE):
"""写春联

text - 春联字符串
bg - 背景图片路径
horv - H-横排,V-竖排
quality - 单字分辨率,H-640像素,L-320像素
out_file - 输出文件名
"""

size, tsize = (320, 128) if quality == "L" else (640, 180)
ow, oh = (size, size * len(text)) if horv == "V" else (size * len(text), size)
im_out = Image.new("RGBA", (ow, oh), "#f0f0f0")
im_bg = Image.open(BG_FILE)
if size < 640:
im_bg = im_bg.resize((size, size))

for i, w in enumerate(text):
im_w = text2image(w, FONT_FILE, size=tsize, color=(0, 0, 0))
w, h = im_w.size
dw, dh = (size - w) // 2, (size - h) // 2

if horv == "V":
im_out.paste(im_bg, (0, i * size))
im_out.paste(im_w, (dw, i * size + dh), mask=im_w)
else:
im_out.paste(im_bg, (i * size, 0))
im_out.paste(im_w, (i * size + dw, dh), mask=im_w)

im_out.save("%s.png" % text)
os.startfile("%s.png" % text)
if __name__ == "__main__":
write_couplets("普天同庆", horv="V", quality="H")
write_couplets("欢度春节", horv="V", quality="H")
write_couplets("国泰民安", horv="H", quality="H")
春联中使用的背景图(可在百度找自己喜欢的): 中国结是一种手工编织工艺品,它身上所显示的情致与智慧正是汉族古老文明中的一个侧面。因为其外观对称精致,可以代表汉族悠久的历史,符合中国传统装饰的习俗和审美观念,故命名为中国结。中国结代表着团结幸福平安,特别是在民间,它精致的做工深受大众的喜爱,下面用Python编一个中国结,运行截图:   完整程序代码:
import turtle as t
from math import sqrt

class chineseKnot:
"""
* @breif: 中国结
"""

def __init__(self) -> None:
# 画笔初始化
self.t = t
self.t.title("中国结-Python代码大全")
self.t.pensize(10)
self.t.setup(700, 700)
self.t.pencolor("red")
self.t.speed(14)
# 结心坐标
self.x = 0
self.y = 200

"""
* @breif: 画中国结
* @param[in]: None
* @retval: None
"""

def drawKnot(self) -> None:
self.drawBody()
self.drawEdge()
self.drawAdorn()
self.t.hideturtle()
self.t.done()

"""
* @breif: 画中国结主体部分
* @param[in]: None
* @retval: None
"""

def drawBody(self) -> None:
for i in range(11):
self.__goto(self.x - i * 10 * sqrt(2), self.y - i * 10 * sqrt(2))
self.t.seth(-45)
self.t.fd(200)
self.__goto(self.x + i * 10 * sqrt(2), self.y - i * 10 * sqrt(2))
self.t.seth(-135)
self.t.fd(200)

"""
* @breif: 画中国结边缘部分
* @param[in]: None
* @retval: None
"""

def drawEdge(self) -> None:
for i in range(4):
# 左上角
self.__goto(-10 * sqrt(2) - i * 20 * sqrt(2),
200 - 10 * sqrt(2) - i * 20 * sqrt(2))
self.t.seth(135)
self.t.fd(20)
self.t.circle(10, 180)
self.t.fd(20)

# 右上角
self.__goto(10 * sqrt(2) + i * 20 * sqrt(2),
200 - 10 * sqrt(2) - i * 20 * sqrt(2))
self.t.seth(45)
self.t.fd(20)
self.t.circle(-10, 180)
self.t.fd(20)

# 左下角
self.__goto(-10 * sqrt(2) - i * 20 * sqrt(2),
200 - 190 * sqrt(2) + i * 20 * sqrt(2))
self.t.seth(-135)
self.t.fd(20)
self.t.circle(-10, 180)
self.t.fd(20)

# 右下角
self.__goto(10 * sqrt(2) + i * 20 * sqrt(2),
200 - 190 * sqrt(2) + i * 20 * sqrt(2))
self.t.seth(-45)
self.t.fd(20)
self.t.circle(10, 180)
self.t.fd(20)

# 左侧
self.t.seth(-45)
self.__goto(90 * sqrt(2), 200 - 110 * sqrt(2))
self.t.circle(20, 270)
self.__goto(-90 * sqrt(2), 200 - 110 * sqrt(2))
self.t.circle(-20, 270)

# 右侧
self.__goto(80 * sqrt(2), 200 - 120 * sqrt(2))
self.t.circle(40, 270)
self.__goto(-80 * sqrt(2), 200 - 120 * sqrt(2))
self.t.circle(-40, 270)

"""
* @breif: 画中国结装饰部分
* @param[in]: None
* @retval: None
"""

def drawAdorn(self):
# 上侧
self.__goto(self.x, self.y)
self.t.pensize(14)
self.t.seth(90)
self.t.fd(60)
self.__goto(0, 320)
self.t.seth(180)
self.t.circle(30, 360)
# 下侧
self.__goto(0, 200 - 200 * sqrt(2))
self.t.pensize(40)
self.t.seth(-90)
self.t.fd(20)
self.t.pensize(2)
for i in range(11):
self.__goto(-20 + 4 * i, 200 - 200 * sqrt(2))
self.t.seth(-90)
self.t.fd(200)

"""
* @breif: 画笔移动到指定位置
* @param[in]: x -> 画笔移动位置横坐标
* @param[in]: y -> 画笔移动位置纵坐标
* @retval: None
"""

def __goto(self, x: int, y: int) -> None:
self.t.penup()
self.t.goto(x, y)
self.t.pendown()

if __name__ == "__main__":
knot = chineseKnot()
knot.drawKnot()
运行效果如图