Skip to content
Permalink
a71281a3d3
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
246 lines (179 sloc) 8.89 KB
#!/usr/bin/python3
# -*- coding: utf-8; mode: python -*-
__version__ = "1.0"
__date__ = "20170323"
__author__ = "kthoden@mpiwg-berlin.mpg.de"
import os
import sys
import logging
import configparser
import textwrap
import argparse
from PIL import Image, ImageFont, ImageDraw
logging.basicConfig(level=logging.DEBUG, format=' %(asctime)s - %(levelname)s - %(message)s')
DIMENSIONS = (2000, 2844) # ratio of 0.703205791106515
BACKGROUND = 0, 0, 0
METADATA_DICT = {'eoa_series': 'Studies', 'eoa_number': '125',
'eoa_authors': ['Klaus Thoden'], 'eoa_title':
'Der ewige Testband', 'eoa_subtitle':
'Experimentell'}
SERIES_COLOURS = {"sources" : (40, 96, 49),
"studies" : (13, 40, 72),
"proceedings" : (173, 54, 50),
"textbooks" : (210, 182, 35)}
def get_cover_image(image_path):
"""Choose a random landscape image from publications in this volume"""
import random
candidates = os.listdir(image_path)
for image in candidates:
tmp_image = Image.open(image_path + "/" + str(image))
ratio = calculate_ratio(tmp_image)
if ratio < 1:
candidates.remove(image)
chosen_image = random.choice(candidates)
return chosen_image
# def get_cover_image ends here
def calculate_ratio(image_object):
"""Determine the aspect ratio of an image"""
width, height = image_object.size
ratio = float(width)/float(height)
return ratio
# def calculate_ratio ends here
def resize_image(image_object, max_size, dimension):
"""Resize an image, preserve ratio.
Takes three arguments, an image object, the maximal size and the
dimension (width or height).
https://stackoverflow.com/questions/273946/how-do-i-resize-an-image-using-pil-and-maintain-its-aspect-ratio
"""
width, height = image_object.size
if dimension == "height":
height_percent = (max_size/float(height))
wsize = int((float(width)*float(height_percent)))
resized_image = image_object.resize((wsize, max_size), Image.ANTIALIAS)
elif dimension == "width":
width_percent = (max_size/float(width))
hsize = int((float(height)*float(width_percent)))
resized_image = image_object.resize((max_size, hsize), Image.ANTIALIAS)
else:
print("You must either specify height or width as dimension. Exiting.")
sys.exit(0)
return resized_image
# def resize_image ends here
def format_authors(authors_list):
"""Format the list of authors
Input is the start and end point of the authors in a list. Return
both a formatted string and the pure list of authors.
"""
if len(authors_list) == 0:
authors_as_string = ""
if len(authors_list) == 1:
authors_as_string = """%s""" % (authors_list[0])
elif len(authors_list) == 2:
authors_as_string = """%s and %s""" % (authors_list[0], authors_list[1])
elif len(authors_list) > 2:
authors_as_string = """%s""" % authors_list[0]
for author in range(1, len(authors_list) - 1):
authors_as_string += ", " + authors_list[author]
authors_as_string += " and %s" % (authors_list[-1])
return authors_as_string
# def format_authors ends here
def add_watermark(image, watermarkstring):
"""Add a string of text across the cover. Return a rotated image object"""
# https://codenhagen.wordpress.com/2015/12/04/putting-rotated-text-on-images-with-pillow-python/
base_image = Image.open(image)
tmp_img = Image.new("RGBA", (DIMENSIONS[1], DIMENSIONS[0]), (0,0,0,0))
font_colour = (255,0,0)
big_red_font = ImageFont.truetype("Helvetica", 200)
text_canvas = ImageDraw.Draw(tmp_img)
text_canvas.text((0, 0), watermarkstring, font=big_red_font, fill=font_colour)
slanted_image = tmp_img.rotate(60, expand=True)
# add third parameter as transparent mask
# https://stackoverflow.com/questions/5324647/how-to-merge-a-transparent-png-image-with-another-image-using-pil
base_image.paste(slanted_image, (200, 100), slanted_image)
base_image.save(image)
print("Added a watermark to", image)
# return slanted_image
# def add_watermark ends here
def centered(textstring, font_spec):
"""Return coordinates for a centered string."""
tmp_draw = ImageDraw.Draw(Image.new("RGB", DIMENSIONS, BACKGROUND))
string_width, string_height = tmp_draw.textsize(textstring, font=font_spec)
coordinate = DIMENSIONS[0] / 2 - string_width / 2
return coordinate
# def centered ends here
def create_cover(metadata_dict, image_directory, cover_filename):
"""Create a cover using PIL"""
img = Image.new("RGB", DIMENSIONS, BACKGROUND)
upper_part = Image.new("RGB", (DIMENSIONS[0], int(DIMENSIONS[1]/3)), SERIES_COLOURS[metadata_dict['eoa_series'].lower()])
img.paste(upper_part, (0, 0))
title_text = metadata_dict['eoa_title']
subtitle_text = metadata_dict['eoa_subtitle']
authors_text = format_authors(metadata_dict['eoa_authors'])
series_number_text = "{0} {1}".format(metadata_dict['eoa_series'], metadata_dict['eoa_number'])
if metadata_dict['eoa_series'].lower() == "sources":
press_text = "Edition Open Sources"
else:
press_text = "Max Planck Research Library for the History and Development of Knowledge"
if metadata_dict['eoa_series'].lower() == "textbooks":
fill_colour_top = (0, 0, 0)
else:
fill_colour_top = (255, 255, 255)
big_bold_font = ImageFont.truetype(font="Times New Roman Bold", size=120)
medium_font = ImageFont.truetype(font="Times New Roman", size=100)
small_font = ImageFont.truetype(font="Times New Roman", size=80)
text_draw = ImageDraw.Draw(img)
# these will eventually also become candidates for multilines
# text_draw.text((centered(title_text, big_bold_font), 200), title_text, font=big_bold_font, fill=fill_colour_top)
title_text_lines = textwrap.wrap(title_text, width=30)
title_text_joined = "\n".join(title_text_lines)
ttcenter = centered(title_text_joined, big_bold_font)
text_draw.multiline_text((ttcenter, 200), title_text_joined, font=big_bold_font, align="center")
if len(subtitle_text) > 0:
text_draw.text((centered(subtitle_text, medium_font), 350), subtitle_text, font=medium_font, fill=fill_colour_top)
authors_text_lines = textwrap.wrap(authors_text, width=50)
authors_text_joined = "\n".join(authors_text_lines)
ttcenter = centered(authors_text_joined, small_font)
text_draw.multiline_text((ttcenter, int(DIMENSIONS[1]/3)-200), authors_text_joined, font=small_font, align="center")
# text_draw.text((centered(authors_text, small_font), int(DIMENSIONS[1]/3)-200), authors_text, font=small_font, fill=fill_colour_top)
press_text_lines = textwrap.wrap(press_text, width=40)
press_text_lines.append(series_number_text)
press_text_joined = "\n".join(press_text_lines)
ptcenter = centered(press_text_joined, small_font)
text_draw.multiline_text((ptcenter,DIMENSIONS[1]-400), press_text_joined, font=small_font, align="center")
if image_is_file == False:
image_on_cover = Image.open(os.path.join(image_directory, get_cover_image(image_directory)))
else:
image_on_cover = Image.open(image_directory)
MAXIMUM_HEIGHT = 1200
resized_image = resize_image(image_on_cover, MAXIMUM_HEIGHT, "height")
coord = DIMENSIONS[0]/2 - resized_image.width/2
img.paste(resized_image, (int(coord), 1200))
img.save(cover_filename)
print("Wrote", cover_filename)
watermark = add_watermark(cover_filename, "Automatically generated cover.\nDo not use in production!")
# def create_cover ends here
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument("image_dir", help="Path to directory with potential images.")
parser.add_argument("-c", "--config", help="File that contains the publication data.", default="publication.cfg")
parser.add_argument("-o", "--output", help="Name of output file.", default="Cover.jpg")
args = parser.parse_args()
IMAGES = args.image_dir
if os.path.exists("publication.cfg"):
logging.debug("Using %s as publication config" % (args.config))
config = configparser.ConfigParser()
config.read(args.config)
list_of_authors = list(set(config['Authors'].values()))
for author in list_of_authors:
if len(author) == 0:
list_of_authors.remove(author)
METADATA_DICT.update({'eoa_series' : config['Technical']['Serie']})
METADATA_DICT.update({'eoa_number' : config['Technical']['Number']})
METADATA_DICT.update({'eoa_title' : config['Technical']['Title']})
METADATA_DICT.update({'eoa_subtitle' : config['Technical']['Subtitle']})
METADATA_DICT.update({'eoa_authors' : list_of_authors})
else:
logging.debug("Using the built-in metadata as publication config")
OUTFILE = args.output
create_cover(METADATA_DICT, IMAGES, OUTFILE)
# finis