Forum: Projekte & Code PCX und BMP zu C-Array Konverter


von Ralph S. (jjflash)


Angehängte Dateien:

Lesenswert?

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:
1
    void bmpsw_show(uint16_t ox, uint16_t oy, const unsigned char* const image, uint16_t fwert);
2
    void bmpcga_show(int ox, int oy, const uint8_t* const image, const uint16_t* const pal);
3
    void bmp16_show(int16_t ox, int16_t oy, const uint8_t* const image, const uint16_t* const palette);
4
    void bmp256_show(uint8_t ox, uint8_t oy, const uint8_t* const image, const uint16_t* const palette);
5
    void pcx256_show(int16_t x, int16_t y, const unsigned char* const image, const uint16_t *const pal);

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

von Egon D. (Gast)


Lesenswert?

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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Angehängte Dateien:

Lesenswert?

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
static char *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:
1
#define noname_width 20
2
#define noname_height 20
3
static char noname_bits[] = {
4
 0xff,0xff,0x0f,0xff,0xfb,0x0f,0xef,0xd7,0x0f,0x37,0xd5,0x0f,0x2f,0xcf,0x0d,
5
 0x37,0xcb,0x06,0x8b,0xe6,0x03,0xbb,0xf5,0x01,0x6b,0xf3,0x0f,0xdd,0xf2,0x0f,
6
 0x45,0xf3,0x0f,0xee,0x5a,0x0e,0xa5,0xb9,0x0e,0x65,0xdd,0x0e,0x71,0x6c,0x0e,
7
 0xff,0x5f,0x0e,0xff,0x77,0x0f,0xff,0x8f,0x0f,0xff,0xff,0x0f,0xff,0xff,0x0f};

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. ;-)

: Bearbeitet durch Moderator
von Ralph S. (jjflash)


Lesenswert?

oooh, das kannte ich nicht und werde ich mir ansehen. Für besseres bin 
ich immer aufgeschlossen.

von Egon D. (Gast)


Lesenswert?

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...

von Yalu X. (yalu) (Moderator)


Lesenswert?

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.

von Ralph S. (jjflash)


Lesenswert?

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.

von Ralph S. (jjflash)


Lesenswert?

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

von W.S. (Gast)


Angehängte Dateien:

Lesenswert?

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.

von Uhu U. (uhu)


Lesenswert?

Bei Graphiken bringt schon eine simple Lauflängenkodierung eine Menge 
Platzersparnis.

von Ralph S. (jjflash)


Lesenswert?

Uhu U. schrieb:
> Bei Graphiken bringt schon eine simple Lauflängenkodierung eine Menge
> Platzersparnis.

... deswegen mach ich ja auch PCX

von Bernd N (Gast)


Angehängte Dateien:

Lesenswert?

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

von Bernd N (Gast)


Lesenswert?

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

von Ralph S. (jjflash)


Lesenswert?

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)

von Bernd N (Gast)


Lesenswert?

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

von Ralph S. (jjflash)


Angehängte Dateien:

Lesenswert?

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

von Bernd N (Gast)


Angehängte Dateien:

Lesenswert?

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

von Ralph S. (jjflash)


Angehängte Dateien:

Lesenswert?

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".

von Ralph S. (jjflash)


Lesenswert?

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).

von Bernd N (Gast)


Lesenswert?

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 ?

von Ralph S. (jjflash)


Lesenswert?

... wie oben schon einmal erwähnt verwende ich hierfür ein ur-ur-uraltes 
Windowsprogramm unter Wine: PaintShop pro 6.0 (ist aus 1998)...

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
Noch kein Account? Hier anmelden.