Created
January 29, 2025 14:49
-
-
Save brouberol/689b3aadda9d3476ae7b1a83d5963fc8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import argparse | |
import os | |
from pathlib import Path | |
from PIL import Image, ImageFilter, ImageDraw | |
A4_WIDTH_MM = 210 | |
A4_HEIGHT_MM = 297 | |
INCH_IN_MM = 25.4 | |
def mm_to_px(dim_mm: int, dpi: int) -> int: | |
return int(dim_mm * dpi / INCH_IN_MM) | |
def parse_args(): | |
parser = argparse.ArgumentParser() | |
parser.add_argument( | |
"-i", "--input", help="The input image(s)", required=True, nargs="+" | |
) | |
parser.add_argument("-o", "--output-dir", help="The output directory", type=Path) | |
parser.add_argument("--dpi", type=int, help="The output image DPI", default=300) | |
parser.add_argument( | |
"--background-gaussian-blur-radius", | |
type=int, | |
help="The background gaussian blur radius", | |
default=19, | |
) | |
parser.add_argument( | |
"--background-zoom-factor", | |
type=float, | |
help="Background image zoom factor", | |
default=1.4, | |
) | |
parser.add_argument( | |
"--bleed-margin-mm", type=int, help="Bleed margins, in mm", default=2 | |
) | |
parser.add_argument("--flip", action='store_true', default=False) | |
return parser.parse_args() | |
def generate_spread_from_dungeondraft_image(image_path: str, args: argparse.Namespace): | |
print(f"Generating pages for {image_path}") | |
filepath = Path(image_path) | |
filename, extension = args.output_dir / filepath.stem, filepath.suffix | |
# Open the input image | |
original_image = Image.open(image_path) | |
# Set A4 dimensions | |
a4_width, a4_height = mm_to_px( | |
A4_WIDTH_MM + 2 * args.bleed_margin_mm, args.dpi | |
), mm_to_px( | |
A4_HEIGHT_MM + 2 * args.bleed_margin_mm, args.dpi | |
) # A4 dimensions in pixels | |
# Create white A4 background | |
a4_image = Image.new("RGB", (a4_width, a4_height), color="white") | |
# Calculate centering coordinates | |
x_offset = 3 if 'left' in filename.name else 1.5 | |
center_x = int((a4_width - original_image.width) // x_offset) | |
center_y = (a4_height - original_image.height) // 2 | |
# Resize the image | |
resized_image = original_image.resize( | |
( | |
int(original_image.width * args.background_zoom_factor), | |
int(original_image.height * args.background_zoom_factor), | |
) | |
) | |
# Apply Gaussian blur | |
blurred_image = resized_image.filter( | |
ImageFilter.GaussianBlur(radius=args.background_gaussian_blur_radius) | |
) | |
# Paste the blurred image onto the A4 page | |
a4_image.paste(blurred_image, (-100, -100), mask=blurred_image) | |
# Paste the original image | |
a4_image.paste(original_image, (center_x, center_y)) | |
# draw = ImageDraw.ImageDraw(a4_image) | |
# draw.rectangle( | |
# [ | |
# ( | |
# mm_to_px(args.bleed_margin_mm, args.dpi), | |
# mm_to_px(args.bleed_margin_mm, args.dpi), | |
# ), | |
# ( | |
# mm_to_px(args.bleed_margin_mm + A4_WIDTH_MM, args.dpi), | |
# mm_to_px(args.bleed_margin_mm + A4_HEIGHT_MM, args.dpi), | |
# ), | |
# ], | |
# outline="black", | |
# width=3, | |
# ) | |
# Save the final A4-sized image with the centered zoomed-in image | |
a4_image.save(f"{filename}-A4{extension}", dpi=(args.dpi, args.dpi)) | |
if args.flip: | |
# Save the same image but reversed vertically | |
flipped_image = a4_image.transpose(Image.FLIP_LEFT_RIGHT) | |
flipped_image.save(f"{filename}-A4-flipped{extension}", dpi=(args.dpi, args.dpi)) | |
def main(): | |
args = parse_args() | |
if not args.output_dir.exists(): | |
args.output_dir.mkdir() | |
for image in args.input: | |
generate_spread_from_dungeondraft_image(image, args) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment