How to capture the whole screen?

Description

How to capture the whole screen? I want a screenshot then I want to save it as a file, like png etc.

What MCU/Processor/Board and compiler are you using?

What do you want to achieve?

What have you tried so far?

Code to reproduce

Add a code snippet which can run in the simulator. It should contain only the relevant code that compiles without errors when separated from your main code base.

The code block(s) should be formatted like:

/*You code here*/

Screenshot and/or video

If possible, add screenshots and/or videos about the current state.

Have a look at this blog post, as it is still relevant and explains the steps needed to capture the screen. I used that post to transfer the picture as a BMP image either to a webclient or to a file like this:

static void gui_take_screenshot(uint8_t * data_p, size_t len)
{
    size_t res = 0;
    switch(guiSnapshot) {
        case 1:
            res = pFileOut.write(data_p, len);
            break;
        case 2:
            res = webClient->client().write(data_p, len);
            break;
        default:
            res = 0; // nothing to do
    }
    if(res != len) {
        Log.warning(F("GUI: Pixelbuffer not completely sent"));
    }
}


static void IRAM_ATTR tft_espi_flush(lv_disp_drv_t * disp, const lv_area_t * area, lv_color_t * color_p)
{
    size_t len = (area->x2 - area->x1 + 1) * (area->y2 - area->y1 + 1); /* Number of pixels */

    /* Update TFT */
    tft.startWrite();                                      /* Start new TFT transaction */
    tft.setWindow(area->x1, area->y1, area->x2, area->y2); /* set the working window */
    tft.setSwapBytes(true);                                /* set endianess */
    tft.pushPixels((uint16_t *)color_p, len);              /* Write words at once */
    tft.endWrite();                                        /* terminate TFT transaction */

    /* Send Screenshot data */
    if(guiSnapshot != 0) {
        gui_take_screenshot((uint8_t *)color_p, len * sizeof(lv_color_t)); /* Number of bytes */
    }

    /* Tell lvgl that flushing is done */
    lv_disp_flush_ready(disp);
}

A bitmap file doesn’t require encoding of the image data, it only needs a header that describes the bytes that follow.

Then you can take a screenshot like this:

void guiTakeScreenshot(const char * pFileName)
{
    pFileOut = SPIFFS.open(pFileName, "w");
    if(pFileOut == 0) {
        Log.warning(F("GUI: %s cannot be opened"), pFileName);
        return;
    }

    guiSnapshot = 1;
    guiSendBmpHeader();

    lv_obj_invalidate(lv_scr_act());
    lv_refr_now(NULL); /* Will call our disp_drv.disp_flush function */
    guiSnapshot = 0;

    pFileOut.close();
    Log.verbose(F("[Display] data flushed to %s"), pFileName);
}