Wie kann man mit PIL in Python ein Bild auf ein anderes Bild zusammensetzen?

77

Ich muss ein Bild aufnehmen und es auf einem neuen, generierten weißen Hintergrund platzieren, damit es in ein herunterladbares Desktop-Hintergrundbild umgewandelt werden kann. Also würde der Prozess gehen:

  1. Generieren Sie ein neues, vollständig weißes Bild mit den Abmessungen 1440 x 900
  2. Platzieren Sie das vorhandene Bild zentriert oben
  3. Als Einzelbild speichern

In PIL sehe ich das ImageDrawObjekt, aber nichts zeigt an, dass es vorhandene Bilddaten auf ein anderes Bild zeichnen kann. Vorschläge oder Links, die jeder empfehlen kann?

Sebastian
quelle

Antworten:

140

Dies kann mit der pasteMethode einer Image-Instanz erreicht werden:

from PIL import Image
img = Image.open('/path/to/file', 'r')
img_w, img_h = img.size
background = Image.new('RGBA', (1440, 900), (255, 255, 255, 255))
bg_w, bg_h = background.size
offset = ((bg_w - img_w) // 2, (bg_h - img_h) // 2)
background.paste(img, offset)
background.save('out.png')

Dieser und viele andere PIL-Tricks können im PIL-Tutorial von Nadia Alramli aufgegriffen werden

unutbu
quelle
1
Je nach Modul / System / Version müssen Sie möglicherweise importieren: vom PIL-Import Image
Nuno Aniceto
3
Vielen Dank an @NunoAniceto, ich habe es geändert from PIL import Image, um den Code mit Pillow kompatibler zu machen .
Unutbu
Wenn Sie Python 3.x verwenden, überprüfen Sie stackoverflow.com/a/17530159/7326714 , um den Ganzzahlfehler "offeset" zu beheben.
LucSpan
9

Basierend auf der Antwort von unutbus:

#!/usr/bin/env python

from PIL import Image
import math


def resize_canvas(old_image_path="314.jpg", new_image_path="save.jpg",
                  canvas_width=500, canvas_height=500):
    """
    Place one image on another image.

    Resize the canvas of old_image_path and store the new image in
    new_image_path. Center the image on the new canvas.
    """
    im = Image.open(old_image_path)
    old_width, old_height = im.size

    # Center the image
    x1 = int(math.floor((canvas_width - old_width) / 2))
    y1 = int(math.floor((canvas_height - old_height) / 2))

    mode = im.mode
    if len(mode) == 1:  # L, 1
        new_background = (255)
    if len(mode) == 3:  # RGB
        new_background = (255, 255, 255)
    if len(mode) == 4:  # RGBA, CMYK
        new_background = (255, 255, 255, 255)

    newImage = Image.new(mode, (canvas_width, canvas_height), new_background)
    newImage.paste(im, (x1, y1, x1 + old_width, y1 + old_height))
    newImage.save(new_image_path)

resize_canvas()

Denken Sie daran, Pillow ( Documentation , GitHub , PyPI ) anstelle von Python-Imaging zu verwenden, da Pillow mit Python 2.X und Python 3.X funktioniert.

Martin Thoma
quelle
3

Dies ist etwas Ähnliches zu tun

Ich begann damit, diesen „weißen Hintergrund“ in Photoshop zu generieren und als PNG-Datei zu exportieren. Dort habe ich im1 bekommen (Bild 1). Verwenden Sie dann die Einfügefunktion, da dies viel einfacher ist.

from PIL import Image

im1 = Image.open('image/path/1.png')
im2 = Image.open('image/path/2.png')
area = (40, 1345, 551, 1625)  
im1.paste(im2, area)
                   l>(511+40) l>(280+1345)
         |    l> From 0 (move, 1345px down) 
          -> From 0 (top left, move 40 pixels right)

Okay so where did these #'s come from? (40, 1345, 551, 1625) im2.size (511, 280) Because I added 40 right and 1345 down (40, 1345, 511, 280) I must add them to the original image size which = (40, 1345, 551, 1625)

im1.show() 

um dein neues Bild zu zeigen

Steven Jeffers
quelle
0

Image.blend()? [ Link ]

Oder noch besser Image.paste(), derselbe Link.

Felix
quelle
"Erstellt ein neues Bild durch Interpolation zwischen den angegebenen Bildern unter Verwendung eines konstanten Alphas. Beide Bilder müssen dieselbe Größe und denselben Modus haben." Aus der Dokumentation geht hervor, dass sie nicht unterschiedlich groß sein können.
Sebastian
Ich bemerkte Image.paste()auch, was letztendlich die Lösung war.
Felix
Die URL ist abgelaufen
Phani Rithvij
0

Vielleicht zu spät, aber für solche Bildoperationen verwenden wir ImageSpecField [ Link ] in einem Modell mit Originalbild.

profuel
quelle