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 import util CUT_GUIDE_WIDTH_INCHES = 0.006 LENGTH_CUT_GUIDE_INCHES = 0.06 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_column): left_x = layout.left_of_column(x_index, with_bleed=False) right_x = layout.right_of_column(x_index, with_bleed=False) draw.line([(left_x, 0), (left_x, layout.h)], fill=color, width=guide_thickness) draw.line([(right_x, 0), (right_x, layout.h)], fill=color, width=guide_thickness) for y_index in range(layout.cards_per_row): top_y = layout.top_of_row(y_index, with_bleed=False) bottom_y = layout.bottom_of_row(y_index, with_bleed=False) draw.line([(0, top_y), (layout.w, top_y)], fill=color, width=guide_thickness) draw.line([(0, bottom_y), (layout.w, 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 card_im = input_card.get_cropped_and_resized(layout) sheet.paste(card_im, layout.topleft_of_card_with_bleed(y_index, x_index)) # 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.left_of_column(x_index, with_bleed=False) right_x = layout.right_of_column(x_index, with_bleed=False) - 1 top_y = layout.top_of_row(y_index, with_bleed=False) bottom_y = layout.bottom_of_row(y_index, with_bleed=False) - 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 # 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] layout = sheet_layout.letter_portrait_3x3_sheet_layout() 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()