Bildskalierung in Gimp mit Python
Ziel: Automatisierung der Bildskalierung. Alle Bilder eines Verzeichnisses sollen in mehrere Bildformate konvertiert werden (export für verschiedene Bildergalerien).
Zunächst werden die benötigten Module geladen, das Quellverzeichnis festgelegt und schon ein Teil des Zielverzeichnisses:
import os import glob targetdir = os.path.expanduser('~/') os.chdir(os.path.join(os.path.expanduser('~/'), 'temp'))
Die zu verarbeitenden Bilder sollen im temp-Verzeichnis liegen. Hier wird eine Liste der JPG-Bilder erstellt.
files = glob.glob('*.jpg')
Die zu erzeugenden Bildgrößen werden als Liste vordefiniert und mit den Zielpfaden ergänzt. Falls ein Zielverzeichnis nicht existiert wird es angelegt:
dstdirs = ( {'name': 'publish', 'size': (600, 400), 'jpgq': .90}, {'name': 'web', 'size': (480, 320), 'jpgq': .90}, {'name': 'webtn', 'size': (120, 80), 'jpgq': .90}, ) for dir in dstdirs: td = os.path.join(targetdir, dir['name'] + "_%dx%d" % dir['size']) if not os.path.exists(td): os.mkdir(td) dstdirs[dir]['path'] = td
Soweit zum Setup der Daten. Jetzt folgen einige Funktionen um die korrekten Werte zum Skalieren eines Bildes zu bestimmen. Digitalkameras haben ja leider nie ein 2:3 Bildformat, es sind immer ein paar Pixel mehr auf einer Kante...
Das Seitenverhältnis liefert einen Aufschluss darüber welche Seite angepasst werden muss.
def cropcorr(width, height, ratio=1.5): return 1.0 * width / height - ratio
Jetzt folgt ein stupides Vergleichen der einzelnen Möglichkeiten: Ist das Bild im Hoch-, Quer- oder quadratischen Format?
def new_image_dimension(width, height, ratio=1.5): cropoffw = 0 cropoffh = 0 if width > height: # Panorama/Querformat cc = cropcorr(width, height, ratio) if cc > 0: cropoffw = width - int(height * ratio) elif cc < 0: cropoffh = height - int(width / ratio) return cropoffw, cropoffh elif width < height: # Portrait/Hochformat cc = cropcorr(height, width, ratio) if cc > 0: cropoffh = height - int(width * ratio) elif cc < 0: cropoffw = width - int(height / ratio) return cropoffw, cropoffh elif width == height: # quadratisch return cropoffw, cropoffh
Die neuen Breiten- und Höhenwerte müssen evtl. umsortiert werden. Dazu werden die Werte des gerade zu bearbeitenden Bildes herangezogen:
def sort_new_image_size(width, height, nw, nh): if width > height: # Panorama/Querformat return nw, nh elif width < height: # Portrait/Hochformat return nh, nw else: return nw, nw
Jetzt kommt endlich Gimp zum Einsatz:
- Bild laden
- tatsächliche Breite und Höhe ermitteln
- Das Bild auf das richtige Seitenformat beschneiden
Dann für jedes definierte Zielformat:
- eine Kopie des Bildes anlegen
- auf das neue Format skalieren
- falls der Zielname 'sw' ist in Graustufen umwandeln
- falls sie Breite kleiner gleich 750 Pixel ist "unscharf Maskieren"
- das Bild als JPEG speichern
- die Bildkopie aus dem Speicher entfernen
for f in files: image = pdb.file_jpeg_load(os.path.join(srcpath, f), '') width = pdb.gimp_image_width(image) height = pdb.gimp_image_height(image) xo, yo = new_image_dimension(width, height) pdb.gimp_image_crop(image, width - xo, height - yo, xo / 2, yo / 2) for dest in dstdirs: workimg = pdb.gimp_image_duplicate(image) nw, nh = dest['size'] nw, nh = sort_new_image_size(width, height, nw, nh) pdb.gimp_image_scale(workimg, nw, nh) drawable = pdb.gimp_image_get_active_drawable(workimg) if dest['name'] == 'sw': pdb.gimp_desaturate_full(drawable, DESATURATE_LIGHTNESS) if nw <= 750: pdb.plug_in_unsharp_mask(workimg, drawable, 0.1, 0.5, 25) targetf = os.path.join(dest['path'], f) pdb.file_jpeg_save(workimg, drawable, targetf, targetf, dest['jpgq'], \ 0, 1, 0, "created with gimp-python", 0, 1, 0, 1) pdb.gimp_image_delete(workimg) pdb.gimp_image_delete(image)