mikrocontroller.net

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


Autor: Ralph S. (jjflash)
Datum:
Angehängte Dateien:

Bewertung
2 lesenswert
nicht 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:
IMAGE2C 0.01   2019 by R. Seelig
--------------------------------------

Converts a graphic to a regular C-arrays

Supported graphics formats are:

- pcx256  PCX with 256 indexed colors 
- bmp256  uncompressed BMP with 256 indexed colors 
- bmp16   uncompressed BMP wit 16 indexed colors 
- bmpsw   BMP black and white
- ascii   from mtpaint (originaly 4 colors, no indexed colors)

Syntax:     image2c options

Options:
    -i inputfile
    -o outputfile
    -a : outfileformat is AVR-progmem array
    -f inputfileformat (allowed formats are pcx256, bmp256, bmp16, bmpsw, ascii
    -p : only generate the colorpalette. Available only with 256 color images
         With 16 color images, the palette is generated with the data
    -h : show this help

Example:
    create the palette for non AVR-MCU
    image2c -i testpic.pcx -o testpicdata -a -f pcx256 -p

    create the palette for a AVR-MCU
    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:
    void bmpsw_show(uint16_t ox, uint16_t oy, const unsigned char* const image, uint16_t fwert);
    void bmpcga_show(int ox, int oy, const uint8_t* const image, const uint16_t* const pal);
    void bmp16_show(int16_t ox, int16_t oy, const uint8_t* const image, const uint16_t* const palette);
    void bmp256_show(uint8_t ox, uint8_t oy, const uint8_t* const image, const uint16_t* const palette);
    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

Autor: Egon D. (egon_d)
Datum:

Bewertung
0 lesenswert
nicht 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.

: Bearbeitet durch User
Autor: Jörg W. (dl8dtl) (Moderator) Benutzerseite
Datum:
Angehängte Dateien:
  • preview image for hi.png
    hi.png
    252 Bytes, 107 Downloads

Bewertung
0 lesenswert
nicht 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":
/* XPM */
static char *noname[] = {
/* width height ncolors chars_per_pixel */
"20 20 4 1",
/* colors */
"  c #000000",
". c #0077D1",
"X c #B9E1FF",
"o c None",
/* pixels */
"                    ",
"          ...       ",
"   ...   ....X      ",
"   ...XX ....X      ",
"  ....XX ....X  ... ",
"  ....XX....XX  ...X",
" ....XX.....X   ...X",
" ..........XX    XXX",
" ..........X        ",
"..........XX        ",
"....XX....XX ...    ",
"....X ....X  ...X   ",
"...XX ...XX ....X   ",
"...XX ...X  ....X   ",
" XXX   XXX .....X   ",
"           ....XX   ",
"           ....X    ",
"            XXX     ",
"                    ",
"                    "
};

… 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:
#define noname_width 20
#define noname_height 20
static char noname_bits[] = {
 0xff,0xff,0x0f,0xff,0xfb,0x0f,0xef,0xd7,0x0f,0x37,0xd5,0x0f,0x2f,0xcf,0x0d,
 0x37,0xcb,0x06,0x8b,0xe6,0x03,0xbb,0xf5,0x01,0x6b,0xf3,0x0f,0xdd,0xf2,0x0f,
 0x45,0xf3,0x0f,0xee,0x5a,0x0e,0xa5,0xb9,0x0e,0x65,0xdd,0x0e,0x71,0x6c,0x0e,
 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
Autor: Ralph S. (jjflash)
Datum:

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

Autor: Egon D. (egon_d)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Yalu X. (yalu) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Ralph S. (jjflash)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Ralph S. (jjflash)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: W.S. (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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.

Autor: Uhu U. (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bei Graphiken bringt schon eine simple Lauflängenkodierung eine Menge 
Platzersparnis.

Autor: Ralph S. (jjflash)
Datum:

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

... deswegen mach ich ja auch PCX

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.