The window screenshot in Android simulator is saved as a file

  • 2020-05-09 19:14:19
  • OfStack

The Android emulator content is rendered with OpenGL, so a 1-like programming screenshot (PrintWindow(), etc.) would be black. That's because the thing that you're drawing is in framebuffer.

One way is to pour framebuffer data of guest /dev/graphics/fb0 to host via adb, and then turn it into a picture. But it's slower.

Fortunately, Android emulator can transmit guest framebuffer to host for display, so it is only necessary to output framebuffer to the file at host.

First, define the callback function for each framebuffer update:

 
void zjin_fb_update(void* context, 
int w, int h, int ydir, 
int format, int type, 
unsigned char* pixels) 
{ 
#define CHANNEL 4 
BITMAPFILEHEADER bf; 
BITMAPINFOHEADER bi; 
int width = w; 
int height = h; 
FILE *file = fopen("capture.bmp", "wb"); 
if( file!=NULL ) 
{ 
memset( &bf, 0, sizeof( bf ) ); 
memset( &bi, 0, sizeof( bi ) ); 
bf.bfType = 'MB';//BM? 
bf.bfSize = sizeof(bf)+sizeof(bi)+width*height*CHANNEL; 
bf.bfOffBits = sizeof(bf)+sizeof(bi); 
bi.biSize = sizeof(bi); 
bi.biWidth = width; 
bi.biHeight = height; 
bi.biPlanes = 1; 
bi.biBitCount = 8 * CHANNEL; 
bi.biSizeImage = width*height*CHANNEL; 
fwrite( &bf, sizeof(bf), 1, file ); 
fwrite( &bi, sizeof(bi), 1, file ); 
fwrite( pixels, sizeof(unsigned char), height*width*CHANNEL, file ); 
fclose( file ); 
} 
return; 
} 

Then register the callback function, as shown in the OpenGL window:
 
android_showOpenglesWindow(winhandle, drect.pos.x, drect.pos.y, 
drect.size.w, drect.size.h, disp->rotation * -90.); 
android_setPostCallback(zjin_fb_update, NULL); 

In this way, every time there is an update of framebuffer, the guest screen will save a picture of bmp, which is the same as using /dev/graphics/fb0.

Note that there are two differences between the image truncated by the above method and the original one. The 1 is Blue and the Red channel is interchanged, because framebuffer is RGB and BGR is bmp. And the zero of the y axis is the lower left corner, because framebuffer is the coordinate system of OpenGL. In other words, to get the original, you have to go through the conversion from RGB to BGR and y-inversion. It is recommended to do this when processing images. One aspect will not slow down the simulator. The other aspect is that there are ready-made functions in OpenCV for calling.


Related articles: