cancel
Showing results for 
Search instead for 
Did you mean: 

Loading Images at Runtime STM32F764

KIlia.1
Associate II

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

5 REPLIES 5
Martin KJELDSEN
Chief III

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
Associate II

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 ??

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
Associate II

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 ?

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