You can set the bitmap height to the negative value to make the client render it mirrored. The BMP spec orders the pixel rows bottom to top by default, but you can also put them top to bottom if you specify a negative height.
I’m using the BITMAPV2INFOHEADER
BMP format while setting BI_BITFIELDS
to 3 for RGB bitmasks like so:
struct bmp_header_t
{
uint32_t bfSize;
uint32_t bfReserved;
uint32_t bfOffBits;
uint32_t biSize;
int32_t biWidth;
int32_t biHeight;
uint16_t biPlanes;
uint16_t biBitCount;
uint32_t biCompression;
uint32_t biSizeImage;
int32_t biXPelsPerMeter;
int32_t biYPelsPerMeter;
uint32_t biClrUsed;
uint32_t biClrImportant;
uint32_t bdMask[3]; // RGB
};
/** Set a Bitmap Header.
*
* Initializes a header in BMP format for the size of the screen.
*
* @note: send header before refreshing the whole screen
*
**/
static void gui_get_bitmap_header(uint8_t* buffer, size_t bufsize)
{
lv_obj_t* scr = lv_disp_get_scr_act(NULL);
lv_coord_t width = lv_obj_get_width(scr);
lv_coord_t height = lv_obj_get_height(scr);
const char* bm = "BM";
memcpy(buffer, bm, strlen(bm));
buffer += strlen(bm);
// Bitmap file header
bmp_header_t* bmp = (bmp_header_t*)buffer;
bmp->bfSize = (uint32_t)(width * height * LV_COLOR_DEPTH / 8);
bmp->bfReserved = 0;
bmp->bfOffBits = bufsize;
// Bitmap information header
bmp->biSize = 40;
bmp->biWidth = width;
bmp->biHeight = -height;
bmp->biPlanes = 1;
bmp->biBitCount = LV_COLOR_DEPTH;
bmp->biCompression = 3; // BI_BITFIELDS
bmp->biSizeImage = bmp->bfSize;
bmp->biXPelsPerMeter = 2836;
bmp->biYPelsPerMeter = 2836;
bmp->biClrUsed = 0; // zero defaults to 2^n
bmp->biClrImportant = 0;
// BI_BITFIELDS
bmp->bdMask[0] = 0xF800; // Red bitmask : 1111 1000 | 0000 0000
bmp->bdMask[1] = 0x07E0; // Green bitmask: 0000 0111 | 1110 0000
bmp->bdMask[2] = 0x001F; // Blue bitmask : 0000 0000 | 0001 1111
}
If you write such header before dumping the LVGL pixels to the file, it should render fine on the client.
I’m using it to take local screenshots on flash and also send the screenshot to a browser via HTTP.