From 902482abb037c99db6c7b92ad74213e9c74e0c44 Mon Sep 17 00:00:00 2001 From: henriquenakashima Date: Mon, 10 Jul 2023 14:53:21 -0400 Subject: [PATCH] Remove intermediary .cropped --- base_proxy.py | 5 +++ card_images.py | 35 +++++++++++++++ crop_card.py | 117 ++++++++++--------------------------------------- 3 files changed, 62 insertions(+), 95 deletions(-) create mode 100644 base_proxy.py create mode 100644 card_images.py diff --git a/base_proxy.py b/base_proxy.py new file mode 100644 index 0000000..f0893ad --- /dev/null +++ b/base_proxy.py @@ -0,0 +1,5 @@ +from pathlib import Path + +LEAVE_BLEED_INCHES = 0.04 + +BASE_DIR = Path(__file__).parent diff --git a/card_images.py b/card_images.py new file mode 100644 index 0000000..5dd5924 --- /dev/null +++ b/card_images.py @@ -0,0 +1,35 @@ +from pathlib import Path + +from PIL import Image + +from base_proxy import LEAVE_BLEED_INCHES + + +W_INCHES_EXPECTED = 2.72 +H_INCHES_EXPECTED = 3.7 +BLEED_INCHES_EXPECTED = 0.12 + + +class InputCardImage: + def __init__(self, path: Path): + self.path = path + + def crop(self) -> Image: + with Image.open(self.path) as im: + # print(im.info) + rgb_im = im.convert('RGB') + w, h = rgb_im.width, rgb_im.height + dpi_by_w = w / W_INCHES_EXPECTED + dpi_by_h = h / H_INCHES_EXPECTED + print(f'By width dpi is {dpi_by_w} dpi') + if dpi_by_h != dpi_by_w: + print(f'dpi by height is different: {dpi_by_h} dpi') + crop_pixels = BLEED_INCHES_EXPECTED * dpi_by_w - LEAVE_BLEED_INCHES * dpi_by_w + crop_pixels_int = round(crop_pixels) + print(f'Image is {w} x {h}, will trim {crop_pixels} pixels (rounded to {crop_pixels_int})') + + # Crop + crop_box = (crop_pixels_int, crop_pixels_int, w - crop_pixels_int, h - crop_pixels_int) + cropped_part = rgb_im.crop(crop_box) + + return cropped_part diff --git a/crop_card.py b/crop_card.py index 9aed28a..2d6cba4 100644 --- a/crop_card.py +++ b/crop_card.py @@ -1,23 +1,21 @@ +import math import os from pathlib import Path from typing import List, Optional, Tuple from PIL import Image, ImageDraw, ImageCms +from base_proxy import BASE_DIR, LEAVE_BLEED_INCHES +from card_images import InputCardImage + import util -W_INCHES_EXPECTED = 2.72 -H_INCHES_EXPECTED = 3.7 -BLEED_INCHES_EXPECTED = 0.12 -LEAVE_BLEED_INCHES = 0.04 + CUT_GUIDE_WIDTH_INCHES = 0.006 LENGTH_CUT_GUIDE_INCHES = 0.06 -BASE_DIR = Path(__file__).parent - - -def gather_images(directory: Path, midfix : Optional[str] = None) -> List[Path]: +def gather_images(directory: Path) -> List[Path]: files_to_crop = [] for f in os.listdir(directory): possible_image_path = directory / f @@ -25,73 +23,12 @@ def gather_images(directory: Path, midfix : Optional[str] = None) -> List[Path]: # Skip directory continue # TODO: Check if is image - if midfix is None or any(s == f'.{midfix}' for s in possible_image_path.suffixes): - files_to_crop.append(possible_image_path) + 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', midfix=None) - - -def gather_cropped_cards() -> List[Path]: - return gather_images(directory=BASE_DIR / 'cropped_cards', midfix='crop') - - -def get_inputs_without_crop(all_inputs: List[Path], already_cropped: List[Path]) -> List[Path]: - # For debug, always crop - for existing_crop in already_cropped: - existing_crop.unlink() - return all_inputs - - already_cropped_set = set(already_cropped) - inputs_without_crop = [] - for input_filepath in all_inputs: - possible_cropped_filepath = input_to_crop_filepath(input_filepath) - if possible_cropped_filepath not in already_cropped_set: - inputs_without_crop.append(input_filepath) - return inputs_without_crop - - -def input_to_crop_filepath(input_filepath: Path) -> Path: - input_filename = input_filepath.stem + '.crop' + input_filepath.suffix - return BASE_DIR / 'cropped_cards' / input_filename - - -def crop(input_filepath: Path) -> Path: - out_dir = BASE_DIR / 'cropped_cards' - out_dir.mkdir(parents=True, exist_ok=True) - cropped_filepath = input_to_crop_filepath(input_filepath) - try: - with Image.open(input_filepath) as im: - # print(im.info) - rgb_im = im.convert('RGB') - w, h = rgb_im.width, rgb_im.height - dpi_by_w = w / W_INCHES_EXPECTED - dpi_by_h = h / H_INCHES_EXPECTED - print(f'By width dpi is {dpi_by_w} dpi') - if dpi_by_h != dpi_by_w: - print(f'dpi by height is different: {dpi_by_h} dpi') - crop_pixels = BLEED_INCHES_EXPECTED * dpi_by_w - LEAVE_BLEED_INCHES * dpi_by_w - crop_pixels_int = round(crop_pixels) - print(f'Image is {w} x {h}, will trim {crop_pixels} pixels (rounded to {crop_pixels_int})') - - # Crop - crop_box = (crop_pixels_int, crop_pixels_int, w - crop_pixels_int, h - crop_pixels_int) - cropped_part = rgb_im.crop(crop_box) - - cropped_part.save(cropped_filepath, 'JPEG', quality=100, subsampling=0) - return cropped_filepath - except OSError as e: - print(e) - return None - - -def crop_all_inputs(files_to_crop: List[Path]): - num_files_to_crop = len(files_to_crop) - for i, input_filepath in enumerate(files_to_crop, 1): - print(f'[{i}/{num_files_to_crop}] Cropping {input_filepath}') - crop(input_filepath) + return gather_images(directory=BASE_DIR / 'input_cards') CARD_W_INCHES = 2.48031 # 63mm @@ -169,7 +106,7 @@ class SheetLayout: return (x, y) -def create_sheet(cropped_filepaths: List[Path], sheet_filepath: Path, sheet_layout: SheetLayout): +def create_sheet(input_cards: List[InputCardImage], sheet_filepath: Path, sheet_layout: SheetLayout): sheet = Image.new('RGB', (sheet_layout.w, sheet_layout.h), 'white') # icc_profile = ImageCms.getOpenProfile(str(BASE_DIR / 'icc' / 'AdobeRGB1998.icc')) @@ -192,18 +129,18 @@ def create_sheet(cropped_filepaths: List[Path], sheet_filepath: Path, sheet_layo draw.line([(0, bottom_y), (sheet_layout.w, bottom_y)], fill=color, width=guide_thickness) # Draw cards - filenames_iter = cropped_filepaths.__iter__() + input_cards_iter = input_cards.__iter__() for y_index in range(sheet_layout.cards_per_column): for x_index in range(sheet_layout.cards_per_row): try: - filepath = filenames_iter.__next__() + input_card: InputCardImage = input_cards_iter.__next__() except StopIteration: break - with Image.open(filepath) as card_im: - card_im = card_im.resize((sheet_layout.cropped_image_dest_w, sheet_layout.cropped_image_dest_h), - resample = Image.Resampling.LANCZOS) - sheet.paste(card_im, sheet_layout.topleft_of_card_with_bleed(y_index, x_index)) + card_im = input_card.crop() + card_im = card_im.resize((sheet_layout.cropped_image_dest_w, sheet_layout.cropped_image_dest_h), + resample = Image.Resampling.LANCZOS) + sheet.paste(card_im, sheet_layout.topleft_of_card_with_bleed(y_index, x_index)) # Draw internal guidelines color = 'magenta' @@ -234,29 +171,19 @@ def create_sheet(cropped_filepaths: List[Path], sheet_filepath: Path, sheet_layo def main(): - all_input_cards = gather_input_cards() - print(f'Found {len(all_input_cards)} input cards:') - print(all_input_cards) + all_input_cards_paths = gather_input_cards() + print(f'Found {len(all_input_cards_paths)} input cards:') + print(all_input_cards_paths) - already_cropped_cards = gather_cropped_cards() - print(f'Found {len(already_cropped_cards)} already cropped cards:') - print(already_cropped_cards) - - new_inputs_to_crop = get_inputs_without_crop(all_input_cards, already_cropped_cards) - print(f'Found {len(new_inputs_to_crop)} new cards to crop:') - print(new_inputs_to_crop) - - crop_all_inputs(new_inputs_to_crop) - - all_cropped_cards = gather_cropped_cards() - print(f'Now there are {len(all_cropped_cards)} cropped cards:') - print(all_cropped_cards) + all_input_cards = [InputCardImage(p) for p in all_input_cards_paths] #sheet_layout = SheetLayout(1200, 11, 8.5) sheet_layout = SheetLayout(1200, 8.5, 11) sheets_dir = BASE_DIR / 'sheets' sheets_dir.mkdir(parents=True, exist_ok=True) - for i, cards_in_sheet in enumerate(util.batched(all_cropped_cards, sheet_layout.cards_per_sheet), 1): + total_sheet_number = math.ceil(len(all_input_cards) / sheet_layout.cards_per_sheet) + for i, cards_in_sheet in enumerate(util.batched(all_input_cards, sheet_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, sheet_layout) print(f'Output {sheet_filepath}')