Generating Chinese Spring Festival Couplets with Python
This article demonstrates how to use Python and the Pillow library to download character glyphs, create background images, and programmatically generate Chinese Spring Festival couplets in both vertical and horizontal layouts, providing complete source code and sample outputs.
Spring Festival couplets are a traditional Chinese literary form used to convey good wishes during the New Year; this tutorial shows how to generate such couplets automatically using Python.
The script requires the following modules:
import io
from PIL import Image
import numpy as np
import requestsThe get_word function retrieves a single Chinese character (or uppercase letter) image from an online service, optionally resizing it according to the requested quality (H, M, L).
def get_word(ch, quality):
#"""获取单个汉字(字符)的图片"""
fp = io.BytesIO(requests.post(url='http://xufive.sdysit.com/tk', data={'ch':ch}).content)
im = Image.open(fp)
w, h = im.size
if quality == 'M':
w, h = int(w*0.75), int(0.75*h)
elif quality == 'L':
w, h = int(w*0.5), int(0.5*h)
return im.resize((w,h))The get_bg function simply calls get_word with the special key 'bg' to obtain the background image for the couplets.
def get_bg(quality):
#"""获取春联背景的图片"""
return get_word('bg', quality)The core routine write_couplets assembles the couplet image. It accepts the text (words separated by spaces for each line), orientation (horizontal 'H' or vertical 'V'), quality, and an optional output file name. It calculates canvas size, creates a new RGBA image, pastes background and character images row by row, and finally displays or saves the result.
def write_couplets(text, HorV='V', quality='L', out_file=None):
usize = {'H':(640,23), 'M':(480,18), 'L':(320,12)}
bg_im = get_bg(quality)
text_list = [list(item) for item in text.split()]
rows = len(text_list)
cols = max([len(item) for item in text_list])
if HorV == 'V':
ow, oh = 40+rows*usize[quality][0]+(rows-1)*10, 40+cols*usize[quality][0]
else:
ow, oh = 40+cols*usize[quality][0], 40+rows*usize[quality][0]+(rows-1)*10
out_im = Image.new('RGBA', (ow, oh), '#f0f0f0')
for row in range(rows):
if HorV == 'V':
row_im = Image.new('RGBA', (usize[quality][0], cols*usize[quality][0]), 'white')
offset = (ow-(usize[quality][0]+10)*(row+1)-10, 20)
else:
row_im = Image.new('RGBA', (cols*usize[quality][0], usize[quality][0]), 'white')
offset = (20, 20+(usize[quality][0]+10)*row)
for col, ch in enumerate(text_list[row]):
if HorV == 'V':
pos = (0, col*usize[quality][0])
else:
pos = (col*usize[quality][0], 0)
ch_im = get_word(ch, quality)
row_im.paste(bg_im, pos)
row_im.paste(ch_im, (pos[0]+usize[quality][1], pos[1]+usize[quality][1]), mask=ch_im)
out_im.paste(row_im, offset)
if out_file:
out_im.convert('RGB').save(out_file)
out_im.show()Example usage:
text = '普天同庆 欢度春节'
write_couplets(text, HorV='V', quality='M', out_file='普天同庆.jpg')Another example with horizontal layout:
text = '年尽岁除岁月如歌 冬去春来春光似画'
write_couplets(text, HorV='H', quality='M', out_file='岁月如歌.jpg')And a third example:
text = '人世间纵有百娇千红 唯独你是我情之所钟'
write_couplets(text, HorV='H', quality='M', out_file='情之所钟.jpg')Running the script displays the generated couplet images and saves them as JPEG files if an output filename is provided.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Python Programming Learning Circle
A global community of Chinese Python developers offering technical articles, columns, original video tutorials, and problem sets. Topics include web full‑stack development, web scraping, data analysis, natural language processing, image processing, machine learning, automated testing, DevOps automation, and big data.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
