Remove intermediary .cropped

This commit is contained in:
henriquenakashima 2023-07-10 14:53:21 -04:00
parent f5175918b6
commit 902482abb0
3 changed files with 62 additions and 95 deletions

5
base_proxy.py Normal file
View file

@ -0,0 +1,5 @@
from pathlib import Path
LEAVE_BLEED_INCHES = 0.04
BASE_DIR = Path(__file__).parent

35
card_images.py Normal file
View file

@ -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

View file

@ -1,23 +1,21 @@
import math
import os import os
from pathlib import Path from pathlib import Path
from typing import List, Optional, Tuple from typing import List, Optional, Tuple
from PIL import Image, ImageDraw, ImageCms from PIL import Image, ImageDraw, ImageCms
from base_proxy import BASE_DIR, LEAVE_BLEED_INCHES
from card_images import InputCardImage
import util 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 CUT_GUIDE_WIDTH_INCHES = 0.006
LENGTH_CUT_GUIDE_INCHES = 0.06 LENGTH_CUT_GUIDE_INCHES = 0.06
BASE_DIR = Path(__file__).parent def gather_images(directory: Path) -> List[Path]:
def gather_images(directory: Path, midfix : Optional[str] = None) -> List[Path]:
files_to_crop = [] files_to_crop = []
for f in os.listdir(directory): for f in os.listdir(directory):
possible_image_path = directory / f possible_image_path = directory / f
@ -25,73 +23,12 @@ def gather_images(directory: Path, midfix : Optional[str] = None) -> List[Path]:
# Skip directory # Skip directory
continue continue
# TODO: Check if is image # 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 return files_to_crop
def gather_input_cards() -> List[Path]: def gather_input_cards() -> List[Path]:
return gather_images(directory=BASE_DIR / 'input_cards', midfix=None) return gather_images(directory=BASE_DIR / 'input_cards')
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)
CARD_W_INCHES = 2.48031 # 63mm CARD_W_INCHES = 2.48031 # 63mm
@ -169,7 +106,7 @@ class SheetLayout:
return (x, y) 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') sheet = Image.new('RGB', (sheet_layout.w, sheet_layout.h), 'white')
# icc_profile = ImageCms.getOpenProfile(str(BASE_DIR / 'icc' / 'AdobeRGB1998.icc')) # icc_profile = ImageCms.getOpenProfile(str(BASE_DIR / 'icc' / 'AdobeRGB1998.icc'))
@ -192,15 +129,15 @@ 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.line([(0, bottom_y), (sheet_layout.w, bottom_y)], fill=color, width=guide_thickness)
# Draw cards # Draw cards
filenames_iter = cropped_filepaths.__iter__() input_cards_iter = input_cards.__iter__()
for y_index in range(sheet_layout.cards_per_column): for y_index in range(sheet_layout.cards_per_column):
for x_index in range(sheet_layout.cards_per_row): for x_index in range(sheet_layout.cards_per_row):
try: try:
filepath = filenames_iter.__next__() input_card: InputCardImage = input_cards_iter.__next__()
except StopIteration: except StopIteration:
break break
with Image.open(filepath) as card_im: card_im = input_card.crop()
card_im = card_im.resize((sheet_layout.cropped_image_dest_w, sheet_layout.cropped_image_dest_h), card_im = card_im.resize((sheet_layout.cropped_image_dest_w, sheet_layout.cropped_image_dest_h),
resample = Image.Resampling.LANCZOS) resample = Image.Resampling.LANCZOS)
sheet.paste(card_im, sheet_layout.topleft_of_card_with_bleed(y_index, x_index)) sheet.paste(card_im, sheet_layout.topleft_of_card_with_bleed(y_index, x_index))
@ -234,29 +171,19 @@ def create_sheet(cropped_filepaths: List[Path], sheet_filepath: Path, sheet_layo
def main(): def main():
all_input_cards = gather_input_cards() all_input_cards_paths = gather_input_cards()
print(f'Found {len(all_input_cards)} input cards:') print(f'Found {len(all_input_cards_paths)} input cards:')
print(all_input_cards) print(all_input_cards_paths)
already_cropped_cards = gather_cropped_cards() all_input_cards = [InputCardImage(p) for p in all_input_cards_paths]
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)
#sheet_layout = SheetLayout(1200, 11, 8.5) #sheet_layout = SheetLayout(1200, 11, 8.5)
sheet_layout = SheetLayout(1200, 8.5, 11) sheet_layout = SheetLayout(1200, 8.5, 11)
sheets_dir = BASE_DIR / 'sheets' sheets_dir = BASE_DIR / 'sheets'
sheets_dir.mkdir(parents=True, exist_ok=True) 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' sheet_filepath = sheets_dir / f'sheet{i:03d}.jpg'
create_sheet(cards_in_sheet, sheet_filepath, sheet_layout) create_sheet(cards_in_sheet, sheet_filepath, sheet_layout)
print(f'Output {sheet_filepath}') print(f'Output {sheet_filepath}')