5 years, 10 months ago.

Mysterious display driver problem DISCO_F746NG parts of bitmap missing!

/media/uploads/Lightsource/image1.jpeg

As shown in this picture, a number of pixels in the upper rows are missing. What's instead shown there are left over pixels from the previous image written to the display, a full size blue bitmap. This despite the lcd.Clear() function has been run in between. So the big question is, what could be the reason for this strange behavior?

My function for loading file from SD-card and displaying it using the BSP_DISCO_F746NG library and the LCD_DISCO_746NG driver wrapper:

My function loading bmp from SD-card

void drawImage(char * name, uint16_t x, uint16_t y){
    int i, fileSize;
    char * buffer;
    FILE *Image = fopen(name, "rb");  // open the bmp file
  
    // obtain file size:
    fseek (Image , 0 , SEEK_END);
    fileSize = ftell (Image);
    rewind (Image);
    
    // allocate memory to contain the whole file:
    buffer = (char*) malloc (sizeof(char)*(fileSize+3)/4);
    
    // copy the file into the buffer:
    fseek (Image, 0 , SEEK_SET );  

    fread (buffer,1,fileSize,Image);
    fclose (Image);

    lcd.DrawBitmap(x,y,(uint8_t *)buffer);

    free (buffer);     
}

This is the bmp-file I'm loading, however I could not upload it here as a bmp so you need to rename it .bmp. Could be that the content is messed up by the browser, but it is supposed to be a 16 bit (5R 6G 5B) formatted bitmap. /media/uploads/Lightsource/minion16bit.jpg

BSP_DISCO_F746NG bitmap function

void BSP_LCD_DrawBitmap(uint32_t Xpos, uint32_t Ypos, uint8_t *pbmp)
{
  uint32_t index = 0, width = 0, height = 0, bit_pixel = 0;
  uint32_t address;
  uint32_t input_color_mode = 0;
  
  /* Get bitmap data address offset */
  index = *(__IO uint16_t *) (pbmp + 10);
  index |= (*(__IO uint16_t *) (pbmp + 12)) << 16;
  
  /* Read bitmap width */
  width = *(uint16_t *) (pbmp + 18);
  width |= (*(uint16_t *) (pbmp + 20)) << 16;
  
  /* Read bitmap height */
  height = *(uint16_t *) (pbmp + 22);
  height |= (*(uint16_t *) (pbmp + 24)) << 16; 
  
  /* Read bit/pixel */
  bit_pixel = *(uint16_t *) (pbmp + 28);   
  
  /* Set the address */
  address = hLtdcHandler.LayerCfg[ActiveLayer].FBStartAdress + (((BSP_LCD_GetXSize()*Ypos) + Xpos)*(4));
  
  /* Get the layer pixel format */    
  if ((bit_pixel/8) == 4)
  {
    input_color_mode = CM_ARGB8888;
  }
  else if ((bit_pixel/8) == 2)
  {
    input_color_mode = CM_RGB565;   
  }
  else 
  {
    input_color_mode = CM_RGB888;
  }
  
  /* Bypass the bitmap header */
  pbmp += (index + (width * (height - 1) * (bit_pixel/8)));  
    
  /* Convert picture to ARGB8888 pixel format */
  for(index=0; index < height; index++)
  {
    /* Pixel format conversion */
    LL_ConvertLineToARGB8888((uint32_t *)pbmp, (uint32_t *)address, width, input_color_mode);
   
    /* Increment the source and destination buffers */
    address+=  (BSP_LCD_GetXSize()*4);
    pbmp -= width*(bit_pixel/8);
  } 
}

Now what I cannot understand is why it's always corrupt in these upper lines, and it's not consistent either, if I run a loop there will be missing spots in different places each time the image is displayed, but always among these upper lines.

Thanks a lot for any help! I've come so far now in this project so problems like this are more than just a bit frustrating! Best Regards /Olle

2 Answers

5 years, 6 months ago.

Any news regarding this issue? I am having the same problem loading bitmap files...

5 years, 10 months ago.

I cant pinpoint the exact problem without more code or runtime analysis, but it seems to be a problem at the end of the image file. Note that the image is actually stored ''upside down'' in the bitmap file!

The code tries to finds the address of the first line, which is near the end of the image file, and then shows that line on the display starting at the top of the screen.

/* Bypass the bitmap header */
pbmp += (index + (width * (height - 1) * (bit_pixel/8)));  // This should point to the start of the first displayline in the image, which is located near the end of the file

The pointer is decremented (from the end of the file back towards the beginning) for every following line

pbmp -= width*(bit_pixel/8);

The first possible errorsource could be in the malloc and loading of the image from SD. It may not be read in completely and the last bit is missing, resulting in some random memory data shown at the top of the display.

The other possibility is that the pbmp pointer calculation above may be wrong and it selects a bit of memory that is somewhere beyond the end of the actual image data. So the first couple of lines on the display point at some part of memory that may contain any random data depending on what happened just before. Hence the changing display content at the top. Since most of the image as such seems to look OK, the problem in this case is most likely in the image height and you need to check the original image file header or the code interpreting the header file of the image bitmap. Do some printf on height, width etc.

I have also seen some errors with headers due to misaligned fields. The header should use some padding to make sure data starts at 32bit addresses. See here

Thanks for taking your time, yes these are my initial thoughts. However I did a trial where I loaded the whole file and forced the pointer way back and in order to avoid decrement it too much, I only printed out 20 rows. But still, they were displaying these random blind spots! And that from data that is displayed correct when the whole image is displayed. Also, if it were reading random data outside the declared memory space, I presume it would print all sorts of colors, but as you can see, the spots that it is actually printing out are in the right colors, and the rest are transparent, showing the last bit of information that was written to that memory space in the display driver, so it almost appears as it's not writing anything at all on those spots. Or it could of course be that it writes values that are outside some kind of limit.

Is there a way of reading back the content of the display driver memory to be able to investigate what has been stored there?

posted by Olle Sköld 05 Jun 2018

I think the problem is the first one I mentioned: The image is not read in correctly from SD and the last bit is corrupted, resulting in some random memory data shown at the top of the display.

The code reads the fileSize which is returned in bytes:

..
fileSize = ftell (Image);
..

The malloc should also be in bytes, but your code seems to request 32bit words:

// allocate memory to contain the whole file:
buffer = (char*) malloc (sizeof(char)*(fileSize+3)/4);

Try this instead:

// allocate memory to contain the whole file:
buffer = (char*) malloc (sizeof(char) * fileSize);
posted by Wim Huiskamp 06 Jun 2018

You probably can read back from the displaymemory. First find the address and read the 32bit 8+RGB888 data:

address = hLtdcHandler.LayerCfg[ActiveLayer].FBStartAdress + (((BSP_LCD_GetXSize()*Ypos) + Xpos)*(4));

Also note that a bitmap image doesnt seem to support the 16bit 565 format. The official formats are 1,4,8 and 24 bit.

posted by Wim Huiskamp 06 Jun 2018