Skip to main content
Associate III
February 29, 2024
Solved

Direct access to screen on TouchGFX?

  • February 29, 2024
  • 2 replies
  • 1423 views

Hi,

after reviewing answers to following post
https://community.st.com/t5/stm32-mcus-touchgfx-and-gui/how-to-draw-pixel-line-or-rectangle/td-p/105737

and as a TouchGFX newby, I'm wondering: how one expects to do a following task by using TouchGFX's:

there are two images and some fading effect needs to be done: pseudo-random pixels from one hidden in-memory image A being moved to corresponding pixels of currently displayed image B, replacing them one by one, eventually making all pixels of image A equal to pixels of image B.

Does it need to be addressed in TouchFGX by creating single-pixel "Line" widget objects for each pixel? Seems like extremely inefficient... Are there any other options to do so?

Thanks

 

This topic has been closed for replies.
Best answer by GaetanGodart

Hello @bear2023R ,

 

If your images take up a whole screen you can just use the block transition which does basically what you want but with bigger blocks than just a single pixel.

 

Another solution would be to use a dynamic bitmap and copy each pixel value individually (but it takes long to read from external ram).

 

The solution I went for is to set the second image visible on top of the first image and then invalidating each pixel individually. (It was taking too long so I added a RECTANGLESIZE define to invalidate multiple pixels at once.)

To be able to access each pixel and delete them once I already invalidated them I use a map that is declared globally :

std::map<int, int> pixels;

Then I initialize it :

void Screen1View::setupScreen()
{
 for(int i = 0; i<WIDTH*HEIGHT/RECTANGLESIZE/RECTANGLESIZE; i++) pixels[i] = i;

 pixelToInvalidate.height = RECTANGLESIZE;
 pixelToInvalidate.width = RECTANGLESIZE;
}

Finally, I update one pixel (or one rectangle to be faster) each tick (60 ticks per second) in the handle tick event function :

void Screen1View::handleTickEvent()
{
 //Set the image visible after the first frame
 if(false == imageKitten.isVisible())
 {
 imageKitten.setVisible(true);
 touchgfx_printf("\nImage set visible\nStarting transition");

 if (HAL::USE_DOUBLE_BUFFERING) Application::getInstance()->copyInvalidatedAreasFromTFTToClientBuffer(); // Synchronize framebuffers if using double framebuffer
 }

 if(pixels.size() > 0) //Running transition
 {
 auto random_it = std::next(std::begin(pixels), rand()%pixels.size()); //Get random pixel from the ones available
 
 pixelToInvalidate.x = (random_it->second)%(WIDTH/RECTANGLESIZE)*RECTANGLESIZE; //Translate pixel number to x position
 pixelToInvalidate.y = (random_it->second)/(WIDTH/RECTANGLESIZE)*RECTANGLESIZE; //Translate pixel number to y position

 imageKitten.invalidateRect(pixelToInvalidate); //Invalidate pixel

 pixels.erase(random_it->first); //Remove invalidated pixel from list of pixels

 touchgfx_printf("Remaining pixels : %05d\n", pixels.size());
 }
 else if(!transitionFinished)
 {
 touchgfx_printf("Transition finished.\n");
 transitionFinished = true;
 }
}

Note that if you want true random behavior you should set a seed.

Please find attached a working project running on the simulator (I also tested on a board).

 

If this post answers your question, make sure to set it as "Best answer" so I can close the ticket.

 

Regards,

2 replies

GaetanGodart
GaetanGodartBest answer
Technical Moderator
March 4, 2024

Hello @bear2023R ,

 

If your images take up a whole screen you can just use the block transition which does basically what you want but with bigger blocks than just a single pixel.

 

Another solution would be to use a dynamic bitmap and copy each pixel value individually (but it takes long to read from external ram).

 

The solution I went for is to set the second image visible on top of the first image and then invalidating each pixel individually. (It was taking too long so I added a RECTANGLESIZE define to invalidate multiple pixels at once.)

To be able to access each pixel and delete them once I already invalidated them I use a map that is declared globally :

std::map<int, int> pixels;

Then I initialize it :

void Screen1View::setupScreen()
{
 for(int i = 0; i<WIDTH*HEIGHT/RECTANGLESIZE/RECTANGLESIZE; i++) pixels[i] = i;

 pixelToInvalidate.height = RECTANGLESIZE;
 pixelToInvalidate.width = RECTANGLESIZE;
}

Finally, I update one pixel (or one rectangle to be faster) each tick (60 ticks per second) in the handle tick event function :

void Screen1View::handleTickEvent()
{
 //Set the image visible after the first frame
 if(false == imageKitten.isVisible())
 {
 imageKitten.setVisible(true);
 touchgfx_printf("\nImage set visible\nStarting transition");

 if (HAL::USE_DOUBLE_BUFFERING) Application::getInstance()->copyInvalidatedAreasFromTFTToClientBuffer(); // Synchronize framebuffers if using double framebuffer
 }

 if(pixels.size() > 0) //Running transition
 {
 auto random_it = std::next(std::begin(pixels), rand()%pixels.size()); //Get random pixel from the ones available
 
 pixelToInvalidate.x = (random_it->second)%(WIDTH/RECTANGLESIZE)*RECTANGLESIZE; //Translate pixel number to x position
 pixelToInvalidate.y = (random_it->second)/(WIDTH/RECTANGLESIZE)*RECTANGLESIZE; //Translate pixel number to y position

 imageKitten.invalidateRect(pixelToInvalidate); //Invalidate pixel

 pixels.erase(random_it->first); //Remove invalidated pixel from list of pixels

 touchgfx_printf("Remaining pixels : %05d\n", pixels.size());
 }
 else if(!transitionFinished)
 {
 touchgfx_printf("Transition finished.\n");
 transitionFinished = true;
 }
}

Note that if you want true random behavior you should set a seed.

Please find attached a working project running on the simulator (I also tested on a board).

 

If this post answers your question, make sure to set it as "Best answer" so I can close the ticket.

 

Regards,

GaetanGodart
Technical Moderator
March 14, 2024

Hello @bear2023R ,

 

Was my answer helpful?

Were you able to solve your problem?

 

Regards,

bear2023RAuthor
Associate III
March 26, 2024

THanks Gaetan

 

sorry for late reply - was on vacation.

I'll try your solution yet it looks reasonable anyway, at first glance. Thanks!

GaetanGodart
Technical Moderator
March 27, 2024

Hello @bear2023R ,

 

No problem, hope you had good holidays.

I will keep this post open for a week or two. If you need more help within this timeline, comment the post, after that I will close it.

 

Regards,