编程使用手机摄像头

 

编程使用手机摄像头

网上资料很少,自己摸索了一阵子。共享出来。
参考资料:
《使用 Windows Mobile 5.0 中的图片、视频和照相机》http://msdn.microsoft.com/zh-cn/library/aa454909.aspx

1. Windows mobile5或6

a) DotnetCF framework中使用CameraCaptureDialog对象。
网上例子很多。实际我使用过程中发现,它仅仅就是调用了Windows mobile系统中的照相机程序。
可以录制一段视频,或是截取到某时刻的图像。 返回的东西呢,就是文件。
如果想高级控制,很难,例如在显示动态图像时候,实时分析图像的内容。

b) C#调用DirectShow来实现访问Camera
可以实现高级控制,(添加Filter. ..)

在此之前我考虑过想用C#调用DirectShow,发现那是极为困难的一件事情。
DirectShow实际上就是<手机目录>\windows\quartz.dll,它并不是C#的类型库。转换它为C#类型库,我至少做不到,1没工具(Tlbimp.exe工具只能转换PCWindows下的quartz.dll,对于WM系统的dll,这工具并不工作),2不清楚原理。

我又想通过 [ComVisible(true), ComImport,
Guid("56a86891-0ad4-11ce-b03a-0020af0ba770"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
这样的导入Com的声明,发现十分有太多的需要导入的内容。 实际上我这样做了,费了很多时间,失败了。有这些时间还不如学习下C++。

c) C++调用DirectShow来实现访问Camera
学习c++之后,发现一个极好的例子: 安装Windows Mobile 5.0 Pocket PC SDK之后。在
C:\Program Files\Windows CE Tools\wce500\Windows Mobile 5.0 Pocket PC SDK\Samples\CPP\Win32\Cameracapture

看懂之后,写了个最简单的程序,完美的演示了手机访问摄像头:
void CTestCPP1Dlg::OnBnClickedButton1()
{
CoInitialize(NULL);

//GraphBuilder and CaptureGraphBuilder
CComPtr<IGraphBuilder>  pGraphBuilder;
CComPtr<ICaptureGraphBuilder2> pCaptureGraphBuilder;

pCaptureGraphBuilder.CoCreateInstance(CLSID_CaptureGraphBuilder);
pGraphBuilder.CoCreateInstance(CLSID_FilterGraph);
pCaptureGraphBuilder->SetFiltergraph(pGraphBuilder);

//FindFirstDevice
DEVMGR_DEVICE_INFORMATION  di;
GUID guidCamera = { 0xCB998A05, 0x122C, 0x4166, 0x84, 0x6A, 0x93, 0x3E, 0x4D, 0x7E, 0x3C, 0x86 };
di.dwSize = sizeof(di);
HANDLE handle = FindFirstDevice(DeviceSearchByGuid, &guidCamera, &di);
FindClose(handle);

//VideoCaptureFilter
CComPtr<IBaseFilter>  pVideoCaptureFilter;
CComPtr<IPersistPropertyBag> pPropertyBag;
pVideoCaptureFilter.CoCreateInstance( CLSID_VideoCapture );
pVideoCaptureFilter.QueryInterface( &pPropertyBag );

CComVariant  varCamName;
varCamName = di.szLegacyName;
CPropertyBag  PropBag;
PropBag.Write(L"VCapName", &varCamName);
pPropertyBag->Load(&PropBag, NULL);
pPropertyBag.Release();

pGraphBuilder->AddFilter(pVideoCaptureFilter, L"Video capture source");

//RenderStream, ControlStream
pCaptureGraphBuilder->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, pVideoCaptureFilter, NULL, NULL );
pCaptureGraphBuilder->ControlStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pVideoCaptureFilter, 0, 0 , 0, 0);

//VideoWindow,设置实时捕捉画面为本身窗体。当然也可以设置为窗体上的一个子窗口.
IVideoWindow  *pVideoWindow;
pGraphBuilder->QueryInterface(IID_IVideoWindow, (void **)&pVideoWindow);
pVideoWindow->put_Owner((OAHWND)this->m_hWnd);
pVideoWindow->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS);
RECT rect;
GetClientRect(&rect);
pVideoWindow->SetWindowPosition(0, 0, rect.right, rect.bottom);

//MediaControl
CComPtr<IMediaControl> pMediaControl;
pGraphBuilder.QueryInterface(&pMediaControl);
pMediaControl->Run();
}

2. J2ME
在手机Java中环境中,也作过一些摸索。
手机一般用MMAPI访问摄像头
1)安装Jdk1.5,安装WTK2.5, 安装Eclipse。
2)配置WTK2.5 & Eclipse

-----------------------------
CatchScreen.java
-----------------------------
import javax.microedition.lcdui.*;
import javax.microedition.media.Player;
import javax.microedition.media.control.VideoControl;
import javax.microedition.media.Manager;
import javax.microedition.media.*;

public class CatchScreen extends Canvas {
Player p;
VideoControl vc;
public static int bytes = 0;
public CatchScreen() {
this.setFullScreenMode(true);
try {
p = Manager.createPlayer("capture://video");
p.realize();
vc = (VideoControl) p.getControl("VideoControl");
if (vc != null) {
vc.initDisplayMode(VideoControl.USE_DIRECT_VIDEO, this);
vc.setDisplaySize(128,160);
}
vc.setVisible(true);
p.start();
} catch (Exception e) {}
}

public void keyPressed(int key)
{
HttpThread thread = new HttpThread();
thread.setData(vc);
thread.start();
}

protected void paint(Graphics g) {
g.setColor(125,125,125);
g.fillRect(0,0,getWidth(),getHeight());
g.setColor(0,0,0);
g.drawLine(10,10,150,10);
}

}

-----------------------------
Test1.java
-----------------------------
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
import javax.microedition.lcdui.*;

public class Test1 extends MIDlet{
private Display display;
public Test1() {
display=Display.getDisplay(this);
}

protected void destroyApp(boolean arg0) throws MIDletStateChangeException {
}

protected void pauseApp() {
}

protected void startApp() throws MIDletStateChangeException {
CatchScreen catchScreen = new CatchScreen();
display.setCurrent(catchScreen);
}
}

最后的效果:
在PC模拟器里面看起来,捕捉画面好像工作了(因为PC模拟器里面没有摄像头,Sun的模拟器很有想像力地播放了一段视频:) )
实际我在WM系统里面(JeoDek Java模拟器), 捕捉画面根本出不来。 可能是JeoDek Java模拟器不支持MMAPI...
索爱的机器也不能显示捕捉画面。

看来Java和Windows mobile 之间的鸿沟不小啊。

posted on 2011-01-07 00:03  xilentz  阅读(2143)  评论(0编辑  收藏  举报