U8g2 Image Converter
Verwandle ein PNG, BMP oder GIF in ein 1-Bit-XBMP-Array für ein SSD1306 oder jedes andere monochrome Display, das U8g2 ansteuert, und sieh es dir auf einem simulierten Screen an, bevor du irgendetwas flashst.
Läuft im Browser. Kostenloses Konto, keine Installation.
Was der Konverter tut
Lopaka ist ein Grafik-Editor für Embedded-Displays. Importiere ein Bild in ein U8g2-Projekt, dann wird es zu einer Ein-Bit-Bitmap-Ebene auf einer Zeichenfläche in der Größe deines Displays, wo du es verschieben, zuschneiden, einzelne Pixel mit dem Paint-Tool neu zeichnen und Text und Formen um es herum platzieren kannst. Das Code-Panel hält Schritt: Es deklariert das Array und gibt den drawXBMP()-Aufruf für die Position aus, an der die Ebene gerade sitzt.
Das ist der Teil, den ein einfacher Konverter dir überlässt. Die Bytes zu bekommen ist ein Schritt; zu wissen, dass das Logo 4 Pixel zu tief sitzt oder dass die Beschriftung bei dieser Schriftgröße damit kollidiert, braucht normalerweise ein Kompilieren und ein Flashen. Hier braucht es das Ziehen der Ebene.
Wie eine monochrome Bitmap wirklich funktioniert
Ein Bit pro Pixel, nicht ein Byte
Ein SSD1306-Panel hat ein Bit Zustand pro Pixel: leuchtend oder dunkel. Es gibt kein Grau und keine Farbe, also speichert eine Bitmap dafür auch ein Bit pro Pixel, acht Pixel in jedes Byte gepackt, Zeile für Zeile. Ein 128x64-Screen sind in dieser Form 1.024 Bytes. Speicherst du dasselbe Bild mit einem Byte pro Pixel, wird es zu 8.192 Bytes, was auf einem klassischen AVR-Board mehr RAM ist, als du hast.
XBM, XBMP und wo PROGMEM ins Spiel kommt
XBM ist dieses gepackte Ein-Bit-Format, und es ist das, was U8g2 von drawXBM() erwartet. XBMP sind dieselben Daten, deklariert im Flash statt im RAM: Mit aktiviertem Declare as PROGMEM markiert Lopaka das Array als U8X8_PROGMEM und ruft drawXBMP() auf, das es aus dem Programmspeicher liest. Auf einem Arduino-Ziel ist das normalerweise das, was du willst, weil Bitmaps konstant sind und RAM die knappe Ressource ist. Die ESP-IDF-Vorlage gibt stattdessen ein einfaches uint8_t-Array und drawXBM() aus.
Schwelle, Dithering und Invertierung
Ein Quellbild hat normalerweise 256 Farbtöne pro Kanal und das Display hat zwei, also muss etwas entscheiden, welche Pixel überleben. Eine einfache Schwelle schickt alles über einem Grenzwert zu Weiß und alles darunter zu Schwarz, was für Logos und Strichzeichnungen mit harten Kanten richtig ist. Dithering verteilt stattdessen den Rundungsfehler in benachbarte Pixel, sodass ein Farbverlauf als Textur wirkt statt als Band. Helligkeit und Kontrast verschieben den Grenzwert, bevor eines von beidem passiert, und Grayscale first hilft, wenn ein Farbbild Farbtöne mit ähnlicher wahrgenommener Helligkeit hat, wie Rot auf Weiß.
| Dithering-Modus | Wann du ihn nutzt |
|---|---|
| Floyd-Steinberg | Detaillierte Fotos und glatte Farbverläufe |
| Atkinson | Ein helleres, kontrastreiches Dithering, das gut für kleine Displays funktioniert |
| Bayer 8x8 | Ein regelmäßiges Pixelmuster mit vorhersehbarer Textur |
| No dithering | Saubere Strichzeichnungen, Logos und Vollflächen |
Es gibt zwei separate Invertierungs-Steuerungen, weil es zwei separate Probleme gibt. Invert palette tauscht Schwarz und Weiß vor dem Dithering, für den Fall, dass der Konverter deinen Hintergrund als Motiv behandelt. Invert result dreht die fertige Bitmap um, für den Fall, dass die Vorschau richtig ist, das Panel sie aber rückwärts rendert.
Displays und Boards
U8g2 ist eine monochrome Grafikbibliothek, die eine lange Liste von OLED- und LCD-Controllern abdeckt, und Lopaka zielt auf ihre grafische API. Die bekannten sind SSD1306, SH1106 und SSD1309, was das meiste von dem ist, was auf einem kleinen I2C- oder SPI-OLED-Modul ausgeliefert wird. Prüfe die Upstream-Konstruktorliste, um dein genaues Panel zu bestätigen.
Lopaka erkennt oder steuert keine Hardware an. Es generiert den Zeichen-Code; du wählst den U8g2-Konstruktor, der zu deinem Controller, deiner Auflösung, deinem Bus und deinen Pins passt, rufst dann begin() auf und führst die Aktualisierungsschleife selbst aus. Stelle die Lopaka-Screen-Größe auf dieselbe logische Auflösung wie diesen Konstruktor ein, dann passen die Zeichenflächen-Koordinaten zum Panel.
Ein Bild konvertieren
- Erstelle ein Projekt, wähle U8g2 als Plattform und stelle die Screen-Größe auf deine Display-Auflösung ein.
- Öffne das Image-Tool und lege ein PNG, BMP oder GIF hinein oder füge ein bestehendes XBMP-Byte-Array ein.
- Schneide zu und skaliere, stelle dann Helligkeit, Kontrast und Dithering ein, während sich die Vorschau aktualisiert.
- Importiere die Bitmap, positioniere sie auf der Zeichenfläche und füge Text oder Formen um sie herum hinzu.
- Kopiere den generierten Quellcode, der das Array deklariert und drawXBMP an dieser Position aufruft.
Wenn die Bitmap auf dem Gerät leer oder verschoben ist, prüfe die Argumente von drawXBMP, Zeilen-Padding und Puffer-Schleife.
Wie die Ausgabe aussieht
Ein 16x16-Icon, platziert bei x 8, y 8 mit einer Beschriftung daneben, auf einem Screen namens Status. Das ist die Arduino (Cpp)-Vorlage, also wird das Array als PROGMEM deklariert und mit drawXBMP gezeichnet.
static const unsigned char image_wifi_bits[] U8X8_PROGMEM = {0x00,0x00,0x00,0x00,0xf8,0x1f,0xfc,0x3f,0x0e,0x70,0x03,0xc0,0x00,0x00,0xf0,0x0f,0xf8,0x1f,0x1c,0x38,0x06,0x60,0x00,0x00,0xc0,0x03,0xe0,0x07,0xc0,0x03,0x00,0x00};
void drawStatus(void) {
u8g2.setFontMode(1);
u8g2.setBitmapMode(1);
// wifi
u8g2.drawXBMP(8, 8, 16, 16, image_wifi_bits);
// label
u8g2.setFont(u8g2_font_6x10_tr);
u8g2.drawStr(32, 21, "Connected");
}Derselbe Screen, exportiert mit der ESP-IDF (C)-Vorlage. Die Bitmap-Bytes sind identisch; nur die Deklaration und die API um sie herum ändern sich.
static const uint8_t image_wifi_bits[] = {0x00,0x00,0x00,0x00,0xf8,0x1f,0xfc,0x3f,0x0e,0x70,0x03,0xc0,0x00,0x00,0xf0,0x0f,0xf8,0x1f,0x1c,0x38,0x06,0x60,0x00,0x00,0xc0,0x03,0xe0,0x07,0xc0,0x03,0x00,0x00};
void drawStatus(void) {
u8g2_ClearBuffer(&u8g2);
u8g2_SetBitmapMode(&u8g2, 1);
u8g2_SetFontMode(&u8g2, 1);
// wifi
u8g2_DrawXBM(&u8g2, 8, 8, 16, 16, image_wifi_bits);
// label
u8g2_SetFont(&u8g2, u8g2_font_6x10_tr);
u8g2_DrawStr(&u8g2, 32, 21, "Connected");
u8g2_SendBuffer(&u8g2);
}Die Schriftart in beiden Beispielen ist eines der integrierten Symbole von U8g2, braucht also keinen heruntergeladenen Header. Eine Schriftart außerhalb dieser Liste wird als Header exportiert, den du neben dem Sketch herunterlädst.
Fragen
Wie konvertiere ich ein Bild in eine U8g2-Bitmap?
Importiere das Bild in ein U8g2-Projekt. Lopaka konvertiert es in ein 1-Bit-XBM-Array, zeigt es auf einer Zeichenfläche in der Größe deines Displays und generiert die Deklaration plus den drawXBMP-Aufruf, der es an die Position setzt, an die du es gezogen hast.
Was ist XBMP und warum nutzt U8g2 es?
XBM packt ein Pixel in ein Bit, acht Pixel pro Byte, Zeile für Zeile. Ein monochromes OLED hat genau ein Bit Zustand pro Pixel, also ist das Array eine direkte Kopie dessen, was das Panel zeigt. XBMP sind dieselben Daten, deklariert im Flash mit U8X8_PROGMEM, weshalb Arduino-Builds es mit drawXBMP statt mit drawXBM paaren.
Mit welchen Displays funktioniert das?
Mit jedem monochromen Display, das U8g2 selbst unterstützt, einschließlich SSD1306-, SH1106- und SSD1309-OLEDs. Lopaka generiert den Zeichen-Code; du wählst den U8g2-Konstruktor für deinen Controller, Bus und deine Pins und rufst begin() und die Aktualisierungsschleife selbst auf.
Was macht Dithering mit einem Foto?
Ein monochromes Display hat kein Grau, also muss jedes Pixel am Ende schwarz oder weiß sein. Dithering streut den Fehler über benachbarte Pixel, sodass ein Farbverlauf als Textur wirkt statt als harte Kante. Floyd-Steinberg und Atkinson eignen sich für Fotos; Logos und Strichzeichnungen sehen mit ausgeschaltetem Dithering meist sauberer aus.
Kann ich meine bestehenden Bitmap-Arrays nutzen?
Ja. Der Import-Assistent akzeptiert ein rohes XBMP-Byte-Array, das aus bestehender Firmware eingefügt wurde. Gib ihm Breite und Höhe, schalte Bytes tauschen um, falls die Vorschau durcheinander aussieht, dann wird es zu einer bearbeitbaren Ebene, die du mit dem Paint-Tool Pixel für Pixel neu zeichnen kannst.
Generiert es auch ESP-IDF-Code genauso wie Arduino?
Ja. Die U8g2-Plattform hat zwei Vorlagen: Arduino (Cpp), die U8X8_PROGMEM-Arrays und u8g2.drawXBMP() ausgibt, und ESP-IDF (C), die einfache uint8_t-Arrays und u8g2_DrawXBM() gegen die C-Schnittstelle ausgibt. Wechsle in den Code-Einstellungen zwischen ihnen.
Ist es kostenlos?
Ja. Bilder zu konvertieren und U8g2-Code zu generieren, ist Teil des kostenlosen Basic-Tarifs, zusammen mit der Community-Icon-Bibliothek und ein paar Cloud-Projekten. Plus fügt höhere Limits, benutzerdefinierten Schriftart-Import, die vollständigen Icon- und Animations-Bibliotheken sowie Datei-Export hinzu, aber nichts auf dieser Seite braucht es.
Probiere es mit deinem eigenen Bild aus
Erstelle ein kostenloses Konto, dann öffnet sich der Editor auf einem leeren Screen in der Größe deines Displays.