Generating Chinese "Fu" Characters with Python and PIL
This tutorial demonstrates how to use Python libraries such as requests and Pillow to scrape individual Chinese characters, resize them, compose them onto a background image, and output a customized "Fu" couplet image, complete with full source code and usage instructions.
The article introduces a Python-based method for automatically generating Chinese "Fu" characters, inspired by the popularity of the Alipay "Collect Five Blessings" activity, and encourages readers to create their own images using code.
Step 1: Import required libraries
import io<br/>from PIL import Image<br/>import requestsStep 2: Define a function to fetch a single character image
def get_word(ch, quality):<br/> fp = io.BytesIO(requests.post(url='http://xufive.sdysit.com/tk', data={'ch':ch}).content)<br/> im = Image.open(fp)<br/> w, h = im.size<br/> if quality == 'M':<br/> w, h = int(w*0.75), int(0.75*h)<br/> elif quality == 'L':<br/> w, h = int(w*0.5), int(0.5*h)<br/> return im.resize((w,h))Step 3: Define a helper to obtain the background image
def get_bg(quality):<br/> return get_word('bg', quality)Step 4: Create the main function that assembles the couplet
def write_couplets(text, HorV='V', quality='L', out_file=None):<br/> usize = {'H':(640,23), 'M':(480,18), 'L':(320,12)}<br/> bg_im = get_bg(quality)<br/> text_list = [list(item) for item in text.split()]<br/> rows = len(text_list)<br/> cols = max([len(item) for item in text_list])<br/> if HorV == 'V':<br/> ow, oh = 40+rows*usize[quality][0]+(rows-1)*10, 40+cols*usize[quality][0]<br/> else:<br/> ow, oh = 40+cols*usize[quality][0], 40+rows*usize[quality][0]+(rows-1)*10<br/> out_im = Image.new('RGBA', (ow, oh), '#f0f0f0')<br/> for row in range(rows):<br/> if HorV == 'V':<br/> row_im = Image.new('RGBA', (usize[quality][0], cols*usize[quality][0]), 'white')<br/> offset = (ow-(usize[quality][0]+10)*(row+1)-10, 20)<br/> else:<br/> row_im = Image.new('RGBA', (cols*usize[quality][0], usize[quality][0]), 'white')<br/> offset = (20, 20+(usize[quality][0]+10)*row)<br/> for col, ch in enumerate(text_list[row]):<br/> if HorV == 'V':<br/> pos = (0, col*usize[quality][0])<br/> else:<br/> pos = (col*usize[quality][0], 0)<br/> ch_im = get_word(ch, quality)<br/> row_im.paste(bg_im, pos)<br/> row_im.paste(ch_im, (pos[0]+usize[quality][1], pos[1]+usize[quality][1]), mask=ch_im)<br/> out_im.paste(row_im, offset)<br/> if out_file:<br/> out_im.convert('RGB').save(out_file)<br/> out_im.show()Step 5: Full script example
import io<br/>from PIL import Image<br/>import requests<br/>def get_word(ch, quality):<br/> fp = io.BytesIO(requests.post(url='http://xufive.sdysit.com/tk', data={'ch':ch}).content)<br/> im = Image.open(fp)<br/> w, h = im.size<br/> if quality == 'M':<br/> w, h = int(w*0.75), int(0.75*h)<br/> elif quality == 'L':<br/> w, h = int(w*0.5), int(0.5*h)<br/> return im.resize((w,h))<br/>def get_bg(quality):<br/> return get_word('bg', quality)<br/>def write_couplets(text, HorV='V', quality='L', out_file=None):<br/> usize = {'H':(640,23), 'M':(480,18), 'L':(320,12)}<br/> bg_im = get_bg(quality)<br/> text_list = [list(item) for item in text.split()]<br/> rows = len(text_list)<br/> cols = max([len(item) for item in text_list])<br/> if HorV == 'V':<br/> ow, oh = 40+rows*usize[quality][0]+(rows-1)*10, 40+cols*usize[quality][0]<br/> else:<br/> ow, oh = 40+cols*usize[quality][0], 40+rows*usize[quality][0]+(rows-1)*10<br/> out_im = Image.new('RGBA', (ow, oh), '#f0f0f0')<br/> for row in range(rows):<br/> if HorV == 'V':<br/> row_im = Image.new('RGBA', (usize[quality][0], cols*usize[quality][0]), 'white')<br/> offset = (ow-(usize[quality][0]+10)*(row+1)-10, 20)<br/> else:<br/> row_im = Image.new('RGBA', (cols*usize[quality][0], usize[quality][0]), 'white')<br/> offset = (20, 20+(usize[quality][0]+10)*row)<br/> for col, ch in enumerate(text_list[row]):<br/> if HorV == 'V':<br/> pos = (0, col*usize[quality][0])<br/> else:<br/> pos = (col*usize[quality][0], 0)<br/> ch_im = get_word(ch, quality)<br/> row_im.paste(bg_im, pos)<br/> row_im.paste(ch_im, (pos[0]+usize[quality][1], pos[1]+usize[quality][1]), mask=ch_im)<br/> out_im.paste(row_im, offset)<br/> if out_file:<br/> out_im.convert('RGB').save(out_file)<br/> out_im.show()<br/>text = '福'<br/>write_couplets(text, HorV='V', quality='M', out_file='福.jpg')The article concludes with encouragement for continuous learning, a reminder that difficulties are normal, and an invitation to join a Python learning community for further discussion and resource sharing.
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.