Bitmap auf TFT darstellen. Klappt, FAST!

OP #3694045
Lesenswert?

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
unsigned int ucBufferCounter = 0;
2
  unsigned int y1,x1;
3

4
  unsigned char ucBuffer[550];
5
  unsigned long temp = 0;
6

7
  long  p2;
8
  unsigned char res;
9
  unsigned short s1;
10
  FATFS fs;
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
    ColorTypeDef color;
24

25
                //Strukt beladen
26
    struct bmp_file_header *bmp_f_hdr;
27
    struct bmp_info_header *bmp_i_hdr;
28
    bmp_f_hdr = (struct bmp_file_header *)&ucBuffer[0];
29
    bmp_i_hdr = (struct bmp_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
35
    LCD_SetArea(x,y,300+x-1,180+y-1);
36
    LCD_WriteCommand(CMD_WR_MEMSTART);
37

38
    Clr_Cs;
39

40
                // erste 512 Bytes in den internen Buffer laden
41
    ucBufferCounter = 0;
42
    pf_read(ucBuffer,512,&s1);
43

44
    for (temp = 0; temp < (300*180); temp++)
45
    {
46
                       //sobald wir 256 * 2 bytes also 512 geladen haben
47
      if(ucBufferCounter == 256)
48
      {
49
        ucBufferCounter = 0;
50
        pf_read(ucBuffer,512,&s1);
51
      }
52

53
      color.U8[0] = ucBuffer[(ucBufferCounter * 2)];
54
      color.U8[1] = ucBuffer[1 + (ucBufferCounter * 2)];
55

56
      LCD_WriteData(color.U16);
57
      ucBufferCounter++;
58
    }
59
    Set_Cs;
60
  }
Angehängte Dateien:
Gast #3694217
Lesenswert?

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...
(Firma: matzetronics) #3694230
Lesenswert?

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.
Gast #3694236
Lesenswert?

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
Gast #3695001
Lesenswert?

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.
Gast #3695009
Lesenswert?

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...
#3695189
Lesenswert?

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.
Gast #3695206
Lesenswert?

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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren