Source code for AutomateTheBoringStuff.Ch17.Projects.P3_seatingCards

"""Seating cards

Chapter 13 included a practice project to create custom invitations from a list of
guests in a plaintext file - :py:mod:`.P3_invitations`. As an additional project, use
:py:mod:`PIL` to create images for custom seating cards for your guests. For each of
the guests listed in ``guests.txt``, generate an image file with the guest's name and
some flowery decoration.

To ensure that each seating card is the same size, add a black rectangle on the edges
of the invitation image so that when the image is printed out, there will be a
guideline for cutting. The PNG files that :py:mod:`PIL.Image` produces are set
to 72 pixels per inch, so a 4×5-inch card would require a 288×360-pixel image.

Note:
    * Flowery decoration from: http://www.reusableart.com/flower-02.html

"""


[docs]def main(): import os from PIL import Image, ImageFont, ImageDraw GUEST_FILE = '../../Ch13/Projects/guests.txt' FLOWER_FILENAME = 'flower-02.png' OUTPUT_FOLDER = 'seatingCards' FONTS_FOLDER = '/usr/share/fonts/truetype' os.makedirs(OUTPUT_FOLDER, exist_ok=True) # Get guest list from file with open(GUEST_FILE) as guest_list: guests = guest_list.read().splitlines() for guest in guests: # Open flowery decoration deco = Image.open(FLOWER_FILENAME) deco_width, deco_height = deco.size # Resize decoration if smaller than 4x5-inch card if deco_width < 288 or deco_height < 360: # Calculate the new width and height to resize to if deco_width > deco_height: deco_height = int((288 / deco_width) * deco_height) deco_width = 288 else: deco_width = int((360 / deco_height) * deco_width) deco_height = 360 print('Resizing decoration...') deco = deco.resize((deco_width, deco_height), Image.ANTIALIAS) deco = deco.convert(mode='L') # Convert back to grayscale (if original image is grayscale) # Add guest's name draw = ImageDraw.Draw(deco) if u'\u014d' in guest: # Replace ō with o since draw.textsize can't translate it guest = guest.replace(u'\u014d', 'o') text_width, text_height = draw.textsize(guest) font = ImageFont.truetype(os.path.join(FONTS_FOLDER, '/liberation/LiberationSerif-Regular.ttf'), 15) draw.text((int((deco_width - text_width) / 2), int((deco_height - text_height) / 2)), guest, fill='black' , font=font) # Make black card with extra space for cutting image = Image.new('RGBA', (deco_width + 10, deco_height + 10), 'black') width, height = image.size # Add modified decoration to background image.paste(deco, (int((width - deco_width) / 2), int((height - deco_height) / 2))) # Save seating card filename = ''.join(filter(str.isalnum, guest)) + '.png' image.save(os.path.join(OUTPUT_FOLDER, filename))
if __name__ == '__main__': main()