photomappe.de

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:

Dann für jedes definierte Zielformat:

    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)