Is there a possibility to capture the photo directly to memory and not write it do disk?
If not, deleting the captured images on Symbian, does it require signing, or self-signing is enough?
Is there a possibility to capture the photo directly to memory and not write it do disk?
If not, deleting the captured images on Symbian, does it require signing, or self-signing is enough?
not a problem, it is feature which was designed to work that way..
Year, but it's uncomfortable. I found many topics where developers want to capture camera images to buffer instead of saving it to file and there is no elegant solve to this problem. We can write this functional on Symbian C++ but such application will not be portable. And by the way symbian native C++ isn't easy to learn and use. Nobody wants to learn programming language for one application module. To our fortunately, now in QtMobility 1.2 QCameraCaptureImage has function setCaptureDestination() where we can transmit QCameraImageCapture::captureToBuffer param. Ok, but how can we receive this buffer now? There is no examples, no documentation pages about how can we put to use this feature.
I need to make photo with my N8 front camera and then pass this photo to another class for processing and saving it in specific format. By now i have that:
Header file:
Implementation:Code:class CVideoSurface : public QAbstractVideoSurface { Q_OBJECT private: QVideoFrame pFrame; QImage::Format pImageFormat; QVideoSurfaceFormat pVideoFormat; public: CVideoSurface(QObject * = 0); bool present (const QVideoFrame&); QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType) const; signals: void imageCaptured(QImage); }; class CCameraCallback : public IBaseCallback { Q_OBJECT private: CVideoSurface pSurface; QCamera* pCamera; public: CCameraCallback(); ~CCameraCallback(); virtual void Run(); private slots: void onImageCapture(int, QImage); friend class CVideoSurface; };
Now image captured and saving to default directory. Now let see whats wrong with this code.Code:#include "CCameraCallback.h" CVideoSurface::CVideoSurface(QObject* parent) : QAbstractVideoSurface(parent) { pImageFormat = QImage::Format_Invalid; } QList<QVideoFrame::PixelFormat> CVideoSurface::supportedPixelFormats( QAbstractVideoBuffer::HandleType handleType) const { if (handleType == QAbstractVideoBuffer::NoHandle) { return QList<QVideoFrame::PixelFormat>() << QVideoFrame::Format_RGB32 << QVideoFrame::Format_ARGB32 << QVideoFrame::Format_ARGB32_Premultiplied << QVideoFrame::Format_RGB565 << QVideoFrame::Format_RGB555; } else { return QList<QVideoFrame::PixelFormat>(); } } bool CVideoSurface::present(const QVideoFrame& frame) { pFrame = frame; if( surfaceFormat().pixelFormat() != pFrame.pixelFormat() || surfaceFormat().frameSize() != pFrame.size() ) { stop(); return false; } else { if ( pFrame.map(QAbstractVideoBuffer::ReadOnly) ) { qobject_cast<CCameraCallback*>(this->parent())->pCamera->stop(); } return true; } } CCameraCallback::CCameraCallback() : pSurface(this) { QByteArray lvCameraDevices = QCamera::availableDevices()[1]; pCamera = new QCamera(lvCameraDevices, this); pCamera->setCaptureMode(QCamera::CaptureStillImage); QVideoRendererControl* lvControl = qobject_cast<QVideoRendererControl*>( pCamera->service()->requestControl("com.nokia.Qt.QVideoRendererControl/1.0") ); if(lvControl){ lvControl->setSurface(&pSurface); } } CCameraCallback::~CCameraCallback() { delete pCamera; } void CCameraCallback::Run() { QCameraImageCapture* lvImageCapture = new QCameraImageCapture(pCamera); QObject::connect(lvImageCapture, SIGNAL(imageCaptured(int,QImage)), this, SLOT(onImageCapture(int,QImage))); pCamera->start(); pCamera->searchAndLock(); lvImageCapture->capture(); pCamera->unlock(); delete lvImageCapture; } void CCameraCallback::onImageCapture(int pID, QImage pPreview) { qDebug() << "IMAGE: " << pPreview.byteCount(); }
1) If I announce QCameraImageCapture as CCameraCallback class member and use it instead of local variable in Run() method then nothing happens. I can't understand why image isn't saved this way.
2) Sometimes "Camera error: "Access to camera device was rejected."" occurs.
3) Sometimes "Camera error: "General camera error."" occurs.
4) Sometimes occurs this messages
[Qt Message] Camera state changed: QCamera::UnloadedState
[Qt Message] Camera state changed: QCamera::LoadedState
and image isn't saved.
5) imageCaptured() signal never emit.
6) if I trying to stop camera just after capture() method i got "Camera error: "Access to camera device was rejected."" error.
I can't understand why each of these errors occurs.
And the main problem is that I can't get captured image directly from the camera BEFORE saving it to file system.
I don't know what to do with all these errors (
Hi,
Did you include the capabilities in your .pro file like ReadUserData, WriteUserData ?
Yes i did.
Code:symbian:TARGET.CAPABILITY += NetworkServices \ ReadUserData \ WriteUserData \ LocalServices \ UserEnvironment symbian:TARGET.EPOCHEAPSIZE = 0x020000 0x2000000
Yes, it is possible -- at least with N8 and N9 and the latest QtMobility.
Set your imageCapture object with:
imageCapture->setCaptureDestination(QCameraImageCapture::CaptureToBuffer);
imageCapture->setBufferFormat(QVideoFrame::Format_Jpeg);
And in your handler for imageAvailable signal you convert the JPEG-encoded frame into QImage or whatever:
int len = frame.mappedBytes();
QImage qim;
qim.loadFromData((const uchar *)frame.bits(), len, (const char *)"JPEG");
It's strange, but for some reason I receive 0 byte buffers =/ Here is code:
Code:CCameraCallback::CCameraCallback() : pSurface(this) { QByteArray lvCameraDevices = QCamera::availableDevices()[1]; pCamera = new QCamera(lvCameraDevices, this); pCamera->setCaptureMode(QCamera::CaptureStillImage); QVideoRendererControl* lvControl = qobject_cast<QVideoRendererControl*>( pCamera->service()->requestControl("com.nokia.Qt.QVideoRendererControl/1.0") ); if(lvControl){ lvControl->setSurface(&pSurface); } pImageCapture = new QCameraImageCapture(pCamera); pImageCapture->setCaptureDestination(QCameraImageCapture::CaptureToBuffer); pImageCapture->setBufferFormat(QVideoFrame::Format_Jpeg); QObject::connect( pImageCapture, SIGNAL( imageAvailable(int, QVideoFrame)), this, SLOT(onBufferAvailable(int, QVideoFrame)) ); } void CCameraCallback::Run() { pCamera->start(); pCamera->searchAndLock(); pImageCapture->capture(); pCamera->unlock(); } void CCameraCallback::onBufferAvailable(int id, const QVideoFrame& pFrame) { QImage lvImage; lvImage.loadFromData((const uchar*)pFrame.bits(), pFrame.mappedBytes(), (const char*)"JPEG"); qDebug() << "IMAGE: " << lvImage.byteCount(); }
Oh, one thing that is missing is mapping the frame to memory in onBufferAvailable:
if (!pFrame.map(QAbstractVideoBuffer::ReadOnly)) {
return;
}
QImage lvImage;
lvImage.loadFromData((const uchar*)pFrame.bits(), pFrame.mappedBytes(), (const char*)"JPEG");
//...And unmapping it...
pFrame.unmap();
Finally I'm got it. Now front camera capture image directly to memory. Then it is processed and write in the directory I needed. Here is the code:
the only thing that bother is debug console messages:Code:void CCameraCallback::Run() { if (pCamera->state() == QCamera::ActiveState) pCamera->stop(); pCamera->start(); pCamera->searchAndLock(); pImageCapture->capture(); /* emited imageAvailable(int, QVideoFrame) signal */ } void CCameraCallback::onBufferAvailable(int id, const QVideoFrame& pFrame) { this->pCamera->unlock(); this->pCamera->stop(); QVideoFrame lvFrame = pFrame; if (!lvFrame.map(QAbstractVideoBuffer::ReadOnly)) { return; } QImage lvImage; lvImage.loadFromData((const uchar*)lvFrame.bits(), lvFrame.mappedBytes(), (const char*)"JPEG"); lvFrame.unmap(); /* here you can process lvImage before saving */ QString lvFileName = "E:\image.jpg"; lvImage.save(lvFileName, "JPEG"); }
[Qt Message] Camera state changed: QCamera::UnloadedState
[Qt Message] Camera state changed: QCamera::LoadedState