Hallo zusammen
Ich versuche ein Bitmap, welches angehängt ist, auf meinem TFT
darzustellen.
Eigentlich funktioniert dies auch. Aber eben nur fast.
Es gibt einen schmalen Rand welcher verschoben ist.
Diesen habe ich markiert.
Zudem ist das Bild nicht hoch genug.
Es handelt sich vermutlich um einen Denkfehler oder ähnliches.
Das Bitmap ist im 16bit RGB 565 Format
Also pro Pixel 2 bytes.
Das Bitmapt wird von einer SD-Karte geladen.
Zuerst wird der Dateiheader in ein Struct geladen (54 Bytes
übersprungen)
Dannach immer zwei Bytes als Farbinformation ans Display gesendet.
Hat jemand eine Idee, was hier schief laufen könnte?
### EDIT: Das forum hat das original blumen2.bmp automatisch in ein png
gewandelt...
Hier mein Code:
1
unsignedintucBufferCounter=0;
2
unsignedinty1,x1;
3
4
unsignedcharucBuffer[550];
5
unsignedlongtemp=0;
6
7
longp2;
8
unsignedcharres;
9
unsignedshorts1;
10
FATFSfs;
11
12
while(disk_initialize()!=0);
13
set_max_speed();
14
res=pf_mount(&fs);
15
res=pf_open("blumen2.bmp");
16
p2=fs.fptr;
17
18
if(res==0)
19
{
20
//54 Bytes einlesen (den FileHeader)
21
pf_read(ucBuffer,54,&s1);
22
23
ColorTypeDefcolor;
24
25
//Strukt beladen
26
structbmp_file_header*bmp_f_hdr;
27
structbmp_info_header*bmp_i_hdr;
28
bmp_f_hdr=(structbmp_file_header*)&ucBuffer[0];
29
bmp_i_hdr=(structbmp_info_header*)&ucBuffer[14];
30
31
x1=bmp_i_hdr->biWidth-1+x;
32
y1=bmp_i_hdr->biHeight-1+y;
33
34
//Hier kann man auch anstelle von 300 und 180 x1 und y1 nehmen
Die Bildteile auf Foto.jpg sind je seitenverkehrt (vertikal gespiegelt).
Bei umgekehrter Pixelfolge in jeweils beiden Abschnitten wäre das Bild
fast richtig, es würde nur noch der obere Teil vom Bild fehlen.
Claudio Hediger schrieb:> Das Bitmap ist im 16bit RGB 565 Format> Also pro Pixel 2 bytes.
Beides sollte beim Laden geprüft werden und nicht einfach als gegeben
angenommen.
> Zuerst wird der Dateiheader in ein Struct geladen (54 Bytes> übersprungen)
Auch das sollte geprüft werden. Weder ist sicher, daß die Datei
überhaupt eine Bitmap ist, noch daß der Header 54Byte lang ist.
> y1 = bmp_i_hdr->biHeight -1 + y;
Was soll das sein? biHeight kann auch mal negativ sein. Das sollte
zumindest geprüft werden.
> //Hier kann man auch anstelle von 300 und 180 x1 und y1> nehmen
Dann tue das!
> LCD_SetArea(x,y,300+x-1,180+y-1);
Bist du sicher, daß der Endpunkt angegeben werden muß und nicht etwa der
Punkt danach oder die Breite?
> // erste 512 Bytes in den internen Buffer laden> ucBufferCounter = 0;> pf_read(ucBuffer,512,&s1);
Und wenn das Bild kleiner als 512 Bytes ist?
> for (temp = 0; temp < (300*180); temp++)
Bei 300Pixel Breite und RGB565 könnte das tatsächlich klappen. Es wird
aber definitiv nicht klappen, wenn die Zahl der Pixel/Zeile ungerade
ist.
Zahl der Bytes/Zeile in der Datei berechnet sich
((PixelsX*BitPerPixel)/32)*4.
> {> //sobald wir 256 * 2 bytes also 512 geladen haben> if(ucBufferCounter == 256)> {> ucBufferCounter = 0;> pf_read(ucBuffer,512,&s1);> }
Wieder das Problem. Was passiert bei EOF?
> LCD_WriteData(color.U16);
Ich hoffe, daß der LCD-Treiber weniger fehlerbehaftet ist als dein Code
und den Pitch korrekt handhabt...
Produzier dir doch erstmal ein echtes RAW ohne Header und im Format, das
es 'mundgerecht' für deine LCD Routine ist. Damit prüfst du die
Geometrie und die LCD Routinen.
Wenn das alles funktioniert, verbessere deine BMP Routinen (wozu dieses
Format auch immer gut sein mag) und mach sie flexibel gegenüber den
Eigenschaften, die ein BMP haben kann.
c-hater schrieb:> Ich hoffe, daß der LCD-Treiber weniger fehlerbehaftet ist als dein Code> und den Pitch korrekt handhabt...
Danke für deine tiefgehende Analyse meines codes.
Der derzeitige Stand ist nur für versuchszwecke.
Deshalb wird nicht geprüft, ob überhaupt ein bitmap geladen wurde
etc....
Matthias Sch. schrieb:> Produzier dir doch erstmal ein echtes RAW ohne Header und im Format, das> es 'mundgerecht' für deine LCD Routine ist. Damit prüfst du die> Geometrie und die LCD Routinen.
Das hat wunderbar geklappt mit dem selbern
LCD_SetArea(x0,y0,x1,y1);
Ich habe den code übernommen und schaufle nun die bytes einfach aus der
SD-Karte.
Matthias Sch. schrieb:> Wenn das alles funktioniert, verbessere deine BMP Routinen (wozu dieses> Format auch immer gut sein mag) und mach sie flexibel gegenüber den> Eigenschaften, die ein BMP haben kann.
Ich werde mich nun also nochmals eingehender damit beschäftigen :)
Danke für eure tipps
c-hater schrieb:> Zahl der Bytes/Zeile in der Datei berechnet sich> ((PixelsX*BitPerPixel)/32)*4.
Das war natürlich Lötzinn, war wohl noch zu früh heut' morgen. Korrekt
muß das natürlich so lauten:
((PixelsX*BitsPerPixel+31)/32)*4
Und ich habe auch noch vergessen, darauf hinzuweisen, daß die Bilddaten
nicht nowendigerweise direkt nach dem Header beginnen müssen, es hilft
also nichtmal, ein Pixelformat zu verwenden, welches implizit einen
Header konstanter Größe produziert, wie es bei RGB565 tatsächlich der
Fall ist. Siehe bmfh.bfOffBits.
Man kommt einfach nicht drumrum, diesen verschissenen Header (eigentlich
sind es ja zwei) wirklich zu verstehen und die darin gebotenen Infos zu
benutzen.
Matthias Sch. schrieb:> Wenn das alles funktioniert, verbessere deine BMP Routinen (wozu dieses> Format auch immer gut sein mag)
Es ist ein sehr gutes Format, gerade für den Bereich µC. Denn es ist
extrem flexibel betreffend der Pixelformate, die es beherbergen kann und
es ist trotzdem sehr einfach gestrickt.
Nenne mir ein Format, welches ähnlich weit verbreitet ist, über ähnliche
Flexibilität verfügt und gleichzeitig einen ähnlich geringem Footprint
verursacht! Das wird dir verdammt schwer fallen...
c-hater schrieb:
> daß die Bilddaten> nicht nowendigerweise direkt nach dem Header beginnen müssen
Wenn ich mich richtig erinnere, dann wird im BMP-Datei-Header neben der
Dateigröße auch ein Byte-Offset für den Anfang der Pixeldaten angegeben.
Der Offset sollte über die Datenstruktur des Headers zu finden sein.
Rainer V. schrieb:> c-hater schrieb:>> daß die Bilddaten>> nicht nowendigerweise direkt nach dem Header beginnen müssen>> Wenn ich mich richtig erinnere, dann wird im BMP-Datei-Header neben der> Dateigröße auch ein Byte-Offset für den Anfang der Pixeldaten angegeben.> Der Offset sollte über die Datenstruktur des Headers zu finden sein.
Deswegen hat sich c-hater ja hier in seiner unverwechselbaren Eloquenz
zu dem Thema geäußert:
c-hater schrieb:> Man kommt einfach nicht drumrum, diesen verschissenen Header (eigentlich> sind es ja zwei) wirklich zu verstehen und die darin gebotenen Infos zu> benutzen.