AWTK是基于C語言開發(fā)的跨平臺GUI框架?!禔WTK使用經(jīng)驗》系列文章將介紹開發(fā)AWTK過程中一些常見問題與解決方案,例如:如何加載外部資源?如何設(shè)計自定義進度條?這些都會在系列文章進行解答。
假設(shè)目前想在ZTP800示教器的AWTK程序中實現(xiàn)播放視頻或者播放攝像頭畫面的效果,可以借助AWTK的mutable_image控件或usb_camera控件來顯示畫面。下圖則是ZTP800示教器使用usb_camera控件Demo顯示攝像頭畫面的效果圖:
圖1ZTP800示教器顯示攝像頭畫面效果圖
usb_camera控件和mutable_image控件的對比
關(guān)于文章開頭提到的兩個控件對比如下:
1. mutable_image控件
mutable_image控件可以顯示視頻畫面,也可以顯示攝像頭等外接設(shè)備畫面。適用性比較廣泛,但使用起來相對繁瑣一些。它本身是不負責(zé)解析視頻或攝像頭設(shè)備畫面數(shù)據(jù)的,用戶可以通過第三方庫解析并獲取畫面原始RGB數(shù)據(jù),將數(shù)據(jù)拷貝到mutable_image控件特定回調(diào)函數(shù)里面即可顯示畫面。
2. usb_camera控件
usb_camera控件本質(zhì)上是對mutable_image控件的封裝,專門用于顯示攝像頭畫面。在控件內(nèi)部實現(xiàn)了獲取并解析攝像頭畫面數(shù)據(jù)的代碼,用戶只需調(diào)用特定的API即可顯示攝像頭畫面,而不用手動拷貝原始RGB數(shù)據(jù)。與mutable_image相比沒那么廣,但是使用起來相對方便。
使用usb_camera控件顯示攝像頭畫面
使用usb_camera控件顯示攝像頭畫面的流程比較簡單:在AWStudio插件列表可以安裝該插件,之后在自己的AWTK應(yīng)用放置一個usb_camera控件和一個按鈕控件,設(shè)置usb_camera控件的攝像頭設(shè)備、大小等屬性,并且給該按鈕注冊點擊事件用于打開攝像頭。圖2使用usb_camera控件頁面布局示例
按鈕點擊事件回調(diào)函數(shù)可以參考以下代碼示例:
static ret_t on_button_click(void* ctx, event_t* e) { ret_t ret = RET_OK; widget_t* win = WIDGET(ctx); widget_t* camera = widget_lookup(win, "usb_camera", TRUE);
if(usb_camera_is_open(camera) && usb_camera_is_play(camera)) { usb_camera_stop(camera); usb_camera_close(camera); } else { ret = usb_camera_open(camera); if (ret != RET_OK) { dialog_toast("open camera fail", 3000); return ret; } return usb_camera_play(camera); } return RET_OK;}
使用mutable_image控件顯示視頻或攝像頭畫面
mutable_image控件主要提供了 mutable_image_set_prepare_image 函數(shù)注冊一個回調(diào)函數(shù),該回調(diào)函數(shù)在每次繪制之前被調(diào)用,用于準備下一幀要顯示的圖片。
由于mutable_image控件本身不帶有獲取視頻或攝像頭畫面的功能,因此獲取畫面數(shù)據(jù)的操作可以借助第三方庫(如:OpenCV)來實現(xiàn)。mutable_image為了以最高性能繪制,會采取和當(dāng)前LCD相同的位圖數(shù)據(jù)格式(調(diào)用lcd_get_desired_bitmap_format 獲?。?strong>。因此為了兼容不同LCD格式,可以在回調(diào)函數(shù)中寫好不同格式的拷貝像素邏輯。
下面則是利用OpenCV接口獲取攝像頭數(shù)據(jù)并顯示到mutable_image控件的部分代碼示例:
static cv::Mat cv_image;static cv::VideoCapture cv_capture;
/* mutable_image_set_prepare_image回調(diào)函數(shù) */ret_t mutable_image_prepare_image(void* ctx, bitmap_t* image) { uint8_t* image_buff = NULL; uint32_t bpp = bitmap_get_bpp(image); widget_t* widget = WIDGET(ctx); bitmap_format_t format = (bitmap_format_t)image->format; cv_capture >> cv_image; image_buff = bitmap_lock_buffer_for_write(image); for (int h = 0; h < image->h; ++h) { uint8_t* p_buff = image_buff + image->w * h * bpp; for (int w = 0; w < image->w; ++w) { /* 調(diào)用OpenCV接口獲取攝像頭當(dāng)前幀的原始RGB數(shù)據(jù) */ cv::Vec3b val = cv_image.at(h, w); if (format == BITMAP_FMT_RGB888 || format == BITMAP_FMT_RGBA8888) { /* RGB888或 RGBA8888示例, 由于該示例上面cv::at數(shù)據(jù)的格式為BGR,需要進行轉(zhuǎn)換, 具體是否需要轉(zhuǎn)換根據(jù)實際格式而決定 */ uint8_t blue = val[0]; uint8_t green = val[1]; uint8_t red = val[2]; p_buff[0] = red; p_buff[1] = green; p_buff[2] = blue; if (format == BITMAP_FMT_RGBA8888) { p_buff[3] = 255; } p_buff += bpp;
} else if (format == BITMAP_FMT_BGR888 || format == BITMAP_FMT_BGRA8888) { ... } else if (format == BITMAP_FMT_BGR565) { } else if (format == BITMAP_FMT_RGB565) { ... } } }
return bitmap_unlock_buffer(image);}
ret_t camera_open(widget_t* win) { widget_t* mutable_image = widget_child(win, "mutable_image");
cv_capture.open(0); mutable_image_set_prepare_image(mutable_image,mutable_image_prepare_image, mutable_image); return RET_OK;}
上面代碼通過設(shè)置mutable_image控件的回調(diào)函數(shù),在回調(diào)函數(shù)里面使用OpenCV的API獲取到攝像頭原始RGB數(shù)據(jù),最后將數(shù)據(jù)寫到mutable_image控件畫面緩沖區(qū)上。
-
視頻
+關(guān)注
關(guān)注
6文章
1942瀏覽量
72884 -
攝像頭
+關(guān)注
關(guān)注
59文章
4836瀏覽量
95597 -
C語言
+關(guān)注
關(guān)注
180文章
7604瀏覽量
136683 -
awtk
+關(guān)注
關(guān)注
0文章
44瀏覽量
226
發(fā)布評論請先 登錄
相關(guān)推薦
評論