Using Python to automate calendar generation and image manipulation via matplotlib tables and PIL/pillow image library

Automatically generate calendars from your photos, for simple self-printed calendars

Calendizer is a simple Python command line tool that generates a set of calendar-month tables and pastes them onto a given set of 12 photos.

The size and position of the calendar-table is fully configurable. This allows for self-printing calendars in a timely manner. Self-printing has several advantages over online/order printing:

- you can iterate several test-prints to get things just right
- often images print slightly darker than on-screen, and self-printing allows you to adjust for that
- no waiting about for the post!
- depending on your printer and the volume required, it can work out cheaper

Example for the month of April 2022:




Main Python Libraries used:

1 - calendar module

2 - matplotlib.pyplot

3 - Pillow (PIL = Python Imaging Library fork)



Main processing steps and the libraries used

1 - calendar module

Python's calendar module has excellent support for working with dates. For Calendizer, obviously months are particularly interesting.

Here are some wrapper functions to encapsulate calls to the calendar module. They can be used as working examples:


def days_in_month(year, month_index):
    return calendar.monthrange(year, month_index)[1]

# 0 = Mon, 1 = Tue, ...
def weekday_zero_is_monday(year, month, day):
    return calendar.weekday(year, month, day)

def month_name(month):
    return calendar.month_name[month]



2 - matplotlib.pyplot - to generate a table-image of one calendar month

The pyplot part of matplotlib is typically used to draw charts and graphs. However, it can also be used to render tables as images. This is how Calendizer produces 'month tables' as follows.

We can execute the render_calendar_tables.py part of Calendizer, to generate the calendar images:

python render_calendar_tables.py 2023 \temp --dpi 150 -b blue


The output looks like this:


Generating January 2023 ...

 - saved to \temp\2023-01-January.png [OK]




For more details, see the calendizer README.

Also see the article linked at the end of this post.



3 -  Pillow (PIL = Python Imaging Library fork) - to combine calendar and background images together

Pillow is a fork of PIL (Python Imaging Library) and provides a simple API for image manipulation.

First, we use the Image class to load the images (image formats used include JPEG and PNG).

    calender_image = Image.open(calendar_image_file_path)
    background_image = Image.open(input_image_path)

Next, we combine the two images, by "pasting" (blending) the month-table image onto the background photo image:

    background_image = paste_with_transparency(
        calender_image, background_image, alpha, offset)

The following code shows how the two images are combined by "pasting" via Image.blend(). Transparency can be specified via the alpha parameter.

def paste_with_transparency(fg_img, bg_img, alpha=1.0, box=(0, 0)):
    fg_img_trans = Image.new("RGBA", fg_img.size)
    fg_img_trans = Image.blend(fg_img_trans, fg_img, alpha)
    bg_img.paste(fg_img_trans, box, fg_img_trans)
    return bg_img


Finally, we use Pillow to save the combined image:

    background_image.save(output_image_path)

These steps are repeated for all 12 months.


Other modules used:

- optparse module

This Python module provides simple support for command line argument parsing and options, with help text.

- typing module

This Python module allows for type hints, so you can add type annotations to your code. See my blog post for more details.

References:

- calendizer OSS tool to generate simple printable calendars from photos

- article: Simple Little Tables with Matplotlib


Comments