> [Site index](https://perfectvector.com/llms.txt) — available pages and descriptions.

# Ein SVG-Wasserzeichen mit Python in eine PDF einfügen

> Füge mit svglib, ReportLab und pypdf ein SVG-Wasserzeichen in eine bestehende PDF ein. Prüfe Deckkraft, beschnittene Seiten, Drehung, erhaltenen Text und Überlagerungsreihenfolge.

Source: https://perfectvector.com/de/blog/svg-watermark-existing-pdf

Language: de
Author: Irene Kim
Published: 2026-10-11T08:00:00+09:00
Updated: 2026-10-16T08:00:00+09:00

Um einer bestehenden PDF mit Python ein SVG-Wasserzeichen hinzuzufügen, wandle die SVG in eine ReportLab-Zeichnung um, rendere diese auf eine kleine PDF-Überlagerung und füge die Überlagerung anschließend mit pypdf in jede Originalseite ein. Bestimme Größe und Position anhand der sichtbaren CropBox jeder Seite und normalisiere vor dem Zusammenführen die Seitendrehung.

Verwende `over=True`, wenn das Zeichen über einem deckenden Seitenhintergrund sichtbar bleiben muss. Auch ein durchscheinendes Zeichen kann oben liegen. Bei `over=False` kommt dieselbe Grafik unter den vorhandenen Inhalt und kann hinter einer gefüllten Seite verschwinden.

Das vollständige Beispiel unten erstellt seine eigene SVG und eine dreiseitige Quell-PDF. Es enthält unterschiedliche Seitengrößen, eine CropBox mit Ursprung ungleich null und eine gedrehte Seite. Das Ergebnis ist eine neue PDF. Behalte die Originaldatei separat.

## Wähle zuerst den Dokumentvorgang

| Ausgangspunkt                                               | Sinnvoller Ablauf                                                                                            |
| ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| Eine bestehende PDF benötigt auf jeder Seite ein SVG-Emblem | SVG-Überlagerung rendern und wie unten in die bestehenden Seiten einfügen                                    |
| Eine neue PDF wird von Grund auf erstellt                   | Den [ReportLab-Ablauf für SVG-Zeichnungen](https://perfectvector.com/de/blog/reportlab-svg) direkt verwenden |
| Eine vorhandene SVG enthält bereits die richtige Grafik     | Diese native Vektorquelle behalten; Nachzeichnen ist unnötig                                                 |
| Ein Logo liegt nur als Rasterbild vor                       | Zuerst geeignete Grafik vorbereiten, dann das PDF-Zusammenführen separat testen                              |

[pypdfs Wasserzeichenanleitung](https://pypdf.readthedocs.io/en/stable/user/add-watermark.html) unterscheidet Inhalte über und unter einer Seite. „Wasserzeichen“ bezeichnet hier das sichtbare Emblem; `over` bestimmt seine tatsächliche Stapelreihenfolge. Dies ist weder ein Sicherheitszeichen noch Manipulationsschutz oder ein Ablauf für signierte Dokumente.

## 1. Beginne mit einer kleinen, unterstützten SVG

Dieser Test verwendet zwei gefüllte Pfade: einen dreieckigen Rahmen mit offener Mitte und drei Balken. Beide Pfade tragen `fill-opacity="0.25"`. Text, Filter, eingebettete Bilder oder externe Ressourcen sind nicht enthalten.

Diese enge Eingrenzung ist wichtig. svglib unterstützt eine nützliche SVG-Teilmenge, doch zu seinen [dokumentierten Einschränkungen](https://github.com/deeplook/svglib) gehören begrenzte CSS-Unterstützung und nicht unterstützte Funktionen wie Masken und `foreignObject`. Eine im Browser richtig aussehende SVG muss nach der Umwandlung weiterhin geprüft werden. Enthält eine Datei Rasterinhalte, lies vor der Annahme eines vollständig vektorbasierten Ergebnisses, [wie du eingebettete Bilder in SVG findest](https://perfectvector.com/de/blog/svg-contains-raster-image).

Eine erste Version dieser Beispieldatei enthielt neben dem Rahmen SVG-Text. Im getesteten Stack wurde der umgewandelte Text vollständig deckend gezeichnet, während der Pfad 0.25 Deckkraft behielt. Ich ersetzte den Text durch eigene Pfadgrafik und testete den Ersatz. Das endgültige Ergebnis belegt diesen reinen Pfadfall, nicht korrekte Deckkraft für jede SVG-Text- oder Stilkombination.

## 2. Führe das vollständige Beispiel aus

Die getestete Umgebung bestand aus Python 3.12.14, svglib 2.2.0, ReportLab 4.4.9 und pypdf 6.10.0. Die aktuelle pypdf-Dokumentation beschreibt auch neuere Veröffentlichungen. Halte deshalb getestete Versionen und Dokumentationsversion auseinander.

Installiere diese Versionen in einer separaten Umgebung:

```bash
python -m venv .venv
source .venv/bin/activate
python -m pip install svglib==2.2.0 reportlab==4.4.9 pypdf==6.10.0
```

Speichere Folgendes als `watermark_demo.py`. Es enthält die gesamte Eingabegrafik und erstellt alle drei PDF-Dateien. Du musst deshalb keine fehlende Beispiel-PDF oder -SVG herunterladen.

```python
from io import BytesIO
from pathlib import Path

from pypdf import PdfReader, PdfWriter, Transformation
from pypdf.generic import RectangleObject
from reportlab.graphics import renderPDF
from reportlab.lib.colors import HexColor
from reportlab.pdfgen import canvas
from svglib.svglib import svg2rlg

SVG = '''<svg xmlns="http://www.w3.org/2000/svg" width="240" height="80"
             viewBox="0 0 240 80">
  <path fill="#315d6f" fill-opacity="0.25" fill-rule="nonzero"
        d="M10 60 L45 8 L80 60 Z M31 48 L59 48 L45 27 Z"/>
  <path fill="#315d6f" fill-opacity="0.25"
        d="M95 23 H216 V31 H95 Z M95 39 H190 V47 H95 Z
           M95 55 H205 V63 H95 Z"/>
</svg>'''


def make_demo_source(destination):
    stream = BytesIO()
    document = canvas.Canvas(stream, pagesize=(420, 300))
    specifications = [
        (420, 300, '#f5eddb', 'SOURCE PAGE ONE'),
        (300, 420, '#ffffff', 'SOURCE PAGE TWO'),
        (360, 260, '#e8eef0', 'SOURCE PAGE THREE')
    ]
    for width, height, background, label in specifications:
        document.setPageSize((width, height))
        document.setFillColor(HexColor(background))
        document.rect(0, 0, width, height, fill=1, stroke=0)
        document.setFillColor(HexColor('#183a42'))
        document.setFont('Helvetica-Bold', 16)
        document.drawString(28, height - 40, label)
        document.setFont('Helvetica', 10)
        document.drawString(28, height - 62, 'Original text remains in the PDF content.')
        document.drawString(28, 28, 'Original vector line and opaque page background')
        document.setStrokeColor(HexColor('#c47b44'))
        document.setLineWidth(3)
        document.line(28, 48, width - 28, 48)
        document.showPage()
    document.save()
    reader = PdfReader(stream)
    reader.pages[1].cropbox = RectangleObject([10, 20, 290, 400])
    reader.pages[2].rotate(90)
    writer = PdfWriter()
    for page in reader.pages:
        writer.add_page(page)
    writer.write(destination)


def make_overlay(svg_path, width, height):
    drawing = svg2rlg(str(svg_path))
    if drawing is None or drawing.width <= 0 or drawing.height <= 0:
        raise ValueError('The SVG did not produce a usable drawing')
    scale = width * 0.65 / drawing.width
    left = (width - drawing.width * scale) / 2
    bottom = (height - drawing.height * scale) / 2
    drawing.scale(scale, scale)
    stream = BytesIO()
    overlay = canvas.Canvas(stream, pagesize=(width, height))
    renderPDF.draw(drawing, overlay, left, bottom)
    overlay.save()
    return PdfReader(stream).pages[0]


def add_artwork(source_path, svg_path, output_path, *, over):
    reader = PdfReader(source_path)
    if reader.is_encrypted:
        raise ValueError('Encrypted inputs are outside this example')
    if reader.get_fields():
        raise ValueError('Form handling is outside this example')
    writer = PdfWriter()
    writer.clone_document_from_reader(reader)
    # Cloning in pypdf 6.10.0 does not retain the source header version.
    # This overlay uses transparency, introduced in PDF 1.4.
    writer.pdf_header = max(reader.pdf_header, '%PDF-1.4')
    for page in writer.pages:
        if page.rotation:
            page.transfer_rotation_to_content()
        box = page.cropbox
        width, height = float(box.width), float(box.height)
        overlay = make_overlay(svg_path, width, height)
        page.merge_transformed_page(
            overlay,
            Transformation().translate(float(box.left), float(box.bottom)),
            over=over,
            expand=False
        )
    writer.write(output_path)


if __name__ == '__main__':
    output = Path('watermark-output')
    output.mkdir(exist_ok=True)
    artwork = output / 'emblem.svg'
    artwork.write_text(SVG)
    source = output / 'source.pdf'
    make_demo_source(source)
    add_artwork(source, artwork, output / 'overlay-top.pdf', over=True)
    add_artwork(source, artwork, output / 'underlay.pdf', over=False)
```

Führe es aus:

```bash
python watermark_demo.py
```

Öffne `watermark-output/source.pdf`, `overlay-top.pdf` und `underlay.pdf`. Seite eins sollte das Emblem in der oberen Überlagerung zeigen, in der darunterliegenden Version aber verbergen, weil ihr ursprünglicher Hintergrund deckend ist. Die beiden anderen Seiten prüfen Beschnitt und Drehung, statt dieselbe Seitengeometrie zu wiederholen.

Behalte für deine eigene gewöhnliche, unsignierte PDF `make_overlay()` und `add_artwork()` und rufe anschließend Folgendes auf:

```python
add_artwork(
    Path("original.pdf"),
    Path("emblem.svg"),
    Path("watermarked.pdf"),
    over=True
)
```

Der Writer behält die Quell-Headerversion mit mindestens PDF 1.4 bei, weil die Überlagerung Transparenz verwendet. In pypdf 6.10.0 kann das reine Klonen des Dokuments den standardmäßigen PDF-1.3-Header des Writers hinterlassen, selbst wenn die Quelle eine spätere Version angibt. Die ausdrückliche Zuweisung verhindert diese Herabstufung; sie ist keine Konformitätsprüfung. Die [Dokumentation zum Writer-Header](https://pypdf.readthedocs.io/en/6.10.0/modules/PdfWriter.html#pypdf.PdfWriter.pdf_header) empfiehlt eine Version, die alle in der Datei verwendeten Funktionen unterstützt.

Die Schutzprüfungen weisen verschlüsselte Eingaben und erkannte Formularfelder zurück. Sie sind kein vollständiges Kompatibilitäts- oder Signaturaudit. Signierte Dokumente, Formulare, Anmerkungen, Verschlüsselung und dokumentspezifische Anforderungen benötigen einen separaten Ablauf und eine Prüfung, bevor du eine funktionierende Datei ersetzt.

## 3. Platziere Grafiken in den sichtbaren Seitenkoordinaten

Ein PDF-Punkt entspricht 1/72 Zoll. In dieser svglib-Version ergeben die einheitenlosen SVG-Maße 240 × 80 eine Zeichnung von 180 × 60 Punkt: Ein CSS-Pixel entspricht 0.75 Punkt. Der Code liest `drawing.width` und `drawing.height`, statt anzunehmen, dass SVG-Pixel bereits PDF-Punkten entsprechen.

Das Beispiel macht den SVG-Ansichtsbereich 65% so breit wie jede sichtbare Seite, behält sein Seitenverhältnis und zentriert ihn. Es zentriert das deklarierte Zeichenrechteck, nicht die visuelle Masse des Emblems. Die 65% sind eine Layoutentscheidung des Beispiels, kein Wasserzeichenstandard. Diese nur auf der Breite beruhende Skalierung passt zum hier gezeigten breiten Emblem. Ein hoher Ersatz kann über die sichtbare Seitenhöhe hinausragen. Begrenze beim Anpassen der Funktion den Maßstab durch verfügbare Breite und Höhe und prüfe jede Seite vor der Verwendung deiner eigenen PDF.

| Seite | Zustand der Quelle                            | Sichtbare Ausgabe-CropBox in Punkt    | Nominelle SVG-Ansichtsbereichsbreite |
| ----- | --------------------------------------------- | ------------------------------------- | ------------------------------------ |
| 1     | 420 × 300 große Querformatseite               | 0, 0 bis 420, 300                     | 273pt                                |
| 2     | 300 × 420 große Seite, nach innen beschnitten | 10, 20 bis 290, 400                   | 182pt                                |
| 3     | 360 × 260 große Seite mit 90° Drehung         | Nach Normalisierung 0, 0 bis 260, 360 | 169pt                                |

Der Aufruf `transfer_rotation_to_content()` überträgt die Drehung in Inhalt und Seitenboxen. Er richtet die ursprünglichen Wörter nicht relativ zum Betrachter gerade aus. Der Originaltext auf Seite drei bleibt so ausgerichtet wie in der angezeigten Quellansicht, während das neue Emblem in den normalisierten sichtbaren Koordinaten platziert wird. Die [pypdf-Seiten-API](https://pypdf.readthedocs.io/en/stable/modules/PageObject.html) empfiehlt die Übertragung der Drehung vor dem Zusammenführen von Seiten.

Die Überlagerung beginnt an ihrem eigenen Ursprung. Durch Verschieben um `cropbox.left` und `cropbox.bottom` liegt sie im sichtbaren Zielbereich, auch wenn die CropBox nicht bei null beginnt. `expand=False` verhindert, dass das Zusammenführen die Seitenboxen vergrößert.

## 4. Prüfe die gespeicherte PDF, nicht nur die SVG-Vorschau

![Tatsächlich gerenderter PDF-Vergleich mit verborgener Unterlegung, sichtbarer durchscheinender oberer Überlagerung, beschnittener Hochformatseite und gedrehter Quellseite mit zentriertem Vektoremblem](https://perfectvector.com/blog/svg-watermark-existing-pdf/pdf-overlay.webp)

*Tatsächliche Poppler-Renderings der gespeicherten PDFs. Die ursprünglichen Seitenhintergründe verbergen die Unterlegung; die obere Überlagerung bleibt sichtbar. Die letzten beiden Ansichten prüfen einen Beschnittursprung ungleich null und eine ursprünglich gedrehte Seite.*

Ich öffnete die gespeicherten PDFs erneut, prüfte Inhaltsströme, Seitenboxen, Drehung, extrahierten Text und Bildressourcen und renderte anschließend die sichtbaren CropBoxen mit Poppler 26.02 bei 96dpi. Die abschließende Dateiprüfung bestand 40 Kontrollen. Ein Browservergleich prüfte außerdem gespeicherte Dateihashes, geladene Renderings und 12 Pixelproben in nativer Auflösung.

| Prüfung dieses Beispiels              | Beobachtetes Ergebnis                                                                                                                              |
| ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| Seitenzahl und bekannter Originaltext | Alle drei Seiten und ihr erwarteter Quelltext blieben in beiden Ausgaben erhalten                                                                  |
| Überlagerungsgeometrie                | Zwei gefüllte Pfade, 18 geprüfte Eckpunkte, Alpha für Füllungen von 0.25 auf jeder Seite                                                           |
| Hinzugefügte Bildressourcen           | Keine in diesen ursprünglichen Quell- und Ausgabeseiten                                                                                            |
| Platzierung und Seitenboxen           | Entsprachen den deklarierten CropBoxen und den Berechnungen der gespeicherten Transformationen; Ausgabedrehung war null                            |
| Rahmen- und offene-Mitte-Proben       | Rahmenpixel der oberen Überlagerung entsprachen der erwarteten Mischung innerhalb von ±2 RGB-Werten; offene Mitten behielten den Seitenhintergrund |
| Unterlegung bei deckendem Hintergrund | Die Renderings von Quelle und Unterlegung der ersten Seite unterschieden sich bei 96dpi in null Pixeln                                             |

Die Platzierungsprüfung scheiterte zunächst an einem strengen Vergleich mit idealen Gleitkommakoordinaten bei 0.00001pt Toleranz. ReportLab speichert Transformationsmatrizen mit endlicher Genauigkeit. Ich behielt dieses fehlgeschlagene Ergebnis bei, berechnete unabhängig die erwarteten gespeicherten Matrizen samt Rundungsgrenze und verglich die gespeicherten Eckpunkte damit. Die größte beobachtete Abweichung von Idealkoordinaten betrug etwa 0.000054pt und lag innerhalb der hergeleiteten Grenze von 0.000086pt. Das prüft die visuell zentrierte Platzierung in diesen Dateien; es ist keine allgemeine Präzisionsgarantie.

Für eine schnelle lokale Sichtprüfung mit installiertem Poppler:

```bash
pdftoppm -cropbox -r 96 -png watermark-output/overlay-top.pdf watermark-output/top
pdftoppm -cropbox -r 96 -png watermark-output/underlay.pdf watermark-output/below
```

Prüfe jede Seite mit sinnvoller Vergrößerung. Wähle oder extrahiere außerdem erwarteten Originaltext, prüfe die Seitenmaße und untersuche, ob das Wasserzeichen Pfade blieb oder Bilder einführte. Ein scharf wirkendes Bildschirmfoto allein belegt diese Dateieigenschaften nicht. Dieser Test maß weder Druck noch Viewerkompatibilität, Dateigrößeneinsparungen oder Widerstand gegen das Entfernen des Wasserzeichens.

## Behebe den Fehler im richtigen Schritt

| Symptom                                                     | Prüfen oder ändern                                                                                                                  |
| ----------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| Das Zeichen verschwindet                                    | Vergleiche `over=False` mit `over=True` und suche nach deckenden Originalhintergründen                                              |
| Das Zeichen sitzt auf einer beschnittenen Seite falsch      | Verwende Größe und Ursprung der CropBox statt einer fest codierten Seitengröße                                                      |
| Gedrehte Seiten zeigen das Zeichen in unerwarteter Richtung | Normalisiere die Drehung vor dem Berechnen der sichtbaren Maße und prüfe die resultierende Ansicht                                  |
| Deckkraft oder Stil verändern sich                          | Vereinfache die SVG, prüfe den Farbauftragszustand der umgewandelten PDF und teste genau diese Datei erneut                         |
| Ein fotoartiger oder pixeliger Bereich bleibt               | Prüfe die SVG auf eingebettete Bilder; eine SVG-Hülle macht ein Bitmap nicht zu Pfaden                                              |
| Text, Formulare oder Dokumentverhalten verändern sich       | Halte an und prüfe die tatsächlichen Dokumentfunktionen, statt anzunehmen, dass ein erfolgreiches Zusammenführen alles erhalten hat |

Die Original-PDF bleibt Seiteninhalt; das Skript rastert keine vollständigen Seiten. Das beweist nicht, dass jede Eingabe-PDF eine beliebige Zusammenführung unverändert übersteht. Verwende eine Kopie und definiere vor einer größeren Stapelverarbeitung die Inhalte und Dokumentfunktionen, die weiter funktionieren müssen.

## Bereite fehlende Grafik vor dem Zusammenführen vor

Wenn ein vorhandenes Logo bereits eine saubere SVG ist, behalte es. Ist nur ein geeignetes flächiges Rasterlogo übrig, kann [PerfectVectors Logovektorisierer](https://perfectvector.com/de/vectorize-logo) vor diesem Python-Schritt bearbeitbare Grafiken vorbereiten. Prüfe gewonnene Silhouette, Löcher und kleine Details und wiederhole anschließend SVG-Umwandlung und Prüfungen der gespeicherten PDF. Das Beispiel hier verwendete eigene native Pfade und führte keine PerfectVector-Konvertierung durch. Vektorisierung führt keine Seiten zusammen, validiert keine Signaturen und garantiert keine svglib-Kompatibilität.

## Häufige Fragen

**Kann pypdf ein SVG-Wasserzeichen direkt lesen?**
Dieses Beispiel wandelt SVG zuerst mit svglib und ReportLab in eine PDF-Überlagerung um. pypdf führt anschließend PDF-Seiteninhalte zusammen; es interpretiert in diesem Ablauf nicht die SVG-Quelle.

**Warum verschwindet ein Wasserzeichen hinter meiner PDF-Seite?**
Eine Unterlegung kann von einem bestehenden deckenden Hintergrund verdeckt werden. Verwende `over=True` für eine sichtbare obere Überlagerung und lege die Grafikdeckkraft separat fest. Prüfe das tatsächliche Ergebnis auf jeder Seite.

**Erhält dies Vektorgrafiken und Originaltext?**
Das getestete reine Pfademblem blieb als gefüllte Pfade erhalten, und erwarteter Originaltext blieb auf allen drei Seiten extrahierbar. SVG-Funktionen und PDF-Dokumentfunktionen außerhalb dieses Beispiels benötigen eine separate Prüfung.

**Bleibt eine digitale Signatur beim Neuschreiben der PDF erhalten?**
Verwende dieses Beispiel nicht als Ablauf für signierte Dokumente. Es schreibt die Datei neu und testet weder Signaturerhalt noch Gültigkeit. Behalte das signierte Original und nutze einen zu seinen Signaturanforderungen passenden Ablauf.

## Quellen

1. [pypdf: Stempel oder Wasserzeichen hinzufügen](https://pypdf.readthedocs.io/en/stable/user/add-watermark.html) — Überlagerungs- und Unterlegungsreihenfolge, Zusammenführen und Drehungshinweise.
2. [pypdf: PageObject-API](https://pypdf.readthedocs.io/en/stable/modules/PageObject.html) — Seitenboxen, Drehungsübertragung und transformiertes Zusammenführen.
3. [svglib-Projektdokumentation](https://github.com/deeplook/svglib) — SVG-zu-ReportLab-Umwandlung, Einheiten und Grenzen unterstützter Funktionen.
4. [ReportLab-Grafikanleitung](https://docs.reportlab.com/reportlab/userguide/ch11_graphics/) — Zeichenobjekte und PDF-Rendering im ReportLab-Grafiksystem.
5. [pypdf 6.10.0: PDF-Headerversion](https://pypdf.readthedocs.io/en/6.10.0/modules/PdfWriter.html#pypdf.PdfWriter.pdf_header) — deklariert eine PDF-Version, die die verwendeten Ausgabefunktionen unterstützt.

Behalte native Grafiken, wenn du sie hast. Ist nur ein geeignetes Rasterlogo übrig, [bereite mit PerfectVector eine bearbeitbare SVG vor](https://perfectvector.com/de/vectorize-logo), prüfe die Grafik und verifiziere die neu zusammengeführte PDF anschließend separat.

## Explore

- [Read the HTML article](https://perfectvector.com/de/blog/svg-watermark-existing-pdf)
- [fpdf2-SVG-Bilder: Pfade in deiner Python-PDF erhalten](https://perfectvector.com/de/blog/fpdf2-svg-image.md)
- [PDFKit-SVG: Ein Vektorlogo ohne Rasterisierung platzieren](https://perfectvector.com/de/blog/pdfkit-svg.md)
- [Product facts](https://perfectvector.com/product-facts.md)
- [FAQ](https://perfectvector.com/faq.md)
- [Pricing and credits](https://perfectvector.com/pricing.md)
