proxyscripts/crop_card.py
2023-07-17 13:10:08 -04:00

128 lines
5.2 KiB
Python

import math
import os
from pathlib import Path
from typing import List
from PIL import Image, ImageDraw, ImageCms
from base_proxy import BASE_DIR
from card_images import InputCardImage
import sheet_layout
from sheet_layout import SheetLayout, CardImageTransfer
import util
DRY_RUN = False
CUT_GUIDE_WIDTH_INCHES = 0.006
LENGTH_CUT_GUIDE_INCHES = 0.04
def gather_images(directory: Path) -> List[Path]:
files_to_crop = []
for f in os.listdir(directory):
possible_image_path = directory / f
if not possible_image_path.is_file():
# Skip directory
continue
# TODO: Check if is image
files_to_crop.append(possible_image_path)
return files_to_crop
def gather_input_cards() -> List[Path]:
return gather_images(directory=BASE_DIR / 'input_cards')
def create_sheet(input_cards: List[InputCardImage], sheet_filepath: Path, layout: SheetLayout):
sheet = Image.new('RGB', (layout.w, layout.h), 'white')
# icc_profile = ImageCms.getOpenProfile(str(BASE_DIR / 'icc' / 'AdobeRGB1998.icc'))
# Draw external guidelines
draw = ImageDraw.Draw(sheet)
color = 'black'
guide_thickness = layout.in_to_px(CUT_GUIDE_WIDTH_INCHES)
for x_index in range(layout.cards_per_row):
left_x = layout.card_area_left_xs[x_index]
right_x = layout.card_area_right_xs[x_index]
min_y = layout.min_padding
max_y = layout.h - 1 - layout.min_padding
draw.line([(left_x, min_y), (left_x, max_y)], fill=color, width=guide_thickness)
draw.line([(right_x, min_y), (right_x, max_y)], fill=color, width=guide_thickness)
for y_index in range(layout.cards_per_column):
top_y = layout.card_area_top_ys[y_index]
bottom_y = layout.card_area_bottom_ys[y_index]
min_x = layout.min_padding
max_x = layout.w - 1 - layout.min_padding
draw.line([(min_x, top_y), (max_x, top_y)], fill=color, width=guide_thickness)
draw.line([(min_x, bottom_y), (max_x, bottom_y)], fill=color, width=guide_thickness)
# Draw cards
input_cards_iter = input_cards.__iter__()
for y_index in range(layout.cards_per_column):
for x_index in range(layout.cards_per_row):
try:
input_card: InputCardImage = input_cards_iter.__next__()
except StopIteration:
break
image_transfer: CardImageTransfer = layout.create_card_image_transfer(y_index, x_index)
card_im = input_card.get_cropped_and_resized(layout, image_transfer)
sheet.paste(card_im, image_transfer.topleft_dest)
# Draw internal guidelines
color = 'magenta'
guide_len = layout.in_to_px(LENGTH_CUT_GUIDE_INCHES)
# -1 because the pixels are in [0, W - 1] and [0, H - 1]
left_x = layout.card_area_left_xs[x_index]
right_x = layout.card_area_right_xs[x_index] - 1
top_y = layout.card_area_top_ys[y_index]
bottom_y = layout.card_area_bottom_ys[y_index] - 1
# Top left
draw.line([(left_x, top_y), (left_x, top_y + guide_len)], fill = color, width = guide_thickness)
draw.line([(left_x, top_y), (left_x + guide_len, top_y)], fill = color, width = guide_thickness)
# Bottom left
draw.line([(left_x, bottom_y), (left_x, bottom_y - guide_len)], fill = color, width = guide_thickness)
draw.line([(left_x, bottom_y), (left_x + guide_len, bottom_y)], fill = color, width = guide_thickness)
# Top right
draw.line([(right_x, top_y), (right_x, top_y + guide_len)], fill = color, width = guide_thickness)
draw.line([(right_x, top_y), (right_x - guide_len, top_y)], fill = color, width = guide_thickness)
# Bottom right
draw.line([(right_x, bottom_y), (right_x, bottom_y - guide_len)], fill = color, width = guide_thickness)
draw.line([(right_x, bottom_y), (right_x - guide_len, bottom_y)], fill = color, width = guide_thickness)
# Save sheet
if not DRY_RUN:
# sheet.save(sheet_filepath, 'JPEG', dpi=(layout.dpi, layout.dpi), quality=100, subsampling=0, icc_profile=icc_profile.tobytes())
sheet.save(sheet_filepath, 'JPEG', dpi=(layout.dpi, layout.dpi), quality=100, subsampling=0)
def main():
all_input_cards_paths = gather_input_cards()
print(f'Found {len(all_input_cards_paths)} input cards:')
print(all_input_cards_paths)
all_input_cards = [InputCardImage(p) for p in all_input_cards_paths]
for input_card in all_input_cards:
print(f'{input_card.path} has borders {input_card.get_borders()}')
layout = sheet_layout.letter_portrait_3x3_sheet_layout_120milborder()
sheets_dir = BASE_DIR / 'sheets'
sheets_dir.mkdir(parents=True, exist_ok=True)
total_sheet_number = math.ceil(len(all_input_cards) / layout.cards_per_sheet)
for i, cards_in_sheet in enumerate(util.batched(all_input_cards, layout.cards_per_sheet), 1):
print(f'Will create sheet {i}/{total_sheet_number}')
sheet_filepath = sheets_dir / f'sheet{i:03d}.jpg'
create_sheet(cards_in_sheet, sheet_filepath, layout)
print(f'Output {sheet_filepath}')
if __name__ == '__main__':
main()