Mit Python und der Bildbearbeitungs-Bibliothek Pillow kann man sich recht einfach ein Skript zusammenbauen, welches ein Foto in beliebigem Seitenformat als Eingabe empfängt und dieses zu einem „Instant-Bild“ aus einer Sofortbildkamera „umbaut“. Entsprechend der verschiedenen im Skript hinterlegten Zielformate wird hierfür zunächst ein Bereich aus dem Zentrum des Eingabebilds ausgeschnitten. Dann wird ein nicht ganz reinweißer Rand um das ausgeschnittene Bild ergänzt. Das so entstandene Instant-Bild wird schließlich auf einem reinweißen Hintergrund samt kleinem Schatten „gelegt“.
Das ganze sieht dann etwa so aus:
Damit das Skript funktioniert, muss noch Pillow per pip3 install Pillow
nachinstalliert werden.
from PIL import Image, ImageOps, ImageFilter
from os.path import exists, isfile
from glob import glob
def polaroidize(image, type="wide", polaroidWAbs=1200):
# relative dimensions of instant photo and the image in it
if type == "mini":
# Fujifilm Instax Mini Format
imageH = 62
imageW = 46
polaroidH = 86
polaroidW = 54
elif type == "wide":
# Fujifilm Instax Wide Format
imageH = 62
imageW = 99
polaroidH = 86
polaroidW = 108
elif type == "square":
# Fujifilm Instax Square
imageH = 62
imageW = 62
polaroidH = 86
polaroidW = 72
elif type == "spectra":
# Polaroid Image/Spectra Format
imageH = 72
imageW = 91
polaroidH = 101
polaroidW = 103
elif type == "sx70":
# Polaroid SX-70 / 600 Format
imageW = 77
imageH = 79
polaroidW = 88
polaroidH = 106
else:
exit()
# compute the relative size of borders
borderLR = (polaroidW - imageW) / 2
borderTop = borderLR
borderBottom = polaroidH - imageH - borderTop
# compute scaling factor
scale = polaroidW / polaroidWAbs
# compute absolute sizes for the "paper", image and borders
polaroidHAbs = round(polaroidH / scale)
imageWAbs = round(imageW / scale)
imageHAbs = round(imageH / scale)
borderLRAbs = round(borderLR / scale)
borderTopAbs = round(borderTop / scale)
borderBottomAbs = round(borderBottom / scale)
width, height = image.size
target_ratio = imageW / imageH
actual_ratio = width / height
if actual_ratio > target_ratio:
new_width = int(height * target_ratio)
left = (width - new_width) // 2
right = left + new_width
top, bottom = 0, height
else:
new_height = int(width / target_ratio)
top = (height - new_height) // 2
bottom = top + new_height
left, right = 0, width
image = image.crop((left, top, right, bottom))
image = image.resize((imageWAbs, imageHAbs))
image = ImageOps.expand(image, border=(borderLRAbs, borderTopAbs, borderLRAbs, borderBottomAbs), fill=0xEEEEEE)
return image
def dropShadow(image, offset=(15, 15), background=0xffffff, shadow=0x666666, border=100, iterations=5):
# code mostly taken from: https://code.activestate.com/recipes/474116-drop-shadows-with-pil/
# create background
totalWidth = image.size[0] + abs(offset[0]) + 2 * border
totalHeight = image.size[1] + abs(offset[1]) + 2 * border
back = Image.new(image.mode, (totalWidth, totalHeight), background)
# create shadow
shadowLeft = border + max(offset[0], 0)
shadowTop = border + max(offset[1], 0)
back.paste(shadow, [shadowLeft, shadowTop, shadowLeft + image.size[0], shadowTop + image.size[1]])
# blur
n = 0
while n < iterations:
back = back.filter(ImageFilter.BLUR)
n += 1
# combine
imageLeft = border - min(offset[0], 0)
imageTop = border - min(offset[1], 0)
back.paste(image, (imageLeft, imageTop))
return back
# the target instant photo's width
polaroidWAbs = 1200
choice = input(f"Pick a format: Instax Mini (1), Wide (2), Square (3), Polaroid Sx-70 (4) or Spectra (5): ")
try:
choice = int(choice)
except:
choice = 2
formats = ["mini", "wide", "square", "sx70", "spectra"]
format = formats[choice-1]
files = glob("*.jpg")
for file in files:
tmp = file.split(("."))
newFileName = f"{tmp[0]}_{format}.{tmp[1]}"
if exists(file) and isfile(file):
image = Image.open(file)
print(f"Processing {file} as {format}.")
else:
print(f"{file} does not exist. Abort.")
image = polaroidize(image, format, polaroidWAbs)
image = dropShadow(image)
image.save(newFileName)
Die automatische Auswahl aus dem Zentrum des Bilds ist nicht immer optimal bzw. exakt das, was man möchte. Wenn man den Fokus auf ein bestimmtes Bildelement richten will – vielleicht die Schaltkulisse rechts vom Lenkrad – muss man zunächst das Bild manuell auf das passende Instant-Bild-Format zuschneiden. Wenn man dann dieses Format im Skript auswählt, wird nichts mehr vom ohnehin beschnittenen Bild abgeschnitten – es ist ja schon im richtigen Format – und nur der Rahmen ergänzt. Das ganze ist natürlich mühselig, ich wollte die Möglichkeit aber kurz erwähnen. Vermutlich ist es besser einfach ein gut passendes Bildformat auszuwählen…
Schreibe einen Kommentar