Inhaltsverzeichnis:
Ghostscript-API einbinden und korrekt initialisieren
Für eine eigene Anwendung wird Ghostscript meist über die mehrfach aufrufbare DLL- oder Shared-Library-Schnittstelle eingebunden. Verwende nicht den Kommandozeilenprozess, wenn deine Anwendung mehrere Dokumente verarbeitet, Statuswerte direkt auswerten oder Ein- und Ausgaben selbst steuern soll. Die API trennt dabei die Bibliothek vom eigentlichen Interpreter-Lauf.
Installiere zunächst eine zur Anwendung passende Ghostscript-Version und Architektur. Eine 64-Bit-Anwendung benötigt in der Regel eine 64-Bit-Bibliothek; bei einer 32-Bit-Anwendung gilt dasselbe für 32 Bit. Unter Windows liegt die dynamische Bibliothek typischerweise als gsdll64.dll oder gsdll32.dll vor. Unter Linux und verwandten Systemen wird sie meist als libgs.so eingebunden. Der konkrete Dateiname kann je nach Paket und Version abweichen.
Nutze die Vorteile einer professionellen Partnerschaft im Bereich der Software-Programmierung. Unsere Experten stehen Dir mit ihrem technischen Know-how und ihrer langjährigen Erfahrung zur Seite.
Für C und C++ wird die öffentliche Header-Datei iapi.h benötigt. Beim Linken muss zusätzlich die Import- beziehungsweise Shared-Library angegeben werden. Bei einer dynamischen Laufzeitbindung lädt die Anwendung die Bibliothek erst zur Laufzeit. Das ist flexibler, verlangt aber eine saubere Prüfung des Ladefehlers:
- Bibliotheksdatei öffnen
- Symbol gsapi_new_instance auflösen
- Funktionszeiger auf die benötigten API-Funktionen setzen
- Versions- und Architekturverträglichkeit prüfen
Die zentrale Reihenfolge ist fest vorgegeben: Instanz erzeugen, Ein- und Ausgabe-Callbacks setzen, Initialisierung ausführen, Interpreter-Befehle verarbeiten, die Instanz beenden und zuletzt den Speicher freigeben. Übergebe eine Instanz nicht gleichzeitig an mehrere Threads. Erzeuge stattdessen pro parallelem Lauf eine eigene Instanz oder synchronisiere den Zugriff.
Ein minimales C-Grundgerüst sieht so aus:
#include "iapi.h"
int main(void) {
void *instance = NULL;
int code = gsapi_new_instance(&instance, NULL);
if (code < 0 || instance == NULL) {
return 1;
}
code = gsapi_init_with_args(instance, 1, NULL);
gsapi_exit(instance);
gsapi_delete_instance(instance);
return code < 0 ? 1 : 0;
}
In echtem Anwendungscode sollte gsapi_init_with_args mit einem gültigen Argumentvektor aufgerufen werden. Das erste Element ist konventionsgemäß der Programmname. Optionen wie -dSAFER, -dBATCH und -dNOPAUSE gehören in diesen Vektor, nicht in einen unkontrolliert zusammengesetzten Shell-Befehl. Jede Zeichenkette muss während des Aufrufs gültig bleiben, und der Vektor endet mit der korrekten Anzahl der Argumente.
Die Initialisierung liefert einen numerischen Statuscode. Werte kleiner als null weisen auf einen Fehler hin; positive Werte können einen besonderen Interpreterzustand anzeigen. Behandle deshalb nicht jeden Wert ungleich null automatisch als Erfolg oder Misserfolg. Für die genaue Bedeutung der Rückgabewerte ist die API-Dokumentation der verwendeten Ghostscript-Version maßgeblich.
Callbacks werden vor dem Interpreterstart registriert, wenn die Anwendung Eingaben aus dem Speicher lesen oder Ausgaben selbst speichern möchte. Dafür stehen unter anderem gsapi_set_stdio, gsapi_set_poll und gsapi_set_display_callback bereit. Ein Callback erhält den von der Anwendung gesetzten Benutzerzeiger. Nutze ihn für Zustände wie Puffer, Dateihandles oder Abbruchflags, statt globale Variablen einzusetzen.
Die verwendete Bibliotheksversion lässt sich über gsapi_revision abfragen. Prüfe damit beim Programmstart, ob die erwartete API-Version vorhanden ist. Unter Linux hilft zusätzlich ein Blick auf den dynamischen Bibliothekspfad; unter Windows sollte die Suchreihenfolge kontrolliert werden.
Für die Fehlersuche empfiehlt sich ein schmaler Initialisierungstest: Bibliothek laden, Version lesen, Instanz erzeugen, einen harmlosen Lauf starten und anschließend alle Ressourcen in umgekehrter Reihenfolge freigeben. Erst wenn dieser Pfad stabil funktioniert, lohnt sich die Integration eigener Callbacks und komplexer Geräteoptionen.
Wichtige Funktionen, Datenstrukturen und Rückgabewerte
Die Ghostscript-API besteht aus wenigen Kernfunktionen. Entscheidend ist, ihren Lebenszyklus und die Bedeutung der Statuscodes korrekt zu behandeln. Eine typische Anwendung arbeitet dabei mit einem undurchsichtigen Instanzzeiger, den sie nicht selbst interpretiert.
Wichtige Datenstrukturen
- void *instance: Handle auf eine laufende Ghostscript-Instanz. Der Inhalt bleibt für die Anwendung verborgen.
- char **argv: Argumentvektor für Interpreter-Optionen und Eingabedateien.
- gsapi_revision_t: Struktur für Versionsnummer, Produktname, Copyright-Text und Versionszeichenfolge.
- gs_main_instance: In älteren oder speziellen Integrationen verwendeter Instanztyp. Maßgeblich bleibt die Header-Datei der eingesetzten Version.
Die API verwendet für viele Übergaben einfache C-Typen. Zeichenketten sind normalerweise nullterminierte Bytefolgen. Eine Unicode-Konvertierung erfolgt nicht automatisch. Wer Dateinamen oder Optionen aus einer anderen Zeichencodierung übernimmt, muss diese vor dem API-Aufruf sauber umwandeln. Gerade bei Pfaden mit Umlauten entstehen sonst schwer lokalisierbare Fehler.
Funktionen für die Ablaufsteuerung
- gsapi_run_string_begin, gsapi_run_string_continue und gsapi_run_string_end führen PostScript in mehreren Teilen aus. Das eignet sich für Datenströme, die nicht vollständig im Speicher liegen.
- gsapi_run_string_with_length verarbeitet einen Puffer mit expliziter Länge. Binärdaten werden dadurch nicht fälschlich am ersten Nullbyte abgeschnitten.
- gsapi_run_file übergibt einen Dateinamen an den Interpreter. Der Aufruf ist praktisch, bindet die Anwendung aber stärker an das Dateisystem.
- gsapi_run_string verarbeitet einen nullterminierten Text. Für dynamisch erzeugte PostScript-Befehle ist die Längenvariante meist robuster.
Bei mehrteiliger Ausführung zählt der Rückgabewert jedes einzelnen Aufrufs. Ein Fehler im mittleren Teil darf nicht einfach ignoriert werden. Rufe danach den Abschluss der Sequenz auf, damit Ghostscript seinen internen Zustand ordnungsgemäß verlassen kann.
Rückgabewerte richtig einordnen
Ghostscript unterscheidet zwischen normalen Interpreterzuständen und Fehlern. Viele Fehlercodes sind negativ und werden in der Header-Datei als Konstanten definiert. Dazu zählen beispielsweise Fehler beim Öffnen einer Datei, ungültige PostScript-Syntax oder ein Abbruch durch die Anwendung. Vergleiche den Wert daher möglichst mit den dokumentierten Konstanten und nicht mit einer selbst erdachten Zahlenliste.
Ein besonderer Status ist gs_error_Quit. Er bedeutet nicht zwingend einen technischen Defekt. Er zeigt an, dass der PostScript-Code den Interpreter mit quit verlassen wollte. Anwendungen sollten diesen Zustand abhängig vom Einsatzzweck behandeln: Bei einem kontrollierten Skript kann er akzeptabel sein, bei einer streng geprüften Dokumentpipeline eher nicht.
Für interaktive oder schrittweise Läufe können außerdem Zustände wie gs_error_NeedInput auftreten. Sie signalisieren, dass weiterer Inhalt erwartet wird. Liefert der Callback danach keine Daten, muss die Anwendung den Lauf gezielt beenden, statt in einer Endlosschleife erneut denselben Aufruf zu starten.
Versionsinformationen auslesen
gsapi_revision schreibt die verfügbaren Versionsdaten in eine dafür vorgesehene Struktur. Übergib die erwartete Strukturgröße, damit die Bibliothek ihre ABI-Kompatibilität prüfen kann. Die Versionsnummer sollte protokolliert werden, wenn Ergebnisse reproduzierbar bleiben müssen. Unterschiede bei eingebetteten Fonts, Geräten oder Sicherheitsstandards können sich zwischen Ghostscript-Versionen sichtbar auswirken.
Ein nützliches Muster ist eine eigene Ergebnisstruktur, die neben dem API-Code auch Kontext speichert:
- betroffene Eingabedatei oder Datenquelle
- verwendeter Geräte- und Farbraum
- letzter erfolgreicher Verarbeitungsschritt
- exakter Rückgabewert
- gesammelte Meldungen aus dem Fehler-Callback
So bleibt ein Fehler auch dann verständlich, wenn mehrere Dokumente nacheinander verarbeitet werden. Wichtig ist die Trennung von technischer Ursache und fachlicher Bewertung: Ein ungültiger Dateipfad ist etwas anderes als ein gültiges PDF, dessen Inhalt nicht zum gewünschten Ausgabegerät passt.
Die API-Deklarationen und Fehlerkonstanten können sich zwischen Hauptversionen ändern. Verwende deshalb immer den Header, der zur geladenen Bibliothek gehört, und prüfe beim Build die passende Dokumentation. Eine scheinbar kleine Abweichung bei Strukturgrößen oder Funktionssignaturen kann sonst zu Abstürzen führen, obwohl der Quellcode zunächst korrekt aussieht.
PDF- und PostScript-Dateien per API verarbeiten
Die Verarbeitung startet mit einem klaren Datenfluss: Eingabedatei öffnen, Inhalt in den Ghostscript-Interpreter geben, ein Ausgabegerät wählen und das Ergebnis aus einem Zielstrom übernehmen. Bei PDF-Dateien übernimmt Ghostscript dabei die Interpretation von Seitenobjekten, Fonts, Transparenzen und eingebetteten Bildern. PostScript wird als Programmiersprache ausgeführt und kann deshalb neben Seitendaten auch Schleifen, Variablen und Operatoren enthalten.
Für eine Datei lässt sich der Lauf über den Interpreter-Operator run anstoßen. Der Dateiname muss dabei korrekt maskiert werden, besonders bei Leerzeichen, Klammern und Sonderzeichen. Robuster ist ein kontrollierter Datenstrom: Die Anwendung liest die Datei selbst und übergibt die Bytes über einen Eingabe-Callback. So bleibt der Zugriff auf erlaubte Quellen begrenzt, und ein Lauf lässt sich leichter abbrechen.
Bei PDF empfiehlt sich die Verwendung des passenden PDF-Interpreters mit einer expliziten Seitensteuerung. Soll nur ein bestimmter Bereich verarbeitet werden, setzt die Anwendung Optionen wie -dFirstPage=3 und -dLastPage=5. Das spart Zeit und Speicher, weil nicht jede Seite gerendert werden muss. Für eine gezielte Seite müssen beide Grenzen gesetzt werden; andernfalls kann eine bestehende Standardeinstellung unerwartete Seiten liefern.
Der Ausgabestrom hängt vom gewählten Gerät ab. Ein Bildgerät erzeugt beispielsweise Pixeldaten, während ein PDF-Gerät wieder eine PDF-Datei schreibt. Für den Speicherbetrieb wird häufig ein temporärer Ausgabepuffer verwendet. Die Callback-Funktion sammelt eingehende Blöcke, vergrößert den Puffer bei Bedarf und prüft dabei Überläufe vor jeder Addition:
- neue Blockgröße gegen den maximal erlaubten Speicher prüfen
- Gesamtgröße vor der Speicheranforderung berechnen
- bei fehlendem Speicher sofort einen Abbruchstatus zurückgeben
- erst nach erfolgreicher Vergrößerung neue Daten kopieren
Ein PDF-Lauf ist nicht automatisch ein reiner Konvertierungsvorgang. Das Ergebnis hängt stark vom Gerät und von den gesetzten Parametern ab. Ein Rastergerät wie png16m erzeugt RGB-Pixel. Ein geräteabhängiger PDF-Lauf kann dagegen Schriften, Vektoren und Bilder in einer neuen PDF-Struktur kombinieren. Für Druckdaten sind daher Auflösung, Farbraum und Seitengröße gemeinsam zu betrachten.
PostScript-Dateien benötigen eine andere Risikobewertung. Da der Inhalt ausführbare Operatoren enthält, darf eine Anwendung fremde Dateien nicht wie harmlose Dokumentdaten behandeln. Beschränke Dateizugriffe, aktiviere den sicheren Modus und erlaube nur die Ressourcen, die der konkrete Auftrag braucht. Ein scheinbar harmloser run-Operator kann sonst weitere Dateien laden oder externe Pfade ansprechen.
Ein typischer Ablauf für einen einzelnen Dokumentstrom ist:
- Quelldaten in kontrollierten Blöcken bereitstellen
- das gewünschte Gerät und die Ausgabeparameter setzen
- die PDF- oder PostScript-Daten an den Interpreter übergeben
- vollständige Ausgabe aus dem Ziel-Callback übernehmen
- Seitensichtbarkeit und Dateigröße des Ergebnisses prüfen
Bei großen PDFs sollte die Anwendung nicht voraussetzen, dass die gesamte Datei in den Arbeitsspeicher passt. Ein Dokument mit vielen hochauflösenden Bildern kann mehrere hundert Megabyte beanspruchen, obwohl die PDF-Datei selbst deutlich kleiner ist. Verarbeite daher möglichst seitenweise oder leite die Ausgabe direkt in eine Datei. Bei Rasterbildern ist zusätzlich die ungefähre Puffergröße relevant: 3.500 × 2.480 Pixel im RGB-Modus benötigen bereits rund 26 MB Rohdaten pro Seite, noch ohne Zusatzpuffer.
Wenn eine PDF-Seite Fehler enthält, kann Ghostscript je nach Fehlerart teilweise weiterarbeiten. Das ist für Vorschauen nützlich, für archivfähige Ergebnisse aber heikel. Unterscheide deshalb zwischen einem erzeugten Ergebnis und einem verlässlich vollständigen Ergebnis. Zähle verarbeitete Seiten, prüfe die erwartete Seitenspanne und vergleiche die Ausgabegröße mit einem plausiblen Mindestwert.
Für reproduzierbare Ergebnisse sollten Eingabe, Ghostscript-Version, Geräteauswahl und alle relevanten Optionen gemeinsam protokolliert werden. Schon eine andere Font-Konfiguration oder ein abweichender Farbraum kann das Ergebnis verändern. Bei PostScript kommt zusätzlich die Reihenfolge der Operatoren hinzu: Derselbe Inhalt kann bei anderer Initialisierung ein anderes Seitenbild erzeugen.
Eine API-Pipeline ist damit am stabilsten, wenn sie Quelle, Interpreterlauf und Ausgabe getrennt behandelt. Diese Trennung erleichtert Wiederholungen, begrenzt Speicherfehler und macht sichtbar, an welcher Stelle ein Dokumentlauf tatsächlich gescheitert ist.
Argumente, Optionen und Ausgabegeräte sicher setzen
Optionen werden bei Ghostscript als Argumentvektor an den Interpreter übergeben. Jede Option steht als eigene Zeichenkette. Baue daraus keinen einzigen Kommando-String. So vermeidest du Probleme mit Leerzeichen, Anführungszeichen und Shell-Regeln.
Ein sauberer Vektor enthält zuerst einen Programmnamen, danach die Schalter und zuletzt die Eingabedatei:
- argv[0]: frei wählbarer Programmname
- -dSAFER: eingeschränkter Zugriff auf Systemressourcen
- -dBATCH: Lauf nach der Verarbeitung beenden
- -dNOPAUSE: Seiten ohne Dialogpause verarbeiten
- -sDEVICE=...: Zielgerät auswählen
- -r...: Auflösung festlegen
- -sOutputFile=...: Ausgabepfad oder Ausgabemuster setzen
Schalter mit -d setzen meist eine boolesche oder numerische Definition. Mit -s wird eine Zeichenkette übergeben. Achte auf die genaue Schreibweise: -sDEVICE=png16m ist eine Gerätezuweisung, während -dSAFER eine Laufzeitoption aktiviert. Ein fehlendes Gleichheitszeichen kann dazu führen, dass Ghostscript die Option als unbekannten Dateinamen interpretiert.
Die Reihenfolge ist nicht bei jedem Parameter egal. Setze globale Optionen vor der Eingabedatei. Parameter, die Ghostscript während der Dokumentverarbeitung auswertet, gehören ebenfalls vor den eigentlichen Lauf. Seitenbegrenzungen, Skalierung und Farbraum sollten feststehen, bevor das erste Dokumentobjekt interpretiert wird.
Ausgabepfade müssen für das gewählte Gerät geeignet sein. Ein einzelner Dateiname reicht bei mehrseitigen Rasterausgaben oft nicht aus. Verwende dann ein Seitenschema wie seite-%03d.png. Das Platzhalterzeichen erzeugt fortlaufende Dateien. Bei einer PDF-Ausgabe ist dagegen meist ein einzelner Zielpfad sinnvoll.
Für Ausgaben im Speicher gibt es zwei praktikable Wege. Du kannst ein Gerät mit Dateiausgabe verwenden und die erzeugte Datei anschließend einlesen. Oder du leitest die Ausgabe über einen eigenen Callback in einen kontrollierten Puffer. Die zweite Variante spart temporäre Dateien, verlangt aber eine Begrenzung der maximalen Datenmenge.
Ein Ausgabegerät bestimmt nicht nur das Dateiformat. Es legt auch fest, wie Farben, Seitenränder, Transparenzen und Rasterdaten behandelt werden. Für typische Aufgaben kommen unter anderem diese Geräte infrage:
- png16m für farbige RGB-Rasterbilder
- pnggray für Graustufenbilder
- tiff24nc für unkomprimierte RGB-TIFF-Daten
- pdfwrite für die Erzeugung einer PDF-Ausgabe
- eps2write für gekapseltes PostScript
Wähle das Gerät nach dem Zielprozess. Eine Vorschau braucht meist ein Rastergerät. Eine drucknahe Weiterverarbeitung benötigt dagegen oft eine kontrollierte Auflösung, einen passenden Farbraum und ein Format, das Vektoren oder Schriften möglichst erhält.
Die Auflösung wird mit -r gesetzt, etwa -r150 für 150 dpi. Höhere Werte erhöhen die Detailtreue, aber auch Speicherbedarf und Laufzeit. Bei einer A4-Seite entstehen bei 300 dpi ungefähr 2.480 × 3.508 Pixel. Im RGB-Modus entspricht das rund 26 MB Rohdaten pro Seite, bevor das Ausgabegerät komprimiert.
Vermeide widersprüchliche Optionen. Ein Graustufengerät und eine erzwungene RGB-Ausgabe passen nicht zusammen. Ebenso kann ein Ausgabemuster ohne Seitennummer bei mehreren Seiten zu Überschreibungen führen. Prüfe daher vor dem API-Aufruf, ob Gerät, Dateiendung, Farbmodell und Zielpfad logisch zusammenpassen.
Übernimm Argumente niemals ungeprüft aus einer Webanfrage. Erlaube nur eine feste Auswahl von Geräten und Optionen. Werte wie Auflösung, Seitenbereich und Ausgabedatei sollten typgeprüft, begrenzt und anschließend in eigene Argumentzeichenketten umgewandelt werden. Pfade sind zu normalisieren; Ausgabedateien gehören in ein kontrolliertes Verzeichnis.
Ein gutes Konfigurationsmodell trennt feste Sicherheitsoptionen von variablen Auftragsdaten:
- unveränderliche Basisoptionen im Programmcode
- validierte Dokumentparameter in einer Auftragstruktur
- erst kurz vor dem API-Aufruf erzeugte Argumentzeichenketten
- Geräte- und Dateimuster aus einer Whitelist
Diese Trennung verhindert, dass ein Dateiname versehentlich als neue Option behandelt wird. Ein kleiner, strikt gebauter Argumentvektor ist deutlich belastbarer als eine flexible, aber schwer prüfbare Zeichenkette.
Beispiel: PDF in PNG-Bilder umwandeln
Für die Umwandlung einer PDF in PNG-Dateien wird ein Rastergerät ausgewählt und über die API mit einem vollständigen Argumentvektor gestartet. Das folgende C-Beispiel verarbeitet eine Datei mit zwei Seiten. Die erzeugten Bilder werden als seite-001.png, seite-002.png und so weiter gespeichert.
Die Funktion kapselt den gesamten Lauf. Sie verwendet feste Optionen und setzt den Dateinamen als eigenes Argument. Dadurch bleibt der Aufruf lesbar und die Anwendung muss keinen Shell-Befehl zusammensetzen.
Beispielcode:
#include
#include
#include "iapi.h"
int pdf_to_png(const char *input_path,
const char *output_pattern) {
void *instance = NULL;
char arg0[] = "gs";
char safer[] = "-dSAFER";
char batch[] = "-dBATCH";
char no_pause[] = "-dNOPAUSE";
char device[] = "-sDEVICE=png16m";
char resolution[] = "-r150";
char output[1024];
char input[1024];
char *argv[] = {
arg0,
safer,
batch,
no_pause,
device,
resolution,
output,
input,
NULL
};
if (snprintf(output, sizeof(output),
"-sOutputFile=%s", output_pattern)
>= (int)sizeof(output)) {
return -100;
}
if (snprintf(input, sizeof(input), "%s", input_path)
>= (int)sizeof(input)) {
return -101;
}
int code = gsapi_new_instance(&instance, NULL);
if (code < 0 || instance == NULL) {
return code;
}
code = gsapi_init_with_args(instance, 8, argv);
int exit_code = gsapi_exit(instance);
gsapi_delete_instance(instance);
if (code < 0) {
return code;
}
return exit_code < 0 ? exit_code : 0;
}
Der Aufruf kann beispielsweise so aussehen:
int result = pdf_to_png(
"rechnung.pdf",
"seite-%03d.png"
);
Das Muster %03d erzeugt eine dreistellige Seitennummer mit führenden Nullen. Bei einer PDF mit zwölf Seiten entstehen damit Dateien von seite-001.png bis seite-012.png. Verwende ein eindeutiges Zielverzeichnis, damit alte Bilder nicht mit dem aktuellen Lauf verwechselt werden.
Die Option -r150 steht für 150 dpi. Für Bildschirmvorschauen genügt dieser Wert oft. Für feinere Ausdrucke sind 300 dpi oder mehr üblich, doch der Speicherbedarf steigt quadratisch mit der Auflösung. Eine Verdopplung von 150 auf 300 dpi erzeugt daher ungefähr die vierfache Pixelzahl.
Prüfe nach dem Lauf nicht nur den API-Status. Zähle die tatsächlich erzeugten Dateien und kontrolliere, ob jede PNG-Datei eine plausible Größe besitzt. Eine leere oder ungewöhnlich kleine Datei deutet häufig auf einen abgebrochenen Lauf, einen fehlerhaften Seiteninhalt oder einen ungeeigneten Zielpfad hin.
Wenn nur einzelne Seiten benötigt werden, ergänzt du den Argumentvektor um -dFirstPage und -dLastPage. Beide Werte sollten aus Ganzzahlen bestehen und vor dem Aufruf auf einen sinnvollen Bereich geprüft werden. Für Seite 4 lautet die Kombination beispielsweise:
-dFirstPage=4
-dLastPage=4
Für transparente PDF-Flächen kann das Ergebnis je nach Ghostscript-Version und Geräteparametern vom ursprünglichen Erscheinungsbild abweichen. Teste deshalb besonders Logos, Schatten und halbtransparente Objekte. Wenn eine Anwendung einen Alphakanal benötigt, muss ein dafür geeignetes PNG-Gerät gewählt und die gewünschte Kanalbelegung separat geprüft werden.
Bei einer Bibliotheksintegration ohne Dateiausgabe ersetzt du -sOutputFile durch einen eigenen Ausgabestrom. Der Callback erhält dann die erzeugten PNG-Daten blockweise. Speichere diese Blöcke mit einer eigenen Seitenlogik, denn bei mehreren Seiten muss der Datenstrom an den jeweiligen Dateigrenzen korrekt getrennt werden. Für einen ersten stabilen Prototyp ist die Ausgabe in Dateien meist einfacher.
Der Code setzt bewusst eine feste Geräteauswahl voraus. In einer produktiven Funktion sollten Dateinamen, Auflösung und Seitenbereich vor dem Aufbau des Argumentvektors geprüft werden.
Beispiel: PDF mit benutzerdefinierter Auflösung erzeugen
Bei pdfwrite erzeugt Ghostscript eine neue PDF-Datei. Eine benutzerdefinierte Auflösung wirkt hier nicht wie bei einem reinen Rastergerät auf jede Seite. Sie beeinflusst vor allem die Berechnung gerasterter Inhalte, etwa Transparenzen, Schatten, Muster und eingebettete Pixelbilder. Vektorgrafiken bleiben grundsätzlich skalierbar.
Für diese Aufgabe wird die Auflösung als Argument in den API-Lauf aufgenommen. Das folgende Beispiel erzeugt eine PDF mit 144 dpi für gerasterte Seitenelemente:
Beispielhafte Argumente:
- -sDEVICE=pdfwrite
- -r144
- -dCompatibilityLevel=1.7
- -sOutputFile=ausgabe.pdf
Die Einstellung -r144 ist keine globale Skalierung. Eine Linie mit Vektorinformationen bleibt unabhängig davon scharf. Anders sieht es bei einem transparenten Objekt aus, das intern in Pixel umgewandelt werden muss. Dort bestimmt die Auflösung, wie fein dieses Zwischenbild berechnet wird.
Ein vollständiger Aufruf aus C kann so aufgebaut werden:
char a0[] = "gs";
char a1[] = "-dSAFER";
char a2[] = "-dBATCH";
char a3[] = "-dNOPAUSE";
char a4[] = "-sDEVICE=pdfwrite";
char a5[] = "-r144";
char a6[] = "-dCompatibilityLevel=1.7";
char a7[] = "-sOutputFile=neu.pdf";
char a8[] = "quelle.pdf";
Übergebe diese Zeichenketten als einzelne Einträge an gsapi_init_with_args. Die Anwendung sollte die gewünschte Auflösung vor dem Aufruf als Ganzzahl prüfen. Werte wie 0, negative Zahlen oder unrealistisch hohe Angaben gehören nicht in den Argumentvektor. Für viele Dokumente sind 72, 96, 144, 150 oder 300 dpi sinnvolle Ausgangspunkte; der passende Wert hängt vom Inhalt ab.
Die Dateigröße wird durch die Auflösung nicht automatisch kleiner. Ein eingebettetes Foto bleibt häufig nahezu unverändert, sofern keine zusätzliche Bildkompression oder Skalierung greift. Bei Transparenzgruppen kann eine höhere Einstellung dagegen deutlich mehr Daten erzeugen. Prüfe daher bei der Qualitätsermittlung sowohl sichtbare Detailtreue als auch resultierende Dateigröße.
Für eine gezielte Bildneuberechnung können zusätzliche Parameter wie -dDownsampleColorImages=true und -dColorImageResolution=144 verwendet werden. Diese Optionen betreffen Farbbilder und sind von der allgemeinen Geräteauflösung zu unterscheiden. Entsprechende Einstellungen gibt es auch für Graustufen- und monochrome Bilder:
- -dGrayImageResolution=144 für Graustufenbilder
- -dMonoImageResolution=300 für einfarbige Bilddaten
- -dColorImageDownsampleType=/Bicubic für eine weichere Neuberechnung
Solche Parameter greifen nur, wenn das jeweilige Downsampling aktiviert ist. Außerdem kann eine bereits stark komprimierte Quelle keine verlorenen Details zurückbringen. Eine höhere Zielauflösung macht daraus also kein schärferes Original, sondern höchstens ein größeres Ergebnis.
Für technische Zeichnungen oder kleine Schrift sollte die Anwendung mit mehreren Testwerten arbeiten. Vergleiche beispielsweise 96, 144 und 300 dpi anhand derselben Seite. Achte auf feine Linien, halbtransparente Flächen, eingebettete Bilder und die PDF-Größe. Eine pauschal maximale Auflösung ist meist unnötig und verlängert den Lauf.
Wenn die erzeugte PDF für Druck oder Archivierung bestimmt ist, sollte zusätzlich ein passendes Farbprofil- und Kompressionskonzept festgelegt werden. Die Auflösung allein definiert keine Druckqualität. Entscheidend ist das Zusammenspiel aus Vektoranteil, Bildauflösung, Farbraum, Transparenzverarbeitung und gewünschter PDF-Kompatibilität.
Die Option -dCompatibilityLevel sollte zur Zielsoftware passen. Ein älterer PDF-Viewer kann bei modernen Strukturen Probleme bereiten, während eine zu alte Kompatibilitätsstufe Funktionen oder Transparenzeffekte verändert. Teste das Ergebnis deshalb mit dem tatsächlich vorgesehenen Folgeprogramm.
Callbacks für Ein- und Ausgabe programmieren
Callbacks verbinden Ghostscript mit der Host-Anwendung. Sie liefern Eingabedaten, nehmen Ausgabebytes entgegen oder melden Interpreter-Meldungen, ohne dass Ghostscript selbst Dateien öffnen muss. Für jede Callback-Funktion wird ein Benutzerzeiger hinterlegt. Dieser Zeiger verweist meist auf eine eigene Struktur mit Puffer, Dateihandle und Abbruchstatus.
Die drei Standardfunktionen sind gsapi_set_stdio, gsapi_set_poll und gsapi_set_display_callback. Die ersten beiden eignen sich für Datenströme und Statusmeldungen. Der Display-Callback ist für gerenderte Seiten gedacht und liefert Informationen über Bildfläche, Format und Speicherzugriff.
Ein Eingabe-Callback hat die Aufgabe, bei Bedarf weitere Bytes bereitzustellen. Die Funktion sollte niemals mehr Daten melden, als tatsächlich im Puffer liegen. Ist das Ende erreicht, liefert sie null Bytes. Ein negatives Ergebnis signalisiert einen Abbruch oder einen Lesefehler.
Für die Ausgabe gilt das Gegenstück: Ghostscript übergibt einen Speicherbereich und dessen Länge. Der Callback kopiert diese Bytes in ein Zielobjekt. Prüfe vor jeder Kopie, ob die Addition aus bisheriger Länge und neuer Blockgröße ohne Überlauf möglich ist. Eine feste Obergrenze schützt vor unkontrolliertem Speicherwachstum.
- Benutzerzeiger auf eine klar definierte Zustandsstruktur setzen
- eingehende und ausgehende Blöcke mit ihrer exakten Länge behandeln
- bei Speicher- oder I/O-Fehlern sofort einen negativen Status liefern
- keine lang laufenden Aufgaben innerhalb des Callbacks starten
- den Callback-Zustand nach dem Lauf eindeutig freigeben
Ein kleiner Ausgabepuffer kann so aussehen:
typedef struct {
unsigned char *data;
size_t length;
size_t capacity;
int failed;
} OutputBuffer;
Die Schreibfunktion vergrößert den Speicher nur dann, wenn der freie Bereich nicht ausreicht. Verwende eine Wachstumsstrategie, etwa eine Verdopplung bis zu einem festgelegten Höchstwert. So entstehen nicht für jeden kleinen Block neue Speicheranforderungen. Bei großen PDF-Ausgaben lohnt sich außerdem die direkte Weiterleitung in eine geöffnete Datei.
Der Poll-Callback wird regelmäßig vom Interpreter abgefragt. Er eignet sich für einen Abbruchknopf, ein Zeitlimit oder eine einfache Fortschrittskontrolle. Die Funktion sollte sehr schnell antworten und keine Sperre abfragen, die von einem anderen Ghostscript-Callback gehalten wird. Sonst kann ein unscheinbarer Abbruch in einem Deadlock enden.
Für einen sicheren Abbruch speichert die Anwendung ein flüchtiges Flag, etwa cancel_requested. Der Poll-Callback prüft dieses Flag und meldet bei gesetztem Wert einen Abbruch. Das Ergebnis ist nicht immer sofort sichtbar, weil Ghostscript den Callback nur an bestimmten Interpreterstellen aufruft. Ein Zeitlimit muss daher zusätzlich außerhalb der Instanz überwacht werden.
Der Display-Callback arbeitet anders als ein Dateistream. Er beschreibt eine gerenderte Seite über eine Callback-Struktur mit Funktionen wie display_open, display_presize, display_size, display_page und display_close. Die Anwendung kann damit Pixel direkt in eine eigene Oberfläche, einen Bildpuffer oder eine nachgelagerte Bildverarbeitung leiten.
Bei display_page darf die Anwendung die übergebene Bildfläche nicht länger verwenden, als der Callback-Vertrag erlaubt. Benötigst du die Daten später, kopiere sie in einen eigenen Speicher. Beachte außerdem Zeilenabstand, Byte-Reihenfolge, Farbmodell und mögliche negative Zeilenstrides. Ein Bild, das gespiegelt oder farblich vertauscht erscheint, ist oft kein Ghostscript-Fehler, sondern eine falsch interpretierte Speicherzeile.
Der Benutzerzeiger sollte pro Instanz eindeutig sein. Globale Puffer sind bei parallelen Aufträgen eine schlechte Idee: Eine Seite kann dann im falschen Ziel landen, und die Ursache zeigt sich erst unter Last. Eine eigene Zustandsstruktur macht die Zuordnung transparent und erleichtert die Wiederverwendung.
Beim Registrieren eines Callbacks muss die zugehörige Struktur länger leben als der gesamte API-Lauf. Übergib niemals die Adresse einer lokalen Variable, wenn der Callback später noch aufgerufen werden kann. Nach dem Abschluss werden zuerst offene Ausgabekanäle geschlossen, danach temporäre Puffer freigegeben. Erst dann darf der Zustandszeiger verschwinden.
Für Tests sind künstliche Kurzströme besonders nützlich: Eingaben in 1-Byte-Blöcken, Ausgaben mit absichtlich kleinen Kapazitäten und ein Abbruchflag mitten während der Seitenausgabe. Damit werden Fehler sichtbar, die bei großen, zusammenhängenden Dateiblöcken gern verborgen bleiben.
Eine robuste Callback-Schicht trennt schließlich drei Dinge: Ghostscript-Status, Transportfehler und Anwendungsabbruch. Diese Zustände sollten intern getrennt gespeichert werden, auch wenn nach außen ein gemeinsamer Fehlercode genügt.
Fehler erkennen, Protokolle auswerten und Ressourcen freigeben
Eine belastbare Fehlerbehandlung wertet nicht nur den abschließenden Rückgabewert aus. Ghostscript kann bereits während eines Laufs Meldungen ausgeben, die für die Diagnose wichtiger sind als der spätere Abbruchcode. Trenne deshalb mindestens drei Ebenen: API-Fehler, Interpreter-Meldung und Fehler der eigenen Ein-/Ausgabe.
Registriere für Standardausgabe und Standardfehler eigene Funktionen. Speichere jede Meldung zunächst mit ihrer Quelle und einem Zeitstempel. Eine kurze interne Struktur genügt:
- Schweregrad oder Nachrichtenkanal
- Text der Meldung
- Auftrags- und Dokumentkennung
- aktueller Verarbeitungsschritt
- Rückgabewert des letzten API-Aufrufs
Vermeide dabei, vollständige Dokumentinhalte oder vertrauliche Pfade unkontrolliert in das Protokoll zu schreiben. Begrenze die maximale Meldungslänge und ersetze Steuerzeichen, damit ein Eingabedokument nicht selbst die Logdatei manipuliert.
Eine einzelne Warnung ist nicht automatisch ein fehlgeschlagener Lauf. Ghostscript kann ein Dokument trotz fehlender Schrift oder beschädigter Ressource teilweise verarbeiten. Für die fachliche Bewertung braucht die Anwendung daher eigene Kriterien: Wurde jede erwartete Seite erzeugt? Ist die Ausgabedatei lesbar? Trat ein schwerer Interpreterfehler auf? Erst aus dieser Kombination entsteht ein verlässlicher Auftragsstatus.
Für die Diagnose empfiehlt sich eine kleine Fehlerklassifikation:
- Konfigurationsfehler: ungültiges Gerät, fehlende Option oder inkompatible Einstellung
- Quelldatenfehler: beschädigte PDF-, PostScript- oder Fontdaten
- Ressourcenfehler: fehlender Speicher, volle Festplatte oder zu viele offene Handles
- Abbruch: manueller Stopp, Zeitlimit oder ausgelöster Poll-Status
- Transportfehler: fehlgeschlagene Callback-Lese- oder Schreiboperation
Ein Protokoll sollte den Fehler an der Stelle erfassen, an der er entsteht. Schreibe also nicht erst am Ende pauschal „Konvertierung fehlgeschlagen“. Speichere zusätzlich den Namen der API-Funktion, die Seitenzahl, soweit bekannt, und den betroffenen Ausgabekanal. Dadurch lässt sich unterscheiden, ob der Interpreter scheiterte oder die Anwendung die erzeugten Bytes nicht mehr ablegen konnte.
Ressourcen werden in umgekehrter Reihenfolge ihrer Erzeugung freigegeben. Schließe zuerst eigene Datei- und Datenströme, entferne danach Callback-Zustände und temporäre Puffer, beende anschließend den Interpreter und lösche zuletzt die Instanz. Jeder Freigabeschritt muss auch nach einem Fehler ausgeführt werden.
In C bietet sich dafür ein gemeinsamer Aufräumpfad an. Mehrere frühe return-Anweisungen sind riskant, weil sie leicht einen Puffer oder ein Handle überspringen. Ein Fehlerstatus wird gesammelt, danach läuft die Freigabe zentral ab. Bei C++ kann ein RAII-Wrapper diese Aufgabe übernehmen, sofern sein Destruktor keine weiteren Interpreteraufrufe benötigt.
Behandle gsapi_exit nicht als Ersatz für die Freigabe eigener Ressourcen. Die Funktion beendet den Interpreterzustand, schließt aber nicht automatisch jeden von der Host-Anwendung geöffneten Stream und repariert auch keinen unvollständigen Ausgabepuffer.
Für wiederholte Aufträge sollte nach jedem Lauf geprüft werden, ob Speicherverbrauch, Handle-Anzahl und Pufferkapazität wieder auf den erwarteten Ausgangswert sinken. Ein einzelner Lauf kann erfolgreich sein, während hundert Läufe wegen einer kleinen Leckage langsam scheitern.
Protokolliere technische Details in strukturierter Form, etwa als JSON oder als klar getrennte Logfelder. Eine Meldung wie „PDF konnte nicht verarbeitet werden“ hilft kaum. Aussagekräftiger sind Fehlercode, Ghostscript-Version, Funktionsname, Dokumentkennung und die Anzahl bereits abgeschlossener Seiten. Produktionslogs sollten außerdem keine vollständigen Argumente enthalten, wenn darin sensible Pfade oder externe Eingabewerte stehen.
Beim Testen gehören absichtlich fehlerhafte Fälle zum Pflichtprogramm: leere Eingaben, abgeschnittene Dateien, fehlende Fonts, volle Zielverzeichnisse, Schreibfehler im Callback und ein Abbruch während der Ausgabe. Ein guter Test prüft nicht nur den Fehlerstatus, sondern auch, ob keine beschädigte Zieldatei als gültiges Ergebnis zurückbleibt.
Speicherverwaltung, Sicherheit und typische API-Fehler
Die Speicherverwaltung beginnt mit klaren Besitzregeln. Ghostscript verwaltet seine internen Objekte selbst. Die Anwendung darf deshalb keine internen Zeiger verändern, nach dem Lauf weiterverwenden oder eigenständig freigeben. Umgekehrt bleiben eigene Puffer, Dateihandles und Konfigurationsstrukturen vollständig in der Verantwortung des Host-Programms.
Besonders kritisch sind Zeiger auf Argumentzeichenketten und Callback-Daten. Sie müssen während der gesamten Nutzung gültig bleiben. Ein temporär erzeugter String, der vor dem eigentlichen API-Aufruf verschwindet, führt zu undefiniertem Verhalten. Halte solche Werte in einer Auftragsstruktur oder in Speicherbereichen mit klar begrenzter Lebensdauer.
- Kapazitäten immer mit size_t berechnen
- Multiplikationen vor der Speicheranforderung auf Überlauf prüfen
- Maximalgrößen für Eingabe, Ausgabe und Zwischenpuffer festlegen
- bei fehlendem Speicher kontrolliert abbrechen
- bereits reservierten Speicher auch bei Teilfehlern freigeben
Bei Rasterausgaben wächst der Bedarf schnell. Eine RGB-Seite mit 2.480 × 3.508 Pixeln benötigt unkomprimiert etwa 26 MiB. Vier Seiten dieser Größe können also bereits mehr als 100 MiB belegen, wenn sie gleichzeitig gehalten werden. Verarbeite große Dokumente deshalb möglichst in einem begrenzten Seitenfenster und gib fertige Bildpuffer sofort weiter.
Sicherheit erfordert eine restriktive Laufzeitumgebung. Aktiviere den sicheren Modus über die passende Ghostscript-Option und erlaube nur Ressourcen, die der konkrete Auftrag benötigt. Ein PostScript-Dokument kann Operatoren enthalten, die Dateien öffnen, externe Ressourcen laden oder Programme beeinflussen. Behandle daher auch scheinbar harmlose PDF-Dateien als potenziell fehlerhafte Eingaben.
Zusätzliche Schutzschichten gehören außerhalb der API dazu:
- separates Betriebssystemkonto mit minimalen Rechten
- eigenes Arbeitsverzeichnis ohne vertrauliche Dateien
- Schreibzugriff nur auf ein kontrolliertes Zielverzeichnis
- Zeit- und Speicherlimit für jeden Auftrag
- Begrenzung der maximalen Seitenzahl und Dateigröße
- keine Weitergabe ungeprüfter Optionen aus externen Eingaben
Vertraue nicht allein auf den Dateinamen. Ein Pfad wie ../ziel.pdf kann aus einem erlaubten Verzeichnis herausführen, sofern er nicht normalisiert und geprüft wird. Verwende nach Möglichkeit intern erzeugte Zielnamen und übergib keine vom Nutzer gelieferten Pfadbestandteile direkt an die Bibliothek.
Ein häufiger API-Fehler ist die falsche Funktionssignatur. Header-Datei und dynamisch geladene Bibliothek müssen zur selben ABI passen. Werden Funktionszeiger mit einem unpassenden Typ aufgerufen, kann das Programm bereits bei scheinbar einfachen Läufen abstürzen. Prüfe deshalb Bibliotheksdatei, Architektur, Compiler-Konvention und verwendete Header gemeinsam.
Auch eine falsche Argumentanzahl verursacht merkwürdige Resultate. Der Vektor muss genau so viele gültige Einträge enthalten, wie der Zähler angibt. Ein zusätzliches NULL beendet den Vektor, wird aber nicht als normales Argument mitgezählt. Ein zu kleiner Zähler kann Optionen verschlucken; ein zu großer Wert liest hinter das Ende des Arrays.
Typische Fehler entstehen außerdem durch:
- Wiederverwendung einer beendeten Instanz
- gleichzeitige Aufrufe auf derselben Instanz aus mehreren Threads
- Freigabe eines Callback-Kontexts vor dem letzten Rückruf
- Verwendung eines bereits geschlossenen Ausgabestreams
- fehlende Prüfung von Integer- und Größenüberläufen
- Ausführung mit einer nicht unterstützten Gerätebezeichnung
Für parallele Verarbeitung sollte jeder Auftrag seinen eigenen Zustand, seine eigenen Puffer und eine eigene Ghostscript-Instanz erhalten. Gemeinsame globale Variablen machen Fehler schwer reproduzierbar und erhöhen das Risiko von Datenvermischung. Eine zentrale Gerätekonfiguration darf geteilt werden, sofern sie nach dem Start nicht mehr verändert wird.
Ein Auftrag sollte nach einem Abbruch als verbraucht gelten. Starte nicht einfach denselben Interpreterzustand erneut, wenn bereits ein schwerer Fehler aufgetreten ist. Erzeuge für den Wiederholungsversuch eine frische Instanz und verwerfe unvollständige Ausgabedateien. Das verhindert, dass interner Zustand oder beschädigte Teilergebnisse in den nächsten Lauf gelangen.
Halte die eingesetzte Ghostscript-Version aktuell und prüfe deren Sicherheitsmeldungen vor einem produktiven Rollout. Die offizielle Projektdokumentation und die jeweiligen Versionshinweise sind dafür die maßgeblichen Quellen: Ghostscript-Dokumentation. Für sicherheitskritische Anwendungen gehört außerdem ein reproduzierbarer Test mit begrenzten Ressourcen zum Freigabeprozess.
Fazit: API-Aufruf testen und produktiv einsetzen
Ein produktiver Ghostscript-API-Aufruf ist erst dann bereit, wenn nicht nur ein einzelnes Beispieldokument funktioniert. Entscheidend ist ein wiederholbarer Prüfablauf, der technische Ergebnisse, Laufzeitverhalten und fachliche Anforderungen gemeinsam bewertet.
Baue dafür eine kleine Referenzsammlung auf. Sie sollte typische Dokumente, absichtlich beschädigte Dateien, Sonderzeichen in Texten, eingebettete Schriften, Transparenzen und mehrseitige Inhalte enthalten. Vergleiche die Ergebnisse nach jeder Änderung mit freigegebenen Referenzdateien oder festgelegten Bildmerkmalen.
- Ergebnisformat und Seitenanzahl prüfen
- Abmessungen, Farbraum und Auflösung vergleichen
- Textpositionen und sichtbare Schriften kontrollieren
- Ausgabedateien auf Lesbarkeit und Vollständigkeit testen
- Laufzeit und Speicherbedarf unter realistischen Bedingungen messen
Für Rasterbilder ist ein Pixelvergleich nützlich, aber nicht immer ausreichend. Kompression, Farbprofile und Rundungen können kleine Abweichungen verursachen. Verwende deshalb je nach Ziel eine Toleranzprüfung, etwa für die mittlere Farbabweichung, und ergänze sie durch eine visuelle Kontrolle kritischer Seiten.
Ein Lasttest sollte mehrere Dokumente hintereinander und parallele Aufträge abbilden. Miss dabei Durchsatz, Spitzenverbrauch und Fehlerquote. Ein erfolgreicher Einzeltest sagt wenig über einen Dienst aus, der acht Stunden lang PDFs verarbeitet. Erst ein längerer Lauf zeigt, ob Ressourcen, Dateinamen und Zustandsdaten sauber getrennt bleiben.
Lege vor dem produktiven Einsatz einen klaren Freigabepunkt fest. Dazu gehören die getestete Ghostscript-Version, Compiler- und Plattformdaten, erlaubte Geräte sowie die erwarteten Rückgabewerte. Änderungen an einer dieser Komponenten sollten einen erneuten Regressionstest auslösen.
Die API-Schicht sollte außerdem eine kleine, stabile Abstraktion anbieten. Anwendungscode muss nicht überall Argumentvektoren, Callback-Zustände und Freigabepfade kennen. Eine zentrale Konvertierungsfunktion mit klaren Eingabe- und Ergebnisobjekten reduziert Fehler und macht spätere Versionswechsel überschaubar.
Für den Betrieb sind messbare Kennzahlen hilfreich. Erfasse etwa Verarbeitungsdauer pro Seite, Größe der Eingabe und Ausgabe, Abbruchrate sowie die häufigsten Fehlerklassen. Daraus wird schnell sichtbar, ob ein Problem an bestimmten Dokumenttypen, Geräten oder Größenordnungen hängt.
Aktualisiere die Bibliothek nicht blind, aber auch nicht erst nach einem Zwischenfall. Lies die offiziellen Versionshinweise, führe den Referenzsatz aus und prüfe besonders Sicherheitsoptionen, Geräteverhalten und PDF-Kompatibilität. Die technische Dokumentation ist unter ghostscript.readthedocs.io verfügbar.
Die wichtigste praktische Regel lautet: Ein API-Aufruf ist dann produktionsfähig, wenn sein Verhalten messbar, sein Fehlerweg definiert und sein Ergebnis reproduzierbar ist. Mit einem begrenzten Funktionsumfang starten, reale Dokumente testen und erst danach weitere Geräte oder Sonderoptionen ergänzen – das ist meist der kürzeste Weg zu einer stabilen Integration.
Häufige Fragen zur Ghostscript-API
Wie wird die Ghostscript-API in eine Anwendung eingebunden?
Die Ghostscript-API wird meist über eine DLL oder Shared Library eingebunden. Für C und C++ werden die Header-Datei iapi.h sowie die passende Bibliothek benötigt. Der typische Ablauf besteht aus dem Erzeugen einer Instanz, dem Setzen optionaler Callbacks, der Initialisierung mit gsapi_init_with_args, der Verarbeitung und anschließendem Beenden und Freigeben der Instanz.
Wie lassen sich PDF- und PostScript-Dateien mit Ghostscript verarbeiten?
Die Anwendung übergibt die Datei entweder über einen kontrollierten Dateilauf oder über eigene Eingabe-Callbacks an den Ghostscript-Interpreter. Über Optionen wie -sDEVICE, -sOutputFile, -r, -dFirstPage und -dLastPage werden Ausgabegerät, Ziel, Auflösung und Seitenbereich festgelegt. PDF-Dateien werden interpretiert, während PostScript als ausführbarer Dokumentcode behandelt werden muss.
Wie kann eine PDF mit der Ghostscript-API in PNG-Bilder umgewandelt werden?
Wähle das Rastergerät -sDEVICE=png16m, setze eine geeignete Auflösung wie -r150 und definiere mit -sOutputFile=seite-%03d.png ein Seitendateimuster. Ergänze -dBATCH, -dNOPAUSE und -dSAFER. Nach dem API-Lauf sollten die erzeugten Dateien, ihre Größe und die erwartete Seitenanzahl geprüft werden.
Welche Bedeutung haben Callbacks und Rückgabewerte?
Callbacks ermöglichen die kontrollierte Ein- und Ausgabe von Daten sowie Abbruch- und Fortschrittsmeldungen. Dafür werden unter anderem gsapi_set_stdio, gsapi_set_poll und gsapi_set_display_callback verwendet. Negative Rückgabewerte weisen in der Regel auf Fehler hin; spezielle Zustände wie gs_error_Quit oder gs_error_NeedInput müssen entsprechend ihrem Kontext bewertet werden.
Was ist bei Sicherheit und Speicherverwaltung zu beachten?
Aktiviere den sicheren Modus, validiere alle externen Optionen und beschränke Dateizugriffe, Arbeitsverzeichnisse, Seitenzahlen, Laufzeit und Speicherverbrauch. Callback-Puffer müssen auf Überläufe geprüft und begrenzt werden. Jede parallele Verarbeitung sollte eine eigene Instanz und einen eigenen Zustand verwenden. Nach Fehlern sind unvollständige Ausgabedateien zu verwerfen und alle Ressourcen zuverlässig freizugeben.




