Skip to main content
KIlia.1
Associate II
Jul 13, 2020 8:56 AM UTC
Question

Loading Images at Runtime STM32F764

Hi,

 

I am building an application for a Custom Board using STM32F746 and TouchGFX.

 

I followed all the instructions found : https://support.touchgfx.com/docs/development/ui-development/scenarios/loading-images-at-runtime/

 

But i can not print an image stored in SD .

//-----------------------------------------------------------------------------------------------------------------------
 
// BoardConfiguration.cpp
 
//-----------------------------------------------------------------------------------------------------------------------
 
static LCD16bpp display;
static uint16_t bitdepth = 16;
static uint32_t bmpCache = (uint32_t)(0xC0008000); // SDRAM
 
namespace touchgfx
 
{
void touchgfx_init()
{
 uint16_t dispWidth = 800;
 uint16_t dispHeight = 480; 
 
 HAL& hal = touchgfx_generic_init<STM32F7HAL>(dma, display, tc, dispWidth, dispHeight, (uint16_t*)bmpCache, 232000, 3);
...

 0693W000001sjdKQAQ.png

//-----------------------------------------------------------------------------------------------------------------------
 
// ScreenView.cpp 
 
//-----------------------------------------------------------------------------------------------------------------------
 
void Screen1View::updateValues(void){
 ...
 
/***************This Part Works Fine***************************/
 
 * if( myBinarySem01Handle != NULL ){
 *
 * /* See if we can obtain the semaphore. If the semaphore is not
 * available wait 10 ticks to see if it becomes free. */
 * if( xSemaphoreTake( myBinarySem01Handle, ( TickType_t ) 10 ) == pdTRUE )
 * {
 
 *********************************************************
 
BMPFileLoader::getBMP24Dimensions(&MyFile, width, height);
 
 bmpId = Bitmap::dynamicBitmapCreate(width, height, Bitmap::RGB565);
 
 if (bmpId != BITMAP_INVALID)
 {
 //read the bitmap file into the dynamic bitmap
 BMPFileLoader::readBMP24File(Bitmap(bmpId), (BMPFileLoader::FileHdl)&MyFile);
 
 image.setBitmap(Bitmap(bmpId));
 
 image.setXY(20, 20);
 image.invalidate();
 }
}

 

//-----------------------------------------------------------------------------------
 
// SD card Read (In Other Task) 
 
//-----------------------------------------------------------------------------------
 
 case MOUNTED:
 
 //Find the first .bmp file
 
// r = f_findfirst(&d, &info, sdpath, "*.jpg");
 
 r=0;
 if (r == 0)
 {
 r = f_open(&f, "trees.bmp"/*info.fname*/, FA_READ);
 
 if (r == 0)
 {
 sdstate = FILE_OPENED;
 
 /*Test Variables*/
 
 MyFile = f;
 
 if( myBinarySem01Handle != NULL )
 {
 if( xSemaphoreGive( myBinarySem01Handle ) != pdTRUE )
 {
 
 // We would expect this call to fail because we cannot give
 
 // a semaphore without first "taking" it!
 asm("nop");
 }
 }
 
//---------------------------------------------------------------------------------------

 

The Question :

As i can see from the debug f_open Finds the file and stores it to f variable. I can also see the data in f in the touchGFX task , So i think this part works.

 

But the function

 

 BMPFileLoader::getBMP24Dimensions(&MyFile, width, height);

returns Huge width and height

 0693W000001sjdFQAQ.png

and  

 

bmpId = Bitmap::dynamicBitmapCreate(width, height, Bitmap::RGB565);

 

returns Invalid ID

This topic has been closed for replies.

5 replies

Martin KJELDSEN
Principal III
Jul 14, 2020 8:26 AM UTC

Does Bitmap::dynamicBitmapCreate(width, height, Bitmap::RGB565); always return invalid ID? Also, are you aware that the simple BMP file-loader in the article is for 24-bpp only?

Try with a small example just to ensure that you can allocate space in the bitmap cache.

dynamicBitmapCreate() returns BITMAP_INVALID if

  • You're out of space in the cache
  • If caching failed even if you have space for an image (not supposed to happen).

/Martin

KIlia.1
KIlia.1Author
Associate II
Jul 14, 2020 8:34 AM UTC

Dear Martin,

 

Just found it,

 

i replaced the :

  1. BMPFileLoader.cpp
  2. BMPFileLoader.hpp

files that i copied from this link https://support.touchgfx.com/docs/development/ui-development/scenarios/loading-images-at-runtime/

 

with some files i found in an example in the forum, and it Works fine.

 

//--------------------------------------------------------------------------------

// The NON WORKING CODE

//--------------------------------------------------------------------------------

int BMPFileLoader::readFile(FileHdl hdl, uint8_t* const buffer, uint32_t length)
{
 uint32_t r = fread(buffer, 1, length, (FILE*)hdl);
 if (r != length)
 {
 return 1;
 }
 return 0;
}
 
void BMPFileLoader::seekFile(FileHdl hdl, uint32_t offset)
{
 fseek((FILE*)hdl, offset, SEEK_SET);
}
 
void BMPFileLoader::getBMP24Dimensions(FileHdl fileHandle, uint16_t& width, uint16_t& height)
{
 uint8_t data[50];
 seekFile(fileHandle, 0);
 readFile(fileHandle, data, 26); //read first part of header.
 
 width = data[18] | (data[19] << 8) | (data[20] << 16) | (data[21] << 24);
 height = data[22] | (data[23] << 8) | (data[24] << 16) | (data[25] << 24);
}
 
void BMPFileLoader::readBMP24File(Bitmap bitmap, FileHdl fileHandle)
{
 uint8_t data[50];
 seekFile(fileHandle, 0);
 readFile(fileHandle, data, 26); //read first part of header.
 
 const uint32_t offset = data[10] | (data[11] << 8) | (data[12] << 16) | (data[12] << 24);
 const uint32_t width = data[18] | (data[19] << 8) | (data[20] << 16) | (data[21] << 24);
 const uint32_t height = data[22] | (data[23] << 8) | (data[24] << 16) | (data[25] << 24);
 
 readFile(fileHandle, data, offset - 26); //read rest of header.
 
 //get dynamic bitmap boundaries
 const uint32_t buffer_width = bitmap.getWidth();
 const uint32_t buffer_height = bitmap.getHeight();
 
 const uint32_t rowpadding = (4 - ((width * 3) % 4)) % 4;
 
 const Bitmap::BitmapFormat format = bitmap.getFormat();
 uint8_t* const buffer8 = Bitmap::dynamicBitmapGetAddress(bitmap.getId());
 uint16_t* const buffer16 = (uint16_t*)buffer8;
 
 for (uint32_t y = 0; y < height; y++)
 {
 for (uint32_t x = 0; x < width; x++)
 {
 if (x % 10 == 0) //read data every 10 pixels = 30 bytes
 {
 if (x + 10 <= width) //read 10
 {
 readFile(fileHandle, data, 10 * 3); //10 pixels
 }
 else
 {
 readFile(fileHandle, data, (width - x) * 3 + rowpadding); //rest of line
 }
 }
 //insert pixel, if within dynamic bitmap boundaries
 if (x < buffer_width && ((height - y - 1) < buffer_height))
 {
 switch (format)
 {
 case Bitmap::RGB565:
 buffer16[x + (height - y - 1) * buffer_width] =
 touchgfx::Color::getColorFrom24BitRGB(data[(x % 10) * 3 + 2], data[(x % 10) * 3 + 1], data[(x % 10) * 3]);
 break;
 case Bitmap::RGB888:
 {
 //24 bit framebuffer
 const uint32_t inx = 3 * (x + (height - y - 1) * buffer_width);
 buffer8[inx + 0] = data[(x % 10) * 3 + 0];
 buffer8[inx + 1] = data[(x % 10) * 3 + 1];
 buffer8[inx + 2] = data[(x % 10) * 3 + 2];
 break;
 }
 case Bitmap::ARGB8888:
 {
 //24 bit framebuffer
 const uint32_t inx = 4 * (x + (height - y - 1) * buffer_width);
 buffer8[inx + 0] = data[(x % 10) * 3 + 0];
 buffer8[inx + 1] = data[(x % 10) * 3 + 1];
 buffer8[inx + 2] = data[(x % 10) * 3 + 2];
 buffer8[inx + 3] = 255; //solid
 break;
 }
 default:
 assert(!"Unsupported bitmap format in BMPFileLoader!");
 }
 }
 }
 }
}

//--------------------------------------------------------------------------------

// THE WORKING CODE

//--------------------------------------------------------------------------------

int BMPFileLoader::readFile(FileHdl hdl, uint8_t* const buffer, uint32_t length)
{
#ifdef SIMULATOR
 uint32_t r = fread(buffer, 1, length, (FILE*)hdl);
#else
 uint32_t r = 0;
 f_read((FIL*)hdl, buffer, length, (unsigned int*)&r);
 
#endif
 if (r != length)
 {
 return 1;
 }
 return 0;
}
 
void BMPFileLoader::seekFile(FileHdl hdl, uint32_t offset)
{
#ifdef SIMULATOR
 fseek((FILE*)hdl, offset, SEEK_SET);
#else
 f_lseek((FIL*)hdl, offset);
#endif
}
 
void BMPFileLoader::getBMP24Dimensions(FileHdl fileHandle, uint16_t& width, uint16_t& height)
{
 uint8_t data[50];
 seekFile(fileHandle, 0);
 readFile(fileHandle, data, 26); //read first part of header.
 
 width = data[18] | (data[19] << 8) | (data[20] << 16) | (data[21] << 24);
 height = data[22] | (data[23] << 8) | (data[24] << 16) | (data[25] << 24);
}
 
void BMPFileLoader::readBMP24File(Bitmap bitmap, FileHdl fileHandle)
{
 uint8_t data[50];
 seekFile(fileHandle, 0);
 readFile(fileHandle, data, 26); //read first part of header.
 
 const uint32_t offset = data[10] | (data[11] << 8) | (data[12] << 16) | (data[12] << 24);
 const uint32_t width = data[18] | (data[19] << 8) | (data[20] << 16) | (data[21] << 24);
 const uint32_t height = data[22] | (data[23] << 8) | (data[24] << 16) | (data[25] << 24);
 
 //could check offset here
 readFile(fileHandle, data, offset - 26); //read rest of header.
 
 const uint32_t buffer_width = bitmap.getWidth();
 const uint32_t buffer_height = bitmap.getHeight();
 
 const uint32_t rowpadding = (4 - ((width * 3) % 4)) % 4;
 
 const Bitmap::BitmapFormat format = bitmap.getFormat();
 
 uint8_t* const buffer8 = Bitmap::dynamicBitmapGetAddress(bitmap.getId());
 uint16_t* const buffer16 = (uint16_t*)buffer8;
 
 for (uint32_t y = 0; y < height; y++)
 {
 for (uint32_t x = 0; x < width; x++)
 {
 if (x % 10 == 0) //read data every 10 pixels = 30 bytes
 {
 if (x + 10 <= width) //read 10
 {
 readFile(fileHandle, data, 10 * 3); //10 pixels
 }
 else
 {
 readFile(fileHandle, data, (width - x) * 3 + rowpadding); //rest of line
 }
 }
 //insert pixel, if within widget boundaries
 if (x < buffer_width && ((height - y - 1) < buffer_height))
 {
 switch (format)
 {
 case Bitmap::RGB565:
 buffer16[x + (height - y - 1) * buffer_width] =
 touchgfx::Color::getColorFrom24BitRGB(data[(x % 10) * 3 + 2], data[(x % 10) * 3 + 1], data[(x % 10) * 3]);
 break;
 case Bitmap::RGB888:
 {
 //24 bit framebuffer
 const uint32_t inx = 3 * (x + (height - y - 1) * buffer_width);
 buffer8[inx + 0] = data[(x % 10) * 3 + 0];
 buffer8[inx + 1] = data[(x % 10) * 3 + 1];
 buffer8[inx + 2] = data[(x % 10) * 3 + 2];
 break;
 }
 case Bitmap::ARGB8888:
 {
 //24 bit framebuffer
 const uint32_t inx = 4 * (x + (height - y - 1) * buffer_width);
 buffer8[inx + 0] = data[(x % 10) * 3 + 0];
 buffer8[inx + 1] = data[(x % 10) * 3 + 1];
 buffer8[inx + 2] = data[(x % 10) * 3 + 2];
 buffer8[inx + 3] = 255; //solid
 break;
 }
 default:
 assert(!"Unsupported bitmap format in BMPFileLoader!");
 }
 }
 }
 }
}

 

 Now i am trying to do the same thing with Jpeg files,

 

Is there any example using Jpeg , or JPEGLib Source that i can use ??

Martin KJELDSEN
Principal III
Jul 14, 2020 8:53 AM UTC

So you're saying there's an error in the code in the article? I'll have to follow up on that.

Check this forum if you can, i uploaded an example using a JPEGFileLoader at some point (uses libjpeg).

/Martin

KIlia.1
KIlia.1Author
Associate II
Jul 14, 2020 9:08 AM UTC

Or i am using an other version of some tool (touchGFX etc).

I think i found the example you are talking about, i ported the libjpeg and the common files but the code gets stuck in

 JPEGFileLoader::getJPEGDimensions(f, width, height);

0693W000001soz1QAA.png

I am using the same cash configuration as in bitmap.

Is there some other cash/memory configuration i have to make ?

Martin KJELDSEN
Principal III
Jul 14, 2020 9:16 AM UTC

The example i uploaded was only tested on windows / simulator. Pretty sure our demos from the designer use dynamic images (jpegs) - i don't have time to check myself right now

/Martin