在Windows Phone 7上获取原始摄像头数据

此篇文章只是拾人牙慧而已,顺带总结过程避免浪费脑细胞。过程比较曲折,也希望遇到的各种问题和错误解决过程能给后来的同学们省时间。

周末拿到HD7后一直在摆弄,发现了一个可以使用对焦摄像头的第三方程序,还有大名鼎鼎的ZXing Barcode的WP7移植版。当时觉得奇怪,因为按照之前看过的教程来看,微软开放出来的摄像头接口只有一个PhotoTask,作用是切换到内置摄像头程序,等用户拍照完毕后返回照片数据,无法直接在程序中打开摄像头查看图像。于是祭出神器Reflector查看,它用到了Microsoft.Phone.Media.Extended.PhotoCamera和VideoCamera类。然后通过ZXing的代码验证,确实如此。

打开VS2010 Express创建工程,却发现根本没有这类——连Microsoft.Phone.Media.Extended这个程序集都没有。顺藤摸瓜找到了Den Delimarsky写的两篇文章Not your regular photo and video camera on Windows Phone 7和How VideoCamera/PhotoCamera content is saved on Windows Phone 7,前一篇介绍了如何使用PhotoCamera和VideoCamera进行摄像头图像实时显示,后一篇则是介绍怎么取到拍照后的数据,写得很棒,通俗易懂。文章中提到:

通过反射调用摄像头比较慢而且增加多余的代码。所以我转而使用GAC程序集“GAC_Microsoft.Phone.Media.Extended_v7_0_0_0_cneutral_1.dll”,由于是托管代码,所以就不用加上WMInteropManifest.xml文件(或者<Capability Name=”ID_CAP_INTEROPSERVICES”/>)了。

并且提供了GAC Dump(可以看作未开放API程序集的集合)下载。不过没有详细教程,于是搜了一下实现GAC Dump的牛人Thomas Hounsell的Blog,找到了方法 Avoiding Reflection: Adding the InteropServices library to the WP7 SDK。总结起来很简单:

首先下载Hounsell那篇文章里面的7z文件。

捡自己需要的放到C:\Program Files\Reference Assemblies\Microsoft\Framework\Silverlight\v4.0\Profile\WindowsPhone,记得改名,把前后下划线前的内容都去掉。比如对于原生摄像头,我们需要Microsoft.Phone.Media.Extended.dll。

打开RedistList文件夹里面的FrameworkList.xml文件,记得用管理员权限。新增一个File标签(复制之前的就行),程序集名改成你刚刚加入的那个dll的,去掉publicKeyToken属性。保存。

于是我欣然照做(后来尝试发现,对于InteropServices需要这么做,但Media.Extended似乎不用,dll扔过去就可以了),结果……

搞屁啊……连设计器都打不开了!只好再搜,找到个帖子[Q] Usage of Microsoft.Phone.Media.Extended,问题类似,都是“强名称验证失败”,不过帖子中还能打开设计器而运行时出现COMException:

解决方法很简单,利用Window SDK的工具sn.exe执行下面的命令跳过验证,看到后面的信息即可(也要用管理员权限,或者从VS命令行执行):

sn.exe -Vr [dll path]

Verification entry added for assembly ‘Microsoft.Phone.Media.Extended,24EEC0D8C86CDA1E’

有关强名称和sn.exe的信息可以参看具有强名称的程序集强名称工具 (Sn.exe)。简单说来强名称就是带有唯一公钥信息的程序集,好处是可以验证程序集的可靠性以及dll名字可以随便改。但坏处就是现在遇到的问题了:每台机器的.net环境都需要强名称程序集验证后才能使用。

其实这个地方还是衰了一下,因为我发现Windows Phone Developer Tools中的Visual C# Express并没有传说中的sn.exe(靠……),于是又跑到微软网站上下了个Visual C++ Express 2010,这才彻底搞定。如果你直接装了Pro版那就没这个困扰了。

最后再说一下有关PhotoCamera的使用。首先建议详读Den Delimarsky那两篇文章,基本覆盖了所有使用和可能碰到的问题。除了里面提到的API外,还有个比较有用的是GetCurrentFrame()。这个函数接受一个WritableBitmap参数,尺寸一定要是640 x 480,不然会有异常抛出来。另外拿到的WritableBitmap最好不要尝试通过ImageBrush画出来,不然会慢死(模拟器上大概200ms处理一帧,真机也就500ms)。下面截图就是模拟器的效果,大的白色区域(加那个黑方块)是原生的View Finder,左上角的是通过GetCurrentFrame()后重新画的。

9 Responses to “在Windows Phone 7上获取原始摄像头数据”

  1. Cell Phone 说道:

    I do not even know the way I ended up here, however I believed this publish was once good. I don’t recognize who you’re however definitely you are going to a famous blogger when you are not already. Cheers!

  2. ブルガリ財布 スーパーコピー
    ブルガリ 財布 偽物 http://nukenpu1972.blog.jp/archives/20911905.html

  3. What i don’t understood is in reality how you are no longer really much more smartly-liked than you may be right now. You are so intelligent. You already know therefore considerably in terms of this subject, made me in my view believe it from numerous various angles. Its like men and women aren’t fascinated except it’s one thing to do with Woman gaga! Your own stuffs outstanding. Always care for it up!

Leave a Reply