2020-07-13 01:56 AM
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);
...
//-----------------------------------------------------------------------------------------------------------------------
// 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
and
bmpId = Bitmap::dynamicBitmapCreate(width, height, Bitmap::RGB565);
returns Invalid ID
2020-07-14 01:26 AM
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
/Martin
2020-07-14 01:34 AM
Dear Martin,
Just found it,
i replaced the :
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 ??
2020-07-14 01:53 AM
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
2020-07-14 02:08 AM
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);
I am using the same cash configuration as in bitmap.
Is there some other cash/memory configuration i have to make ?
2020-07-14 02:16 AM
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