2024-04-26 03:53 AM
My problems with Portrait orientation don't end.
I have a very large project where changing the architecture and function calls costs much more than changing a single function.
My problem is how?
The function is readBMP24File.
In my project it is loaded from several places and many different screens.
In the original project it works very well, many images are called or even of different sizes from an MMC with fatfs.
Has anyone solved the problem of changing orientation without having to change the position and orientation of the images?
I'm starting to have serious doubts that the touchgfx gui really helps in the work I do.
If anyone can help me in solving the problem with a new or different algorithm I would be grateful.
Solved! Go to Solution.
2024-04-30 05:29 AM
Thank you for the information. One important thing, are you allways using and facing issues with 'big' pictures in your project. I mean pictures which are in some direction bigger than display. What if you make for example 200x400 pixel picture. Is it also disturbed in portrait mode ?
Br jtp
2024-04-30 05:42 AM
480x272 picture:
this is the output:
2024-04-30 06:01 AM
Did you change the width and height vice versa which were exracted by getBMP24dimensions, like earlier with chip bag image ?
Br jtp
2024-04-30 06:26 AM
thanks for your attention...
but no luck...
2024-04-30 07:13 AM
Thank you for sharing
I can see that in the BMPFileLoader, the loop that writes data into the framebuffer should be changed to support portrait mode. Keep in mind that when you want to display using portrait mode, the framebuffer still looks like landscape but the coordination is different now. In other words, in landscape, the top left corner represents the first element of framebuffer array. It is the same case in the portrait mode however, now if we want to move through the framebuffer elements, we have to switch the values of x and y, and this is not reflected inside the loop (line 24-76 of the code you shared).
(I added a simple image to demonstrate what I mean)
A similar implementation is available in the QR Code widget that is shared on the forum. I suggest you taking a look at that, and apply some changes to the BMPFileLoader.
Sorry, I don't have the time to test that myself, but I'm sure you can apply the required changes.
Best of luck
2024-04-30 11:17 AM
Hello
Please test the attached version. It should keep now the image same position in landscape and portrait mode (eg. rotates the image). was it what you needed ?
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;
if(HAL::getInstance()->getDisplayOrientation() == ORIENTATION_LANDSCAPE) // original code for landscape
{
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] =
LCD16bpp::getNativeColorFromRGB(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!");
}
}
}
}
}
else // portrait orientation
{
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. Manipulated for portrait mode.
if ((buffer_width-x-1) < buffer_width && ((height - y - 1) < buffer_height))
{
switch (format)
{
case Bitmap::RGB565:
buffer16[height-y-1 + ((buffer_width-x-1) * buffer_height)] =
LCD16bpp::getNativeColorFromRGB(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 * (height-y-1 + ((buffer_width-x-1) * buffer_height));
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 * (height-y-1 + ((buffer_width-x-1) * buffer_height));
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!");
}
}
}
}
}
}
Br JTP
2024-05-01 05:02 AM
IT WORKS!
Thanks JTP, really thanks, everything works and does what it's supposed to.
However, I would like to reflect on what happened.
Basically I didn't want someone to do the job for me, I'm grateful to JTP for providing me with the solution, but I was looking for someone who had the problem and solved it with a supplement to the lack of touchgfx.
The intervention of MORADI ESFAHANIASL was superfluous, he explained how the water is heated, if he had read the problem from the beginning he would have realized that this was what I was saying from the first moment.
I don't deal with interfaces in general, I'm a consultant who usually works on power and control systems for motors and inverters, but here I had an interface and I started the project two years ago encouraged by ST's direct tool.
A tool that is not open source for half of its system, which helps you, but apparently not all the way.
Here, now, imagine having an enormous amount of work, having (like everyone) tight deadlines and having to rediscover everything starting from the wheel because a hole of this level is left open in the support, an algorithm is produced and provided for a horizontal but not vertical display...."you do it"... imagine telling that to a customer. I actually had a psychological refusal to want to watch it...
The tool is certainly free, but is this the type of support you have if you rely professionally on a brand?
You may not like it, but it's my opinion.
A huge thank you to JTP, if you send me your address as a private message, I will repay your time with a gift from Italy!
2024-05-01 07:44 AM
Hello
Glad you get your problem solved. For me, the motivation for trying to solve these problems is purely willingness to learn more and get better understanding about TGFX. So this lesson is also very useful for me in my future challenges.
I think it would be good idea to update the example of reading a bitmap from a file so that it has support also portrait mode.
Anycase @Mohammad MORADI ESFAHANIASL post about framebuffer organisation and also tip about portrait mode implementation in QR code widget were helpful. Maybe this kind information (clear pictures) could be even in framebuffer basic documentation in some format:
https://support.touchgfx.com/docs/basic-concepts/framebuffer
But actually, the the portrait mode of dynamic bitmaps is very well documented here, but who reads the documents... not me at least :face_with_tears_of_joy:
Maybe, in future releases, it would be useful to have better support for landscape and portrait views. For example so that any object on the screen could have separate location and rotation settings for different 'Orientation profiles', all image selections could have separate images for different orientations (buttons, images, sliders etc).
Happy Labor day for all.
Br JTP
2024-05-01 10:38 AM
LVGL and squareline studio.. this will be my next choice.
2024-05-06 01:58 AM
Hello @Msolinas ,
We're sorry to hear that the support provided by our team did not fully meet your expectations. We thank @JTP1 for offering a helpful answer to your query.
From what I can see on this thread, @Mohammad MORADI ESFAHANIASLaimed to guide you toward finding a solution. However, I agree that our response times could have been more prompt. Like all the other TouchGFX supporters on the forum, we might be busy sometimes with other work, and that's the reason why we have a dedicated support team working on business cases.
So for the future, if you are working under tight deadlines as you mentioned, I invite you to contact us on these links, and be certain that your inquiries will be prioritized, and we will strive to deliver a high-quality response.
https://www.st.com/content/st_com/en/support/support-home.html
Best regards,