Android模擬器內容是用OpenGL渲染的,所以用一般的編程(如PrintWindow()等)會是黑屏。這是因為畫的東西放在framebuffer裡。 一種方法是通過adb把guest的framebuffer資料/dev/graphics/fb0倒到host,再轉為圖片。但這樣速度比較慢。 好在Android模擬器中把guest的framebuffer傳到host進行顯示,所以在host端只要將framebuffer輸出到檔案即可。 首先定義每次framebuffer更新時的回呼函數: [cpp] 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; } 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;}然後把這個回呼函數註冊上去,比如在OpenGL視窗顯示之後: [cpp] android_showOpenglesWindow(winhandle, drect.pos.x, drect.pos.y, drect.size.w, drect.size.h, disp->rotation * -90.); android_setPostCallback(zjin_fb_update, NULL); android_showOpenglesWindow(winhandle, drect.pos.x, drect.pos.y, drect.size.w, drect.size.h, disp->rotation * -90.); android_setPostCallback(zjin_fb_update, NULL);這樣,每次有framebuffer的更新時,guest的螢幕都會存成一張bmp圖片,這和用/dev/graphics/fb0的效果是一樣的。 注意用以上方法截下來的圖和原圖有兩點不同,一是Blue和Red通道互換,這是因為framebuffer是RGB,bmp格式裡是BGR。還有就是y軸的零點是左下角,這是由於framebuffer中是OpenGL的座標系。也就是說,要得到原圖還要經過RGB到BGR的轉換和y-inversion。建議到處理圖片時再做這些處理,一方面不會拖慢模擬器速度,另一方面像OpenCV裡有現成的函數可供調用。