×
Namespaces

Variants
Actions
(Difference between revisions)

How to add multithread support to your Qt application

From Nokia Developer Wiki
Jump to: navigation, search
galazzo (Talk | contribs)
m (Galazzo -)
galazzo (Talk | contribs)
m (Galazzo -)
Line 32: Line 32:
 
The capture image in sequence have to be faster than possible. Heach time the QML component will be asked to shot a frame it saves in a default path the captured image and after is ready  to capture another frame.<br />
 
The capture image in sequence have to be faster than possible. Heach time the QML component will be asked to shot a frame it saves in a default path the captured image and after is ready  to capture another frame.<br />
 
At the end of the three image capturing process, the flow process need to load all three photo into memory for the raw image processing to produce our HDR image.<br />
 
At the end of the three image capturing process, the flow process need to load all three photo into memory for the raw image processing to produce our HDR image.<br />
The loading process is very slow, expecially at resolution growing, due to the ( time of writing ) phone memory speed, so this has impacts the overall processing time. If during the next frame shooting application was able to begin the previous saved frame into memory this will reduce the waiting time, enhancing user experience.
+
The loading process is very slow, expecially at resolution growing, due to the ( time of writing ) phone memory speed, so this has impacts the overall processing time. If during the next frame shooting application was able to begin the previous saved frame into memory this will reduce the waiting time, enhancing user experience.<br />
 +
The solution provided uses [http://qt-project.org/doc/qt-4.8/qrunnable.html QRUnnable] interface and [http://qt-project.org/doc/qt-4.8/qthreadpool.html qthreadpool] class.
  
 +
== QRunnable ==
 +
The QRunnable class is an interface for representing a task or piece of code that needs to be executed, represented by your reimplementation of the run() function.<br />
 +
QThreadPool executes your code in a separate thread supporting execution of the same QRunnable more than once.
 +
 +
== Multithread Image Loading ==
 +
The first step is to implement  the QRunnable interface:
 +
<code cpp>
 +
class LoadingThread : public QRunnable
 +
{
 +
public:
 +
    LoadingThread(QString*, QImage*);
 +
 +
private:
 +
    QString* path;
 +
    QImage* image;
 +
 +
protected:
 +
    void run();
 +
};
 +
 +
LoadingThread::LoadingThread(QString* path, QImage* image){
 +
    this->path = path;
 +
    this->image = image;
 +
}
 +
 +
void LoadingThread::run()  {
 +
    if( image->load(*path) ){
 +
        qDebug() << "Image loaded";
 +
    } else {
 +
        qDebug() << "Error during image loading " << *path;
 +
    }
 +
}
 +
</code>
 +
 +
=== QThreadPool ===
 +
The QML Camera component provide the ''onImageSaved ( path )'' signal, called after the image has been written to the filesystem, in this context connected to '''setSho'''''x'' SLOTs.
 +
<code cpp>
 +
void QHdrCamera::setShot1(QString path) {
 +
    if( !QFile::rename(path, QDir::toNativeSeparators(s_shot1)) ) {
 +
        qDebug() << "Impossible to rename shot1:" << path;
 +
    } else {
 +
        LoadingThread* tLoad = new LoadingThread(&s_shot1, &shot1);
 +
        QThreadPool::globalInstance()->start(tLoad);
 +
        emit savedShot1();
 +
    }
 +
}
 +
 +
void QHdrCamera::setShot2(QString path) {
 +
    if( !QFile::rename(path, s_shot2) ) {
 +
        qDebug() << "Impossible to rename shot2";
 +
    } else {
 +
        LoadingThread* tLoad = new LoadingThread(&s_shot2, &shot2);
 +
        QThreadPool::globalInstance()->start(tLoad);
 +
        emit savedShot2();
 +
    }
 +
}
 +
 +
void QHdrCamera::setShot3(QString path) {
 +
    if( !QFile::rename(path, s_shot3) ){
 +
        qDebug() << "Impossible to rename shot3";
 +
    } else {
 +
        LoadingThread* tLoad = new LoadingThread(&s_shot3, &shot3);
 +
        QThreadPool::globalInstance()->start(tLoad);
 +
        emit savedShot3();
 +
    }
 +
}
 +
</code>
  
 
''Add categories below. Remove Category:Draft when the page is complete or near complete''
 
''Add categories below. Remove Category:Draft when the page is complete or near complete''

Revision as of 13:20, 21 May 2012

Article Metadata
Tested with
Devices(s): Nokia C7-00, Nokia N8, Nokia N950
CompatibilityArticle
Keywords: Thread, QThread, QRunnable,QThreadPool
Created: galazzo (21 May 2012)
Last edited: galazzo (21 May 2012)

Contents

Introduction

This article explains how to manage multithread into a mobile application. QHdrCamera will be used as showcase.

Showcase

QHdrCamera is a component component able to create High Dynamic Range images.
Basically to do that the component captures three photos at different exposure range mixing them using some algorithms. For further information, please referr to this article.

The capture image in sequence have to be faster than possible. Heach time the QML component will be asked to shot a frame it saves in a default path the captured image and after is ready to capture another frame.
At the end of the three image capturing process, the flow process need to load all three photo into memory for the raw image processing to produce our HDR image.
The loading process is very slow, expecially at resolution growing, due to the ( time of writing ) phone memory speed, so this has impacts the overall processing time. If during the next frame shooting application was able to begin the previous saved frame into memory this will reduce the waiting time, enhancing user experience.
The solution provided uses QRUnnable interface and qthreadpool class.

QRunnable

The QRunnable class is an interface for representing a task or piece of code that needs to be executed, represented by your reimplementation of the run() function.
QThreadPool executes your code in a separate thread supporting execution of the same QRunnable more than once.

Multithread Image Loading

The first step is to implement the QRunnable interface:

class LoadingThread : public QRunnable
{
public:
LoadingThread(QString*, QImage*);
 
private:
QString* path;
QImage* image;
 
protected:
void run();
};
 
LoadingThread::LoadingThread(QString* path, QImage* image){
this->path = path;
this->image = image;
}
 
void LoadingThread::run() {
if( image->load(*path) ){
qDebug() << "Image loaded";
} else {
qDebug() << "Error during image loading " << *path;
}
}

QThreadPool

The QML Camera component provide the onImageSaved ( path ) signal, called after the image has been written to the filesystem, in this context connected to setShox SLOTs.

void QHdrCamera::setShot1(QString path) {
if( !QFile::rename(path, QDir::toNativeSeparators(s_shot1)) ) {
qDebug() << "Impossible to rename shot1:" << path;
} else {
LoadingThread* tLoad = new LoadingThread(&s_shot1, &shot1);
QThreadPool::globalInstance()->start(tLoad);
emit savedShot1();
}
}
 
void QHdrCamera::setShot2(QString path) {
if( !QFile::rename(path, s_shot2) ) {
qDebug() << "Impossible to rename shot2";
} else {
LoadingThread* tLoad = new LoadingThread(&s_shot2, &shot2);
QThreadPool::globalInstance()->start(tLoad);
emit savedShot2();
}
}
 
void QHdrCamera::setShot3(QString path) {
if( !QFile::rename(path, s_shot3) ){
qDebug() << "Impossible to rename shot3";
} else {
LoadingThread* tLoad = new LoadingThread(&s_shot3, &shot3);
QThreadPool::globalInstance()->start(tLoad);
emit savedShot3();
}
}

Add categories below. Remove Category:Draft when the page is complete or near complete

321 page views in the last 30 days.