Draw external guidelines
This commit is contained in:
parent
7d5b4b0fcf
commit
9fd1ec6e1e
1 changed files with 56 additions and 11 deletions
67
crop_card.py
67
crop_card.py
|
|
@ -10,6 +10,8 @@ W_INCHES_EXPECTED = 2.72
|
||||||
H_INCHES_EXPECTED = 3.7
|
H_INCHES_EXPECTED = 3.7
|
||||||
BLEED_INCHES_EXPECTED = 0.12
|
BLEED_INCHES_EXPECTED = 0.12
|
||||||
LEAVE_BLEED_INCHES = 0.04
|
LEAVE_BLEED_INCHES = 0.04
|
||||||
|
CUT_GUIDE_WIDTH_INCHES = 0.006
|
||||||
|
|
||||||
|
|
||||||
BASE_DIR = Path(__file__).parent
|
BASE_DIR = Path(__file__).parent
|
||||||
|
|
||||||
|
|
@ -59,7 +61,6 @@ def add_cut_guides(im: Image, dpi: float):
|
||||||
cut_pixels_int = round(cut_pixels)
|
cut_pixels_int = round(cut_pixels)
|
||||||
draw = ImageDraw.Draw(im)
|
draw = ImageDraw.Draw(im)
|
||||||
LENGTH_CUT_GUIDE_INCHES = 0.06
|
LENGTH_CUT_GUIDE_INCHES = 0.06
|
||||||
CUT_GUIDE_WIDTH_INCHES = 0.006
|
|
||||||
guide_len = round(LENGTH_CUT_GUIDE_INCHES * dpi)
|
guide_len = round(LENGTH_CUT_GUIDE_INCHES * dpi)
|
||||||
guide_thickness = round(CUT_GUIDE_WIDTH_INCHES * dpi)
|
guide_thickness = round(CUT_GUIDE_WIDTH_INCHES * dpi)
|
||||||
cut_x_l = cut_pixels_int
|
cut_x_l = cut_pixels_int
|
||||||
|
|
@ -98,7 +99,7 @@ def crop(input_filepath: Path) -> Path:
|
||||||
print(f'By width dpi is {dpi_by_w} dpi')
|
print(f'By width dpi is {dpi_by_w} dpi')
|
||||||
if dpi_by_h != dpi_by_w:
|
if dpi_by_h != dpi_by_w:
|
||||||
print(f'dpi by height is different: {dpi_by_h} dpi')
|
print(f'dpi by height is different: {dpi_by_h} dpi')
|
||||||
crop_pixels = (BLEED_INCHES_EXPECTED - LEAVE_BLEED_INCHES) * dpi_by_w
|
crop_pixels = BLEED_INCHES_EXPECTED * dpi_by_w - LEAVE_BLEED_INCHES * dpi_by_w
|
||||||
crop_pixels_int = round(crop_pixels)
|
crop_pixels_int = round(crop_pixels)
|
||||||
print(f'Image is {w} x {h}, will trim {crop_pixels} pixels (rounded to {crop_pixels_int})')
|
print(f'Image is {w} x {h}, will trim {crop_pixels} pixels (rounded to {crop_pixels_int})')
|
||||||
|
|
||||||
|
|
@ -141,8 +142,9 @@ class SheetLayout:
|
||||||
self.h_inches = h_inches
|
self.h_inches = h_inches
|
||||||
self.w = self.in_to_px(self.w_inches)
|
self.w = self.in_to_px(self.w_inches)
|
||||||
self.h = self.in_to_px(self.h_inches)
|
self.h = self.in_to_px(self.h_inches)
|
||||||
self.cropped_image_dest_w = self.in_to_px(self.card_w_inches + LEAVE_BLEED_INCHES)
|
self.leave_bleed = self.in_to_px(LEAVE_BLEED_INCHES)
|
||||||
self.cropped_image_dest_h = self.in_to_px(self.card_h_inches + LEAVE_BLEED_INCHES)
|
self.cropped_image_dest_w = self.card_w + self.leave_bleed * 2
|
||||||
|
self.cropped_image_dest_h = self.card_h + self.leave_bleed * 2
|
||||||
|
|
||||||
self.spacing_inches = 0.05
|
self.spacing_inches = 0.05
|
||||||
self.spacing = self.in_to_px(self.spacing_inches)
|
self.spacing = self.in_to_px(self.spacing_inches)
|
||||||
|
|
@ -164,21 +166,62 @@ class SheetLayout:
|
||||||
def in_to_px(self, inches: float) -> float:
|
def in_to_px(self, inches: float) -> float:
|
||||||
return round(inches * self.dpi)
|
return round(inches * self.dpi)
|
||||||
|
|
||||||
def topleft_of_card(self, y_index: int, x_index: int) -> Tuple[int, int]:
|
def top_of_row(self, y_index: int, with_bleed: bool) -> int:
|
||||||
assert 0 <= x_index < self.cards_per_row
|
|
||||||
assert 0 <= y_index < self.cards_per_column
|
assert 0 <= y_index < self.cards_per_column
|
||||||
x = self.blank_space_w + (self.cropped_image_dest_w + self.spacing) * x_index
|
top = self.blank_space_h + (self.cropped_image_dest_h + self.spacing) * y_index
|
||||||
y = self.blank_space_h + (self.cropped_image_dest_h + self.spacing) * y_index
|
if not with_bleed:
|
||||||
|
top += self.leave_bleed
|
||||||
|
return top
|
||||||
|
|
||||||
|
def bottom_of_row(self, y_index: int, with_bleed: bool) -> int:
|
||||||
|
if with_bleed:
|
||||||
|
return self.top_of_row(y_index, True) + self.cropped_image_dest_h
|
||||||
|
else:
|
||||||
|
return self.top_of_row(y_index, False) + self.card_h
|
||||||
|
|
||||||
|
def left_of_column(self, x_index: int, with_bleed: bool) -> int:
|
||||||
|
assert 0 <= x_index < self.cards_per_row
|
||||||
|
left = self.blank_space_w + (self.cropped_image_dest_w + self.spacing) * x_index
|
||||||
|
if not with_bleed:
|
||||||
|
left += self.leave_bleed
|
||||||
|
return left
|
||||||
|
|
||||||
|
def right_of_column(self, x_index: int, with_bleed: bool) -> int:
|
||||||
|
if with_bleed:
|
||||||
|
return self.left_of_column(x_index, True) + self.cropped_image_dest_w
|
||||||
|
else:
|
||||||
|
return self.left_of_column(x_index, False) + self.card_w
|
||||||
|
|
||||||
|
def topleft_of_card_with_bleed(self, y_index: int, x_index: int) -> Tuple[int, int]:
|
||||||
|
x = self.left_of_column(x_index, with_bleed=True)
|
||||||
|
y = self.top_of_row(y_index, with_bleed=True)
|
||||||
return (x, y)
|
return (x, y)
|
||||||
|
|
||||||
|
|
||||||
def create_sheet(cropped_filepaths: List[Path], sheet_filepath: Path, sheet_layout: SheetLayout):
|
def create_sheet(cropped_filepaths: List[Path], 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')
|
||||||
|
|
||||||
|
# Draw external guidelines
|
||||||
|
draw = ImageDraw.Draw(sheet)
|
||||||
|
color = 'black'
|
||||||
|
guide_thickness = sheet_layout.in_to_px(CUT_GUIDE_WIDTH_INCHES)
|
||||||
|
|
||||||
|
for x_index in range(sheet_layout.cards_per_column):
|
||||||
|
left_x = sheet_layout.left_of_column(x_index, with_bleed=False)
|
||||||
|
right_x = sheet_layout.right_of_column(x_index, with_bleed=False)
|
||||||
|
draw.line([(left_x, 0), (left_x, sheet_layout.h)], fill=color, width=guide_thickness)
|
||||||
|
draw.line([(right_x, 0), (right_x, sheet_layout.h)], fill=color, width=guide_thickness)
|
||||||
|
|
||||||
|
for y_index in range(sheet_layout.cards_per_row):
|
||||||
|
top_y = sheet_layout.top_of_row(y_index, with_bleed=False)
|
||||||
|
bottom_y = sheet_layout.bottom_of_row(y_index, with_bleed=False)
|
||||||
|
draw.line([(0, top_y), (sheet_layout.w, top_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__()
|
filenames_iter = cropped_filepaths.__iter__()
|
||||||
for y in range(sheet_layout.cards_per_column):
|
for y_index in range(sheet_layout.cards_per_column):
|
||||||
for x in range(sheet_layout.cards_per_row):
|
for x_index in range(sheet_layout.cards_per_row):
|
||||||
try:
|
try:
|
||||||
filepath = filenames_iter.__next__()
|
filepath = filenames_iter.__next__()
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
|
|
@ -187,7 +230,9 @@ def create_sheet(cropped_filepaths: List[Path], sheet_filepath: Path, sheet_layo
|
||||||
with Image.open(filepath) as card_im:
|
with Image.open(filepath) as card_im:
|
||||||
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(y, x))
|
sheet.paste(card_im, sheet_layout.topleft_of_card_with_bleed(y_index, x_index))
|
||||||
|
|
||||||
|
# TODO: Draw internal guidelines
|
||||||
|
|
||||||
# Save sheet
|
# Save sheet
|
||||||
sheet.save(sheet_filepath, 'JPEG', dpi=(sheet_layout.dpi, sheet_layout.dpi), quality=100, subsampling=0)
|
sheet.save(sheet_filepath, 'JPEG', dpi=(sheet_layout.dpi, sheet_layout.dpi), quality=100, subsampling=0)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue