Bilder & Grafiken – speedata Publisher
Description: Bilder in das PDF einfügen ist sehr einfach, es reicht ein kurzer Befehl: <Record element="data"> <PlaceObject> <Image …

Version 5.9.2

# Bilder & Grafiken

Bilder in das PDF einfügen ist sehr einfach, es reicht ein kurzer Befehl:

    <Record element="data">
      <PlaceObject>
        <Image file="_samplea.pdf" width="5cm"/>
      </PlaceObject>
    </Record>

Das Bild `_samplea.pdf` ist (wie `_sampleb.pdf`) Bestandteil des Publishers und für Testzwecke gut nutzbar. Als Bildformate sind PDF, PNG und JPEG möglich. Andere Formate müssen vor der Verarbeitung in eines dieser Formate konvertiert werden. Wenn das Programm inkscape installiert ist, wird das genutzt um Dateien im SVG-Format automatisch nach PDF zu konvertieren (siehe dazu den Abschnitt über Konfiguration - dort können auch die Kommandozeilenparameter für die Konvertierung gesetzt werden). Das Format, das in der Praxis am wenigsten Probleme bereitet, ist PDF. Hier können auch Farbprofile eingebettet werden.

Die Bilder werden bei der Verarbeitung im Publisher nicht verändert, das heißt, sie behalten unter anderem ihre ursprüngliche (Datei-)Größe bei. Bei sehr großen Bildern ist die Verarbeitungsgeschwindigkeit geringer und die Größe der resultierenden PDF-Datei nimmt natürlich zu. Daher kann es sich lohnen, für die Verarbeitung spezielle Versionen mit kleineren Dateigrößen bereitzuhalten.

## Breite und Höhe der Bilder

Wenn man Bilder einbindet, dann ist es immer sinnvoll, eine Größenangabe mitzugeben. Ansonsten wird die natürliche Größe des Bildes genommen. Was die natürliche Größe ist, ist nicht immer eindeutig zu sagen. In der Regel gibt es in der Bilddatei eine DPI-Angabe. Die ist oftmals willkürlich vom Bildbearbeitungsprogramm gesetzt. Wenn dort beispielsweise 72 DPI steht, ist ein 720 Pixel breites Bild 10 Zoll breit; bei 300 DPI nur 2,4 Zoll.

Da man sich auf die Angabe nicht verlassen kann, werden Größenangaben für die Ausgabe benötigt. Das kann entweder die gewünschte Höhe oder die gewünschte Breite des Bildes sein, oder beide Angaben zusammen. Im Beispiel oben hat das Bild eine Breite von fünf Zentimeter. Die Angabe kann auch als Anzahl von Rasterzellen gemacht werden. Die Angabe von `width="100%"` bedeutet, dass die gesamte verfügbare Breite genutzt werden soll (derzeit werden andere Prozentangaben noch nicht unterstützt). Die Angabe `auto` ist wie das Weglassen der Angabe und ist nur wegen der Kompatibilität zu CSS vorhanden.

Wenn beide Proportionen angegeben sind (Breite und Höhe) gibt es zwei Modi: Beibehalten des Seitenverhältnisses (`clip="yes"`) oder Strecken bzw. Stauchen (`clip="no"`) der Ausgabe.

    <PlaceObject>
        <Image file="ocean.pdf" width="10" height="3" clip="no"/>
    </PlaceObject>

Das Bild wird horizontal gestreckt.

Mit `clip="yes"` ist das Bild so ausgeschnitten, dass auf einer Seite die maximalen Ausmaße genommen werden

    <PlaceObject>
        <Image file="ocean.pdf" width="10" height="3" clip="yes"/>
    </PlaceObject>

Die Größe von Bildern kann man mit den beiden XPath-Funktionen `sd:imagewidth(<Dateiname>)` und `sd:imageheight(<Dateiname>)` ermitteln. Das Ergebnis ist in Rasterzellen. Vorsicht, hier wird die natürliche Größe genommen, die gegebenenfalls ohne Aussagekraft ist (s.o.).

## Maximale Höhe und Breite, minimale Höhe und Breite

Um die natürliche Größe zu benutzen, aber Einschränkungen anzugeben, gibt es die vier Kombinationen aus min/max und width/height. Das Bild in dem folgenden Beispiel wird nicht breiter als 10 Rasterzellen und nicht höher als 3. Das Seitenverhältnis bleibt erhalten:

    <PlaceObject>
        <Image file="forest.jpg" maxwidth="10" maxheight="3" />
    </PlaceObject>

Falls die natürliche Größe des Bildes kleiner ist als die vorgegebenen Angaben von `maxwidth` und `maxheight`, kann man `stretch` auf `yes` setzen, um das Bild so weit zu vergrößern, bis eine der beiden Einschränkungen erreicht wird.

## Drehen von Bildern

Das Drehen von Bildern und anderen Objekten beschreibt der Abschnitt Rotation von Inhalten.

## Speicherort der Bilddateien

Meist liegen die Bilder im Dateisystem oder in einem DAM (digital asset management). Im Dateisystem können sie entweder mit einem absoluten Pfad angesprochen werden:

    <Image file="file:///path/to/the/image.pdf"  />

oder als Datei in einem der Unterverzeichnisse des Suchpfads, wie in den Beispielen oben. Beispielsweise können die Bilder in dem Unterverzeichnis `images` liegen. Siehe dazu den Abschnitt über Dateiorganisation.

Die Bilder können auch mittels http(s)-Protokoll von einem Webserver geladen werden. Die Syntax ist analog zum Beispiel mit dem absoluten Pfad:

    <Layout xmlns="urn:speedata.de:2009/publisher/en" >

      <Record element="data">
        <PlaceObject>
          <Image file="https://picsum.photos/400/300" width="5"/>
        </PlaceObject>
      </Record>
    </Layout>

## Caching

Die Bilder, die über http und https geladen werden, werden auf der Festplatte zwischengespeichert. Bei jedem Request wird überprüft, ob das Bild noch aktuell ist und ggf. nicht erneut heruntergeladen. Ist das Bild auf dem Server gelöscht, wird es auch im lokalen System gelöscht.

Mit `sp --cache=fast` kann man auf die schnelle Caching-Methode zurückgreifen, die das Bild nur einmal vom Server herunterlädt und dann nicht wieder auf Aktualität prüft.

Mit dem Befehl `sp clearcache` wird der Zwischenspeicher gelöscht.

Der Ort, wo der Bildercache liegt, kann entweder über `tempdir` (Kommandozeile und Konfigurationsdatei) gesteuert werden oder über den Schlüssel `imagecache` in der Konfigurationsdatei (nicht auf der Kommandozeile).

## Platzhalterbilder

Während der Layoutentwicklung sind die finalen Bilder oft noch nicht verfügbar. Statt mit Bilddateien als Stellvertreter zu arbeiten, kann das Pseudo-URL-Schema `placeholder://` benutzt werden. Es erzeugt zur Laufzeit einen grauen Platzhalter mit Diagonalkreuz und Rahmen in der angegebenen natürlichen Größe (in PostScript-Punkten):

    <PlaceObject>
        <Image file="placeholder://400x200" width="3"/>
    </PlaceObject>

Die Syntax lautet `placeholder://<Breite>x<Höhe>`. Die natürliche Größe verhält sich wie bei einer echten Bilddatei mit den Maßen `<Breite> pt × <Höhe> pt`, das heißt, alle gewohnten Mechanismen für Skalierung, Seitenverhältnis (`width`/`height`/`maxwidth`/`maxheight`) und das Beschneiden mit `clip` funktionieren wie bei einem normalen Bild.

Es wird keine Datei auf der Festplatte erzeugt; der Platzhalter wird intern über MetaPost gerendert.

## Bild nicht gefunden?

Was passiert, wenn ein Bild nicht gefunden wird? Das normale Verhalten ist die Ausgabe einer Fehlermeldung und einem Platzhalterbild, das das Fehlen anzeigt:

    <PlaceObject>
        <Image file="doesnotexist" width="5"/>
    </PlaceObject>

Eine andere Möglichkeit besteht darin, mit `fallback` ein Platzhalterbild selber zu bestimmen:

    <PlaceObject>
        <Image file="doesnotexist" fallback="......" width="5"/>
    </PlaceObject>

Man kann auch noch einstellen, ob es ein Fehler ist, wenn ein Platzhalterbild ausgewählt wird, oder nur eine Warnung.

    <Options imagenotfound="error"/>

bzw. `warning` für eine Warnung.

## Besonderheiten bei PDF-Dateien

PDF-Dateien haben einige Besonderheiten: sie können mehrere Seiten enthalten und die einzelnen Seiten haben verschiedene Boxen, die den sichtbaren Bereich und andere Bereiche markieren. Manche der Boxen sind für den Ausdruck wichtig, manche für die Ansicht im PDF-Anzeigeprogramm. Die Box, die mit den angegebenen Größen angezeigt werden soll, wird mit dem Attribut `visiblebox` bestimmt:

    <Image file="seite.pdf" visiblebox="artbox" width="210mm" height="297mm" />

bedeutet, dass die »artbox« in der Größe 210mm × 297mm dargestellt wird.

Die Auswahl der Seite über das Attribut `page` und die Layoutfunktion `sd:number-of-pages()` beschreibt der Abschnitt Mehrseitige PDF-Dateien einbetten.

### Angabe der Seite bei Layout-Funktionen

Einige Layoutfunktionen (`sd:aspectratio()`, `sd:imageheight()` und `sd:imagewidth()`) greifen auf Bilddateien zu. Im Falle einer PDF Datei, kann man neben dem Dateinamen die Seite und die gewünschte PDF-Box angeben. Diese Angaben sind optional.

Beispiel: `sd:aspectratio("ocean.pdf",1,"cropbox")`

Falls keine Box angegeben wird, wird die cropbox benutzt. Mögliche Werte für die Box-Angabe: `artbox`, `cropbox`, `trimbox`, `mediabox` und `bleedbox`.

## Externe Konvertierungstools

Der Publisher verarbeitet in der Regel nur PDF, PNG und JPEG Dateien. Um andere Formate nutzen zu können, muss man sie in eines der drei Formate umwandeln. Das kann im Vorfeld gemacht werden, aber auch zur Laufzeit des Publishers.

| Seit Version 5.9.2 lassen sich externe Konverter auch über den Lua-Callback `image_handler` definieren, siehe Lua-Callbacks. Der Callback kommt ohne die unten beschriebenen `%%input%%`/`%%output%%`-Platzhalter und Anführungszeichen-Regeln aus und ist der empfohlene Weg für neue Projekte. Die in diesem Abschnitt beschriebenen Konfigurationseinstellungen funktionieren weiterhin; ein registrierter Callback hat Vorrang.

    <Layout xmlns="urn:speedata.de:2009/publisher/en"
      xmlns:sd="urn:speedata:2009/publisher/functions/en">

      <Record element="data">
        <PlaceObject>
          <!-- tiff can only be used with an external converter -->
          <Image file="rhslogo.tiff"/>
        </PlaceObject>
      </Record>
    </Layout>

Um die Konvertierung zu nutzen, muss man die Programmaufrufe in der Konfigurationsdatei eintragen. Hier wird das Programm `convert` von ImageMagick genutzt:

    imagehandler="tiffimage:(convert %%input%% %%output%%.pdf)"
    extensionhandler="tiff:tiffimage"

Der Dateinamenendung `.tiff` wird der Handler `tiffimage` zugeordnet (Zeile 2). In der ersten Zeile wird dem Handler `tiffimage` dem Programm `convert %%input%% %%output%%.pdf`, wobei die Dateinamen zur Laufzeit ersetzt werden. Wenn Leerzeichen in Dateinamen enthalten sind, müssen die Ersetzungen wie `%%input%%` in Anführungszeichen (ohne Schrägstrich o.ä. davor) gesetzt werden:

    imagehandler="tiffimage:("/path/with space/convert" "%%input%%" "%%output%%.pdf")"

Man kann auch mehrere Handler für verschiedene Dateitypen angeben:

    imagehandler="tiffimage:(...);gifimage:(...)"
    extensionhandler="tiff:tiffimage;gif:gifimage"

## Bilder aus textuellen Beschreibungen

Es gibt unzählige Bildbeschreibungssprachen, in denen Bilder nicht mit einem externen Programm gezeichnet oder gemalt werden, sondern textuell beschrieben werden. Z.B. »zeichne ein Quadrat mit der Kantenlänge 4cm« oder »erstelle ein Tortendiagramm mit den folgenden Werten: ….«. Diese Grafiken werden dann aus der Beschreibungssprache in verschiedene Formate umgewandelt, meist als PNG oder PDF. Mit dem Publisher ist es seit Version 3.9.1 möglich, solche Beschreibungen einzubetten:

    <Layout xmlns="urn:speedata.de:2009/publisher/en"
       xmlns:sd="urn:speedata:2009/publisher/functions/en">

       <Record element="data">
          <PlaceObject>
            <!-- we need to specify the imagetype -->
            <Image width="7cm" imagetype="mermaid" >
              <Value>sequenceDiagram
                participant Alice
                participant Bob
                Alice->>John: Hello John, how are you?
                loop Healthcheck
                    John->>John: Fight against hypochondria
                end
                Note right of John: Rational thoughts &lt;br/>prevail!
                John-->>Alice: Great!
                John->>Bob: How about you?
                Bob-->>John: Jolly good!
              </Value>
            </Image>
          </PlaceObject>
        </Record>
    </Layout>

Notwendig ist natürlich die Konfiguration, wie der externe Konverter aufgerufen wird. Das funktioniert analog zu dem TIFF-Beispiel im vorherigen Abschnitt:

    imagehandler="mermaid:(/usr/bin/mmdc -i %%input%% -o %%output%%.pdf)"

Beim Lua-Callback `image_handler` (Lua-Callbacks) steht der Wert des Attributs `imagetype` als `job.imagetype` zur Verfügung.

Das Ergebnis ist ein Sequenzdiagramm, von `mermaid` erzeugt und nach PDF konvertiert.

Natürlich ist es auch möglich, die Bildbeschreibung aus den Daten zu entnehmen. Dazu muss der Image-Befehl wie folgt aufgebaut werden.

    <PlaceObject>
      <Image width="7cm" imagetype="mermaid" >
         <Value select="imagedata" />
      </Image>
    </PlaceObject>

## MetaPost Bilder

Zu MetaPost gibt es ein eigenes Kapitel. Hier ist jedoch gezeigt, mit welchen Möglichkeiten diese Grafiken eingebunden werden können:

1. Als Bild mit der Endung `.mp`:

    <Image file="myfile.mp" />

2. Als textuelle Beschreibung mit dem Typ `metapost`:

    <Image width="7cm" imagetype="metapost">
        <Value>....</Value>
    </Image>

3. Als Referenz bei Seitentypen (AtPageCreation, AtPageShipout), bei Td und bei Boxen (Box).

Siehe auch das Kapitel über MetaPost sowie die MetaPost-Beispiele.

## Bildgröße und Auflösung PRO

Große Bilddateien erzeugen auch große PDF-Dateien, wenn sie eingebunden werden, unabhängig davon, wie breit und hoch sie im PDF dargestellt werden. Möchte man die Auflösung (und damit die Dateigröße) begrenzen, kann man dies mit der `dpi`-Option bei PDFOptions erreichen. DPI steht für Punkte pro Zoll (dots per inch) und ist eine Maßeinheit für die Pixeldichte. Je geringer die Zahl, desto »schlechter« sieht das Bild aus. Durch eine Begrenzung der Auflösung erhält man teilweise wesentlich kleinere Dateien.

Beispiel: soll ein Bild mit der Breite von 720 Pixeln auf einer Papierbreite von 1 Zoll (inch) dargestellt werden, wäre die Auflösung im PDF 720 dpi. In der Regel ist eine so hohe Auflösung nicht notwendig. Je nach Anwendungsfall (Druck/Onlinebetrachtung) kann z.B. eine Auflösung von 300 dpi oder 120 dpi ausreichend sein.

### Konfiguration des Resizehandlers

Zusätzlich zu den normalen `imagehandler`-Einträgen in der Konfigurationsdatei gibt es einen `resizehandler`, der die Bildgröße an die gewünschte DPI-Zahl anpasst. Wird der resizehandler nicht gesetzt, nutzt der Publisher eine eingebaute Bibliothek, die die Bildgröße ändert.

| Seit Version 5.9.2 kann die Größenänderung auch der Lua-Callback `resize_handler` übernehmen, der ohne Platzhalter auskommt, siehe Lua-Callbacks. Die unten beschriebene Einstellung `resizehandler` funktioniert weiterhin; ein registrierter Callback hat Vorrang.

Der resizehandler wird intern vom Publisher genutzt, wenn die Bildgröße anhand der `dpi`-Einstellung reduziert werden soll.

Die Definition funktioniert analog zu einem `imagehandler`, jedoch stehen die Platzhalter `%%width%%` und `%%height%%` für die automatisch ermittelte Zielgröße zur Verfügung. Der Benutzer gibt diese Werte nicht selbst an – sie werden vom Publisher anhand der Ausgabegröße und der eingestellten Auflösung (`dpi`) berechnet.

Beispiel mit ImageMagick:

    resizehandler="jpegimage:(magick %%input%% -resize %%width%%x%%height%%! %%output%%)"

In diesem Beispiel wird für JPEG-Dateien der Befehl `magick` (ImageMagick) aufgerufen, um das Bild intern auf die vom Publisher berechnete Größe herunterzuskalieren. Das Ausrufezeichen (`!`) erzwingt die exakte Zielgröße. Diese Mechanik stellt sicher, dass die Ausgabegröße und die gewünschte Auflösung eingehalten werden, ohne dass der Benutzer manuell eingreifen muss.

Wichtig ist, dass auch ein extensionhandler für die Dateiendung (im Beispiel `jpg` oder `jpeg`) gesetzt ist, damit der resizehandler auch genutzt wird.

## Vertikale Ausrichtung von Bildern im Absatz

Bilder können innerhalb eines `[Paragraph](/de/reference/commands/paragraph/)`-Elements inline platziert werden, zusammen mit Text oder anderen Bildern. Standardmäßig stehen alle Bilder auf der Textgrundlinie und ragen mit ihrer gesamten Höhe nach oben. Bei Bildern unterschiedlicher Höhe kann das ungleichmäßig aussehen.

Das Attribut `vertical-align` auf `[Image](/de/reference/commands/image/)` steuert, wie Bilder zueinander und zum Text ausgerichtet werden. Vier Modi stehen zur Verfügung:

### baseline (Standard)

Jedes Bild steht auf der Textgrundlinie. Höhere Bilder ragen weiter nach oben, niedrigere weniger weit. Die Oberkanten sind nicht ausgerichtet.

    <Paragraph>
        <Image width="1cm" file="_samplea.pdf" />
        <Image width="1cm" height="2cm" file="_sampleb.pdf" />
        <Value>Text</Value>
    </Paragraph>

### top

Alle Oberkanten liegen auf einer horizontalen Linie. Die Grundlinie verschiebt sich an die Unterkante des höchsten Bildes, sodass Text unten erscheint.

    <Paragraph>
        <Image width="1cm" file="_samplea.pdf" vertical-align="top" />
        <Image width="1cm" height="2cm" file="_sampleb.pdf" vertical-align="top" />
        <Value>Text</Value>
    </Paragraph>

### middle

Die vertikalen Mitten aller Bilder sind ausgerichtet. Die Grundlinie liegt auf halber Höhe des höchsten Bildes.

    <Paragraph>
        <Image width="1cm" file="_samplea.pdf" vertical-align="middle" />
        <Image width="1cm" height="2cm" file="_sampleb.pdf" vertical-align="middle" />
        <Value>Text</Value>
    </Paragraph>

### hanging

Jedes Bild hängt unterhalb der Textgrundlinie. Die Oberkante jedes Bildes liegt auf der Grundlinie und das Bild ragt nach unten. Das ist nützlich, wenn Text über einer Bildreihe stehen soll.

    <Paragraph>
        <Image width="1cm" file="_samplea.pdf" vertical-align="hanging" />
        <Image width="1cm" height="2cm" file="_sampleb.pdf" vertical-align="hanging" />
        <Value>Text</Value>
    </Paragraph>

| Das Attribut `vertical-align` wirkt nur, wenn Bilder inline in einem Absatz verwendet werden. Bei direkter Platzierung über `[PlaceObject](/de/reference/commands/placeobject/)` hat es keine Auswirkung.

## Weitere Parameter

- Man kann über die `padding-*`-Angaben festlegen, wie viel Abstand das Bild vom entsprechenden Rand haben soll.

- Mit `dpiwarn` kann eine Warnung herausgegeben werden, wenn die tatsächliche Anzahl der Pixel je Zoll geringer ist, als die Vorgabe.

#### Inhalt