PureBasic操作摄像头

呵呵,一共两种方法,用avicap32.dll,或者用DirectShow

前者简单一点,也是比较通用的办法,样例代码:

 

ContractedBlock.gif ExpandedBlockStart.gif Code
#WM_CAP_START = #WM_USER 
#WM_CAP_DRIVER_CONNECT 
= #WM_CAP_START + 10 
#WM_CAP_DRIVER_DISCONNECT 
= #WM_CAP_START + 11 
#WM_CAP_DRIVER_GET_CAPS 
= #WM_CAP_START + 14 
#WM_CAP_SET_PREVIEW 
= #WM_CAP_START + 50 
#WM_CAP_SET_PREVIEWRATE 
= #WM_CAP_START + 52 
#WM_CAP_STOP 
= #WM_CAP_START + 68 
Debug #CLSID_SystemDeviceEnum
If OpenWindow(
000660500"Video capture",#PB_Window_ScreenCentered | #PB_Window_SystemMenu) 
  If OpenLibrary(
0"C:\WINDOWS\system32\avicap32.dll"
    
*capAddress = GetFunction(0"capCreateCaptureWindowA"
    hWndC 
= CallFunctionFast(*capAddress, "My Capture Window", #WS_CHILD | #WS_VISIBLE, 1010640480, WindowID(0),1
    SendMessage_(hWndC, #WM_CAP_DRIVER_CONNECT, 
00
    SendMessage_(hWndC, #WM_CAP_SET_PREVIEW, #True, 
0
    SendMessage_(hWndC, #WM_CAP_SET_PREVIEWRATE, 
300
  EndIf 
EndIf 

Repeat 
  Event 
= WaitWindowEvent() 
Until Event 
= #PB_Event_CloseWindow 

SendMessage_(hWndC, #WM_CAP_STOP, 
00
SendMessage_(hWndC, #WM_CAP_DRIVER_DISCONNECT, 
00
DestroyWindow_(hWndC) 
CloseLibrary(
0

End 

 

如果用directshow的话,就比较麻烦,但是效率高一些,需要使用带wdm驱动的摄像头

开始前,首先要搞到一大堆directshow的头文件(样例代码中已经把需要的部分都写进去了,不够用自己转),不大好找,因为现在directshow已经从directx挪到windows里去了

purebasic可以理解成c+,注意,少个+,毕竟不支持面向对象,所以头文件也可以当原料使用

lib文件就不用了,已经集成了一部分,干这种小事足够了

用头文件主要是抄袭里面的常量定义,没别的用处

direct×××是以com为基础的,vc可以用,purebasic当然也可以,而且更简洁一些

闲话少说,上菜:

 

ContractedBlock.gif ExpandedBlockStart.gif Code
#S_OK  = 0
#OATRUE 
= -1
#OAFALSE 
= 0
 
#CLSCTX_INPROC_SERVER  
= $01
#CLSCTX_INPROC_HANDLER 
= $02
#CLSCTX_LOCAL_SERVER   
= $04
#CLSCTX_REMOTE_SERVER  
= $10

#CLSCTX_ALL    
= #CLSCTX_INPROC_SERVER|#CLSCTX_INPROC_HANDLER|#CLSCTX_LOCAL_SERVER|#CLSCTX_REMOTE_SERVER
#CLSCTX_INPROC 
= #CLSCTX_INPROC_SERVER|#CLSCTX_INPROC_HANDLER
#CLSCTX_SERVER 
= #CLSCTX_INPROC_SERVER|#CLSCTX_LOCAL_SERVER|#CLSCTX_REMOTE_SERVER

#WM_GRAPHNOTIFY
=#WM_USER+1

#ROTFLAGS_REGISTRATIONKEEPSALIVE
=0

Procedure.l L(
*pWideChar, string.s) ; Ansi->Unicode
  PokeS(
*pWideChar, string, Len(string), #PB_Unicode)
  ProcedureReturn 
*pWideChar 
EndProcedure 

Macro FAILED(Status)
  Status 
< 0
EndMacro

Macro SUCCEEDED(Status)
  Status 
>= 0
EndMacro

Macro DEFINE_GUID(Name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) 
  Global Name.GUID
  Name\Data1 
= l
  Name\Data2 
= w1
  Name\Data3 
= w2
  Name\Data4[
0= b1
  Name\Data4[
1= b2
  Name\Data4[
2= b3
  Name\Data4[
3= b4
  Name\Data4[
4= b5
  Name\Data4[
5= b6
  Name\Data4[
6= b7
  Name\Data4[
7= b8
EndMacro
DEFINE_GUID(CLSID_FilterGraph,$E436EBB3,$524F,$11CE,$9F,$
53,$00,$20,$AF,$0B,$A7,$70)
DEFINE_GUID(IID_IGraphBuilder,$56A868A9,$0AD4,$11CE,$B0,$3A,$
00,$20,$AF,$0B,$A7,$70)
DEFINE_GUID(CLSID_CaptureGraphBuilder2,$BF87B6E1,$8C27,$11D0,$B3,$F0,$
00,$AA,$00,$37,$61,$C5)
DEFINE_GUID(IID_ICaptureGraphBuilder2,$93E5A4E0,$2D50,$11D2,$AB,$FA,$
00,$A0,$C9,$C6,$E3,$8D)
DEFINE_GUID(CLSID_SystemDeviceEnum,$62BE5D10,$60EB,$11D0,$BD,$3B,$
00,$A0,$C9,$11,$CE,$86)
DEFINE_GUID(IID_ICreateDevEnum,$
29840822,$5B84,$11D0,$BD,$3B,$00,$A0,$C9,$11,$CE,$86)
DEFINE_GUID(CLSID_VideoInputDeviceCategory,$860BB310,$5D01,$11D0,$BD,$3B,$
00,$A0,$C9,$11,$CE,$86)
DEFINE_GUID(IID_IBaseFilter,$56A86895,$0AD4,$11CE,$B0,$3A,$
00,$20,$AF,$0B,$A7,$70)
DEFINE_GUID(PIN_CATEGORY_PREVIEW,$FB6C4282,$
0353,$11D1,$90,$5F,$00,$00,$C0,$CC,$16,$BA)
DEFINE_GUID(PIN_CATEGORY_CAPTURE,$FB6C4281,$
0353,$11D1,$90,$5F,$00,$00,$C0,$CC,$16,$BA)
DEFINE_GUID(MEDIATYPE_Video,$
73646976,$0000,$0010,$80,$00,$00,$AA,$00,$38,$9B,$71)
DEFINE_GUID(IID_IMediaEventEx,$56A868C0,$0AD4,$11CE,$B0,$3A,$
00,$20,$AF,$0B,$A7,$70)
DEFINE_GUID(IID_IVideoWindow,$56A868B4,$0AD4,$11CE,$B0,$3A,$
00,$20,$AF,$0B,$A7,$70)
DEFINE_GUID(IID_IMediaControl,$56A868B1,$0AD4,$11CE,$B0,$3A,$
00,$20,$AF,$0B,$A7,$70)

*pWc=AllocateMemory(1024);转换unicode用的

*pGraph.IGraphBuilder
*pCapture.ICaptureGraphBuilder2

*pMC.IMediaControl
*pVW.IVideoWindow
*pME.IMediaEventEx

*pCDE.ICreateDevEnum
*pEM.IEnumMoniker

*pM.IMoniker
Fetched.l
*pBF.IBaseFilter

*pROT.IRunningObjectTable

CoInitialize_(
0)

OpenWindow(
0,0,0,320,240,"test")


;
///获得接口
hr=CoCreateInstance_(@CLSID_FilterGraph, #Null, #CLSCTX_INPROC,@IID_IGraphBuilder, @*pGraph)

If FAILED(hr)
  MessageRequester(
"error","init dx filter failed!")
EndIf

hr
=CoCreateInstance_(@CLSID_CaptureGraphBuilder2 , #Null, #CLSCTX_INPROC,@IID_ICaptureGraphBuilder2, @*pCapture)

If FAILED(hr)
  MessageRequester(
"erro","init dx capture failed!")
EndIf

;
///查询并绑定接口
*pGraph\QueryInterface(@IID_IMediaControl,  @*pMC)
*pGraph\QueryInterface(@IID_IMediaEventEx, @*pME)
*pGraph\QueryInterface(@IID_IVideoWindow,  @*pVW)

;
///将过滤和捕获进行连接
*pCapture\SetFiltergraph(*pGraph)

;
///枚举设备
hr=CoCreateInstance_(@CLSID_SystemDeviceEnum, #Null, #CLSCTX_INPROC,@IID_ICreateDevEnum,@*pCDE)
If FAILED(hr)
  MessageRequester(
"error","enum sys devices failed!")
EndIf

*pCDE\CreateClassEnumerator(@CLSID_VideoInputDeviceCategory,@*pEM, 0)
If 
*pEM=0
  MessageRequester(
"error","enum video devices failed!")
EndIf  

;
///获取设备
If *pEM\Next(1,@*pM,@Fetched)=#S_OK
*pM\BindToObject(0,0,@IID_IBaseFilter,@*pBF)
*pM\Release()
Else
  MessageRequester(
"error","capture device not found!")
EndIf

;
///将设备添加到滤镜
hr = *pGraph\AddFilter(*pBF, L(*pWc,"Video Capture"))
If FAILED(hr)
  MessageRequester(
"error","add filter failed!")
EndIf

;
///设置流格式
hr= *pCapture\RenderStream(@PIN_CATEGORY_PREVIEW,@MEDIATYPE_Video,*pBF,#Null,#Null)
If FAILED(hr)
  MessageRequester(
"error","render stream failed!")
EndIf
*pBF\Release()

;
///设置预览窗口
hr=*pVW\put_Owner(WindowID(0))
If FAILED(hr)
  MessageRequester(
"error","preview window init failed!")
EndIf
hr
=*pVW\put_WindowStyle(#WS_CHILD | #WS_CLIPCHILDREN)
hr
=*pVW\SetWindowPosition(00320240)
hr
=*pVW\put_Visible(#OATRUE);

;
///获取消息
hr=*pME\SetNotifyWindow(WindowID(0), #WM_GRAPHNOTIFY, 0)

;
///启动预览
hr=*pMC\run()
If FAILED(hr)
  MessageRequester(
"error","start preview failed!")
EndIf

;
///通知系统组件已运行
GetRunningObjectTable_(0,@*pROT)

hr
=CreateItemMoniker_(L(*pWc,"!"),L(*pWc,"FilterGraph "+RSet(Hex(*pGraph),8,"0")+" pid "+RSet(Hex(GetCurrentProcessId_()),8,"0")),@*pM);
If FAILED(hr)
  MessageRequester(
"error","create moniker failed!")
EndIf

hr 
= *pROT\Register(#ROTFLAGS_REGISTRATIONKEEPSALIVE,*pGraph,*pM,@dwGraphRegister);
If FAILED(hr)
  MessageRequester(
"error","ROT register failed!")
EndIf

*pM\Release()

Repeat
  Event
=WaitWindowEvent()
  If Event
=#PB_Event_CloseWindow
    quit
=1
  EndIf
Until quit
=1 
  
CoUninitialize_()

 

上述代码只是简单的实现摄像头预览,保存图片什么的其实也不困难,目前只适用于一个摄像头,有兴趣的兄弟可以完善一下,这个是从dirext sdk样例照猫画虎写的,漏洞很多,挖咔咔

多说几句,purebasic中一个常用的东东是“*”,可以简单理解为指针或内存符号,vc中的类型转换都可以通过这个玩意实现,其实c++和c主要都是玩内存,这个东西就是内存指针最直白的描述,通过修饰,即可完成几乎全部操作;另一个有用的东东是“@”,相当于c++中的&,可以理解为引用,@*写在一起可以实现c++中**的用途(偶没看过***,可能孤陋寡闻了);第三个让人兴奋的东西是“\”,是半面向对象的(只有数据类型,没有方法),不过只要能认识到方法其实也是内存指针,就没什么不可能的,这个配合interface,可以搞定很多东西,不过现在没空研究interface,有机会仔细看看

转载于:https://www.cnblogs.com/andyryu/archive/2008/12/19/1358592.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值