Forum: Mikrocontroller und Digitale Elektronik STM32 24Bit Bmp nach 565RGB Format


von andreas (Gast)


Lesenswert?

Hallo,
Ich habe ein  kleines Problem mit einer Bitmat Routiene.
Ichlese von der SD-Card ein BMP Bild 24Bit Farbtiefe und zeige es auf 
dem display an, aber so ganz funktioniert das nicht richtig  die Farben 
passen nicht ganz.
Vielleicht kann mir jemand von ihnen weiterhelfen
mfg

Als Board nutze ich diese.
http://www.ebay.de/itm/STM32-STM32F103VCT6-Dev-Board-3-2-TFT-LCD-Module-/190509403384?_trksid=p2045573.m2042&_trkparms=aid%3D111000%26algo%3DREC.CURRENT%26ao%3D1%26asc%3D27%26meid%3D6292494594737146901%26pid%3D100033%26prg%3D1011%26rk%3D1%26sd%3D190509403384%26
1
u32 RGB888ToRGB565(u8 r,u8 g,u8 b)
2
 {return (u32) (r & 0xF8) << 8 | (g & 0xFC) << 3 | (b & 0xF8) >> 3;}  //565
3
4
5
void test(void)
6
{
7
  u8 scan_bit1;  //µ¥¸ö°´¼üɨÃè±äÁ¿
8
  u8 scan_bit2;  //µ¥¸ö°´¼üɨÃè±äÁ¿
9
  char aa[10];
10
  int jj=1;
11
  f_mount(0, &fs);
12
  while(1)
13
  {
14
15
16
  //LCD_Clear(BLUE);
17
  scan_bit1 = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3);
18
  scan_bit2 = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_8);
19
  if(scan_bit1==0) jj++; 
20
  if(scan_bit2==0) jj--;
21
  jj++;
22
  if(jj<1) jj=9;
23
  if(jj>9) jj=1;
24
  Delay(400);
25
26
27
  if(jj<10)
28
  {
29
    aa[0]=jj+'0';
30
  aa[1]='.';
31
  aa[2]='B';
32
  aa[3]='M';
33
  aa[4]='P';
34
  aa[5]='\0';
35
  }
36
  else
37
  {
38
    aa[0]=jj/10+'0';
39
  aa[1]=jj%10+'0';
40
  aa[2]='.';
41
  aa[3]='B';
42
  aa[4]='M';
43
  aa[5]='P';
44
  aa[6]='\0';
45
  }
46
  
47
48
  res = f_open(&fsrc, aa, FA_OPEN_EXISTING | FA_READ);   //´òÉÏͼƬÎļþÃû
49
  res = f_read(&fsrc, &bmp, sizeof(bmp), &br);
50
  if((bmp.pic_head[0]=='B')&&(bmp.pic_head[1]=='M'))
51
   {
52
  res = f_lseek(&fsrc, ((bmp.pic_data_address_h<<16)|bmp.pic_data_address_l));
53
54
55
  for(tx=0;tx<bmp.pic_h_l;tx++){
56
  
57
              f_read(&fsrc, buffer, (bmp.pic_w_l)*3, &br);
58
               f_read(&fsrc, buffer, (bmp.pic_w_l), &br);
59
              for(ty=0;ty<bmp.pic_w_l;ty++){
60
61
                r_data = *(ty*3 +2+buffer);
62
                g_data = *(ty*3 +1+buffer);
63
                b_data = *(ty*3 +0+buffer);  
64
                  point.x = tx;
65
                  point.y = ty;
66
                  point.r = r_data;
67
                  point.g = g_data;
68
                  point.b = b_data;
69
              //Èç¹ûÓÃÌṩ×ÊÁÏÉϵÄÆÁÇý¶¯¡£DrawPixelº¯ÊýÀïÃæµÄX  YÊÇu8 .Òª¸Ä³Éu16  
70
                                LCD_SetPoint(point.y,point.x ,RGB888ToRGB565(point.r,point.g,point.b));  
71
              }        
72
          }
73
    f_close(&fsrc);  
74
   }
75
}
76
 }

von andreas (Gast)


Angehängte Dateien:

Lesenswert?

so hier hab ich nochmal 2 bilder
1 bild auf lcd
2 orginal bild

von vampire (Gast)


Lesenswert?

Moin,moin!
Die SD-Fkt. fopen/fseek funktionieren .
Die "Direction" des LCD (wahrscheinlich im *.h --wobei * hier LCD/GLCD 
o.ä.) muss um 90grad gedreht werden.
Dann ist es noch gespiegelt. Dazu muss ich die *.init sehen in der *.c;
Der Typ des Display-Controller ist ebenfalls nötig --

von andreas (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
Die Farben passen aber auch nich richtig:

von holger (Gast)


Lesenswert?

>Die Farben passen aber auch nich richtig:

Warum nimmst du nicht RGB565CONVERT()?

von andreas (Gast)


Lesenswert?

hab ich auch schon Probiert mit dem gleichen ergebniss,
das Bild wird angezeigt mit streifen im bild drin
egal ob ich RGB565CONVERT() oder RGB888ToRGB565() es bleiben immer die 
seltsamen streifen hier im bild 1 
Beitrag "Re: STM32 24Bit Bmp nach 565RGB Format"

von Ingo (Gast)


Lesenswert?

Wusstest du übrigens, dass ein u8 dem Copiler mehr Arbeit macht als ein 
int (32Bit!), da es eine 32Bit CPU ist?

von holger (Gast)


Lesenswert?

Steht das wirklich so in deinem Code?

              f_read(&fsrc, buffer, (bmp.pic_w_l)*3, &br);
               f_read(&fsrc, buffer, (bmp.pic_w_l), &br);

Mit dem zweiten f_read bügelst du über buffer drüber.

von lapsi (Gast)


Lesenswert?

Kannst Du's mal mit einem Farbtestbild versuchen. Vielleicht kann man 
dann besser erkennen, wie der Fehler entsteht.

von andreas (Gast)


Lesenswert?

holger schrieb:
> Steht das wirklich so in deinem Code?
>
>               f_read(&fsrc, buffer, (bmp.pic_w_l)*3, &br);
>                f_read(&fsrc, buffer, (bmp.pic_w_l), &br);
>
> Mit dem zweiten f_read bügelst du über buffer drüber.
hatte ich wohl vergessen auszuklammern
So ists bei mir

1
void test(void)
2
{
3
  u8 scan_bit1;  //µ¥¸ö°´¼üɨÃè±äÁ¿
4
  u8 scan_bit2;  //µ¥¸ö°´¼üɨÃè±äÁ¿
5
  char aa[10];
6
  int jj=1;
7
  f_mount(0, &fs);
8
  while(1)
9
  {
10
11
12
  //LCD_Clear(BLUE);
13
  scan_bit1 = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3);
14
  scan_bit2 = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_8);
15
  if(scan_bit1==0) jj++; 
16
  if(scan_bit2==0) jj--;
17
  jj++;
18
  if(jj<1) jj=9;
19
  if(jj>9) jj=1;
20
  Delay(400);
21
22
23
  if(jj<10)
24
  {
25
    aa[0]=jj+'0';
26
  aa[1]='.';
27
  aa[2]='B';
28
  aa[3]='M';
29
  aa[4]='P';
30
  aa[5]='\0';
31
  }
32
  else
33
  {
34
    aa[0]=jj/10+'0';
35
  aa[1]=jj%10+'0';
36
  aa[2]='.';
37
  aa[3]='B';
38
  aa[4]='M';
39
  aa[5]='P';
40
  aa[6]='\0';
41
  }
42
  
43
44
  res = f_open(&fsrc, aa, FA_OPEN_EXISTING | FA_READ);   //´òÉÏͼƬÎļþÃû
45
  res = f_read(&fsrc, &bmp, sizeof(bmp), &br);
46
  if((bmp.pic_head[0]=='B')&&(bmp.pic_head[1]=='M'))
47
   {
48
  res = f_lseek(&fsrc, ((bmp.pic_data_address_h<<16)|bmp.pic_data_address_l));
49
50
51
  for(tx=0;tx<bmp.pic_h_l;tx++){
52
  
53
              f_read(&fsrc, buffer, (bmp.pic_w_l)*3, &br);
54
           
55
              for(ty=0;ty<bmp.pic_w_l;ty++){
56
57
                r_data = *(ty*3 +2+buffer);
58
                g_data = *(ty*3 +1+buffer);
59
                b_data = *(ty*3 +0+buffer);  
60
                  point.x = tx;
61
                  point.y = ty;
62
                  point.r = r_data;
63
                  point.g = g_data;
64
                  point.b = b_data;
65
              //Èç¹ûÓÃÌṩ×ÊÁÏÉϵÄÆÁÇý¶¯¡£DrawPixelº¯ÊýÀïÃæµÄX  YÊÇu8 .Òª¸Ä³Éu16  
66
                                LCD_SetPoint(point.y,point.x ,RGB888ToRGB565(point.r,point.g,point.b));  
67
              }        
68
          }
69
    f_close(&fsrc);  
70
   }
71
}
72
 }

von vampire (Gast)


Lesenswert?

-nach dem ebay-Bild steht da HY32D und google ergibt
http://www.hotmcu.com/32-touch-screen-tft-lcd-with-16-bit-parallel-interface-p-36.html
ein    ILI9320 LCD-Controller;
jetzt in LCD_Init nach DeviceCode==0x9320 gesucht und
LCD_WriteReg(0x60,0x2700);  /* Driver Output Control */
in
LCD_WriteReg(0x60,0xA700);  /* Driver Output Control */
umgewandelt;
-probier mal !

von vampire (Gast)


Lesenswert?

-und haste dein Bild eigentlich schon gedreht?
sonst in glcd.h --> #define DISP_ORIENTATION          0

von vampire (Gast)


Lesenswert?

andreas schrieb:
> das Bild wird angezeigt mit streifen im bild drin

zieh mal die Schutzfolie ab!

von andreas (Gast)


Angehängte Dateien:

Lesenswert?

vampire schrieb:
> andreas schrieb:
>> das Bild wird angezeigt mit streifen im bild drin
>
> zieh mal die Schutzfolie ab!

Hab ich gemacht es bleiben aber weiterhin die Strifen im Display
woran kann das denn nur liegen wenn ich die Original aplikation drauf 
lade
sind keine Fehlstellen auf dem display

von andreas (Gast)


Lesenswert?

hallo,
Der Display controller ist ein SSD1289 Das Display sebst ist ein HY32C

Egal was ich ein stelle bei der #define DISP_ORIENTATION  0
bekomme ich das Display sebst nicht gedreht es bleibt immer in der 
240x320 Position

von vampire (Gast)


Lesenswert?

DeviceCode = LCD_ReadReg(0x0000);    /* ¶ÁÈ¡ÆÁID  */
  if(DeviceCode==0x9325 || DeviceCode==0x9328)  /* ²»Í¬ÆÁÇý¶¯IC 
³õÊŒ»¯²»Í¬ */
  {
und
else if(DeviceCode==0x8989)
  {
-- ich habe auchnoch ein SSD1289(sainsmart) auf meinem Board(Selbstbau);
Dies kann man aber nicht auslesen !!!
Daher hab ich LCD_ReadReg(0x0000) ausgeklammert.Würde ich Dir auch 
empfehlen, denn dein Display ist doch fest verbaut(Kein Steckplatz?)
-obiges ausklammern(und die schliessenden Klammern)
Sowie die anderen Display-init raus;

Der Unterschied im Init-Ablauf ist wohl nur dies Register
-bei Dir:
LCD_WriteReg(0x0007,0x0133);    LCD_Delay(5);
-bei mir:
LCD_WriteReg(0x0007,0x0233);    delay_ms(1);

Ohne das gesammte Projekt vor mir zu haben, ist dies alles aber nur ein 
planloses "Rumgestochere" --

von vampire (Gast)


Lesenswert?

LCD_WriteReg(0x001E,0x00B7);    delay_ms(1);
LCD_WriteReg(0x0007,0x0233);    delay_ms(1);

-- und diese beiden sind anders;

von Karl H. (kbuchegg)


Lesenswert?

andreas schrieb:

> Hab ich gemacht es bleiben aber weiterhin die Strifen im Display
> woran kann das denn nur liegen wenn ich die Original aplikation drauf
> lade
> sind keine Fehlstellen auf dem display

In deinem Bild sieht man recht deutlich, dass zb in dem grünen Blatt 
rote Punkte enthalten sind.
Für mich sieht das danach aus, dass deine Bitkodierung hier
 LCD_SetPoint(point.y,point.x ,RGB888ToRGB565(point.r,point.g,point.b));
nicht stimmt.

An deiner Stelle würde ich mir erst mal klar machen, und auch 
ausprobieren, wie die Bits sein müssen. An welcher Stelle die einzelnen 
Farbbits sitzen und wie sie gegeneinander im int verschoben sind. 
Irgendwas geht da in deinen Funtionen / Makros schief, bzw. ist nicht 
richtig.

Mit einem Bild eines Papagei kriegst du das aber nicht raus. Das muss 
man systematisch mit Farbverläufen angehen. Sonst dauert das alles 5 mal 
so lange als notwendig. Also nicht einfach nur ein Bild da drauf 
klatschen, sondern

  for( red = 0; red < 255; red ++)
    Pixel mit RGB888ToRGB565( red, 0, 0 ) ausgeben

Das muss einen roten Farbkeil ergeben, andere Farbpixel dürfen nicht zu 
sehen sein. Wenn doch: nachgehen in welchen red-WErten sie auftreten, 
nachvollziehen wie RGB888ToRGB565 das in die 5 Pixel reinverschiebt und 
mit dem Datenblatt vergleichen, ob das so richtig ist.

Selbiges mit den anderen Farben.

Damit kommt man dem recht schnell auf die Spur, wo welche Bits falsch 
verschoben werden und an der falschen Stelle im 565-Ergebnis rauskommen. 
Aus dem sichtbaren Bild und der Position der Pixel kannst du dann mehr 
oder weniger die komplette Berechnungskette nachvollziehen.
Aber indem du ein Photo auf das Display klatscht, siehst genau gar 
nichts, ausser das das Bild komisch aussieht. Fehlersuche beginnt immer 
damit, dass man sich einen einfachen Testfall konstruiert, mit dem man 
nachvollziehbar und immer gleich den ganzen Prozess von vorne bis hinten 
systematisch durchleuchten kann. Je einfacher diese Test ist (auch in 
den Zahlenwerten), desto besser. Ein fertiges Photo hat viel zu viel 
"Unruhe" und "Unsystematik" in den Zahlenwerten, um für die Fehlersuche 
auf unterster Bit-Ebene nützlich zu sein.

von andreas (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
Ich habe noch ein Problem mit dem anzeigen vom BMPs aus
dem internen Flash.
Leider wird das pic nicht geladen
Vielleicht könnte mir da einer weiterhelfen.

Aufruf  zum anzeigen:
LCD_DrawPicture(0,0,20,20, "RButtonA") ;

MFG

von andreas (Gast)


Lesenswert?

Hallo,
Beim auslesen der Bitmaps von sd karte dind erstmal die streifen im Bild 
weg.
Allerdings wird das bild nur in blau und schwarztöne wiedergegeben.

Vielleicht könnte mir jemand weiterhelfen
mfg
1
#define B_BITS 5
2
#define G_BITS 6
3
#define R_BITS 5
4
5
#define R_MASK ((1 << R_BITS) -1)
6
#define G_MASK ((1 << G_BITS) -1)
7
#define B_MASK ((1 << B_BITS) -1)
8
9
uint16_t LCD_Color2Index_565(uint32_t Color) {
10
11
  uint16_t r,g,b;
12
  r = (Color>> (8  - B_BITS)) & R_MASK;
13
  g = (Color>> (16 - G_BITS)) & G_MASK;
14
  b = (Color>> (24 - R_BITS)) & B_MASK;
15
   return r + (g << R_BITS) + (b << (G_BITS + R_BITS));
16
} 
17
18
     
19
  
20
void test(unsigned int point_x , unsigned int point_y ,char *name)
21
{
22
 uint32_t rgb;    
23
 
24
  res = f_open(&fsrc, name, FA_READ);    
25
  if ( res == FR_OK )
26
  { 
27
    f_read(&fsrc, (uint8_t *)&bmp, sizeof(bmp), &br);   
28
    if( (bmp.pic_head[0]=='B') && (bmp.pic_head[1]=='M') )  
29
    {
30
        f_lseek(&fsrc, ((bmp.pic_data_address_h<<16)|bmp.pic_data_address_l));
31
       for(ty=0;ty<bmp.pic_h_l;ty++)
32
    
33
    {  
34
      f_read(&fsrc, &buffer[0], (bmp.pic_w_l)*3, &br);
35
      for(tx=0;tx<bmp.pic_w_l;tx++)
36
      {
37
          point.r = *(tx*3 +2+buffer);
38
        point.g = *(tx*3 +1+buffer);
39
        point.b = *(tx*3 +0+buffer);                
40
        point.x = tx;
41
        point.y = bmp.pic_h_l -1 -ty;//ty;
42
43
          rgb   =    point.r | point.g | point.b;  
44
      LCD_SetPoint(point.x + point_x  ,point.y + point_y  ,LCD_Color2Index_565(rgb));
45
46
    }                         
47
    }
48
    } 
49
    /*close file */
50
    f_close(&fsrc);      
51
 
52
53
  }
54
55
}

von Falk B. (falk)


Lesenswert?

Vergiss erstmal die Bilder, erzeuge ein künstliches Testbild.

Beitrag "Re: STM32 24Bit Bmp nach 565RGB Format"

Fehlersuche

von holger (Gast)


Lesenswert?

>Ich habe noch ein Problem mit dem anzeigen vom BMPs aus
>dem internen Flash.

>Aufruf  zum anzeigen:
>LCD_DrawPicture(0,0,20,20, "RButtonA") ;

Wirklich sehr lustig. Du hast keine Ahnung von C.
Dein Flash kennt keine Dateien.

So wird da vieleicht ein Bild draus

LCD_DrawPicture(0,0,20,20, RButtonA);

Hast du mal auch nur einen Blick auf die Warnungen vom Compiler 
geworfen?

von andreas (Gast)


Lesenswert?

So wenn ich die Bild grösse auf 100x100 Pixel setze dann stimmen alle 
Farben
mit RGB888ToRGB565 .
An was kann denn die nur liegen das bmps gösser 100x100 nicht richtig 
dargestellt werden

von andreas (Gast)


Lesenswert?

Scheinbar gibs niemand der die rgb convert funktion benuzt .
Denn bis 100x100 pixel gehts ja.

von Falk B. (falk)


Lesenswert?

Hast du mal versucht, die Bildgröße punktweise zu ändern? Also 101, 102 
etc.? Möglicherweise hat die Funktion ein Problem mit nicht durch 4/8/16 
whatever teilbaren Abmessungen.

von Uwe B. (derexponent)


Lesenswert?

Hi andreas,

-bei BMP Files werden die Anzahl der Bytes pro Zeile
immer auf ein vielfaches von 4 "aufgerundet"
(es werden 0 bis 3 Füllbytes mit 0x00 eingefügt)

d.h wenn du ein Bild mit der X-Auflösung von z.B. 5 Pixel hast,
werden pro Zeile 16 Bytes gespeichert

5*3 Bytes für die Farbinformation der 5 Pixel = (15 Bytes)
1 Fülllbytes (mit 0x00)


bei einer Breite von 7 Pixel werden 24 Bytes gespeichert :
7*3 Bytes für die Farbinformation der 7 Pixel = (21 Bytes)
3 Fülllbytes (mit 0x00)

wahrscheinlich kommt daher dein Problem

ein Bild mit der Breite von 100 Pixel
besitzt keine Füllbytes (weil 100/4 ohne Rest teilbar ist)

Gruss Uwe

von andreas (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
Wenn meine Auflösung bei 320 Pixel liegt ,dann hab ich doch gar kein 
Rest wenn ich 320:4 = 80
oder liege ich da falsch.

Anbei noch 2 Pics.
display = so wirds auf dem Display angezeigt

orginal = so sollte es sein
mfg

von holger (Gast)


Lesenswert?

>      f_read(&fsrc, &buffer[0], (bmp.pic_w_l)*3, &br);

Wie gross ist buffer eigentlich?
Du liest da ja scheinbar eine komplette Zeile.
320 x 3 = 960 Bytes.

von andreas (Gast)


Lesenswert?

char buffer[1024];

von Falk B. (falk)


Lesenswert?

Das ist eindeutig ein Problem mit der Länge einer Zeile, denn es gibt 
ein typisches, konstantes Treppenmuster, welches auftritt, wenn der 
LCD-Controller die Daten mit einer anderen Zeilenlänge liest als sie im 
Speicher stehen. Ergo schreibt jemand die Daten mit der falschen 
Zeilenlänge in den Framebuffer.

von holger (Gast)


Lesenswert?

>char buffer[1024];

Ok, reicht.

Wo ist dein kompletter Sourcecode?
Poste auch mal die Bitmapdatei.

Am weissen Balken sieht man eigentlich schon das
irgendwie ein Offset in der Reihenfolge der RGB Bytes ist.
Die kleinen Ausfransungen am Rand.

von Falk B. (falk)


Lesenswert?

Hm, ich rate mal. Das Bild hat bei 320 Pixel Breite 5 Streifen, macht 64 
Pixel / Streifen. Die Farben sind rot-blau-grün-weis-schwarz. Wenn man 
genau hinsieht, gibt es einige Zeilen, wo das passt. In der nächsten 
Zeile ist Blau plötzlich um 1/3 verkürzt. 1/3 von 64 Pixel sind ~21 
Pixel.

Eine Zeile in 565 Kodierung hat 640 Byte, in 888 960 Byte
Ein Streifen also in 555 128 Byte bzw. in 888 192.
1/3 Streifen sind somit ~ 42 Byte, in 888 64.

Scheinbar werden pro Zeile 42 Bytes zu wenig geschrieben. ODER der 
Controller ist intern auf eine größere Zeilenlänge programmiert, nur 
dass nicht alles angezeigt wird. Dann muss ein Schreibroutone die 
größere, virtuelle Zeilenlänge bei der Berechung der Anfangsadresse der 
nächsten Zeile berücksichtigen.

von andreas (Gast)


Angehängte Dateien:

Lesenswert?

>Poste auch mal die Bitmapdatei.
hier
Beitrag "Re: STM32 24Bit Bmp nach 565RGB Format"
1
typedef struct
2
{
3
  u8  pic_head[2];        //1
4
  u16 pic_size_l;          //2
5
  u16 pic_size_h;          //3
6
  u16 pic_nc1;            //4
7
  u16 pic_nc2;            //5
8
  u16 pic_data_address_l;      //6
9
  u16 pic_data_address_h;    //7  
10
  u16 pic_message_head_len_l;  //8
11
  u16 pic_message_head_len_h;  //9
12
  u16 pic_w_l;          //10
13
  u16 pic_w_h;            //11
14
  u16 pic_h_l;            //12
15
  u16 pic_h_h;            //13  
16
  u16 pic_bit;            //14
17
  u16 pic_dip;            //15
18
  u16 pic_zip_l;          //16
19
  u16 pic_zip_h;          //17
20
  u16 pic_data_size_l;        //18
21
  u16 pic_data_size_h;        //19
22
  u16 pic_dipx_l;          //20
23
  u16 pic_dipx_h;          //21  
24
  u16 pic_dipy_l;          //22
25
  u16 pic_dipy_h;          //23
26
  u16 pic_color_index_l;      //24
27
  u16 pic_color_index_h;      //25
28
  u16 pic_other_l;          //26
29
  u16 pic_other_h;          //27
30
  u16 pic_color_p01;        //28
31
  u16 pic_color_p02;        //29
32
  u16 pic_color_p03;        //30
33
  u16 pic_color_p04;        //31
34
  u16 pic_color_p05;        //32
35
  u16 pic_color_p06;        //33
36
  u16 pic_color_p07;        //34
37
  u16 pic_color_p08;      //35      
38
}BMP_HEAD;
39
40
BMP_HEAD bmp;
41
42
typedef struct
43
{
44
  u16 x;
45
  u16 y;
46
47
  u8  r;
48
  u8  g;
49
  u8  b;    
50
}BMP_POINT;
51
52
BMP_POINT point;
53
54
uint16_t  tx,ty;
55
56
57
FATFS fs;            // Work area (file system object) for logical drive
58
FIL fsrc, fdst;      // file objects
59
FRESULT res;         // FatFs function common result code
60
FIL  fil;           // 
61
char buffer[1024];  // file copy buffer
62
unsigned int  br;                // File R/W count
63
64
65
66
 //24λ¡£¡£±ä³É16λͼ 
67
u32 RGB888ToRGB565(u8 r,u8 g,u8 b)
68
 {return (u32) (r & 0xF8) << 8 | (g & 0xFC) << 3 | (b & 0xF8) >> 3;}  //565
69
70
71
72
 
73
void read_pic(uint16_t point_x , uint16_t point_y ,char *name)
74
{
75
76
 
77
  res = f_open(&fsrc, name, FA_READ);    
78
  if ( res == FR_OK )
79
  { 
80
    f_read(&fsrc, (uint8_t *)&bmp, sizeof(bmp), &br);   
81
    if( (bmp.pic_head[0]=='B') && (bmp.pic_head[1]=='M') )  
82
    {
83
        f_lseek(&fsrc, ((bmp.pic_data_address_h<<16)|bmp.pic_data_address_l));
84
       for(ty=0;ty<bmp.pic_h_l;ty++)
85
    
86
    {  
87
      f_read(&fsrc, &buffer[0], (bmp.pic_w_l)*3, &br);
88
      for(tx=0;tx<bmp.pic_w_l;tx++)
89
      {
90
        point.r = *(tx*3 +2+buffer);
91
        point.g = *(tx*3 +1+buffer);
92
        point.b = *(tx*3 +0+buffer);                
93
        point.x = ty;//tx;
94
        point.y = tx;//bmp.pic_h_l -1 -ty;//ty;
95
      
96
97
98
        LCD_SetPoint(point.x+ point_x  ,point.y + point_y  ,RGB888ToRGB565(point.r,point.g,point.b));  
99
100
     }                         
101
   }
102
  } 
103
    /*close file */
104
    f_close(&fsrc);      
105
 }
106
}

von holger (Gast)


Lesenswert?

>>Poste auch mal die Bitmapdatei.
>hier
>Beitrag "Re: STM32 24Bit Bmp nach 565RGB Format"

Danach habe ich nicht gefragt. Ich will die Bitmap Datei.

von andreas (Gast)


Lesenswert?

Das Bitmap ist auf der sd-Card gespeichert

von holger (Gast)


Lesenswert?

>Das Bitmap ist auf der sd-Card gespeichert

Dann schick mir deine SD Karte.

von andreas (Gast)


Angehängte Dateien:

Lesenswert?

bitte

von holger (Gast)


Lesenswert?

>bitte

Das ist keine Bitmap, das ist ein PNG.

von SummerWilli (Gast)


Lesenswert?

das hat mikrocontroller.net so gemacht

von W.Sprengel (Gast)


Lesenswert?

holger schrieb:
>>Das Bitmap ist auf der sd-Card gespeichert
>
> Dann schick mir deine SD Karte.

Ich lach mich schlapp. Mir wäre das schon lange zuviel wenn Ratschläge 
permanent ignoriert werden...

von holger (Gast)


Lesenswert?

>das hat mikrocontroller.net so gemacht

Ja, ok sorry für die Anmache.

Dann halt Bitmap als ZIP packen.

von andreas (Gast)


Angehängte Dateien:

Lesenswert?

so bitte

von SummerWilli (Gast)


Lesenswert?

probiert mal:
f_read(&fsrc, &buffer[0], (((bmp.pic_w_l)*3)/8)*8, &br);
anstatt:
f_read(&fsrc, &buffer[0], (bmp.pic_w_l)*3, &br);

von SummerWilli (Gast)


Lesenswert?

entschuldigung.
ich meinte:
f_read(&fsrc, &buffer[0], (((bmp.pic_w_l)*3+7)/8)*8, &br);

von andreas (Gast)


Angehängte Dateien:

Lesenswert?

das ist besser aber diese schatierung in den farben

von holger (Gast)


Lesenswert?

>so bitte

Danke Andreas. Noch mal Entschuldigung für den rauhen Ton.
Dein Problem ist schon etwas komisch.

In deinem Foto sieht man das jede Zeile mit einem weissen Pixel anfängt.
Genau so wie in der Bitmap. Das spricht gegen einen Offset wie ich oder 
auch Falk vermutet haben.

In der obersten Zeile passen die weissen Pixel auch noch.
Sie gehen über den (eigentlich) roten Balken.

Und dann wird es merkwürdig. Rot geht noch so, blau ist nicht wirklich 
blau
sondern grün und grün passt gar nicht mehr so richtig und ist eher 
braun.
Dann kommen noch die merkwürdigen Farbtreppen dazu. Sowas kommt 
eigentlich
von einem falschen Offset beim schreiben der RGB Daten oder falcher 
Einstellung des Displays.

Letzter Versuch:
Schreib deine Routine mal um:

Moment mal:

        point.x = ty; //holger wieso eigentlich x zu y?
        point.y = tx; //holger wieso eigentlich y zu x?

von Uwe B. (derexponent)


Lesenswert?

andreas schrieb:
> Wenn meine Auflösung bei 320 Pixel liegt ,dann hab ich doch gar kein
> Rest wenn ich 320:4 = 80


es kommt nicht auf die Breite von deinem Display an,
sondern auf die Breite von den BMP-Bild

hat das auch eine Breite von 320 Pixel ?

hier die Beschreibung aus der WIKI vom BMP-Format :

"Jede Bildzeile ist durch rechtsseitiges Auffüllen mit Nullen auf ein 
ganzzahliges Vielfaches von 4 Bytes ausgerichtet. "




Gruss Uwe

von vampire (Gast)


Lesenswert?

statt dein Bild in der lcd.h zu drehen, hast Du den Cursor gedreht.
if(DeviceCode==0x8989)
  {
  LCD_WriteReg(0x004e,Ypos);          /* Line */
    LCD_WriteReg(0x004f,0x13f-Xpos);    /* Row */
  }
in LCD_SetCursor(uint16_t Xpos,uint16_t Ypos);
-deine Fkt. LCD_DrawPicture und LCD_SetPoint schreiben nun eine 
Bildzeile (320 Pix ) auf 240 -->
dadurch die Artefarkte;

von SummerWilli (Gast)


Lesenswert?

>"Jede Bildzeile ist durch rechtsseitiges Auffüllen mit Nullen auf ein
>ganzzahliges Vielfaches von 4 Bytes ausgerichtet. "

Ok. dann sollte es eher so sein:
f_read(&fsrc, &buffer[0], (((bmp.pic_w_l)*3+3)/4)*4, &br);
Das alleine ändert aber nichts an Deinem Problem.

>statt dein Bild in der lcd.h zu drehen, hast Du den Cursor gedreht.
Was passiert denn, wenn Du's wieder änderst auf:
point.x = tx;
point.y = ty;
?

von SummerWilli (Gast)


Lesenswert?

1
#include <stdio.h>
2
3
typedef unsigned char u8;
4
typedef unsigned short int u16;
5
typedef unsigned int u32;
6
typedef unsigned short int uint16_t;
7
8
typedef struct
9
{
10
  u8  pic_head[2];        //1
11
  u16 pic_size_l;          //2
12
  u16 pic_size_h;          //3
13
  u16 pic_nc1;            //4
14
  u16 pic_nc2;            //5
15
  u16 pic_data_address_l;      //6
16
  u16 pic_data_address_h;    //7  
17
  u16 pic_message_head_len_l;  //8
18
  u16 pic_message_head_len_h;  //9
19
  u16 pic_w_l;          //10
20
  u16 pic_w_h;            //11
21
  u16 pic_h_l;            //12
22
  u16 pic_h_h;            //13  
23
  u16 pic_bit;            //14
24
  u16 pic_dip;            //15
25
  u16 pic_zip_l;          //16
26
  u16 pic_zip_h;          //17
27
  u16 pic_data_size_l;        //18
28
  u16 pic_data_size_h;        //19
29
  u16 pic_dipx_l;          //20
30
  u16 pic_dipx_h;          //21  
31
  u16 pic_dipy_l;          //22
32
  u16 pic_dipy_h;          //23
33
  u16 pic_color_index_l;      //24
34
  u16 pic_color_index_h;      //25
35
  u16 pic_other_l;          //26
36
  u16 pic_other_h;          //27
37
  u16 pic_color_p01;        //28
38
  u16 pic_color_p02;        //29
39
  u16 pic_color_p03;        //30
40
  u16 pic_color_p04;        //31
41
  u16 pic_color_p05;        //32
42
  u16 pic_color_p06;        //33
43
  u16 pic_color_p07;        //34
44
  u16 pic_color_p08;      //35      
45
}BMP_HEAD;
46
47
BMP_HEAD bmp;
48
49
typedef struct
50
{
51
  u16 x;
52
  u16 y;
53
54
  u8  r;
55
  u8  g;
56
  u8  b;    
57
}BMP_POINT;
58
59
BMP_POINT point;
60
61
u16  tx,ty;
62
63
FILE *f;
64
65
char buffer[1024];  // file copy buffer
66
unsigned int  br;                // File R/W count
67
68
69
70
 //24λ¡£¡£±ä³É16λͼ 
71
u32 RGB888ToRGB565(u8 r,u8 g,u8 b)
72
 {return (u32) (r & 0xF8) << 8 | (g & 0xFC) << 3 | (b & 0xF8) >> 3;}  //565
73
74
75
76
 
77
void read_pic(uint16_t point_x , uint16_t point_y)
78
{
79
80
  f = fopen("test.bmp", "rt");
81
82
83
    fread((u8 *)&bmp, 1,sizeof(bmp), f); 
84
    if( (bmp.pic_head[0]=='B') && (bmp.pic_head[1]=='M') )  
85
    {
86
 
87
  fseek(f,  ((bmp.pic_data_address_h<<16)|bmp.pic_data_address_l), SEEK_SET);
88
printf("%d\n",((bmp.pic_data_address_h<<16)|bmp.pic_data_address_l));
89
90
       for(ty=0;ty<bmp.pic_h_l/2;ty++)
91
    
92
       { 
93
  fread(&buffer[0], 1, (((bmp.pic_w_l)*3+3)/4)*4, f); 
94
        for(tx=0;tx<bmp.pic_w_l;tx++)
95
          {
96
            point.r = *(tx*3 +2+buffer);
97
            point.g = *(tx*3 +1+buffer);
98
            point.b = *(tx*3 +0+buffer);                
99
            point.x = ty;//tx;
100
            point.y = tx;//bmp.pic_h_l -1 -ty;//ty;
101
      printf("%d %d %d\n",point.x+ point_x  ,point.y + point_y  ,RGB888ToRGB565(point.r,point.g,point.b));
102
            //LCD_SetPoint(point.x+ point_x  ,point.y + point_y  ,RGB888ToRGB565(point.r,point.g,point.b));  
103
104
         }                         
105
       }
106
107
    }
108
    /*close file */
109
    fclose(f);      
110
}
111
112
113
114
main()
115
{
116
 read_pic(0,0);
117
}
Habs nach Linux portiert. Klappt alles, ohne die Streifen. Es muss also 
entweder am Filesystem oder an der LCD Ausgabe liegen.

von Phil (Gast)


Lesenswert?

Hallo,

ich hatte ein ähnliches Problem allerdings mit einem AVR32.

Hier hatte ich das Endian vertauscht. Das tauscht bei 888 nur die 
Farbenreihenfolge, bei 565 wirft es die Farben aber durcheinander. Ich 
kenn jetzt den STM32 nicht, weiß auch nicht welches Endiansystem er 
verwendet.

Außerdem hatte ich ähnliche Fehler da das Display hardwaretechnisch auf 
18 bit codiert und meine Ausgabe mit dem Displaycontroller auf 24bit. 
(Wie als wenn ein LVDS Kanal fehlt).

Ist die Front und Back Porch des Displays korrekt eingestellt oder ist 
das dort fest eingegossen?

4 Byte Padding beim Bitmap lesen? Der BMP Header erscheint mir außerdem 
etwas lang: sicher, dass dieser so in der Datei vorhanden ist? evtl. mal 
mit Hex Editor reinschauen.

Außerdem stellt sich mir die Frage, warum die Bilder nicht direkt im 565 
Format gespeichert werden. Das erhöht die Performance doch gewaltig.

Gruß
Phil

von SummerWilli (Gast)


Lesenswert?

Wenn Du nicht weiterkommst, dann ersetzte mal
LCD_SetPoint(point.x+ point_x  ,point.y + point_y 
,RGB888ToRGB565(point.r,point.g,point.b));
durch
LCD_SetPoint(point.x+ point_x  ,point.y + point_y 
,RGB888ToRGB565(ty,0,0));
und später durch
LCD_SetPoint(point.x+ point_x  ,point.y + point_y  ,ty);

Hast Du dann einen gleichmäßigen Farbverlauf ? Oder sind die Striche 
immer noch drin ?

von andreas (Gast)


Lesenswert?

SummerWilli schrieb:
> Wenn Du nicht weiterkommst, dann ersetzte mal
> LCD_SetPoint(point.x+ point_x  ,point.y + point_y
> ,RGB888ToRGB565(point.r,point.g,point.b));
> durch
> LCD_SetPoint(point.x+ point_x  ,point.y + point_y
> ,RGB888ToRGB565(ty,0,0));
> und später durch
> LCD_SetPoint(point.x+ point_x  ,point.y + point_y  ,ty);
>
> Hast Du dann einen gleichmäßigen Farbverlauf ? Oder sind die Striche
> immer noch drin ?

Hiermit sind keine striche mehr drin
mfg

von andreas (Gast)


Angehängte Dateien:

Lesenswert?

hiermit werd die BMP's bis 168x320 ohne Streifen angezeigt
es liegt denn an dieser Zeile
Das Funktioniert mit BMP's 168x320
f_read(&fsrc, &buffer, (((bmp.pic_w_l)*3+3)/4)*4, &br);

bmp.pic_w_l=168
168*3+3/4*4 = 507

Wie kann ich das umrechnen damit das auch mit 240x320
geht
1
void read_pic(uint16_t point_x , uint16_t point_y ,char *name)
2
{
3
4
 res = f_open(&fsrc, name, FA_READ);    
5
 if ( res == FR_OK )
6
 { 
7
  f_read(&fsrc, (uint8_t *)&bmp, sizeof(bmp), &br);   
8
  if( (bmp.pic_head[0]=='B') && (bmp.pic_head[1]=='M') )  
9
   {
10
    res = f_lseek(&fsrc, ((bmp.pic_data_address_h<<16)|bmp.pic_data_address_l));
11
12
      ty=bmp.pic_h_l;
13
      while(ty) {
14
      
15
          ty--;
16
             // 168x320
17
         f_read(&fsrc, &buffer, (((bmp.pic_w_l)*3+3)/4)*4, &br);
18
       
19
       for(tx=0;tx<bmp.pic_w_l;tx++) 
20
        {
21
               point.r = *(tx*3 +2+buffer);
22
               point.g = *(tx*3 +1+buffer);
23
               point.b = *(tx*3 +0+buffer);       
24
                 
25
           if(tx<320)
26
           {
27
                    point.x = ty;//ty;
28
                    point.y = tx;//tx;
29
                          
30
              LCD_SetPoint(point.x+ point_x  ,point.y + point_y  ,RGB888ToRGB565(point.r,point.g,point.b));  
31
                   }               
32
              }
33
             if(ty==0) continue;
34
         }
35
       f_close(&fsrc);  
36
   }       
37
 }
38
}

von tom (Gast)


Angehängte Dateien:

Lesenswert?

...hier hast du mal dein testbild als C-source uint16 array landscape 
korrekt im RGB565 format.

das sollte richtig angezeigt werden, wenn das address-window vorher 
korrekt gesetzt ist auf 320x240, die orientierung stimmt und die 
RGB-reihenfolge des display-controllers richtig konfiguriert wurde.

wenn du geschafft hast, dieses bild anzuzeigen kanst du ja mit eigener 
888->565 konvertierung und filezugriff weitermachen, schritt für 
schritt.

gutt lack, tom.

von andreas (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
also bei mir hängt sich alles auf.

Aufruf für das Pic LCD_WriteBMP(0,0,320,240,test_565 );
im Anhang die glcd Routine

von tom (Gast)


Lesenswert?

nun, auch ein (zugegeben unschöner) weg zur finalen lösung eines 
scheinbaren, wohl eher trolligem, problems.
ick hau mich wech, so ist meine gut gemeinte hilfe doch noch etwas wert 
;o)))).

meine oma hat immer gesagt: "Junge, wenn die Dummen fleissig werden, 
dann wird es gefährlich !".

Eine Bitte an die Mods, bitte diesen thread löschen.

Danke + Gute Nacht an alle hilfsbereiten und engagierten Leute hier !

tom.

von tom (Gast)


Lesenswert?

...ich habe gerade eine dieser O-Zitat des TO: "schatierungen" in meinem 
Glas Bier.

Wie wäre es mal mit einem Tuden ???

von andreas (Gast)


Lesenswert?

tom schrieb:
> nun, auch ein (zugegeben unschöner) weg zur finalen lösung eines
> scheinbaren, wohl eher trolligem, problems.
> ick hau mich wech, so ist meine gut gemeinte hilfe doch noch etwas wert
> ;o)))).
>
> meine oma hat immer gesagt: "Junge, wenn die Dummen fleissig werden,
> dann wird es gefährlich !".
>
> Eine Bitte an die Mods, bitte diesen thread löschen.
>
> Danke + Gute Nacht an alle hilfsbereiten und engagierten Leute hier !
>
> tom.

Sorry das gefragt habe.

von andreas (Gast)


Lesenswert?

so das Anzeigen des BMP von 
Beitrag "Re: STM32 24Bit Bmp nach 565RGB Format" Funktioniert 
Tadellos nur bleibt immer noch das Problem
dasbeim Lesen von sd  card immer diese streifen im Bild sind

von Torsten S. (tse)


Lesenswert?

andreas schrieb:
> so das Anzeigen des BMP von
> Beitrag "Re: STM32 24Bit Bmp nach 565RGB Format" Funktioniert
> Tadellos nur bleibt immer noch das Problem
> dasbeim Lesen von sd  card immer diese streifen im Bild sind

Mit dem gleichen Problem kämpfe ich auch gerade.

Im Prinzip ist der von Andreas verwendete Code eine Variante von in 
Chan's TJpgDec-Beispielprojekt enthaltenen load_bmp(); . Anders als die 
ST-Beispiele läuft das richtig fix und ist besser strukturiert. Wenn 
dieser Bug nicht wäre...

Mit einem einfarbigen Testbild sieht man sehr deutlich das manchmal 
falsch gelesen wird. Die Anzahl der Streifen kann man drastisch 
reduzieren wenn man buffer nennenswert erhöht. Hab ein externes 1MB SRAM 
on board und in reinem Übermut mal buffer[524288] probiert - nun sind 
nur noch 2-3 Streifen bei einem 800x480 großen Bitmap. Also bei jedem 
Nachladen von buffer.

Eine andere Vermutung wäre ein nicht an DWORD ausgerichteter Zugriff von 
buffer im SDIO Interface. Ist es aber nicht der Fall, habs überprüft.

Hat noch jemand dieses Problem?

von Uwe B. (derexponent)


Lesenswert?

Hi Torsten,

ich hab meine BMP-Funktionen nicht bis zum excess getestet
und auch eine Bildgrössen Begrenzung von 240x320 Pixel eingebaut
(weil mein Display nicht grösser ist)

aber Streifen hatte ich nie im Bild, wenn du willst,
schau doch mal den Code an und kopier dir die Teile raus
die du brauchst

das laden von einem 320x240 Bild mit 24bpp von SD-Karte dauert ca. 165ms
(ob das jetzt schnell oder langsam ist, musst du entscheiden)

Quellen gibt es hier :

http://mikrocontroller.bplaced.de

von Torsten S. (tse)


Lesenswert?

Hi Uwe,

Danke für den Hinweis, diese lib schaue ich mir gleich mal genauer an.

[OT]
Schade das Du meinen Bugreport fürs SDIO (Lib 13) noch nicht 
berücksichtigt hast - es sind wirklich nur ne handvoll Zeilen die 
eingepflegt werden müssen um Datenmüll auf der SD-Karte zu vermeiden.

von andreay (Gast)


Lesenswert?

Hi Torsten,
Also die SD-Card ist bei mir am SDIO-Interface angeschlossen, ich hab 
damals das Beispiel
Verwendet was auf der CD zu dem Board dabei war funktionierte nur leider 
nich Richtig.
Hab jetz eine andere Lib damit gehts wunderbar bis800x480.

von Uwe B. (derexponent)


Lesenswert?


von Torsten S. (tse)


Angehängte Dateien:

Lesenswert?

Jetzt gehts.

Es lag doch am SDIO.
Und zwar am nicht richtig ausgerichteten Puffer den die DMA überhaupt 
nicht leiden kann und dann stillschweigend die Bytes verwürfelt.

Das bedeutet, der von Andreas anfänglich gepostete Code sollte ohne 
Änderungen funktionieren wenn man Anpassungen am SDIO vornimmt. Der von 
ChaN tuts bei mir jetzt exzellent.

Die Sachen findet man bei ST im 
"STM32F2-F4_Demonstration_Builder_V1.3.0". Die interressante Datei hab 
ich einfach mal angehangen. Dort kann man sehen, was für ein riesen 
Aufwand getrieben wird beim lesen/schreiben.

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.