Skip to main content
KIlia.1
Associate II
July 13, 2020
Question

Loading Images at Runtime STM32F764

  • July 13, 2020
  • 5 replies
  • 1655 views

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
July 14, 2020

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
July 14, 2020

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
July 14, 2020

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
July 14, 2020

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
July 14, 2020

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