commit 72da13f34974449eef3168600f5bca9609be9403 Author: maia arson crimew Date: Tue Apr 26 21:31:57 2022 +0200 initial commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..655f22c --- /dev/null +++ b/README.md @@ -0,0 +1,18 @@ +# shirtgen - a maiacore t-shirt design generator + +How to use: + +* write a shirtfile (see example.shirt for an example and the comments in gen.py for a documentation of the format) +* run `gen.py ` to generate a png + +## Example + +shirtfile: +``` +m:b:fill FIRST +m:r:fill second line +r:r:400 third line +``` + +output: +![three lines of text, the first one is really big and says "first", the second line is smaller and says "second line" a third, even smaller line says "third line"](example.png) \ No newline at end of file diff --git a/example.png b/example.png new file mode 100644 index 0000000..83b2f8d Binary files /dev/null and b/example.png differ diff --git a/example.shirt b/example.shirt new file mode 100644 index 0000000..5dcc84d --- /dev/null +++ b/example.shirt @@ -0,0 +1,3 @@ +m:b:fill FIRST +m:r:fill second line +r:r:400 third line \ No newline at end of file diff --git a/fonts/F25_Bank_Printer.ttf b/fonts/F25_Bank_Printer.ttf new file mode 100644 index 0000000..9124324 Binary files /dev/null and b/fonts/F25_Bank_Printer.ttf differ diff --git a/fonts/F25_Bank_Printer_Bold.ttf b/fonts/F25_Bank_Printer_Bold.ttf new file mode 100644 index 0000000..7ca3ec5 Binary files /dev/null and b/fonts/F25_Bank_Printer_Bold.ttf differ diff --git a/gen.py b/gen.py new file mode 100644 index 0000000..68546c8 --- /dev/null +++ b/gen.py @@ -0,0 +1,103 @@ +from PIL import Image, ImageDraw, ImageFont +import sys + +# fonts are defined here +fonts = { + "r": "fonts/F25_Bank_Printer.ttf", + "b": "fonts/F25_Bank_Printer_Bold.ttf", +} + +if len(sys.argv) == 1: + print("please specify a path to a shirtfile") + exit(1) + +# parse shirtfile into list of tuples +# +# shirtfile syntax: +# a shirtfile is a plain-text file made up of lines in the following format +# {alignment}:{font}:{size} {text} +# where: +# - alignment can be: +# * 'm' for centered text +# * 'l' for left aligned text +# * 'r' for right aligned text +# - font can be one of the configured fonts above, included per default are: +# * 'r' for F25 Bank Printer (regular) +# * 'b' for F25 Bank Printer Bold +# - size is either 'fill' to automatically calculate a font size to fill the width of the canvas +# or a font size in pixels +# - text is your desired line of text (with no line breaks) +# the shirtfile parser treats lines starting with # as comments and ignores empty lines +# +texts = [] +with open(sys.argv[1], "r") as f: + lines = f.readlines() + + for line in lines: + # skip comments and empyt lines + if line.startswith("#") or len(line.strip()) == 0: + continue + + parts = line.strip().split(" ", 1) + texts.append(tuple(parts[0].split(":")) + (parts[1],)) + +# create transparent 5000x5000 image +im = Image.new("RGBA", (5000, 5000), (0, 0, 0, 0)) + +# quick maths +# calculate appropriate text sizes and bounding box sizes for positioning later +p_texts = [] +total_height = 0 +for text in texts: + font_size = 50 + font_path = fonts[text[1]] + bbox_size = (0, 0) + font = None + + if text[2] == "fill": + # dynamic font size calc is hell + # reload font at increasing size until we fill out the whole canvas width + while bbox_size[0] < (im.size[0] - 5): + font = ImageFont.truetype(font_path, font_size) + bbox = font.getbbox(text[3], anchor=f"{text[0]}b") + bbox_size = (bbox[2] - bbox[0], bbox[3] - bbox[1]) + font_size += 5 + else: + # load font for configured size and do bbox calculation + font_size = int(text[2]) + font = ImageFont.truetype(font_path, font_size) + bbox = font.getbbox(text[3], anchor=f"{text[0]}b") + bbox_size = (bbox[2] - bbox[0], bbox[3] - bbox[1]) + + print(f"selected font size {font_size}") + + total_height += bbox[1] + p_texts.append(text + (font, bbox_size)) + +# account for padding +total_height += (len(texts) - 1) * 20 + +# draw the text +draw = ImageDraw.Draw(im) +y_offset = 0 +for text in p_texts: + # set x location dependent on alignment + loc_x = 0 + if text[0] == "m": + loc_x = (im.size[0]/2) + elif text[0] == "r": + loc_x = im.size[0] + + # calculate y location based on total height of all text + current line height to + # center all text together in the center of the canvas + loc_y = (im.size[1]/2 + total_height / 2) + text[5][1] + y_offset + + draw.text((loc_x, loc_y), text[3], font=text[4], anchor=f"{text[0]}b") + + # add height of this line to offset + y_offset += text[5][1] + 20 + +# crop to content and save +im = im.crop(im.getbbox()) +filename = sys.argv[1].removesuffix(".shirt") +im.save(f"{filename}.png", 'PNG')