不通过Qt Mobility操纵Symbian设备的相机
hamishwillee
(Talk | contribs) m (Text replace - "<code cpp>" to "<code cpp-qt>") |
|||
| (20 intermediate revisions by 3 users not shown) | |||
| Line 1: | Line 1: | ||
| + | [[Category:Symbian]][[Category:Lang-Chinese]][[Category:Qt Mobility]][[Category:Camera]] | ||
| + | {{ArticleMetaData <!-- v1.2 --> | ||
| + | |sourcecode= [[Media:testOfCameraApiOnN8(2).zip]] [[Media:testOfCameraApiOnN8(3).zip]] | ||
| + | |installfile= <!-- Link to installation file (e.g. [[Media:The Installation File.sis]]) --> | ||
| + | |devices= <!-- Devices tested against - e.g. ''devices=Nokia 6131 NFC, Nokia C7-00'') --> | ||
| + | |sdk= <!-- SDK(s) built and tested against (e.g. [http://linktosdkdownload/ Nokia Qt SDK 1.1]) --> | ||
| + | |platform= <!-- Compatible platforms - e.g. Symbian^1 and later, Qt 4.6 and later --> | ||
| + | |devicecompatability= <!-- Compatible devices e.g.: All* (must have internal GPS) --> | ||
| + | |dependencies= <!-- Any other/external dependencies e.g.: Google Maps Api v1.0 --> | ||
| + | |signing= <!-- Signing requirements - empty or one of: Self-Signed, DevCert, Manufacturer --> | ||
| + | |capabilities= <!-- Capabilities required by the article/code example (e.g. Location, NetworkServices. --> | ||
| + | |keywords= <!-- APIs, classes and methods (e.g. QSystemScreenSaver, QList, CBase --> | ||
| + | |language= Lang-Chinese | ||
| + | |translated-by= <!-- [[User:XXXX]] --> | ||
| + | |translated-from-title= <!-- Title only --> | ||
| + | |translated-from-id= <!-- Id of translated revision --> | ||
| + | |review-by= <!-- After re-review: [[User:username]] --> | ||
| + | |review-timestamp= <!-- After re-review: YYYYMMDD --> | ||
| + | |update-by= <!-- After significant update: [[User:username]]--> | ||
| + | |update-timestamp= <!-- After significant update: YYYYMMDD --> | ||
| + | |creationdate= 20100905 | ||
| + | |author= [[User:Zhouhl]] | ||
| + | }} | ||
| + | {{ArticleNeedsUpdate|language=Lang-Chinese|timestamp=20111213024922|user=[[User:Hamishwillee|<br />----]]|Article is out of date and requires either an update or to be deleted (specifically, I believe that the limitations presented are not present in the current version of Qt.}} | ||
| + | |||
== 概述 == | == 概述 == | ||
标准Qt API没有为我们提供操纵Symbian设备的相机的接口,包括现在的Qt Mobility 1.0.2也没有为我们提供相应的接口。Qt Mobility 1.1倒是包含了camera的部分,不过现在的Qt Mobility 1.1还只是一个Technology Preview版本。 | 标准Qt API没有为我们提供操纵Symbian设备的相机的接口,包括现在的Qt Mobility 1.0.2也没有为我们提供相应的接口。Qt Mobility 1.1倒是包含了camera的部分,不过现在的Qt Mobility 1.1还只是一个Technology Preview版本。 | ||
| − | 本文将通过另一种方式为大家提供一种Symbian设备上的Qt camera API,它不使用Qt Mobility,直接封装的是Symbian代码。此camera API的所有源码以及例程都可以通过本文末尾所附链接下载。本例程大部分源码得益于[ | + | 本文将通过另一种方式为大家提供一种Symbian设备上的Qt camera API,它不使用Qt Mobility,直接封装的是Symbian代码。此camera API的所有源码以及例程都可以通过本文末尾所附链接下载。本例程大部分源码得益于[[Archived:Mobile Extensions]],[http://www.developer.nokia.com/info/sw.nokia.com/id/1cde08b0-1f57-41ba-851b-776c43fdec6c/S60_Platform_Camera_Example_v3_0_en.zip.html S60 Platform: Camera Example v3.0],以及Liuxg的指导,在此一并表示感谢。 <br> |
下面就具体为大家讲解如何使用这个camera API。 | 下面就具体为大家讲解如何使用这个camera API。 | ||
| Line 8: | Line 33: | ||
== 将API源码加入工程 == | == 将API源码加入工程 == | ||
| − | + | 首先,解压附件testOfCameraApiOnN8.zip 得到testOfCameraApiOnN8文件夹,将testOfCameraApiOnN8文件夹里的cameraX文件夹整体拷贝到当前Qt工程的根目录。<br> | |
然后修改pro文件,将API源码添加进去:<br> | 然后修改pro文件,将API源码添加进去:<br> | ||
| − | <code cpp> | + | <code cpp-qt> |
| − | SOURCES += | + | SOURCES += cameraX\xqviewfinderwidget.cpp \ |
| − | + | cameraX\xqviewfinderwidget_p.cpp \ | |
| + | cameraX\xqcamera.cpp \ | ||
| + | cameraX\xqcamera_p.cpp\ | ||
| + | cameraX\xqutils.cpp \ | ||
| + | cameraX\xqutils_p.cpp \ | ||
| + | cameraX\xqconversions.cpp | ||
| − | HEADERS += | + | HEADERS += cameraX\xqviewfinderwidget.h \ |
| − | + | cameraX\xqviewfinderwidget_p.h \ | |
| + | cameraX\xqcamera.h \ | ||
| + | cameraX\xqcamera_p.h \ | ||
| + | cameraX\xqutils.h \ | ||
| + | cameraX\xqutils_p.h \ | ||
| + | cameraX\xqconversions.h | ||
| + | </code> | ||
| + | 接着继续修改pro文件,把API所用到的公共Symbian库文件添加进去: | ||
| + | <code cpp-qt> | ||
| + | LIBS += -lfbscli\ | ||
| + | -lapmime \ | ||
| + | -lcommonui \ | ||
| + | -lplatformenv \ | ||
| + | -lcharconv | ||
</code> | </code> | ||
| − | == | + | == 将API所依赖的CameraWrapper加入SDK和device == |
| − | + | 由于API中用到了并未加入公版SDK的Symbian库,所以我们需要手动加入,不过也很简单,我们可以让程序在编译的时候自动替我们加上。<br> | |
| − | <code cpp> | + | 首先将testOfCameraApiOnN8文件夹里的cameraengineWrapper文件夹整体拷贝到当前Qt工程的根目录。<br> |
| − | LIBS += - | + | 然后先向SDK加入所依赖的头文件和库:<br> |
| + | <code cpp-qt> | ||
| + | BLD_INF_RULES.prj_exports += \ | ||
| + | "cameraengineWrapper\InstallToSDK\epoc32\include\cameraengine.h \epoc32\include\cameraengine.h" \ | ||
| + | "cameraengineWrapper\InstallToSDK\epoc32\include\cameraengineobserver.h \epoc32\include\cameraengineobserver.h" \ | ||
| + | "cameraengineWrapper\InstallToSDK\epoc32\release\armv5\lib\camerawrapper.dso \epoc32\release\armv5\lib\camerawrapper.dso" \ | ||
| + | "cameraengineWrapper\InstallToSDK\epoc32\release\armv5\lib\camerawrapper.lib \epoc32\release\armv5\lib\camerawrapper.lib" \ | ||
| + | "cameraengineWrapper\InstallToSDK\epoc32\release\armv5\lib\camerawrapper{000a0000}.dso \epoc32\release\armv5\lib\camerawrapper{000a0000}.dso" \ | ||
| + | "cameraengineWrapper\InstallToSDK\epoc32\release\armv5\lib\camerawrapper{000a0000}.lib \epoc32\release\armv5\lib\camerawrapper{000a0000}.lib" \ | ||
| + | "cameraengineWrapper\InstallToSDK\epoc32\release\armv5\urel\camerawrapper.dll \epoc32\release\armv5\urel\camerawrapper.dll" \ | ||
| + | "cameraengineWrapper\InstallToSDK\epoc32\release\armv5\urel\camerawrapper.dll.map \epoc32\release\armv5\urel\camerawrapper.dll.map" \ | ||
| + | "cameraengineWrapper\InstallToSDK\epoc32\release\winscw\udeb\CamAutoFocus.dll \epoc32\release\winscw\udeb\CamAutoFocus.dll" \ | ||
| + | "cameraengineWrapper\InstallToSDK\epoc32\release\winscw\udeb\camerawrapper.dll \epoc32\release\winscw\udeb\camerawrapper.dll" \ | ||
| + | "cameraengineWrapper\InstallToSDK\epoc32\release\winscw\udeb\camerawrapper.lib \epoc32\release\winscw\udeb\camerawrapper.lib" \ | ||
| + | |||
| + | </code> | ||
| + | 再将CameraWrapper一起打包入SIS:<br> | ||
| + | <code cpp-qt> | ||
| + | cameraengineEmbeddedsis.pkg_postrules = "@\"cameraengineWrapper\InstallToDevice\camerawrapper.sisx\",(0x2001EC5F)" | ||
| + | DEPLOYMENT += cameraengineEmbeddedsis | ||
| + | </code> | ||
| + | 最后将CameraWrapper库链接到我们自己的Qt工程:<br> | ||
| + | <code cpp-qt> | ||
| + | LIBS += -lcamerawrapper | ||
</code> | </code> | ||
| − | == | + | == 在代码中使用camera API == |
| − | + | 好了,经过上述步骤,我们终于成功的做完了所有准备工作,下面就可以使用这个camera API了。<br> | |
| − | + | 首先在需要使用camera的地方引入API头文件: | |
| − | <code cpp> | + | <code cpp-qt> |
| − | #include " | + | #include "xqcamera.h" |
</code> | </code> | ||
| + | 在需要显示camera所捕获图像的地方引入API头文件: | ||
| + | <code cpp-qt> | ||
| + | #include "xqviewfinderwidget.h" | ||
| + | </code> | ||
| + | |||
| + | <br> | ||
| − | + | 接下来就可以创建一个XQCamera对象,以及对应的XQViewFinderWidget。XQViewFinderWidget是用于显示XQCamera所捕获的图像的一个QWidget。 | |
| − | <code cpp> | + | 然后记得把创建的XQCamera对象赋给XQViewFinderWidget,使他们之间建立对应关系。<br> |
| − | + | <code cpp-qt> | |
| + | viewFinderWidget->setCamera(*m_camera); | ||
</code> | </code> | ||
| − | + | 可以通过XQViewFinderWidget来设置viewfinder的尺寸,viewfinder的尺寸和呈现在手机屏幕上的取景画面直接相关。例如我们可以设置:<br> | |
| − | <code cpp> | + | <code cpp-qt> |
| − | + | viewFinderWidget->setViewfinderSize(QSize(128, 96)); | |
| − | + | ||
| − | + | ||
</code> | </code> | ||
| − | + | <br> | |
| − | <code cpp> | + | |
| − | + | <br> | |
| + | |||
| + | 打开相机,使用:<br> | ||
| + | <code cpp-qt> | ||
| + | bool XQCamera::open(int index); | ||
</code> | </code> | ||
| − | + | 当camera被成功打开,并且可以使用的时候,XQCamera 会发送一个 cameraReady() 的signal 。<br> | |
| + | 参数index表示要打开哪一个相机,比如N97上就有两个相机,默认是0。如果返回值为false,表明发生了错误,我们可以调用error()来获取具体是那种错误。 | ||
| + | <br> | ||
| + | <br> | ||
| + | |||
| + | 打开相机之后,我们需要等待 cameraReady()信号,如果camera没有ready,我们是没办法使用相机的。<br> | ||
| + | 当我们收到cameraReady()信号之后,我们就可以启动Viewfinder了,调用bool XQViewFinderWidget::start(),例如我们可以这样做:<br> | ||
| + | <code cpp-qt> | ||
| + | connect(m_camera, SIGNAL(cameraReady()), viewFinderWidget, SLOT(start())); | ||
| + | </code> | ||
| + | |||
| + | <br> | ||
| + | <br> | ||
| + | |||
| + | bool XQViewFinderWidget::start()所做的是启动Viewfinder。<br> | ||
| + | <br> | ||
| + | Viewfinder启动后的就会不间断将camera所捕获的图像传递给XQViewFinderWidget,并在UI界面上显示出来。<br> | ||
| + | |||
| + | <br> | ||
| + | <br> | ||
| + | |||
| + | 拍照,使用:<br> | ||
| + | <code cpp-qt> | ||
| + | bool XQCamera::capture(); | ||
| + | </code> | ||
| + | 此函数令camera开始拍照,当图像拍好之后,XQCamera会发送一个captureCompleted()的 signal。<br> | ||
| + | 如果返回值为false,表明发生了错误,我们可以调用error()来获取具体是那种错误。<br> | ||
| + | |||
| + | <br> | ||
| + | <br> | ||
| + | |||
| + | 我们可以这样捕获 captureCompleted()信号: | ||
| + | <code cpp-qt> | ||
| + | connect(m_camera, SIGNAL(captureCompleted(QImage*)), this, SLOT(captured(QImage*))); | ||
| + | </code> | ||
| + | <br> | ||
| + | <br> | ||
| + | |||
| + | 收到 captureCompleted()的信号之后,我们就可以进行自己的处理了,首先必须要做的是要停止viewfinder,然后通常是将拍摄的画面显示在屏幕上,例如:<br> | ||
| + | <code cpp-qt> | ||
| + | void testOfCameraApiOnN8MainWindow::captured(QImage* snapImage) | ||
| + | { | ||
| + | ui->viewFinderWidget->stop(); | ||
| + | |||
| + | m_image = QPixmap::fromImage(snapImage->copy()).toImage(); | ||
| + | m_camera->releaseImageBuffer(); | ||
| + | ui->viewFinderWidget->setImage(m_image); | ||
| + | |||
| + | m_captureAction->setDisabled(true); | ||
| + | m_changeCameraAction->setDisabled(true); | ||
| + | m_focusAction->setDisabled(true); | ||
| + | m_newPhotoAction->setEnabled(true); | ||
| + | m_saveAction->setEnabled(true); | ||
| + | ui->captureButton->setDisabled(true); | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | <br> | ||
| + | <br> | ||
| + | |||
| + | 拍摄完之后,我们也许还想存一下照片,不用担心,本例程中同样包含了保存照片的例子代码,并且还额外提供了一个非常方便的用于打开文件的类XQUtils。 | ||
| + | 好了,到此一个拍摄的过程就基本结束了,我们可以一直这么循环拍摄下去,直到用户退出程序。 | ||
| + | |||
| + | <br> | ||
| + | <br> | ||
| + | |||
| + | 一定要记得退出程序需要做的清理工作: | ||
| + | <code cpp-qt> | ||
| + | void XQCamera::close(); | ||
| + | </code> | ||
| + | 此函数释放程序对camera的占用,并power off相机。 | ||
| + | |||
| + | <br> | ||
| + | <br> | ||
| + | |||
| + | ==可以改进的地方 == | ||
| + | 需要注意的是在API的源码中,也就是在XQCameraPrivate中,使用了一个iCaptureSize(QSize(640, 480)),这里的size不同于viewfinder的size,这个size指的是所拍摄照片的尺寸。这个程序里面是写死的,我们可以进行更改,比如如果相机硬件支持更大尺寸的照片,我们可以设置的更大一些,比如: | ||
| + | <code cpp-qt> | ||
| + | XQCameraPrivate::XQCameraPrivate(XQCamera* qq) : q(qq), iCaptureSize(QSize(1280, 960)) | ||
| + | { | ||
| + | } | ||
| + | </code> | ||
| + | 另外取景的图片我们也是可以设置得更大一些,从而使得取景的画面更清晰一些,例如: | ||
| + | <code cpp-qt> | ||
| + | viewFinderWidget->setViewfinderSize(QSize(480, 360)); | ||
| + | </code> | ||
| + | 不过需要注意的是硬件必须要支持这么大尺寸,比如N8是没问题的,其他相机可以酌情更换其他尺寸。 | ||
| + | 此外如果大家觉得这个API封装的不好,那么也可以自己进行改进,源码都提供给大家了。 | ||
| + | |||
| + | <br> | ||
| + | <br> | ||
== 测试设备 == | == 测试设备 == | ||
| − | + | 本代码已通过在N97、N8上的测试。<br> | |
| − | + | 下面是程序在N97上运行时的截图:<br> | |
| − | + | ||
[[File:camera.JPG]] | [[File:camera.JPG]] | ||
== 下载源码和例子程序== | == 下载源码和例子程序== | ||
| − | [[Media: | + | 把cameraWrapper作为embedded SIS加入工程的实现:<br> |
| + | <br> | ||
| + | [[Media:testOfCameraApiOnN8(2).zip]]<br> | ||
| + | <br> | ||
| + | |||
| + | 直接使用cameraEngine源码的实现:<br> | ||
| + | <br> | ||
| + | [[Media:testOfCameraApiOnN8(3).zip]] | ||
| + | |||
| + | == 注意事项 == | ||
| + | 这里要特别提醒大家,如果目标设备是N8,那么就要特别注意选择一个恰当的时间做打开camera的操作。虽说Qt是跨平台的,但是针对特定的设备还是会有细微差别,这要取决于设备上所用的Qt版本。<br> | ||
| + | |||
| + | 在目前的Qt实现中,系统显示所涉及的东西(还有QPixmap等)都是全部存放在graphics memory中的,据测算一张1058 x 1058的图片完全解码后在graphics memory中会占用约4.3MB的空间。由于打开Camera之后ViewFinderWidget会不断收到相机发来的图片,进而ViewFinderWidget需要paint这些图片,这些要显示的图片都在graphics memory中进行处理,因此稍不注意,或者发生冲突graphics memory就会被耗尽,从而出现打不开Camera的表面现象。 | ||
| + | |||
| + | 我们的解决办法是:打开camera的操作要避开系统显示相关的操作。<br> | ||
| + | |||
| + | 比如我们不能在showEvent中直接m_camera->open(0),但是我们可以在Widget show 完之后发一个消息进行打开Camera的操作,正如例子程序中所用的方法。或者大家可以这么做 | ||
| + | <code cpp-qt> | ||
| + | QTimer::singleShot(1000, this, SLOT(openCamera())); | ||
| + | </code> | ||
| + | 也就是说延迟一两秒之后再打开Camera,这样避免和系统的显示操作发生冲突。这样就基本可以解决问题了。 | ||
| + | |||
| + | N8上用的是Qt 4.6.4,据称在将来发布的Qt 4.7.1中这一问题会得到改善。 | ||
| + | |||
| − | [[ | + | ==相关链接== |
| + | *[[Qt 开发]] | ||
| + | [[Category:Code Examples]] | ||
Latest revision as of 04:23, 11 October 2012
文章信息
原因: hamishwillee (13 Dec 2011)
Article is out of date and requires either an update or to be deleted (specifically, I believe that the limitations presented are not present in the current version of Qt.
Contents |
概述
标准Qt API没有为我们提供操纵Symbian设备的相机的接口,包括现在的Qt Mobility 1.0.2也没有为我们提供相应的接口。Qt Mobility 1.1倒是包含了camera的部分,不过现在的Qt Mobility 1.1还只是一个Technology Preview版本。
本文将通过另一种方式为大家提供一种Symbian设备上的Qt camera API,它不使用Qt Mobility,直接封装的是Symbian代码。此camera API的所有源码以及例程都可以通过本文末尾所附链接下载。本例程大部分源码得益于Archived:Mobile Extensions,S60 Platform: Camera Example v3.0,以及Liuxg的指导,在此一并表示感谢。
下面就具体为大家讲解如何使用这个camera API。
将API源码加入工程
首先,解压附件testOfCameraApiOnN8.zip 得到testOfCameraApiOnN8文件夹,将testOfCameraApiOnN8文件夹里的cameraX文件夹整体拷贝到当前Qt工程的根目录。
然后修改pro文件,将API源码添加进去:
SOURCES += cameraX\xqviewfinderwidget.cpp \
cameraX\xqviewfinderwidget_p.cpp \
cameraX\xqcamera.cpp \
cameraX\xqcamera_p.cpp\
cameraX\xqutils.cpp \
cameraX\xqutils_p.cpp \
cameraX\xqconversions.cpp
HEADERS += cameraX\xqviewfinderwidget.h \
cameraX\xqviewfinderwidget_p.h \
cameraX\xqcamera.h \
cameraX\xqcamera_p.h \
cameraX\xqutils.h \
cameraX\xqutils_p.h \
cameraX\xqconversions.h
接着继续修改pro文件,把API所用到的公共Symbian库文件添加进去:
LIBS += -lfbscli\
-lapmime \
-lcommonui \
-lplatformenv \
-lcharconv
将API所依赖的CameraWrapper加入SDK和device
由于API中用到了并未加入公版SDK的Symbian库,所以我们需要手动加入,不过也很简单,我们可以让程序在编译的时候自动替我们加上。
首先将testOfCameraApiOnN8文件夹里的cameraengineWrapper文件夹整体拷贝到当前Qt工程的根目录。
然后先向SDK加入所依赖的头文件和库:
BLD_INF_RULES.prj_exports += \
"cameraengineWrapper\InstallToSDK\epoc32\include\cameraengine.h \epoc32\include\cameraengine.h" \
"cameraengineWrapper\InstallToSDK\epoc32\include\cameraengineobserver.h \epoc32\include\cameraengineobserver.h" \
"cameraengineWrapper\InstallToSDK\epoc32\release\armv5\lib\camerawrapper.dso \epoc32\release\armv5\lib\camerawrapper.dso" \
"cameraengineWrapper\InstallToSDK\epoc32\release\armv5\lib\camerawrapper.lib \epoc32\release\armv5\lib\camerawrapper.lib" \
"cameraengineWrapper\InstallToSDK\epoc32\release\armv5\lib\camerawrapper{000a0000}.dso \epoc32\release\armv5\lib\camerawrapper{000a0000}.dso" \
"cameraengineWrapper\InstallToSDK\epoc32\release\armv5\lib\camerawrapper{000a0000}.lib \epoc32\release\armv5\lib\camerawrapper{000a0000}.lib" \
"cameraengineWrapper\InstallToSDK\epoc32\release\armv5\urel\camerawrapper.dll \epoc32\release\armv5\urel\camerawrapper.dll" \
"cameraengineWrapper\InstallToSDK\epoc32\release\armv5\urel\camerawrapper.dll.map \epoc32\release\armv5\urel\camerawrapper.dll.map" \
"cameraengineWrapper\InstallToSDK\epoc32\release\winscw\udeb\CamAutoFocus.dll \epoc32\release\winscw\udeb\CamAutoFocus.dll" \
"cameraengineWrapper\InstallToSDK\epoc32\release\winscw\udeb\camerawrapper.dll \epoc32\release\winscw\udeb\camerawrapper.dll" \
"cameraengineWrapper\InstallToSDK\epoc32\release\winscw\udeb\camerawrapper.lib \epoc32\release\winscw\udeb\camerawrapper.lib" \
再将CameraWrapper一起打包入SIS:
cameraengineEmbeddedsis.pkg_postrules = "@\"cameraengineWrapper\InstallToDevice\camerawrapper.sisx\",(0x2001EC5F)"
DEPLOYMENT += cameraengineEmbeddedsis
最后将CameraWrapper库链接到我们自己的Qt工程:
LIBS += -lcamerawrapper
在代码中使用camera API
好了,经过上述步骤,我们终于成功的做完了所有准备工作,下面就可以使用这个camera API了。
首先在需要使用camera的地方引入API头文件:
#include "xqcamera.h"在需要显示camera所捕获图像的地方引入API头文件:
#include "xqviewfinderwidget.h"
接下来就可以创建一个XQCamera对象,以及对应的XQViewFinderWidget。XQViewFinderWidget是用于显示XQCamera所捕获的图像的一个QWidget。
然后记得把创建的XQCamera对象赋给XQViewFinderWidget,使他们之间建立对应关系。
viewFinderWidget->setCamera(*m_camera);
可以通过XQViewFinderWidget来设置viewfinder的尺寸,viewfinder的尺寸和呈现在手机屏幕上的取景画面直接相关。例如我们可以设置:
viewFinderWidget->setViewfinderSize(QSize(128, 96));
打开相机,使用:
bool XQCamera::open(int index);
当camera被成功打开,并且可以使用的时候,XQCamera 会发送一个 cameraReady() 的signal 。
参数index表示要打开哪一个相机,比如N97上就有两个相机,默认是0。如果返回值为false,表明发生了错误,我们可以调用error()来获取具体是那种错误。
打开相机之后,我们需要等待 cameraReady()信号,如果camera没有ready,我们是没办法使用相机的。
当我们收到cameraReady()信号之后,我们就可以启动Viewfinder了,调用bool XQViewFinderWidget::start(),例如我们可以这样做:
connect(m_camera, SIGNAL(cameraReady()), viewFinderWidget, SLOT(start()));
bool XQViewFinderWidget::start()所做的是启动Viewfinder。
Viewfinder启动后的就会不间断将camera所捕获的图像传递给XQViewFinderWidget,并在UI界面上显示出来。
拍照,使用:
bool XQCamera::capture();
此函数令camera开始拍照,当图像拍好之后,XQCamera会发送一个captureCompleted()的 signal。
如果返回值为false,表明发生了错误,我们可以调用error()来获取具体是那种错误。
我们可以这样捕获 captureCompleted()信号:
收到 captureCompleted()的信号之后,我们就可以进行自己的处理了,首先必须要做的是要停止viewfinder,然后通常是将拍摄的画面显示在屏幕上,例如:
void testOfCameraApiOnN8MainWindow::captured(QImage* snapImage)
{
ui->viewFinderWidget->stop();
m_image = QPixmap::fromImage(snapImage->copy()).toImage();
m_camera->releaseImageBuffer();
ui->viewFinderWidget->setImage(m_image);
m_captureAction->setDisabled(true);
m_changeCameraAction->setDisabled(true);
m_focusAction->setDisabled(true);
m_newPhotoAction->setEnabled(true);
m_saveAction->setEnabled(true);
ui->captureButton->setDisabled(true);
}
拍摄完之后,我们也许还想存一下照片,不用担心,本例程中同样包含了保存照片的例子代码,并且还额外提供了一个非常方便的用于打开文件的类XQUtils。 好了,到此一个拍摄的过程就基本结束了,我们可以一直这么循环拍摄下去,直到用户退出程序。
一定要记得退出程序需要做的清理工作:
void XQCamera::close();
此函数释放程序对camera的占用,并power off相机。
可以改进的地方
需要注意的是在API的源码中,也就是在XQCameraPrivate中,使用了一个iCaptureSize(QSize(640, 480)),这里的size不同于viewfinder的size,这个size指的是所拍摄照片的尺寸。这个程序里面是写死的,我们可以进行更改,比如如果相机硬件支持更大尺寸的照片,我们可以设置的更大一些,比如:
XQCameraPrivate::XQCameraPrivate(XQCamera* qq) : q(qq), iCaptureSize(QSize(1280, 960))
{
}
另外取景的图片我们也是可以设置得更大一些,从而使得取景的画面更清晰一些,例如:
viewFinderWidget->setViewfinderSize(QSize(480, 360));
不过需要注意的是硬件必须要支持这么大尺寸,比如N8是没问题的,其他相机可以酌情更换其他尺寸。 此外如果大家觉得这个API封装的不好,那么也可以自己进行改进,源码都提供给大家了。
测试设备
本代码已通过在N97、N8上的测试。
下面是程序在N97上运行时的截图:
下载源码和例子程序
把cameraWrapper作为embedded SIS加入工程的实现:
Media:testOfCameraApiOnN8(2).zip
直接使用cameraEngine源码的实现:
Media:testOfCameraApiOnN8(3).zip
注意事项
这里要特别提醒大家,如果目标设备是N8,那么就要特别注意选择一个恰当的时间做打开camera的操作。虽说Qt是跨平台的,但是针对特定的设备还是会有细微差别,这要取决于设备上所用的Qt版本。
在目前的Qt实现中,系统显示所涉及的东西(还有QPixmap等)都是全部存放在graphics memory中的,据测算一张1058 x 1058的图片完全解码后在graphics memory中会占用约4.3MB的空间。由于打开Camera之后ViewFinderWidget会不断收到相机发来的图片,进而ViewFinderWidget需要paint这些图片,这些要显示的图片都在graphics memory中进行处理,因此稍不注意,或者发生冲突graphics memory就会被耗尽,从而出现打不开Camera的表面现象。
我们的解决办法是:打开camera的操作要避开系统显示相关的操作。
比如我们不能在showEvent中直接m_camera->open(0),但是我们可以在Widget show 完之后发一个消息进行打开Camera的操作,正如例子程序中所用的方法。或者大家可以这么做
QTimer::singleShot(1000, this, SLOT(openCamera()));
也就是说延迟一两秒之后再打开Camera,这样避免和系统的显示操作发生冲突。这样就基本可以解决问题了。
N8上用的是Qt 4.6.4,据称在将来发布的Qt 4.7.1中这一问题会得到改善。

