Improve screenshot functions

This commit is contained in:
fvanroie 2020-04-03 12:53:13 +02:00
parent ccb21fe0a1
commit ebc12fc14a

View File

@ -87,84 +87,105 @@ static bool guiCheckSleep()
return false; return false;
} }
static void gui_take_screenshot(lv_disp_drv_t * disp, const lv_area_t * area, lv_color_t * color_p) // static void gui_take_screenshot(lv_disp_drv_t * disp, const lv_area_t * area, lv_color_t * color_p)
// {
// uint i = 0;
// uint16_t c;
// uint8_t pixel[1024];
// for(int y = area->y1; y <= area->y2; y++) {
// for(int x = area->x1; x <= area->x2; x++) {
// /* Function for converting LittlevGL pixel format to RGB888 */
// // data = DISP_IMPL_lvgl_formatPixel(*color_p);
// // Complex 32 bpp
// /* pixel[i++] = (LV_COLOR_GET_B(*color_p) * 263 + 7) >> 5;
// pixel[i++] = (LV_COLOR_GET_G(*color_p) * 259 + 3) >> 6;
// pixel[i++] = (LV_COLOR_GET_R(*color_p) * 263 + 7) >> 5;
// pixel[i++] = 0xFF;*/
// // Simple 32 bpp
// // pixel[i++] = (LV_COLOR_GET_B(*color_p) << 3);
// // pixel[i++] = (LV_COLOR_GET_G(*color_p) << 2);
// // pixel[i++] = (LV_COLOR_GET_R(*color_p) << 3);
// // pixel[i++] = 0xFF;
// c = color_p->full;
// // Simple 16 bpp
// pixel[i++] = c & 0xFF;
// pixel[i++] = (c >> 8) & 0xFF;
// color_p++;
// if(i + 4 >= sizeof(pixel)) {
// switch(guiSnapshot) {
// case 1:
// // Save to local file
// pFileOut.write(pixel, i);
// break;
// case 2:
// // Send to remote client
// if(webClient->client().write(pixel, i) != i) {
// Log.warning(F("GUI: Pixelbuffer not completely sent"));
// lv_disp_flush_ready(disp); /* tell lvgl that flushing is done */
// return;
// }
// }
// i = 0;
// }
// }
// }
// if(i > 0) {
// switch(guiSnapshot) {
// case 1:
// // Save to local file
// pFileOut.write(pixel, i);
// break;
// case 2:
// // Send to remote client
// if(webClient->client().write(pixel, i) != i) {
// Log.warning(F("GUI: Pixelbuffer not completely sent"));
// }
// }
// }
// }
/* Flush VDB bytes to a stream */
static void gui_take_screenshot(uint8_t * data_p, size_t len)
{ {
uint i = 0; size_t res = 0;
uint16_t c;
uint8_t pixel[1024];
for(int y = area->y1; y <= area->y2; y++) {
for(int x = area->x1; x <= area->x2; x++) {
/* Function for converting LittlevGL pixel format to RGB888 */
// data = DISP_IMPL_lvgl_formatPixel(*color_p);
// Complex 32 bpp
/* pixel[i++] = (LV_COLOR_GET_B(*color_p) * 263 + 7) >> 5;
pixel[i++] = (LV_COLOR_GET_G(*color_p) * 259 + 3) >> 6;
pixel[i++] = (LV_COLOR_GET_R(*color_p) * 263 + 7) >> 5;
pixel[i++] = 0xFF;*/
// Simple 32 bpp
// pixel[i++] = (LV_COLOR_GET_B(*color_p) << 3);
// pixel[i++] = (LV_COLOR_GET_G(*color_p) << 2);
// pixel[i++] = (LV_COLOR_GET_R(*color_p) << 3);
// pixel[i++] = 0xFF;
c = color_p->full;
// Simple 16 bpp
pixel[i++] = c & 0xFF;
pixel[i++] = (c >> 8) & 0xFF;
color_p++;
if(i + 4 >= sizeof(pixel)) {
switch(guiSnapshot) { switch(guiSnapshot) {
case 1: case 1:
// Save to local file res = pFileOut.write(data_p, len);
pFileOut.write(pixel, i);
break; break;
case 2: case 2:
// Send to remote client len = webClient->client().write(data_p, len);
if(webClient->client().write(pixel, i) != i) {
Log.warning(F("GUI: Pixelbuffer not completely sent"));
lv_disp_flush_ready(disp); /* tell lvgl that flushing is done */
return;
}
}
i = 0;
}
}
}
if(i > 0) {
switch(guiSnapshot) {
case 1:
// Save to local file
pFileOut.write(pixel, i);
break; break;
case 2: default:
// Send to remote client res = 0; // nothing to do
if(webClient->client().write(pixel, i) != i) { }
if(res != len) {
Log.warning(F("GUI: Pixelbuffer not completely sent")); Log.warning(F("GUI: Pixelbuffer not completely sent"));
} }
}
}
} }
/* Experimetnal Display flushing */ /* Experimetnal Display flushing */
static void IRAM_ATTR tft_espi_flush(lv_disp_drv_t * disp, const lv_area_t * area, lv_color_t * color_p) 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 */ /* Update TFT */
tft.startWrite(); /* Start new TFT transaction */ tft.startWrite(); /* Start new TFT transaction */
tft.setWindow(area->x1, area->y1, area->x2, area->y2); /* set the working window */ tft.setWindow(area->x1, area->y1, area->x2, area->y2); /* set the working window */
tft.setSwapBytes(true); // endianess tft.setSwapBytes(true); /* set endianess */
tft.pushPixels((uint16_t *)color_p, (area->x2 - area->x1 + 1) * (area->y2 - area->y1 + 1)); tft.pushPixels((uint16_t *)color_p, len); /* Write words at once */
tft.endWrite(); /* terminate TFT transaction */ tft.endWrite(); /* terminate TFT transaction */
/* Send Screenshot data */ /* Send Screenshot data */
if(guiSnapshot != 0) { if(guiSnapshot != 0) {
gui_take_screenshot(disp, area, color_p); gui_take_screenshot((uint8_t *)color_p, len * sizeof(lv_color_t)); /* Number of bytes */
} }
/* Tell lvgl that flushing is done */ /* Tell lvgl that flushing is done */
@ -607,75 +628,57 @@ bool guiSetConfig(const JsonObject & settings)
return changed; return changed;
} }
static void guiSetBmpHeader(uint8_t * buffer_p, int32_t data)
{
*buffer_p++ = data & 0xFF;
*buffer_p++ = (data >> 8) & 0xFF;
*buffer_p++ = (data >> 16) & 0xFF;
*buffer_p++ = (data >> 24) & 0xFF;
}
/** Send Bitmap Header. /** Send Bitmap Header.
* *
* Sends a header in BMP format for the size of the screen. * Sends a header in BMP format for the size of the screen.
* *
* @note: data pixel should be formated to uint32_t RGBA. Imagemagick requirements. * @note: send header before refreshing the whole screen
* *
**/ **/
void guiSendBmpHeader() static void guiSendBmpHeader()
{ {
uint8_t buffer[128]; uint8_t buffer[128];
memset(buffer, 0, sizeof(buffer)); memset(buffer, 0, sizeof(buffer));
int32_t res;
lv_disp_t * disp = lv_disp_get_default(); lv_disp_t * disp = lv_disp_get_default();
buffer[0] = 0x42; buffer[0] = 0x42; // B
buffer[1] = 0x4D; buffer[1] = 0x4D; // M
buffer[10 + 0] = 122; // full header size buffer[10 + 0] = 122; // full header size
buffer[14 + 0] = 122 - 14; // dib header size buffer[14 + 0] = 122 - 14; // dib header size
buffer[26 + 0] = 1; // number of color planes buffer[26 + 0] = 1; // number of color planes
buffer[28 + 0] = 16; // 24; // bbp buffer[28 + 0] = 16; // or 24, bbp
buffer[30 + 0] = 3; // compression, 0 = RGB / 3 = RGBA buffer[30 + 0] = 3; // compression, 0 = RGB / 3 = RGBA
// file size // file size
int32_t res = 122 + disp->driver.hor_res * disp->driver.ver_res * buffer[28] / 8; guiSetBmpHeader(&buffer[2], 122 + disp->driver.hor_res * disp->driver.ver_res * buffer[28] / 8);
buffer[2 + 3] = (res >> 24) & 0xFF;
buffer[2 + 2] = (res >> 16) & 0xFF;
buffer[2 + 1] = (res >> 8) & 0xFF;
buffer[2 + 0] = res & 0xFF;
// horizontal resolution // horizontal resolution
res = disp->driver.hor_res; guiSetBmpHeader(&buffer[18], disp->driver.hor_res);
buffer[18 + 3] = (res >> 24) & 0xFF;
buffer[18 + 2] = (res >> 16) & 0xFF;
buffer[18 + 1] = (res >> 8) & 0xFF;
buffer[18 + 0] = res & 0xFF;
// vertical resolution // vertical resolution
res = -disp->driver.ver_res; // top down lines guiSetBmpHeader(&buffer[22], -disp->driver.ver_res);
buffer[22 + 3] = (res >> 24) & 0xFF; // bitmap size
buffer[22 + 2] = (res >> 16) & 0xFF; guiSetBmpHeader(&buffer[34], disp->driver.hor_res * disp->driver.ver_res * buffer[28 + 0] / 8);
buffer[22 + 1] = (res >> 8) & 0xFF; // horizontal pixels per meter
buffer[22 + 0] = res & 0xFF; guiSetBmpHeader(&buffer[38], 2836);
// vertical pixels per meter
// bitmp size guiSetBmpHeader(&buffer[42], 2836);
res = disp->driver.hor_res * disp->driver.ver_res * buffer[28 + 0] / 8; //* 2;
buffer[34 + 3] = (res >> 24) & 0xFF;
buffer[34 + 2] = (res >> 16) & 0xFF;
buffer[34 + 1] = (res >> 8) & 0xFF;
buffer[34 + 0] = res & 0xFF;
res = 2836;
buffer[38 + 3] = (res >> 24) & 0xFF;
buffer[38 + 2] = (res >> 16) & 0xFF;
buffer[38 + 1] = (res >> 8) & 0xFF;
buffer[38 + 0] = res & 0xFF;
buffer[42 + 3] = (res >> 24) & 0xFF;
buffer[42 + 2] = (res >> 16) & 0xFF;
buffer[42 + 1] = (res >> 8) & 0xFF;
buffer[42 + 0] = res & 0xFF;
// R: 1111 1000 | 0000 0000 // R: 1111 1000 | 0000 0000
buffer[54 + 1] = 0xF8; guiSetBmpHeader(&buffer[54], 0xF800); // Red bitmask
// G: 0000 0111 | 1110 0000 // G: 0000 0111 | 1110 0000
buffer[58 + 0] = 0xE0; guiSetBmpHeader(&buffer[58], 0x07E0); // Green bitmask
buffer[58 + 1] = 0x07;
// B: 0000 0000 | 0001 1111 // B: 0000 0000 | 0001 1111
buffer[62 + 0] = 0x1F; guiSetBmpHeader(&buffer[62], 0x001F); // Blue bitmask
// A: 0000 0000 | 0000 0000 // A: 0000 0000 | 0000 0000
// buffer[66 + 0] = 0x00; guiSetBmpHeader(&buffer[66], 0x0000); // No Aplpha Mask
// "Win // "Win
buffer[70 + 3] = 0x57; buffer[70 + 3] = 0x57;