Forum: Mikrocontroller und Digitale Elektronik jpg mit STM32 dekodieren


von Holger K. (holgerkraehe)


Lesenswert?

Hallo zusammen

Ich würde gerne einige Grafiken für mein TFT direkt im Programmcode 
einbinden.

Da BMP zu viel Platz benötigen, möchte ich die Grafiken als jpg ablegen.

Idealerweise, würde die Funktion ein Pixel nach dem anderen ausgeben.
Damit könnte ich diese dann direkt aufs Display schreiben um RAM zu 
sparen.

Natürlich mit der damit einhergehenden Trägheit des Bildaufbaus.


Nun bin ich auf der Suche nach einem möglichst kompakten C-Code welcher 
JPGs verarbeiten kann.

Hat hier jemand einen Tipp oder Code?

Danke!

von Phantomix X. (phantomix)


Lesenswert?

Die ersten zwei Suchergebnisse, wenn ich nach "jpg decoder c" suche, 
sind bei mir

http://keyj.emphy.de/nanojpeg/
https://code.google.com/p/picojpeg/

Möglicherweise ist da schon was dabei. Also mein Tipp: Suchmaschinen 
lohnen sich!

von Holger K. (holgerkraehe)


Lesenswert?

Phantomix Ximotnahp schrieb:
> Die ersten zwei Suchergebnisse, wenn ich nach "jpg decoder c"
> suche,
> sind bei mir
>
> http://keyj.emphy.de/nanojpeg/
> https://code.google.com/p/picojpeg/
>
> Möglicherweise ist da schon was dabei. Also mein Tipp: Suchmaschinen
> lohnen sich!

Vielen Dank!

Picojpeg sieht eigentlich ganz gut aus.
Das Problem ist, dass ich keinerlei Dokumentaion finde und deshalb keine 
Idee habe, wie dies zu verwenden ist.

Bei Nanojpeg fehlt mir ebenfalls die Dokumentation...

von Rene H. (Gast)


Lesenswert?

Holger Krähenbühl schrieb:
> Picojpeg sieht eigentlich ganz gut aus.
> Das Problem ist, dass ich keinerlei Dokumentaion finde und deshalb keine
> Idee habe, wie dies zu verwenden ist.
>
> Bei Nanojpeg fehlt mir ebenfalls die Dokumentation...

Naja, wenn ich mir den Sourcecode anschaue, ist mir ziemlich schnell 
klar geworden wie die anzuwenden sind.  Z.Bsp. bei nanojpeg, kleines 
main und sehr leicht zu verstehen. Mehr braucht es da nicht. Das 
Kompilieren dürfte an der Stelle aber mehr Aufwand sein.

Grüsse,
René

von Karl H. (kbuchegg)


Lesenswert?

Holger Krähenbühl schrieb:

> Bei Nanojpeg fehlt mir ebenfalls die Dokumentation...

Du hast recht. Wenn sich da im Header File diese Liste von Funktionen 
findet ....
1
void njInit(void);
2
nj_result_t njDecode(const void* jpeg, const int size);
3
int njGetWidth(void);
4
int njGetHeight(void);
5
int njIsColor(void);
6
unsigned char* njGetImage(void);
7
int njGetImageSize(void);
8
void njDone(void);

dann ist es völlig unmöglich, daraus zu erschliessen, wie man das ganze 
wohl verwenden wird.

Aber: die Entwickler haben auch noch ein übriges getan. Sie haben sogar 
Kommentar dazu geschrieben, welche Funktion was macht.

Nein, da kann man nicht drauf kommen. Weiter suchen.

von Holger K. (holgerkraehe)


Lesenswert?

Danke für den Hinweis!

Macht es einen Sinn, dass die Nanojpeg lib keine header datei hat?

Soll man hier die gesamte C-Datei Includen?

von Karl H. (kbuchegg)


Lesenswert?

Holger Krähenbühl schrieb:
> Danke für den Hinweis!
>
> Macht es einen Sinn, dass die Nanojpeg lib keine header datei hat?

Das ist das einzige, was ich dir zu gute halte.
Das ist ein wenig, nun ja, ungewöhnlich gemacht.

Das Header File ist in das C-File inkludiert.

Gemacht ist es so, dass mit einem Präprozessor-Direktiv quasi 
umgeschaltet wird, ob das File nur als Header File oder als komplettes 
C-File fungieren soll.
1
void foo( void );
2
3
#ifndef _HEADER_ONLY
4
void foo( void )
5
{
6
  mach was
7
}
8
#endif

umgeschaltet wird, in dem man beim Compiler Aufruf eine entsprechende 
Option mitgibt, ob das bewusste Makro _HEADER_ONLY vordefiniert werden 
soll oder nicht. Gibt es das Makro, dann wird der eigentliche Code nicht 
mitcompiliert und es bleibt nur die Header Sektion übrig.

Ganz ehrlich: Das würde ich auftrennen. Ich seh da keinen wirklichen 
Grund bzw. Sinn drinn, ausser den, dass man beim Download sich nur 1 
Datei holen muss. Wers braucht.

Der Header Abschnitt ist im File leicht zu finden (steht am Anfang). 
Kopier ihn raus in ein eigenes Header File und gut ists.

Es steht ja auch ein etsprechender Kommentar drinn
1
///////////////////////////////////////////////////////////////////////////////
2
// HEADER SECTION                                                            //
3
// copy and pase this into nanojpeg.h if you want                            //
4
///////////////////////////////////////////////////////////////////////////////

: Bearbeitet durch User
von Holger K. (holgerkraehe)


Lesenswert?

> Der Header Abschnitt ist im File leicht zu finden (steht am Anfang).
> Kopier ihn raus in ein eigenes Header File und gut ists.


Danke! Habe ich gemacht.

Eine Frage noch... Der Code braucht statisch 512 kBytes...
Das liegt daran, dass er memalloc für dieses strukt macht:
1
typedef struct _nj_ctx {
2
    nj_result_t error;
3
    const unsigned char *pos;
4
    int size;
5
    int length;
6
    int width, height;
7
    int mbwidth, mbheight;
8
    int mbsizex, mbsizey;
9
    int ncomp;
10
    nj_component_t comp[3];
11
    int qtused, qtavail;
12
    unsigned char qtab[4][64];
13
    nj_vlc_code_t vlctab[4][65536];
14
    int buf, bufbits;
15
    int block[64];
16
    int rstinterval;
17
    unsigned char *rgb;
18
} nj_context_t;

Somit dürfte sich nanojpeg wohl leider nicht eignen für den STM32 :(

von Karl H. (kbuchegg)


Lesenswert?

Holger Krähenbühl schrieb:


>     nj_vlc_code_t vlctab[4][65536];

Ja das ist heftig.

Dann nimm den anderen. Der ist drauf ausgelegt, dass er das JPEG in 
kleinen Happen dekodieren kann und dementsprechend weniger Speicher 
braucht.

: Bearbeitet durch User
von Holger K. (holgerkraehe)


Lesenswert?

Karl Heinz schrieb:
> Die Nano dekodiert das Bild in einem Rutsch. Du stopfst das JPEG rein,
> grummel grummel grummel und kannst dir die fertig aufgedröselten Bits
> abholen. Das braucht natürlich Speicher, denn irgendwo muss ja das
> fertige Bild gespeichert werden, bis du es holst.

Das wäre eigentlich meine bevorzugte Variante gewesen.
Aber anstelle des RAMs des Controllers wollte ich die Bilddaten direkt 
in den Controller des LCDs schreiben.

Beim anderen Code habe ich so meine Mühe mit der Doku...
Bim Nanojpeg wäre es klar und einfach gewesen...

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Holger Krähenbühl schrieb:
> Karl Heinz schrieb:
>> Die Nano dekodiert das Bild in einem Rutsch. Du stopfst das JPEG rein,
>> grummel grummel grummel und kannst dir die fertig aufgedröselten Bits
>> abholen. Das braucht natürlich Speicher, denn irgendwo muss ja das
>> fertige Bild gespeichert werden, bis du es holst.
>
> Das wäre eigentlich meine bevorzugte Variante gewesen.

Fehler meinerseits.
Das sind noch nicht mal die Pixel sondern irgendwelche Steuerdaten. Ich 
schätze mal, dass sie sich da eine Tabelle mit irgendwelchen Werten zur 
Kosinustransformation ablegen.

Die Pixel sind dann nochmal extra

von Karl H. (kbuchegg)


Lesenswert?

Holger Krähenbühl schrieb:

> Picojpeg sieht eigentlich ganz gut aus.
> Das Problem ist, dass ich keinerlei Dokumentaion finde und deshalb keine
> Idee habe, wie dies zu verwenden ist.

Irgendwie scheinst du es nicht so recht damit zu haben, aus dem was auf 
den Webseiten steht, deine Schlüsse zu ziehen.

Auf der Pico Seite ist ein Link zu einem damit durchgezogenem Projekt.
http://www.toughdev.com/2014/03/using-picojpeg-library-on-pic24-with.html


> Bei Nanojpeg fehlt mir ebenfalls die Dokumentation...

Sorry. Aber du willst bei den Großen mitspielen? Dann akzeptiere auch, 
dass du ab sofort auch Eigeninitiaitive aufbringen musst und auch mal 
anderer Leute Code studieren musst. Die Zeiten, in der die Tante mit dir 
Lulu geht, sind vorbei. Nicht immer wird einem alles mundgerecht auf 
einem Silbertablett serviert.

: Bearbeitet durch User
von peter (Gast)


Lesenswert?


von Holger K. (holgerkraehe)


Lesenswert?

peter schrieb:
> Die ist auch super
>
> http://elm-chan.org/fsw/tjpgd/00index.html
>
> Peter

Vielen Dank für diesen Hinweis!

Ich versuche gerade den Elm-Chan zu portieren.
Leider motzt mein CooCox mit ARM-GCC dass er bei fread kein _write, 
_exit etc kennt.

Ein weiteres Problem ist, dass ich nur ein Array mit den bytes des JPEGs 
habe. Die meisten Codes erwarten ein "FILE" wie auc fread als letzten 
Parameter ein "FILE" erwartet.

Ich habe jedoch nur einen Buffer mit den Bytes des JPEGs

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Holger Krähenbühl schrieb:

> Ich versuche gerade den Elm-Chan zu portieren.
> Leider motzt mein CooCox mit ARM-GCC dass er bei fread kein _write,
> _exit etc kennt.

Was willst Du mit fread? Warum versuchst Du, Module zu portieren, die Du 
gar nicht brauchst? fread() liest einen Block aus einer Datei. Ohne mir 
den Code angesehen zu haben: wie ich Chan kenne, liest er bestimmt eine 
Datei von einer SD-Karte... das brauchst Du aber gar nicht!

> Ein weiteres Problem ist, dass ich nur ein Array mit den bytes des JPEGs
> habe. Die meisten Codes erwarten ein "FILE" wie auc fread als letzten
> Parameter ein "FILE" erwartet.

Wieso "weiteres Problem"? Du hast kein File, Du brauchst kein File. Also 
versuche die Routine, welche per fread Blöcke liest, einfach Blöcke aus 
Deinem Array lesen zu lassen. Notfalls per memcpy() bzw. memcpy_P(). 
Oder Du mappst Dein Array direkt in den Speicher dieser Routine. Dann 
liegen die Blöcke nicht doppelt im Speicher.

Copy & Paste reicht bei einem solchen Vorhaben bei weitem nicht aus. 
Versuche erst, den Code zu verstehen. Dann schreibe die Sachen um, die 
bei Dir anders sind.

: Bearbeitet durch Moderator
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.