Hallo zusammen, ich habe ein kleines Projekt mit einem STM32F446RE und einem ILI9341-Farbdisplay. Ich habe den ganzen Flash bezahlt - ich werde den ganzen Flash nutzen. Also kommt noch ein schickes Logo dazu. Stellt sich die Frage nach dem passenden Format. Beim ATmega und den klassischen 128x64-Pixel-Displays war der Speicherplatz ja kein Problem. Hat man einfach das Bitmap unkomprimiert gespeichert. Das klappt hier nicht mehr. Anforderungen wären wohl: - Das Bild und Entpackalgorithmus sollten halbwegs klein sein - Es sollte sich blockweise entpacken lassen (für einen kompletten Framebuffer ist eben kein Platz da) - Der Entpack-Algorithmus sollte bekannt und offen sein - Für Logo-artige Bilder sind wohl indizierte Farbformate Mittel der Wahl Was ist geeignet? Der erste Gedanke war PNG. Ein erster Versuch hat gezeigt, dass ein indiziertes RLE-komprimiertes BMP aber noch kleiner ist. Oder gibt es noch etwas Besseres? Für jemand wie mich, der in der Bildbearbeitung Anfänger ist, ist auf einfacher == besser.
Walter T. schrieb: > - Das Bild und Entpackalgorithmus sollten halbwegs klein sein Du hast den ganzen Flash bezahlt also nutze ihn auch mit einem so großen wie möglichen Algorithmus ;-)
Ich will den übrigen Platz aber für interessanten Blödsinn, nicht für blöden Blödsinn nutzen. Wie dem auch sei. Der Wikipedia-Artikel über BMP sieht brauchbar aus, und der Header ließ sich nicht schwer dekodieren. Jetzt führe ich mir mal den Bildaufbau zu Gemütze.
:
Bearbeitet durch User
solche Daten könnte man auch auf ein SPI Flash auslagern, die kleinen 8 pin ICs kosten nicht viel.
Ein speicherfüllendes Bild in 16 Bit Farbtiefe für das ILI9341 hat unkomprimiert eine Grösse von 320x240x2 = 153600 Bytes. Bei 153K passen in das Flash eines STM Controllers jede Menge Bildchen rein, und wenn man sich ein externes SPI Flash gönnt könnte man locker ein kleines Filmchen ablaufen lassen. Wozu also der Ehrgeiz mit Formaten und Dekodierung .... Beschäftigungstherapie? Sonnst nicht ausgelastet?
Die Antwort hast du dir ja schon gegeben. Die Ilitek-Dinger haben intern eh nur RGB5:6:5, und fuer ein Logo kann man auch auf 3:3:2 gehen oder gleich indizieren. So als 'Anekdote': Die guten alten digital picture frames ('dpf-ax') von Pearl hatten einen 8051 drin und ein paar Custom-JPEG-Routinen, inkl. USB-storage. Passte alles auf ein 2 Mbyte SPI-Flash, mit ca. 20-40 Bildern.
Walter T. schrieb: > ein indiziertes RLE-komprimiertes BMP aber noch kleiner > ist. > > Oder gibt es noch etwas Besseres? Für Logos mit wenigen Farben und großen gleichfarbigen Flächen: nein, da ist ein indiziertes Format mit RLE kaum zu schlagen. Für Bilder aber, die man normalerweise mit JPEG komprimieren würde, gibt es was, was zwar längst nicht so gut wie JPEG komprimiert, dafür aber darauf ausgelegt ist, sich leicht und schnell dekomprimieren zu lassen: ASTC. Wird z.B. bei OpenGL für Texturen verwendet, aber z.B. auch bei, Trommelwirbel, Displays, nämlich denen mit BT81x-Displaycontrollern. Der Algorithmus ist allerdings wesentlich komplexer als etwa RLE.
c-hater schrieb: > Für Logos mit wenigen Farben und großen gleichfarbigen Flächen: nein, da > ist ein indiziertes Format mit RLE kaum zu schlagen. Auch in der Hinsicht ist RLE nicht zu schlagen: Walter T. schrieb: > Für jemand wie mich, der in der Bildbearbeitung Anfänger ist, ist auf > einfacher == besser. Letztendlich kommt's beim Logo auch drauf an, wie viele Farben es hat. Man kann ja auch auf 4 Bit pro Pixel mit Indizierung runter. Dann hat man immer noch 16 Farben, oder eben 2 Bit für 4 Farben. Für die meisten Logos wird selbst das reichen. Walter T. schrieb: > Ich will den übrigen Platz aber für interessanten Blödsinn, nicht für > blöden Blödsinn nutzen. Das klingt halt etwas widersprüchlich. Du willst den ganzen Flash nutzen, also willst du ein Logo haben. Nur ist für das Logo zu wenig Flash da, deshalb willst du es komprimieren. Und das ganze muss so klein wie möglich sein, weil du den verbleibenden Flash eigentlich noch für wichtigere Dinge brauchst.
BMP lässt sich zeilenweise dekodieren. Das ist natürlich noch handlicher als blockweise. Ich fand das eine interessante Programmieraufgabe. Wäre das Padding für den "absolute mode" in den Beschreibungen bei Microsoft, und nicht nur in alten Büchern, die man nur per Google Books zufällig findet beschrieben, wäre das im Wesentlichen nur eine nette Fingerübung. Das Bild ist mit 4 Bit indizierten Farben (RLE_4) und nimmt knapp 11 kB ein. Man sieht ganz gut, dass das für Farbverläufe alles andere als ideal ist. Aber RLE_8 wird wohl jetzt auch kein Hexenwerk mehr sein. Bei Interesse stelle ich mal die Dokumente zusammen.
:
Bearbeitet durch User
ImageConverter565 ist ein gutes Werkzeug, um Grafik Files passend zu skalieren und in C-Include-Files zu wandeln.
Den Tipp werden sicherlich einige hilfreich finden. Hier brauche ich das aber gar nicht. Eine BMP-Datei einzulesen und in ein C-Array mit dem selben Inhalt umzuwandeln ist ein Wenigzeiler in Matlab oder Python. Unter Linux geht das m.W. sogar mit Bordmitteln.
Walter T. schrieb: > Eine BMP-Datei einzulesen und in > ein C-Array mit dem selben Inhalt umzuwandeln ist ein Wenigzeiler in > Matlab oder Python. Das dürfte in keiner normalerweise verwendeten Sprache eine besondere Herausforderung sein, nichtmal in C...
Walter T. schrieb: > BMP lässt sich zeilenweise dekodieren. Das ist natürlich noch handlicher > als blockweise. Poste doch mal das Originalbild. Mal schauen, was da so alles geht. Also als Kompromiss aus Decodieraufwand und Platzbedarf des komprimierten Bildes.
Walter T. schrieb: > Hier brauche ich das aber gar nicht Größe ändern und Farbtiefe anpassen machst du auch mit drei Zeilen. Glückwunsch.
c-hater schrieb: > Das dürfte in keiner normalerweise verwendeten Sprache eine besondere > Herausforderung sein, nichtmal in C... Genau das macht den Reiz aus. Einfach draufschieben ohne besondere Konvertierung. Und jetzt der sehr wirklich schöne Teil: BMPs mit der Speicherart BI_BITFIELDS haben das Datenformat so, dass man sie direkt auf das Display schieben kann. Mehrkosten gegenüber einem "speziell" konvertierten Bild: 138 Bytes für den Header und noch ein bischen fürs Padding am Zeilenende. Ich habe mal die passenden Einstellungen für GIMP dargestellt. Nachdem RLE4 funktioniert hat, waren die anderen Modi nur noch eine Fingerübung.
Walter T. schrieb: > Stellt sich die Frage nach dem passenden Format. Und dabei kommt dir nix anderes als die üblichen am PC gebräuchlichen Formate in den Sinn, als allererstes PNG. Guck hier bei den Projekten mal nach sowas. Ich hatte vor Zeiten mal etwas dazu gepostet - aber dabei eher an die Bildkacheln für Googlemaps und Artverwandtes gedacht. W.S.
Zu ASTC? Welches Malprogramm kann denn überhaupt Daten in diesem Format speichern?
Und welches Malprogramm kann den Quellcode für die Dekodier-Routine ausgeben? Nö, beides (angepaßtes Bildformat + Dekodier-Routine) sind Obliegenheit des Programmierers. Falls dir nach sowas sein sollte, dann suche hier mal nach "BildConv" und "BildReTester". Notfalls lade ich das Zeugs hier nochmal hoch. W.S.
Okay... also Du hälst es für vorteilhaft, auf beiden Seiten (PC und eigene Plattform) eine Baustelle zu haben, anstelle einfach eine Standardlösung zu nutzen? Ich nicht. Wahrscheinlich liegt das daran, dass ich hier fachfremd bin.
als fertige Lösung würde ich da wieder auf lvgl verweisen, das hat einen Konverter https://lvgl.io/tools/imageconverter und passende Image Routinen in der Software. Da lvgl alles über einen Render Buffer macht, der min. nur 10 Zeilen der physikalischen Displaygröße groß sein muss, ist es da auch nötig einen beliebigen Teilausschnitt des Image adressieren zu können. Angezeigt wird das dann vom Image Widget das dann zusätzlich einige Optionen hat. https://docs.lvgl.io/master/widgets/core/img.html
Walter T. schrieb: > Okay... also Du hälst es für vorteilhaft, auf beiden Seiten (PC und > eigene Plattform) eine Baustelle zu haben, anstelle einfach eine > Standardlösung zu nutzen? Standard-Lösungen muß man immer auf ihre Zweckmäßigkeit unter den gegebenen Umständen abklopfen. Und die sind auf einem µC völlig anders als am PC. W.S.
Johannes S. schrieb: > einen > beliebigen Teilausschnitt des Image adressieren zu können. Das ist tatsächlich ein brauchbarer Mehrwert. Johannes S. schrieb: > Da lvgl alles über einen Render Buffer macht, der min. nur 10 Zeilen der > physikalischen Displaygröße groß sein muss, Das ist natürlich eine Einschränkung. 6,4 kB für ein 320-Spalten-Display sind nicht nichts. Bei BMP kann ich notfalls alles über einen 4 Byte großen Buffer machen. Aber für einen verschiebbaren Ausschnitt müsste ich das Bitmap-Array jedes Mal von vorn komplett durchsuchen und Zeilenumbrüche zählen. Für Bilder mit verschiebbarem Ausschnitt kann der Mehrwert die Einschränkung also wahrscheinlich in vielen Fällen wettmachen.
:
Bearbeitet durch User
Wieso will man Flash benutzen den man bezahlt hat und sucht dann Kompressionsmethoden? Die Lösung richtet sich ja nach Datenmenge, Bildqualität, Auflösung, Farbtiefe und erwarteter Qualität auf dem Display. Es gibt ja erstmal mindestens 100 Tools für Mikrocontroller die Bilder als Headerfiles konvertieren.. rgb8,rgb444,rgb555,rgb565.. etc. Dazu kann man mit z.B. Irfanview schauen wann die eigentliche Bildqualität je nach Input bei Farbreduzierung flöten geht. Dann kann man schauen in welche Richtung man muss.
Im neuen MagPi ist ein kleines Projekt erwähnt, Sprites auf dem Pi Pico https://twitter.com/jamessutherland/status/1360330220277018628 wenn es Bewegtbilder sein sollen. Hier ein kleines Video dazu in miserabler Qualität BMP habe ich auch mal benutzt Beitrag "Re: Für Retro-Zwecke - PAL Sender?" auf der letzten Seite des PDF sind zwei TV-"Testbilder", aus einem BMP ins Eprom, 3+3+2 Bit für RGB-Daten.
:
Bearbeitet durch User
Schick ist das. Manchmal finde ich es echt schade, dass kein kompletter Frame ins RAM passt. Und machen wir uns nichts vor: Spaß macht es erst, wenn zwei passen.
:
Bearbeitet durch User
Philipp K. schrieb: > Wieso will man Flash benutzen den man bezahlt hat und sucht dann > Kompressionsmethoden? Weil der in einem üblichen µC zur Verfügung stehende Flash von 64K bis 1M im Vergleich zu Bildern (480x360 .. 800x480 und das jeweils in 16 bis 32 Bit) doch recht klein ist. Darum. W.S.
wegwerfname++ schrieb: > auch PNG kann komprimieren http://www.libpng.org/pub/png/libpng.html Deswegen war es auch mein erster Gedanke. Und unterstützt auch indizierte Farben und einen Alphakanal. Im Vergleich zu BMP ist es selbst bei kleinen Dateien (so 40x40 Pixel) ungefähr halb so groß, wenn man nicht vergisst, ohne Vorschau und ohne EXIF zu speichern. Vorteil BMP: - Recht einfach implementiert - Kann auch direkt Bitmaps im RGB565-Format speichern, was sich direkt ans Display schicken lässt und was ich diese Woche neu gelernt habe: - Unterstützt auch Alphakanal und nicht-rechteckige Bildränder - Es reicht ein beliebig kleiner Pixelpuffer (2 Bytes) zum Entpacken aus. Ich bin zufrieden und es hat Spaß gemacht.
Walter T. schrieb: > Vorteil BMP: > - Recht einfach implementiert > - Kann auch direkt Bitmaps im RGB565-Format speichern, was sich direkt > ans Display schicken lässt Naja, das bloß halt nicht komprimiert. Entweder BI_BITFIELDS oder BI_RLEx. Beides gleichzeitig ist nicht. Aber man kann im Prinzip beliebige Komprimierungen im BMP-Format unterbringen. Bei AVIs (die ebenfalls einen BMIH verwenden) wird's ja auch seit Jahrzehnten so gemacht. Bloß für's *.bmp-Fileformat ist sowas halt nicht spezifiziert.
c-hater schrieb: > Bloß für's *.bmp-Fileformat ist sowas > halt nicht spezifiziert. Wobei das auch nicht mehr ganz korrekt ist. Zwar meines Wissens nach nicht direkt für's BMP-Fileformat dokumentiert, aber trotzdem: Intern verwendet Windows mittlerweile auch in BMPs "eingebettete" PNGs, z.B. für Icons. Dafür ist es dann auch dokumentiert, allerdings eher etwas verschämt, garnicht so leicht zu finden, wenn man nicht gezielt danach sucht. Was ja erstmal voraussetzt, dass man schon weiss, dass es das überhaupt gibt.
c-hater schrieb: > Zwar meines Wissens nach > nicht direkt für's BMP-Fileformat dokumentiert, Eingebettete PNGs oder JPEGs sind dokumentiert. Nur eben nicht in den alten Dokus fürs V3-Format. Ich sehe allerdings auch keinen Mehrwert, diese Daten in einen BMP-Container zu packen. Was mich wirklich wurmt: Es gibt kein RLE-1-Format (also gepackte 1-Bit-SW-Bilder). Damit sind indizierte 4-Farb-Bilder faktisch kleiner als SW-Bilder.
:
Bearbeitet durch User
Walter T. schrieb: > Was mich wirklich wurmt: Es gibt kein RLE-1-Format (also gepackte > 1-Bit-SW-Bilder). Damit sind indizierte 4-Farb-Bilder faktisch kleiner > als SW-Bilder. Das gab's schon in den 80ern auf dem Atari ST: https://www.fileformat.info/format/gemraster/egff.htm
Sieh an. Vielleicht ist das einen Blick wert: "PNG Image Decoding Library Does It With Minimal RAM" https://hackaday.com/2021/07/17/png-image-decoding-library-does-it-with-minimal-ram/ Jemand hat eine Arduino-Library für PNG gebastelt. Wenn die Lizenz nicht ganz weit weg von nutzbar ist, wird mein BMP-Dekoder eine Woche nach dem Start direkt wieder auf den Altenteil geschickt.
c-hater schrieb: > Das dürfte in keiner normalerweise verwendeten Sprache eine besondere > Herausforderung sein, nichtmal in C Und obendrein könnte man es auch verlinken und direkt verwenden
Walter T. schrieb: >> "PNG Image Decoding Library Does It With Minimal RAM" Da steht doch gleich auch: > It will run on any microcontroller that can spare at least 48 K of RAM Damit ist das meiste Arduino-unterstützten Gelumpe gleich mal eben raus... Ich bin völlig sicher: das kann nicht das Ende der Fahnenstange sein. ;o)
Sieh an. Ich hatte den Github-Teil noch gar nicht gelesen. Das hatte ich mir für heute abend vorgenommen. Aber "minmal memory footprint" und 48K ist arg Etikettenschwindel. 48K im RAM wäre einmal 240*200*1 Byte. Das klingt gerade nach einmal Framebuffer mit indizierten Farben. Schade.
:
Bearbeitet durch User
Walter T. schrieb: > Sieh an... Schade. Tja, gelegentlich ist es tatsächlich besser, sich eigene Gedanken zu machen als das Internet nach Kopierbarem abzusuchen. Was schwebt dir eigentlich vor - so als Flash-Füllung? Etwas eher cartoon-ähnliches oder ein Hintergrundbild oder noch was anderes? W.S.
Zitat aus dem Artikel von Larry Bank:
1 | I decided to set a max image width of 640 x 32-bpp (which can also be 2560 x 8-bpp). The total memory required for decoding images of up to this width (and any length) is around 46K. This seemed like a reasonable balance, but unfortunately excludes a lot of smaller embedded devices. This couldn't be avoided because the zlib structures require 39K of RAM by themselves. |
Da wird der Speicherbedarf kaum zu optimieren sein. Wenn das Bild allerdings nur als Splashscreen beim Gerätestart dient, dann kann man den Speicher danach ja wieder anderweitig verwenden. Ein Bild das sich im Zeitlupentempo aufbaut sieht aber auch wie gewollt und nicht gekonnt aus, sowas würde ich auch nicht einbauen.
Johannes S. schrieb: > Wenn das Bild > allerdings nur als Splashscreen beim Gerätestart dient [...] Verlockend für den Entwickler, nervig für den Nutzer. Ich halte Splash-Screens mittlerweile für Antifeatures. Entweder sie sind zu kurz zum Lesen oder sie dauern so lange, dass sie bei jedem Gerätestart stören. W.S. schrieb: > Tja, gelegentlich ist es tatsächlich besser, sich eigene Gedanken zu > machen als das Internet nach Kopierbarem abzusuchen. Meine BMP-Implementierung ist fertig und rockt. Siehe oben. W.S. schrieb: > Etwas eher > cartoon-ähnliches oder ein Hintergrundbild oder noch was anderes? Noch exotischer: Grafiken mit den Steckerbelegungen einblenden (da auf dem Gehäuse leider nur wenig Platz für Aufkleber ist). Ich ärgere mich regelmäßig, wenn ich "im Feld" Kabel konfektionieren muss und nur dafür der Laptop auf dem wackeligen Campingtisch oder der dreckigen Werkbank herumsteht. Aber Hintergrundbild für den Info-Bildschirm ist auch angedacht. Wobei das gar nicht so einfach ist, eine Grafik zu entwerfen, die bei diesen Displays gut aussieht.
:
Bearbeitet durch User
Walter T. schrieb: > Aber Hintergrundbild für den Info-Bildschirm ist auch angedacht. Wobei > das gar nicht so einfach ist, eine Grafik zu entwerfen, die bei diesen > Displays gut aussieht. Naja - was gut aussieht, ist Geschmackssache. Ich häng dir mal was dran - bloß um zu zeigen, was man mit (im Grunde) einfachen Mitteln selber machen kann. Der Kartenausschnitt ist nur rund 131K groß und hat doch so etwa 1000x500 Pixel. Und entpacken geht recht einfach - ohne 46K an RAM. Der Viewer ist für Windows. W.S.
"QMFT" - sehr aussagekräftig. Die Kompression ist nicht übel. Das sieht nach 16 Farben indiziert aus. BMP ist mit seiner primitiven RLE-Kompression da fast 40% größer. PNG fast 30% kleiner. Bei mir wird der Speicherverbrauch der Karte allerdings auch mit ca. 2 MB angesetzt (Task Manager Karte geladen/ungeladen).
:
Bearbeitet durch User
Walter T. schrieb: > Die Kompression ist nicht übel. Das sieht nach 16 Farben indiziert aus. > BMP ist mit seiner primitiven RLE-Kompression da fast 40% größer. PNG > fast 30% kleiner. GIF mit 8 indizierten Farben kommt mit dem Beispielbild auf 72 KBytes. Im Direktvergleich sind keine großen Unterschiede zum 16-Farben-Original erkennbar.
:
Bearbeitet durch User
Walter T. schrieb: > "QMFT" - sehr aussagekräftig. Was erwartest du? Etwa eine 4 stellige DIN-Nummer? Das Format ist kein am PC übliches Grafikformat. Zum Gucken hier noch eine andere Landkarte. W.S.
https://www.urbandictionary.com/define.php?term=QMFT Und ich traue Dir nicht zu, den Terminus nicht zu kennen. So jung bist Du nicht.
Nachtrag: Ich hatte später an diesem Zeugs noch etwas weiter gemacht, weil ich sowas für grafische Menüs benötigte. Ich hab hier auch mal was davon gepostet, aber das haben die Leute damals nicht kapiert. Stattdessen kamen Ansichten derart, daß man Bilder im 565 BMP Format bereits als "komprimiert" angesehen hatte. Nun ja... Das Prinzip bei meinem Zeugs ist einfach: Es wird eine Palette verwendet und die Anzahl der Farben reduziert, was zum einen bei Icons und Grafiken überhaupt nicht stört (nur bei richtigen Bildern hat man da Probleme) und zum anderen die benötigte Bitbreite der Pixel reduziert. Wenn dann noch die Wertebereiche passend gewählt werden, so daß die Bitbreite für etwas mehr als für die Palettenindizes ausreicht, dann kann man den Überstand als Zähler für Wiederholungen nutzen. Das alles ist in Summe recht platzsparend und trotzdem leicht zu dekodieren. Obendrein hat man nur Bedarf an einigen wenigen Variablen im RAM und benötigt keinen großen Scratch-RAM. Der momentane Ist-Stand ist noch verbesserungsfähig: Man könnte Bitbreite und Farbanzahl separat voneinander einstellen. W.S.
Walter Tarpan (Gast) schrieb: > So jung bist > Du nicht. Höhö.. Anstatt zu frozzeln mach lieber was Schönes draus. W.S.
W.S. schrieb: > Das Prinzip bei meinem Zeugs ist einfach: Es wird eine Palette verwendet > und die Anzahl der Farben reduziert, W.S. schrieb: > dann > kann man den Überstand als Zähler für Wiederholungen nutzen. Das alles > ist in Summe recht platzsparend und trotzdem leicht zu dekodieren. Okay, also indizierte Farben und umgekehrt polnische Lauflängenkodierung. Da kann ich mir gut vorstellen, dass das noch ein Stück effizienter als Lauflängenkodierung mit festen 4-Bit- oder 8-Bit-Paketen mit Padding auf 4-Bytes-Grenzen je Zeile ist.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.