Die Idee hinter jSingleColorPNG
Statt jedes Mal den Weg über Zeichenfläche und Speichern zu gehen, habe ich mir mal das PNG-Dateiformat angesehen. Dieses Format
kann lizenzfrei implementiert werden und die Spezifikation wird vom W3C verwaltet.
Kleiner Exkurs: das PNG-Dateiformat
PNG vereint die Vorzeile von JPEG und GIF: es werden bis zu 16,7 Millionen Farben (vgl. JPEG) sowie Transparenz (vgl. GIF) unterstützt.
Die Daten werden dabei verlustfrei gespeichert, und trotzdem können die Dateien recht klein gehalten werden. Für mehr Details
empfehle ich das Studium der entsprechenden W3C-Spezifikation.
In einer PNG-Datei können sich u.a. ein Header, eine Farbpalette, die Deflate-komprimierten Daten sowie ein Abschlussbereich befinden.
Die Idee: Erzeugen der Binärdaten von PNG statt Nutzung einer Zeichenfläche
Zunächst wird der Header geschrieben, in dem Größenangabe, Farbtiefe und der Verweis auf die Nutzung einer Farbpalette stehen.
Die Farbtiefe wird auf 1 Bit gesetzt, denn unser Bild wird nur aus zwei Farben bestehen: dem Hintergrund sowie der Vordergrundfarbe.
In der darauf folgenden Palette wird diese Farbe als RGB-Wert hinterlegt.
Schliesslich folgen Deflate-komprimiert die Bilddaten. Dabei werden nur Nullen geschrieben, denn in der Palette steht im Index 0 die Farbe,
die wir verwenden möchten. Die Pixel "laufen" dabei zeilenweise von links nach rechts, aufgrund der 1-Bit-Farbtiefe
8 Pixel pro Byte. Pro Zeile wird noch ein Byte für einen Filter eingefügt, der aber auch 0 ist, da er nicht verwendet wird.
Das Ende der Datei bildet ein fester Abschlussblock.
Jeder dieser vier Blöcke hat enthält neben dem jeweiligen Typ, der Länge und den Nutzdaten auch noch eine CRC16-Prüfsumme.
Das Ergebnis
Aus dem Aufruf von MiniPngCreator.createSingleColoredImage(r, g, b, width, height, increaseCompat) bekommt man
dann das byte[] mit den PNG-Daten heraus.
Was hat es mit dem Parameter increaseCompat auf sich?
Bei den Tests der erzeugten Daten ist mir aufgefallen, dass nicht jede Software mit den 1-Bit-Farbtiefe palettenbasierten Bildern zurecht zu kommen scheint.
Deshalb kann der Parameter increaseCompat auf true gesetzt werden, und es wird dann
eine 8-Bit-Farbtiefe-Datei erzeugt. Diese ist natürlich ein bisschen länger, denn in den Nutzdaten wird nun ein Byte pro Pixel geschrieben
(entgegen 1 Byte pro 8 Pixel), was zwar durch die Komprimierung zum Teil kompensiert wird, aber eben nicht vollständig.
Trotzdem sind diese Dateien auch sehr klein, und die Erzeugung der Daten ziemlich schnell.