Die Welt des Druckens unter Linux und Unix-artigen Betriebssystemen wird größtenteils von CUPS, dem Common Unix Printing System, geprägt. Für viele Anwender läuft Druck in der Regel ohne größere Problem ab, da standardisierte Treiber die Kommunikation mit gängigen Druckern übernehmen. Doch was passiert, wenn man einen spezialisierten Drucker besitzt, für den kein nativer Treiber für Linux verfügbar ist oder die vorhandenen Treiber veraltet bzw. schlecht gepflegt sind? Genau dort setzt die Möglichkeit an, einen eigenen CUPS-Druckertreiber zu entwickeln. In diesem Beitrag schauen wir uns an, wie man mit rund 100 Zeilen Python-Code einen voll funktionsfähigen CUPS-Filter erstellt, der etwa einen Thermoticketdrucker ansteuert, der das originale Druckprotokoll FGL („Friendly Ghost Language“) versteht.
Dabei werden praktische Schritte erläutert, die von der Verarbeitung eingehender Druckaufträge bis zur Umwandlung in druckbare Befehle für den Drucker führen. Ein aufschlussreicher Einblick in ein vergleichsweise unterschätztes Thema der Druckerentwicklung, der besonders Entwickler, Systemadministratoren und Anwender mit spezialisierten Druckanforderungen ansprechen wird. Die Herausforderung bei spezialisierten Druckern Für viele Standarddrucker existieren Treiberpakete, die out-of-the-box unter Linux als fertige Pakete in den gängigen Distributionen angeboten werden. Gedruckte Dokumente werden meist als PDF, PostScript oder Rasterdaten an den Druckserver übermittelt, der sie dann mit passenden Konvertern aufbereitet. Die Schwierigkeit besteht insbesondere dann, wenn man einen Drucker besitzt, der ausschließlich proprietäre Sprachen oder Spezialprotokolle versteht, wie etwa FGL bei Ticketsystemen.
Gerade im Bereich von Thermoticketdruckern oder Event-Ticketdruckern sind viele Modelle nur mit Windows-Treibern ausgestattet, die unter Linux nicht nutzbar sind. Die vorhandenen Alternativen sind oft unflexibel, schlecht dokumentiert oder verfügen nicht über eine offene Schnittstelle, was die Nutzung im Linux-Umfeld erschwert. Genau hier ist Eigeninitiative gefragt – die Entwicklung eines eigenen CUPS-Filters, der als Schnittstelle zwischen der vom System gelieferten Rasterausgabe und der spezifischen Sprache des Druckers agiert. Dies ermöglicht nicht nur maßgeschneiderte Anpassungen, sondern auch eine langfristige Wartbarkeit und Kostenersparnis gegenüber proprietären Lösungen. CUPS und die Struktur von Druckertreibern CUPS basiert auf einem modularen Konzept, bei dem Filterprogramme eine entscheidende Rolle spielen.
Ein Filter nimmt die einströmenden Druckdaten entgegen, verarbeitet sie und übergibt sie in einem für den Drucker verständlichen Format weiter. Für unseren Anwendungsfall erfassen wir die Druckdaten im sogenannten CUPS-Rasterformat Version 3, welches präzise Pixelinformationen enthält – genau das, was ein Bild in Graustufen oder Farbe repräsentiert. Der Filter fungiert somit als Übersetzer, der aus diesen Rasterdaten druckerspezifische Befehle formt. Dieses Vorgehen ist universell einsetzbar, solange man versteht, wie der Drucker Daten entgegen nimmt. Im Fall von FGL sind das einfache ASCII-Befehle, mit denen Druckpositionen gesetzt, Grafiken übertragen und Schnittbefehle ausgeführt werden können.
Warum Python als Programmiersprache? Traditionell werden CUPS-Filter häufig in C programmiert. Dies ergibt Sinn für maximale Performance, die in seriösen Drucksystemen auch wichtig ist. Doch für kleinere, speziell angepasste Treiber kann Python eine überzeugende Alternative sein. Python liest und verarbeitet Data Streams bequem, bietet eine große Standardbibliothek und ermöglicht schnelle Entwicklung. Zudem entfällt der Aufwand des Cross-Compilings auf unterschiedliche Architekturen.
So lässt sich ein Python-basierter Filter leicht auf Systemen wie dem Raspberry Pi einsetzen, was gerade bei Drucklösungen mit speziellen Thermoticketdruckern häufig gewünscht ist. Das Herzstück: Lesen und Verstehen des CUPS-Rasterformats Der erste technische Schritt besteht darin, die vom Drucksystem gelieferten Daten korrekt einzulesen und in eine strukturierte Form zu überführen. Dies gelingt mit Hilfe des Python-Moduls struct, das Binärdaten in Python-Objekte umwandelt. Es ist wichtig zu verstehen, dass das Rasterformat neben den Bilddaten umfangreiche Metadaten enthält – etwa Informationen zur Druckausgabe, Auflösung sowie Papierformat. Zur übersichtlichen Verarbeitung nutzt man eine Namedtuple-Struktur, die alle relevanten Header-Daten zusammenfasst und das Handling vereinfacht.
Anschließend liest man mithilfe der Header-Informationen die eigentlichen Bilddaten ein. Dadurch verrät uns der erste Teil des Treibers präzise, wie das aktuelle Druckbild aussieht, wie groß es ist, wie viele Farbkanäle existieren und wie die Daten auszulesen sind. Damit schaffen wir eine stabile Basis für die spätere Umwandlung in die Drucksprache des Druckers. Bilder verarbeiten und in druckbare Befehle verwandeln Da unser Ziel ein Thermoticketdrucker ist, der nur Schwarzweiß-Pixel unterstützt, muss die ursprüngliche Graustufendarstellung in ein binäres Bild umgewandelt werden. Genau an dieser Stelle kommt die Python-Bibliothek Pillow ins Spiel, die erweiterte Bildbearbeitung ermöglicht.
Mit ihrem Hilfsmittelset lassen sich Bilder laden, drehen, konvertieren und dithered (also mit Musterung gefärbt) aussgeben – um so einen möglichst exakten Schwarzweißausdruck zu erzielen. Anschließend wird die Pixelmatrix in sogenannte FGL-Grafikblöcke zerlegt, die in 8-Pixel-Höhe Kommandos bilden. Diese speziellen Byteserien werden über das ASCII-Protokoll an den Drucker gesendet. Der Clou ist, dass sich Zeile für Zeile überprüft wird, ob der Pixelblock mindestens einen schwarzen Punkt enthält. Nur dann folgt die Ausgabe, was sowohl Effizienz erhöht als auch das Material schont.
Die finale Feinjustierung Neben der reinen Bildausgabe ist die Ansteuerung der eingebauten Cutter-Funktion essenziell. Denn die meisten Thermoticketdrucker verfügen über automatische Schneidemechanismen, die per Befehl ein- oder ausgeschaltet werden können. Der Filter bezieht für diese Entscheidung die vom CUPS-Kernel übergebenen Optionen mit ein. So wird entschieden, ob ein Schnitt nach jedem Ticket, nach dem kompletten Druckjob oder gar nicht ausgeführt wird, was über definierte CUPS-Variablen gesteuert wird. Hier zeigt sich die Stärke der selbstgebauten Lösung, da genau auf Anforderungen und Gegebenheiten des Druckprozesses eingegangen werden kann, ohne auf Hersteller-Vorgaben angewiesen zu sein.
Die PPD-Datei – Schlüssel zur Benutzerkonfiguration Ein Druckertreiber besteht nicht nur aus einem Filterprogramm, sondern benötigt außerdem eine PPD-Datei (PostScript Printer Description). Diese beschreibt dem Drucksystem, wie der Drucker konfiguriert werden kann und welche Optionen zur Verfügung stehen. Da PPD-Dateien komplex sind und das Schreiben per Hand mühsam ist, bietet CUPS das Tool ppdc an, mit dem man aus einfacheren DRV-Dateien PPDs generieren kann. Im Fall des ITL-2003-Ticketdruckers umfasst die PPD neben den Druckerbezeichnungen auch die Angabe des benutzten Filters. Darüber hinaus werden die unterstützten Papierformate definiert.
Besonders wichtig ist die Erwähnung des Farbmodells, der Druckauflösung und der optionalen Cutter-Einstellungen. Dadurch kann der User bequem im Druckdialog den gewünschten Zuschnittmodus wählen. Erfahrungen und Herausforderungen Die Entwicklung eines eigenen Druckertreibers ist ein lohnendes Projekt, das vielen Anwendern Spezialdrucker unter Linux zugänglich macht. Im genannten Beispiel entstanden in einem halben Tag ein zuverlässiger Filter mit knapp 100 Zeilen Python sowie die entsprechende PPD-Datei. Der handliche Treiber wurde erfolgreich unter Arch Linux und Debian als Paket erstellt und konnte reibungslos diverse Testdrucke ausspielen.
Trotz der Einfachheit sind noch Grenzen und Herausforderungen zu berücksichtigen. So traten in bestimmten Szenarien, etwa beim Drucken aus GTK-basierten PDF-Viewern, unerwartete Ausfälle auf. Der Grund dafür liegt wahrscheinlich in Unterschieden der Datenströme, die an den Filter gesendet werden, was weitere Debugging- und Testarbeit erfordert. Für Entwickler bietet es sich somit an, den Filter schrittweise zu erweitern und weitere Druckanwendungen abzuprüfen. Gleichzeitig zeigen diese Einschränkungen die Komplexität moderner Drucksysteme und die Stärken individualisierter Lösungen auf.
Ausblick und praktische Tipps Wer einen eigenen Druckertreiber entwickeln möchte, sollte sich in die CUPS-Dokumentation und besonders in die Architektur von Filtern vertiefen. Python ist eine ausgezeichnete Wahl für schnelle Prototypen und kleine, spezialisierte Filter. Für komplexere Aufgaben oder höhere Performance empfiehlt sich eventuell eine Implementierung in C oder C++. Hilfreich ist auch die umfangreiche Nutzung von vorhandenen Bibliotheken zur Bildverarbeitung und die Automatierung von PPD-Erzeugung mit ppdc. Das bietet eine stabile Grundlage, die eigene Hardware gezielt im Linux-Umfeld zum Drucken zu bringen.
Der Open-Source-Gedanke hilft dabei, langfristig Wartbarkeit und Anpassbarkeit zu gewährleisten. Abschließend kann das Schreiben eines individuellen CUPS-Treibers nicht nur technische Grenzen überwinden, sondern auch für mehr Unabhängigkeit von Herstellerzwängen sorgen. Besonders in Nischen wie Eventticketdruck oder spezialisierten Thermodruckern beseitigt es Hindernisse beim Einsatz unter freien Betriebssystemen und öffnet die Tür zu kreativen Drucklösungen. Wer sich auf dieses kleine Abenteuer einlässt, erwirbt wertvolle Kenntnisse, die in vielen IT-Bereichen Anwendung finden können.