cancel
Showing results for 
Search instead for 
Did you mean: 

Direct access to screen on TouchGFX?

bear2023R
Associate III

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

 

1 ACCEPTED SOLUTION

Accepted Solutions
GaetanGodart
ST Employee

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,

Gaetan Godart
Software engineer at ST (TouchGFX)

View solution in original post

4 REPLIES 4
GaetanGodart
ST Employee

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,

Gaetan Godart
Software engineer at ST (TouchGFX)
GaetanGodart
ST Employee

Hello @bear2023R ,

 

Was my answer helpful?

Were you able to solve your problem?

 

Regards,

Gaetan Godart
Software engineer at ST (TouchGFX)

THanks Gaetan

 

sorry for late reply - was on vacation.

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

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,

Gaetan Godart
Software engineer at ST (TouchGFX)