Skip to content

Instantly share code, notes, and snippets.

@ssj71
Created February 18, 2022 21:53
Show Gist options
  • Save ssj71/7a8710f722c80e89747833c1c6c54889 to your computer and use it in GitHub Desktop.
Save ssj71/7a8710f722c80e89747833c1c6c54889 to your computer and use it in GitHub Desktop.
Image extrapolation to add bleed for card printing
#!/usr/bin/env python3
#copied from the example at https://scikit-image.org/docs/stable/auto_examples/filters/plot_inpaint.html
import numpy as np
import matplotlib.pyplot as plt
import sys
import fitz
from skimage.morphology import disk, binary_dilation
from skimage.restoration import inpaint
from skimage.transform import resize
from skimage.io import imread,imsave
from skimage.util import img_as_float, img_as_ubyte
from os.path import splitext
from math import floor, ceil, sqrt
#default new_size if for a euro poker card on game crafter
def bleedify(imgfile, radius=38, extra_margin=1, new_size=(1125,825), show=False):
image_orig = img_as_float(imread(imgfile,plugin="imageio"))
rad = radius #corner radius (pixels)
marg = extra_margin #extra edge distance to extrapolate into (pixels)
bigger_img = resize(image_orig, new_size)
#get center points
ctop = ceil((bigger_img.shape[0] - image_orig.shape[0])/2.0)
cbot = ctop + image_orig.shape[0]
cl = floor((bigger_img.shape[1] - image_orig.shape[1])/2.0)
cr = cl + image_orig.shape[1]
#create mask
mask = np.zeros(bigger_img.shape[:-1], dtype=bool)
mask[ 0:ctop+marg, 0:] = 1
mask[ cbot-marg:, 0:] = 1
mask[ 0:, 0:cl+marg] = 1
mask[ 0:, cr-marg:] = 1
#add rounded corners
for i in range(rad):
l = rad-floor(sqrt(rad*rad - (rad-i)*(rad-i)))
mask[ ctop:(ctop+l), cl+i ] = 1
mask[ (cbot-l):cbot, cl+i ] = 1
mask[ ctop:(ctop+l), cr-i ] = 1
mask[ (cbot-l):cbot, cr-i ] = 1
#copy img into middle
bigger_img[ctop:cbot, cl:cr,:] = image_orig
show_mask = bigger_img*mask[..., np.newaxis]
#now the inpainting
image_result = bigger_img
image_result = inpaint.inpaint_biharmonic(bigger_img, mask, channel_axis=-1)
if show:
#show it
fig, axes = plt.subplots(ncols=2, nrows=2)
ax = axes.ravel()
ax[0].set_title('Original image')
ax[0].imshow(image_orig)
ax[1].set_title('Mask')
ax[1].imshow(show_mask)
ax[2].set_title('resized image')
ax[2].imshow(bigger_img)
ax[3].set_title('Inpainted image')
ax[3].imshow(image_result)
for a in ax:
a.axis('off')
fig.tight_layout()
plt.show()
return image_result
def proc_doc(name):
doc = fitz.open(name)
shortname = splitext(name)[0]
for i in range(len(doc)):
for img in doc.get_page_images(i):
xref = img[0]
pix = fitz.Pixmap(doc, xref)
if pix.n < 5: # this is GRAY or RGB
buf = pix.tobytes()
else: # CMYK: convert to RGB first
pix1 = fitz.Pixmap(fitz.csRGB, pix)
buf = pix1.tobytes()
bled = bleedify(buf)
imsave("output/%s_p%i_%i.png"%(shortname,i,xref),img_as_ubyte(bled))
print("page %i done\n"%(i))
def help():
print("bleedify - a card or other image full bleed extrapolator")
print("useage: 'bleedify <path to pdf> <path to 2nd pdf> ...")
print(" this method takes a list of pdfs, extracts all images, adds bleed and saves them")
print("useage 2: 'bleedify <path image> <output width pixels> <output height pixels>")
print(" this method takes a single image and adds bleed to the specified size. mostly for")
print(" special cases like player boards. If the width and height are omitted, the default")
print(" card size 825x1125 is assumed.")
if len(sys.argv) < 2:
help()
elif splitext(sys.argv[1])[1].lower() == ".pdf":
for i in range(len(sys.argv)-1):
proc_doc(sys.argv[i+1])
else:
shortname = splitext(sys.argv[1])[0]
if len(sys.argv) > 3:
bled = bleedify(sys.argv[1], new_size=(int(sys.argv[3]),int(sys.argv[2])), show=True)
else:
bled = bleedify(sys.argv[1], show=True)
imsave("output/%s_w_bleed.png"%(shortname),img_as_ubyte(bled))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment