Mein erstes Spiel war die Pokémon Rote Edition auf dem ersten Game Boy: 160 mal 144 Pixel, vier Grüntöne. Mehr gab es nicht, und trotzdem steckte darin eine ganze Welt. Damit hat meine Liebe zu Gaming angefangen, und die hat mich am Ende in meinen Beruf geführt.
Der Look ist hängen geblieben. Er ist der Grund, warum diese Seite aussieht, wie sie aussieht.
Für die Seite wollte ich mein Porträt als Sprite, also als kleine Pixelgrafik, wie es die Figuren in alten Spielen sind. Ich hätte dafür ein fertiges Tool nehmen können. Aber ich wollte verstehen, was zwischen Foto und Sprite eigentlich passiert, und Spaß an Pixel Art hatte ich sowieso. Herausgekommen ist Spriteworks: ein kleiner Pixel Art Converter, der komplett im Browser läuft, ohne Upload und ohne Server.
Warum Verkleinern allein nicht reicht
Der naheliegende Weg ist, das Bild auf 48 Pixel zu verkleinern und wieder groß zu ziehen. Das Ergebnis sieht aus wie ein unscharfes Foto mit Treppenstufen, nicht wie ein Sprite.
Ein Sprite hat zwei Eigenschaften: wenige Pixel und wenige Farben. Ein verkleinertes Foto hat nur die erste. Es enthält immer noch tausende Farbtöne mit weichen Übergängen, und genau die verraten es.
Spriteworks geht deshalb in drei Schritten vor: erst verkleinern (Downscaling), dann Kontrast und Farben nachziehen, dann die Farben auf eine kleine Palette reduzieren.
Downscaling mit Box Average
Aus einem Foto mit einer Million Pixeln sollen ein paar tausend werden. Die Frage ist, welche Farbe jeder der neuen, großen Pixel bekommt.
Die einfachste Methode heißt Nearest Neighbor: Für jeden neuen Pixel wird genau ein Pixel aus dem Original genommen, alle anderen fallen weg. Das ist schnell, aber Glückssache. Bei feinen Strukturen wie Haaren oder Stoff entscheidet der Zufall, ob gerade ein heller oder ein dunkler Pixel erwischt wird. Ein Schritt am Slider weiter, und das Bild sieht anders aus.
Spriteworks nimmt stattdessen den Box Average: Alle Pixel des Originals, die auf einen neuen Pixel fallen, werden zu einer Durchschnittsfarbe gemischt. Durchsichtige Stellen zählen dabei weniger, sonst bekämen freigestellte Motive einen dunklen Rand.
Vier Farben müssen reichen
Eine Palette ist eine feste Liste erlaubter Farben. Der Game Boy hatte vier, andere alte Systeme sechzehn. Spriteworks bringt die Paletten von Game Boy, NES, PICO-8, C64 und CGA mit und ersetzt jede Farbe im Bild durch die ähnlichste aus der Liste.
„Ähnlich“ ist die interessante Stelle. Am einfachsten rechnet man mit den Rot-, Grün- und Blauwerten wie mit Koordinaten und misst den Abstand zwischen zwei Farben. Das passt aber schlecht zu dem, was wir sehen: Das Auge reagiert auf Grün viel stärker als auf Blau. Es gibt Farbmodelle wie CIELAB, die dem Sehen nachgebaut sind, nur ist die Umrechnung für jeden einzelnen Pixel teuer.
Ich nutze deshalb Redmean, eine günstige Näherung: Grün zählt immer am stärksten, und wie stark Rot und Blau zählen, hängt davon ab, wie rot die Farbe ist.
const redMean = (r + p[0]) * 0.5;
const dr = r - p[0];
const dg = g - p[1];
const db = b - p[2];
const distance =
(2 + redMean / 256) * dr * dr +
4 * dg * dg +
(2 + (255 - redMean) / 256) * db * db;Wer keine feste Palette will, lässt Spriteworks eine aus dem Bild selbst bauen. Das Verfahren heißt Median Cut: Alle Farben des Bildes kommen in einen Topf, der immer wieder dort halbiert wird, wo die Farben am weitesten auseinanderliegen. Aus jeder Hälfte wird am Ende eine Palettenfarbe. So gehen seltene, aber auffällige Töne nicht unter.
Dithering: Gradients aus vier Farben
Mit vier Farben wird aus einem Himmel ein Streifenmuster, weil es zwischen den Tönen nichts gibt.
Dithering ist der Trick dagegen: Fehlt eine Farbe, setzt man zwei vorhandene im Wechsel nebeneinander, wie ein Schachbrett aus hellen und dunklen Pixeln. Aus etwas Abstand mischt das Auge daraus einen Ton dazwischen. Zeitungen drucken Fotos seit jeher so, mit nichts als schwarzen Punkten.
![]()
Spriteworks kann zwei Verfahren. Bayer legt ein festes 4×4-Muster über das Bild. Das wirkt regelmäßig und sehr nach alter Hardware.
Floyd–Steinberg arbeitet mit Error Diffusion. Ein Beispiel: Ein Pixel soll mittelgrün sein, die Palette hat aber nur Hell und Dunkel. Er wird hell und ist damit etwas zu hell geraten. Diesen Fehler bekommen die Nachbarn mit, die noch nicht dran waren: Sie werden etwas dunkler gerechnet, damit es im Schnitt wieder stimmt. Die vier Zahlen im Code sind die Anteile, die jeder Nachbar abbekommt.
const spread = [
[dir, 0, 7 / 16],
[-dir, 1, 3 / 16],
[0, 1, 5 / 16],
[dir, 1, 1 / 16],
];Zwei Details haben dabei mehr ausgemacht als erwartet. Jede zweite Zeile läuft rückwärts, sonst wandert der Fehler immer nach rechts und erzeugt diagonale Streifen. Und der Fehler braucht Nachkommastellen.
Pixel Art ist nicht wenig Auflösung. Es ist wenig Auflösung mit Absicht.
Selbst ausprobieren
Spriteworks läuft unter crondung.com/spriteworks. Bild hineinziehen, an den Slidern drehen, PNG speichern. Das Bild verlässt den Browser nicht.
Womit ich die besten Ergebnisse bekomme:
- Auflösung zwischen 32 und 64 Pixel, darunter wird ein Gesicht unlesbar
- Motiv mit klarem Umriss vor ruhigem Hintergrund
- PICO-8 für Porträts, Game Boy für alles, was nach Kindheit aussehen soll
- Floyd–Steinberg bei etwa 70 Prozent, volle Stärke rauscht zu sehr
- Kontrast und Saturation leicht anheben, bevor die Palette greift
Das Porträt oben auf der Startseite ist so entstanden. Der PIXELN-Button daneben öffnet das Tool direkt mit meinem Foto.