Ich habe meine kleinen (Linux) Konverterprogramme zu einem Programm
zusammengepackt.
Es kann Bilddateien zu einem C-Array konvertieren. Viele Bildformate
kann es (ich) nicht, ist allerdings für mich absolut ausreichend.
Unterstützt werden:
- unkompremierte BMP - Dateien mit 256, 16, 4 und 2 Farben.
- PCX - Dateien mit 256 Farben
Erläuterung:
Beide Formate, BMP und PCX sind sogenannte Indexbildformate. In der
Bilddatei sind deren Farbpaletten zur Anzeige gespeichert. D.h. , dass
jede der Bildformate Farben aus dem RGB Spektrum beinhalten kann. In
beiden Formaten, PCX und BMP, sind dieses jeweils 1 Byte für Farbe rot,
grün und blau.
Mein Konverter extrahiert für die 256-Farben Grafiken die Bildpalette
seperat, beim Konvertieren einer 16-Farben Grafik wird eine Datei mit 2
C-Arrays erzeugt.
Hintergrund dazu, dass ich noch das PCX-Format verwende:
Das PCX-Format war das erste, das ich zu MSDOS-Zeiten (richtig gelesen)
umgesetzt hatte und meine (einfachen) Spieleprogramme mit PCX-Grafiken
ausgestattet hatte. PCX-Dateien komprimieren eine Grafik in der Art,
dass in der Datei in einem Byte die Anzahl gespeichert ist, wieviel
gleiche Farbpixel hintereinander auftauchen. Sind in der Grafik kaum
gleiche Farbpixel hintereinander angeordnet kann es sogar sein, dass
eine Grafik größer wird als eigentliche Pixel vorhanden sind.
PCX-Dateien eigenen sich daher gut für Bilder die viele gleiche
Bildpunkte beinhalten. Werden Fotos auf 256 Farben reduziert sollten die
tunlichst NICHT gedithert werden.
In aller Regel ist die Datei jedoch kleiner als eine unkomprimierte
BMP-Datei.
Mein Konverter extrahiert die Farbpalette in der Art, dass er aus einem
24-Bit RGB Farbwert (je ein Byte für rot, grün und blau) einen so
genannten RGB565 Wert (16 Bit) erzeugt: 5 Bits fuer rot, 6 Bits fuer
grün, 5 Bits für Blau.
Das hat den Vorteil, dass eine Farbpalette zum einem um 256 Byte kleiner
wird als die originale und zum anderen, dass viele preiswerte
TFT-Displays wie sie mit Microcontrollern verwendet werden sowieso nur
16-Bit Farben unterstützen und somit gleich das Format der Displays
vorherscht.
Bei einem 16 Farben BMP wird eine Bildpalette mit in die Ausgabedatei
aufgenommen, weil die Palette nur 16 x uint16_t Integer groß ist.
Grafiken können mit dem Linuxprogramm in ihrer Farbvielfalt mit dem
Programm MTPAINT reduziert werden. Gibt man hier bei indexed Colors 4
an, wird eine Grafik erzeugt, die hier als sogenannte "Ascii-Art"
exportiert werden kann.
Mein Grafikkonverter kann nur diese Ascii-Datei (ehemals 4-Farben BMP)
konvertieren, die mit MTPAINT erzeugt wurde.
Warum bei den 256-Farben Grafiken die Farbpalette extra speichern ?
Eine mögliche (von mir genutzte) Vorgehensweise ist, alle benötigten
Grafiken im 256-Farbenmodus in einem Bild zu haben (und somit benutzen
alle dieselbe Farbpalette). Aus dieser großen Grafik werden mittels
Grafikprogramme mehrere kleine Dateien erzeugt, die alle dieselbe
Farbpalette verwenden. So muß später beim Microcontroller auch nur diese
eine Farbpalette mit integriert werden.
Der Syntax meines Konverterprogramms ist folgender:
1
IMAGE2C 0.01 2019 by R. Seelig
2
--------------------------------------
3
4
Converts a graphic to a regular C-arrays
5
6
Supported graphics formats are:
7
8
- pcx256 PCX with 256 indexed colors
9
- bmp256 uncompressed BMP with 256 indexed colors
10
- bmp16 uncompressed BMP wit 16 indexed colors
11
- bmpsw BMP black and white
12
- ascii from mtpaint (originaly 4 colors, no indexed colors)
13
14
Syntax: image2c options
15
16
Options:
17
-i inputfile
18
-o outputfile
19
-a : outfileformat is AVR-progmem array
20
-f inputfileformat (allowed formats are pcx256, bmp256, bmp16, bmpsw, ascii
21
-p : only generate the colorpalette. Available only with 256 color images
22
With 16 color images, the palette is generated with the data
23
-h : show this help
24
25
Example:
26
create the palette for non AVR-MCU
27
image2c -i testpic.pcx -o testpicdata -a -f pcx256 -p
28
29
create the palette for a AVR-MCU
30
image2c -i testpic.pcx -o testpicdata -a -f pcx256 -p -a
Das Konverter kann übersetzt werden mit :
gcc image2c.c -o image2c
Die mit dem Konverter erzeugten Dateien können bei den entsprechenden
Projekten mittels
#include "meine_carray_grafik"
eingebunden werden.
Es empfiehlt sich die erzeugten Dateien zu editieren um den erzeugten
Arraynamen zu ändern.
Um diese Grafikarrays anzuzeigen werden meine C-Sourcecodes in
gfx_pictures.c sowie eine Bildpunktausgabefunktion benötigt:
void putpixel(uint16_t x, uint16_t y, uint16_t rgb565color);
Diese Putpixel-Funktion wird von den Bilddarstellungsfunktionen der
Datei gfx_picures.c benötigt und sind NICHT (und können es auch nicht
sein) Bestandteil von gfx_pictures.
In der Headerdatei zu gfx_pictures müssen folgende Angaben gemacht
werden:
#define avr_mcu 0
Wird hier eine 0 eingetragen, wird Code für NICHT-AVR MCU's erzeugt,
eine 1 erzeugt AVR-Code
#define bmpsw_enable 1
#define bmpcga_enable 1
#define bmp16_enable 1
#define bmp256_enable 1
#define pcx256_enable 1
Wählt aus, welche Unterstützung gegeben sein soll.
Die Prototypen aus gfx_pictures sind:
Beispiel:
Eine PCX256 Grafik kann folgenderweise angezeigt werden:
#include "pcximagefile"
#include "pcximagepalfile"
.
.
.
pcx256_show(0,0, &pcximage[0], &pcximagepal[0]);
----------------------------------------------------------
Viel Spaß beim Rumspielen
JJ
Ralph S. schrieb:> Ich habe meine kleinen (Linux) Konverterprogramme> zu einem Programm zusammengepackt.>> Es kann Bilddateien zu einem C-Array konvertieren.> Viele Bildformate kann es (ich) nicht, ist allerdings> für mich absolut ausreichend.
Ohne Deinen Elan bremsen zu wollen: Das netpbm-package
kennst Du?!
Falls nicht: Es enthält alle möglichen Konverter und
verwendet pbm/pgm/ppm als Austauschformat.
Ein wirklich freies ppmtoc-Tool scheint es nicht zu
geben; das wäre sicher mal ein gutes Werk.
Da es pcxtoppm und bmptoppm gibt, wird auch Dein
ursprünglicher Anwendungsfall abgedeckt.
Egon D. schrieb:> Ein wirklich freies ppmtoc-Tool scheint es nicht zu geben
Es gibt ppmtoxpm, das erzeugt ja auch "eine Art C-Code":
1
/* XPM */
2
staticchar*noname[]={
3
/* width height ncolors chars_per_pixel */
4
"20 20 4 1",
5
/* colors */
6
" c #000000",
7
". c #0077D1",
8
"X c #B9E1FF",
9
"o c None",
10
/* pixels */
11
" ",
12
" ... ",
13
" ... ....X ",
14
" ...XX ....X ",
15
" ....XX ....X ... ",
16
" ....XX....XX ...X",
17
" ....XX.....X ...X",
18
" ..........XX XXX",
19
" ..........X ",
20
"..........XX ",
21
"....XX....XX ... ",
22
"....X ....X ...X ",
23
"...XX ...XX ....X ",
24
"...XX ...X ....X ",
25
" XXX XXX .....X ",
26
" ....XX ",
27
" ....X ",
28
" XXX ",
29
" ",
30
" "
31
};
… und es gibt pbmtoxbm, das erzeugt echten C-Code, aber nur
schwarz-weiß, hier mal das Ergebnis, nachdem das PPM durch ppmtopgm |
pgmtopbm gepipet worden ist:
Ein vergleichbarer Konverter für PPM in C-Arrays (vielleicht noch mit
über die Kommandozeile konfigurierbarer Anordnung R/G/B) wäre auch aus
meiner Sicht sinnvoller, als die komplette Kette von der Quelle zum Ziel
neu zu schreiben, denn dann wäre man in der Wahl des Eingabeformates
wieder völlig frei (im Rahmen dessen, was netpbm kann, aber das ist ja
verdammt viel).
ps: Man könnte natürlich allemal netpbm nehmen, um aus einem beliebigen
Image ein BMP zu machen, und dann Ralphs Tool, um daraus C-Code zu
bauen. ;-)
Ralph S. schrieb:> oooh, das kannte ich nicht und werde ich mir> ansehen. Für besseres bin ich immer aufgeschlossen.
Naja, ich dachte nur, dass Du vielleicht Dein Tool
dort beisteuern oder ggf. ein vorhandenes erweitern
willst...
Hier gibt es auch ein Online-Tool:
https://littlevgl.com/image-to-c-array
Wenn man so etwas aber öfter braucht, ist ein lokal installiertes Tool
natürlich von Vorteil.
Ich hab mir jetzt die Sachen angesehen: Nicht schlecht.
Mir ging es jedoch darum, die Grafiken auf einem Controller anzuzeigen
und die Grafiken ins Flash einzubinden. Für die dort generierten
C-Arrays müsste ich den Code für die Controller neu schreiben (und wie
gesagt hatte ich Teile davon früher für MS-DOS geschrieben gehabt).
Außerdem wollte ich definitiv die Farbpaletten von den Bilddaten
getrennt haben, damit die nicht bei jeder Grafik neu mitgespeichert wird
(bei BMP 256 Farben sind das pro Farbe 4 Bytes = 1 kByte) um Platz im
Controller zu sparen. Zudem wollte ich nur RGB565 verwenden damit die
Farbpalette (für PCX und BMP) "nur" 512 Byte belegt. Macht sich bspw.
satt bemerkbar, wenn man nur mit kleinen aber mehreren Sprites / Icons
hantiert.
Egon D. schrieb:> Naja, ich dachte nur, dass Du vielleicht Dein Tool dort beisteuern oder> ggf. ein vorhandenes erweitern willst...
... dafür bin ich glaub ich nicht gut genug
Ralph S. schrieb:> Ich hab mir jetzt die Sachen angesehen: Nicht schlecht.
Aber auch nicht wirklich gut. Die Leute dort bleiben kleben bei den
üblichen Formaten und die tragen ja doch recht heftig in einem µC auf.
Ich hatte hier schon ein paarmal eine bessere Lösung gepostet: Farbtiefe
reduzieren, mit Palette arbeiten und Pixel komprimieren. Ich hab dir
dazu mal zwei irgendwo im Inet gefundene Bildchen als Beispiel sowie
deren Entsprechung in C und meine zugehörige Zeichenroutine dafür
drangehängt. Vielleicht findest du das nützlich, in dem Falle mach draus
was du magst.
W.S.
Hallo Ralph,
ich habe dein Tool gerade auf nem Linux Rechner kompiliert und die BMP
16 Farben konvertierung durchgeführt. Den Code für die Ausgabe habe ich
meinem ILI9341 Treiber hinzugefügt und soweit funktioniert auch die
Darstellung auf dem Display. Also Tool inklusive BMP16 code sind ok.
In einem 2ten Versuch habe ich mich an das PCX256 Format herangemacht
aber hier scheint etwas nicht zu funktionieren, die Ausgabe die ich von
dem Tool erhalte ist extrem kurz und die Farb Palette fehlt.
Das PCX256 Bild habe ich mittels Irfanview aus einem BMP erzeugt /
gewandelt. Das Bild mal anbei. Kannst du dir das einmal ansehen ?
Vielen Dank
Hallo Ralph,
es gibt weitere Neuigkeiten und Fehler zu berichten. Ich habe nun
verschiedene Formate getestet sowie varianten von BMP, BMP SW und PCX.
Ich denke das der Konverter nicht mit allen Ausgangsformaten klar kommt
daher wäre es hilfreich wenn du diese benennen könntest.
Also z.B.
- pcx256 PCX with 256 indexed colors (Quelle z.B.IrfanView)
- bmp256 uncompressed BMP with 256 indexed colors (Quelle
z.B.IrfanView)
- bmp16 uncompressed BMP wit 16 indexed colors (Quelle z.B.IrfanView)
- bmpsw BMP black and white (Quelle z.B.IrfanView)
- ascii from mtpaint (originaly 4 colors, no indexed colors)(Quelle
z.B.MTPaint)
Wenn ich z.B. SW BMPs von IrfanView verwende dann scheint das ok zu
sein. Verwende ich bmp16 und verkleiner / verändere die Ursprungsdatei
dann scheint die Farbpalette korrupt zu sein (ebenfalls mit IrfanView).
Mit anderen Worten, je nach verwendeter Grafik Software sind die
Ergebnisse sehr unterschiedlich. Für ascii hast du MTPaint angegeben,
wie ist das bei den anderen Formaten ?
PS: Die PCX Frage ist auch noch offen.
Nochmals Danke
Im Moment bin ich eines Herzinfarktes wegen in der Reha... wenn ich
wieder zu Hause bin, schau ich mir das an. Die BMP sind alle
unkomprimierte Bitmaps und sollten eigentlich mit allen Programmen
gehen. Das PCX256 Format stammt bei mir aus einer Uralt Software namens
PaintShop Pro 6 (das unter Wine läuft)
Hallo Ralph,
werde erst einmal wieder gesund. Die Sache hier hat Zeit und läuft uns
ja nicht weg. Wenn du wieder Lust und Energie für das Thema hast dann
melde dich zurück und dann kann ich dir gerne mehr Informationen und
Beispiele geben. Ich habe insgesamt 3 Fehler aber das kann warten.
Alles Gute und vor allem gute Besserung.
Lg,
Bernd
Bernd N schrieb:> In einem 2ten Versuch habe ich mich an das PCX256 Format herangemacht> aber hier scheint etwas nicht zu funktionieren, die Ausgabe die ich von> dem Tool erhalte ist extrem kurz und die Farb Palette fehlt.
So, jetzt bin ich mal kurz dazu gekommen mir deinen Tiger "anzusehen".
Ich konnte da nichts fehlerhaftes erkennen und IMAGE2C hat die PCX-Datei
klaglos konvertiert.
Vielleicht hast du die Kommandozeilenparameter falsch angewendet ? (mein
Tool ist hier nicht sehr fehlertolerant).
Erzeugen der Imagedateien OHNE die Farbpalette:
image2c -f pcx256 -i tiger.pcx -o tigerpcx.c
Erzeugen der Farbpalette
image2c -f pcx256 -i tiger.pcx -i tigerpal.c -p
Ich habe deine Datei tiger.pcx genommen so, wie du sie hier hochgeladen
hattest.
Hier ist angemerkt: Das Foto des Tigers ist so detailiert, dass bei dem
PCX-Format kaum hintereinander anliegende Flächen existieren so dass das
Bild im PCX-Format groesser als im BMP-Format ist.
Im Anhang hier habe ich mein Makefile-Projekt für ein Nucleo STM32F411
Board in Verbindung mit libopencm3 angehängt.
Foto im Thread hier ist das Nucleoboard in Verbindung mit einem 320x240
Pixel Paralleldisplay
Gruß Ralph
Hallo Ralph,
schön von dir zu hören, hoffe es geht dir wieder einigermaßen. Danke das
du auf meine Fragen zurückkommst.
>> Vielleicht hast du die Kommandozeilenparameter falsch angewendet ?
Ja, beim PCX auf jeden Fall, es war mir nicht klar das die Palette
seperat erzeugt werden muß, danke für das Beispiel.
Es gibt aber noch weitere Fehler. Beim SW Bitmap ist immer das letzte
Zeichen falsch. Im Anhang mal ein Beispielbild und dem Ergebnis. Als
letztes Zeichen steht da ein 0x3F was zu einem Pixel auf dem LCD führt.
Das macht der Konverter immer falsch. Ich entferne daher das Zeichen
einfach.
Ein weiterer Fehler findet sich beim 16 Farben BMP. Ich habe das
originale Bild verkleinert und dann erzeugt der Konverter die
Farbpalette nicht mehr korrekt, siehe Anhang Test.rar. Die 320x240
Grafik ist ok, das kleine Bild hat nach der Konvertierung die falsche
Palette. Bin sicher das klärt sich auch noch.
Vielen Dank
So, ich hab es mir jetzt angesehen gehabt, und die Codegenerierung für
bmpsw war im letzten Byte tatsächlich falsch (es wurde schlichtweg ein
willkürliches Byte geschrieben, weil ich für das lSo, ich hab es mir
jetzt angesehen gehabt, und die Codegenerierung für bmpsw war im letzten
Byte tatsächlich falsch (es wurde schlichtweg ein willkürliches Byte
geschrieben, weil ich für das letzte Byte bei sprintf zu einem %etzte
Byte bei sprintf zu einem %.2X keine Variable angegeben hatte, WAS
ausgegeben werden soll).
Behoben !
Einen weiterern Fehler hab ich bei der Ausgabefunktion in gfx_pictures.c
entdeckt: Der Offset der Ausgabeposition für s/w BMP's auf dem Display
war falsch,
Behoben !
-----------------------------------------
Zur Farbpalette bei einer Verkleinerung eines 16 Farben Bitmaps: Wenn
die Farbpalette nach einer Verkleinerung nicht mehr stimmt (wie du
schreibst), so liegt das an deinem Grafikprogramm, aber nicht an dem
Konverter. Ich bin hergegangen und habe dein Ausgangs BugsBunny
verkleinert und das dann dargestellt, funktioniert.
Grundsätzlich:
Wenn du ein 16 Farben Bitmap verkleinern möchtest, empfiehlt es sich,
zuerst die Farbtiefe auf 24 Bit zu erhöhen, das Bild anschließend zu
verkleinern und danach die Farbtiefe wieder auf 16 Farben zurück setzen.
Das ergibt in der Praxis oft bessere Ergebnisse als wenn du bei einem
16-Farben Pixelbild "einfach nur verkleinerst".
Was für ein Wahnsinn, wie "verdreht" ist der Text oben denn?
Nochmal richtig (auch wenn die korrigierten Dateien das wichtige sind,
und nicht der Text des Threads):
So, ich hab es mir jetzt angesehen gehabt, und die Codegenerierung für
bmpsw war im letzten Byte tatsächlich falsch (es wurde schlichtweg ein
willkürliches Byte geschrieben, weil ich für das letzte Byte bei sprintf
zu einem %.2X keine Variable angegeben hatte, die ausgegeben werden
soll).
Besten Dank für die fixes.
>> Wenn die Farbpalette nach einer Verkleinerung nicht mehr stimmt>> (wie du schreibst), so liegt das an deinem Grafikprogramm
Kannst du mir noch sagen welches Programm du zum verkleinern verwendet
hast ?