This file is indexed.

/usr/share/qt5/doc/qtwebkitexamples/qtwebkitexamples-webkitwidgets-imageanalyzer-example.html is in qtwebkit5-examples-doc-html 5.5.1+dfsg-2build1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!-- webkit-bridge-imageanalyzer.qdoc -->
  <title>The Webkit Bridge Tutorial - Hybrid Client Application | Qt WebKit Examples 5.5</title>
  <link rel="stylesheet" type="text/css" href="style/offline.css" />
</head>
<body>
<div class="header" id="qtdocheader">
    <div class="main">
    <div class="main-rounded">
        <div class="navigationbar">
        <ul>
<li>Qt 5.5</li>
<li><a href="qtwebkitexamples-index.html">Qt WebKit Examples</a></li>
<li>The Webkit Bridge Tutorial - Hybrid Client Application</li>
<li id="buildversion">Qt 5.5.1 Reference Documentation</li>
    </ul>
    </div>
</div>
<div class="content">
<div class="line">
<div class="content mainContent">
<div class="sidebar"><div class="sidebar-content" id="sidebar-content"></div></div>
<h1 class="title">The Webkit Bridge Tutorial - Hybrid Client Application</h1>
<span class="subtitle"></span>
<!-- $$$webkitwidgets/imageanalyzer-description -->
<div class="descr"> <a name="details"></a>
<p>In this example, we will show how to write a hybrid application using <a href="../qtwebkit/qtwebkit-bridge.html">Qt WebKit Bridge</a>, which distinguishes itself from a thin client in that it performs heavy calculations on the client side in C++, like a native application, but presents nothing more than a <code>QWebView</code> for its user interface, displaying web content written in HTML/JavaScript. The application uses <a href="../qtconcurrent/qtconcurrent.html">QtConcurrent</a> to distribute its work across as many CPU cores as are available from the system, so it can process each image in parallel.</p>
<p>For the full reference documentation of <a href="../qtwebkit/qtwebkit-qmlmodule.html">QtWebKit</a> hybrid development, see <a href="../qtwebkit/qtwebkit-bridge.html">The Qt WebKit Bridge</a>.</p>
<p>Initially, you will see a user interface with an empty list of images. Clicking on some of the images in the lower pane below adds them to the list view above, as shown in the screenshot below.</p>
<p class="centerAlign"><img src="images/webkit-imageanalyzer-screenshot.png" alt="" /></p><p>Now, we can click on <b>Analyze</b>, and each image is analyzed using some computationally intensive C++ function, in parallel and on different cores. Progress is shown while the analysis is proceeding.</p>
<p class="centerAlign"><img src="images/webkit-imageanalyzer-progress.png" alt="" /></p><p>and in the end, we will see something like this, where the average RGB values of each image are shown.</p>
<p class="centerAlign"><img src="images/webkit-imageanalyzer-complete.png" alt="" /></p><p>The MainWindow is defined in C++, and creates a <a href="../qtnetwork/qnetworkdiskcache.html">QNetworkDiskCache</a> and a <a href="../qtwebkit/qwebview.html">QWebView</a>, and tells the <a href="../qtwebkit/qwebview.html">QWebView</a> to load the starting page, providing us with a user interface for the client.</p>
<pre class="cpp">MainWin<span class="operator">::</span>MainWin(<span class="type"><a href="../qtwidgets/qwidget.html">QWidget</a></span> <span class="operator">*</span> parent) : <span class="type"><a href="../qtwebkit/qwebview.html">QWebView</a></span>(parent)
{
    m_network <span class="operator">=</span> <span class="keyword">new</span> <span class="type"><a href="../qtnetwork/qnetworkaccessmanager.html">QNetworkAccessManager</a></span>(<span class="keyword">this</span>);
    m_cache <span class="operator">=</span> <span class="keyword">new</span> <span class="type"><a href="../qtnetwork/qnetworkdiskcache.html">QNetworkDiskCache</a></span>(<span class="keyword">this</span>);
    m_cache<span class="operator">-</span><span class="operator">&gt;</span>setCacheDirectory(<span class="type"><a href="../qtcore/qstandardpaths.html">QStandardPaths</a></span><span class="operator">::</span>writableLocation(<span class="type"><a href="../qtcore/qstandardpaths.html">QStandardPaths</a></span><span class="operator">::</span>CacheLocation) <span class="operator">+</span> <span class="string">&quot;/imageanalyzer&quot;</span>);
    m_cache<span class="operator">-</span><span class="operator">&gt;</span>setMaximumCacheSize(<span class="number">1000000</span>); <span class="comment">//set the cache to 10megs</span>
    m_network<span class="operator">-</span><span class="operator">&gt;</span>setCache(m_cache);
    page()<span class="operator">-</span><span class="operator">&gt;</span>setNetworkAccessManager(m_network);

    m_analyzer <span class="operator">=</span> <span class="keyword">new</span> ImageAnalyzer(m_cache<span class="operator">,</span> <span class="keyword">this</span>);

    <span class="comment">// Signal is emitted before frame loads any web content:</span>
    <span class="type"><a href="../qtcore/qobject.html">QObject</a></span><span class="operator">::</span>connect(page()<span class="operator">-</span><span class="operator">&gt;</span>mainFrame()<span class="operator">,</span> SIGNAL(javaScriptWindowObjectCleared())<span class="operator">,</span>
                     <span class="keyword">this</span><span class="operator">,</span> SLOT(addJSObject()));

    <span class="comment">// qrc:// URLs refer to resources. See imagenalayzer.qrc</span>
    <span class="type"><a href="../qtcore/qurl.html">QUrl</a></span> startURL <span class="operator">=</span> <span class="type"><a href="../qtcore/qurl.html">QUrl</a></span>(<span class="string">&quot;qrc:/index.html&quot;</span>);

    <span class="comment">// Load web content now!</span>
    setUrl(startURL);
}</pre>
<p>In this example, the sample content is addressed with the <code>qrc:/index.html</code> URL. <code>qrc:/</code> indicates that the file is stored as a Qt resource (attached to the executable). In a real-world application, the content and images would likely be retrieved from the network rather than from resources.</p>
<p>We wish to initialize an object reference in the JavaScript web page to point to our <code>ImageAnalyzer</code> before any other scripts are run. To do this, we connect the <a href="../qtwebkit/qwebframe.html#javaScriptWindowObjectCleared">javaScriptWindowObjectCleared()</a> signal to a slot which does the object creation and handoff to JavaScript.</p>
<pre class="cpp"><span class="type">void</span> MainWin<span class="operator">::</span>addJSObject() {
    <span class="comment">// Add pAnalyzer to JavaScript Frame as member &quot;imageAnalyzer&quot;.</span>
    page()<span class="operator">-</span><span class="operator">&gt;</span>mainFrame()<span class="operator">-</span><span class="operator">&gt;</span>addToJavaScriptWindowObject(<span class="type"><a href="../qtcore/qstring.html">QString</a></span>(<span class="string">&quot;imageAnalyzer&quot;</span>)<span class="operator">,</span> m_analyzer);
}</pre>
<p>The ImageAnalyzer object is created and added to a JavaScript object on the web page's mainFrame with <code>addToJavaScriptWindowObject()</code>.</p>
<p>The start page is resources/index.html. In one of its &lt;div&gt; regions, we have images, each with an <code>onClick()</code> handler that calls <code>addImage()</code>.</p>
<pre class="cpp">&lt;div id=imagediv style=&quot;clear:both; text-align:center&quot;&gt;
&lt;hr/&gt;
    &lt;img src=&quot;images/mtRainier.jpg&quot; height=150px onclick='return addImage(this);' /&gt;
    &lt;img src=&quot;images/bellaCoola.jpg&quot; height=150px onclick='return addImage(this);'/&gt;
    &lt;img src=&quot;images/seaShell.jpg&quot; height=150px onclick='return addImage(this);'/&gt;</pre>
<p>Clicking an image adds it to an images list.</p>
<pre class="cpp">function addImage(newimg) {
    var imglist = document.getElementById('imglist');
    var curChildren = imglist.childNodes;
    var newline = document.createElement('option');
    newline.innerHTML = newimg.src.substring(newimg.src.lastIndexOf('/')+1);
    newline.value = newimg.src;
    imglist.appendChild(newline);
}</pre>
<p>The <b>Analyze</b> button at the bottom of the image list is clicked when we want to start the analysis:</p>
<pre class="cpp">    &lt;div style=&quot;float:right; width:50%; border-left: solid 1px black&quot;&gt;
        &lt;div id=&quot;listdiv&quot; align=&quot;center&quot;&gt;
            &lt;h5&gt;Images to be analyzed:&lt;/h5&gt;
            &lt;select multiple size=10 id=imglist style=&quot;width:80%&quot;&gt;&lt;/select&gt;
            &lt;br /&gt;
            &lt;input type=&quot;button&quot; id=&quot;evalbutton&quot; value=&quot;Analyze&quot; onclick=&quot;analyzeImages()&quot; /&gt;
        &lt;/div&gt;
    &lt;/div&gt;</pre>
<p>When the user clicks the <b>Analyze</b> button, <code>analyzeImages()</code> is called, another regular JavaScript method, shown below. Notice it assumes the <code>imageAnalyzer</code> object is already defined and initialized in JavaScript space, but we guaranteed that by connecting our setup slot to the appropriate signal, <a href="../qtwebkit/qwebframe.html#javaScriptWindowObjectCleared">javaScriptWindowObjectCleared()</a>.</p>
<pre class="cpp">function analyzeImages() {
    connectSlots();
    var imglist = document.getElementsByTagName('option');
    if (imglist.length &gt; 0) {
        stringlist = [];
        for(var i=0; i&lt;imglist.length; i++) {
            stringlist[i]=imglist[i].value;
        }
        if (!imageAnalyzer.busy) {
            remaining = stringlist.length;
            imageAnalyzer.startAnalysis(stringlist);
        } else {
            alert(&quot;Processing, please wait until finished.&quot;);
        }</pre>
<p>The only methods on <code>ImageAnalyzer</code> that we can or do call from JavaScript are those which are exposed through {The Meta-Object System}{Qt's MetaObject} system: <a href="../qtcore/properties.html">property</a> getter/setter methods, <code>public</code> <a href="../qtcore/signalsandslots.html">signals and slots</a>, and other <a href="../qtcore/qobject.html#Q_INVOKABLE">Q_INVOKABLE</a> functions.</p>
<pre class="cpp"><span class="keyword">class</span> ImageAnalyzer : <span class="keyword">public</span> <span class="type"><a href="../qtcore/qobject.html">QObject</a></span>
{
    Q_OBJECT
<span class="keyword">public</span>:
    ImageAnalyzer(<span class="type"><a href="../qtnetwork/qnetworkdiskcache.html">QNetworkDiskCache</a></span> <span class="operator">*</span> netcache<span class="operator">,</span> <span class="type"><a href="../qtcore/qobject.html">QObject</a></span> <span class="operator">*</span> parent<span class="operator">=</span><span class="number">0</span>);

    <span class="type"><a href="../qtgui/qcolor.html#QRgb-typedef">QRgb</a></span> lastResults();
    <span class="type">float</span> lastRed();
    <span class="type">float</span> lastGreen();
    <span class="type">float</span> lastBlue();
    bool isBusy();
    Q_PROPERTY(bool busy READ isBusy);
    Q_PROPERTY(<span class="type">float</span> red READ lastRed);
    Q_PROPERTY(<span class="type">float</span> green READ lastGreen);
    Q_PROPERTY(<span class="type">float</span> blue READ lastBlue);
    <span class="operator">~</span>ImageAnalyzer();

<span class="keyword">public</span> <span class="keyword">slots</span>:
    <span class="comment">/*! initiates analysis of all the urls in the list */</span>
    <span class="type">void</span> startAnalysis(<span class="keyword">const</span> <span class="type"><a href="../qtcore/qstringlist.html">QStringList</a></span> <span class="operator">&amp;</span> urls);

<span class="keyword">signals</span>:
    <span class="type">void</span> finishedAnalysis();
    <span class="type">void</span> updateProgress(<span class="type">int</span> completed<span class="operator">,</span> <span class="type">int</span> total);
    ...
<span class="keyword">private</span>:
<span class="type"><a href="../qtnetwork/qnetworkaccessmanager.html">QNetworkAccessManager</a></span><span class="operator">*</span> m_network;
<span class="type"><a href="../qtnetwork/qnetworkdiskcache.html">QNetworkDiskCache</a></span><span class="operator">*</span> m_cache;
<span class="type"><a href="../qtcore/qstringlist.html">QStringList</a></span> m_URLQueue;
<span class="type"><a href="../qtcore/qlist.html">QList</a></span><span class="operator">&lt;</span><span class="type"><a href="../qtgui/qimage.html">QImage</a></span><span class="operator">&gt;</span> m_imageQueue;
<span class="type">int</span> m_outstandingFetches;
<span class="type"><a href="../qtcore/qfuturewatcher.html">QFutureWatcher</a></span><span class="operator">&lt;</span><span class="type"><a href="../qtgui/qcolor.html#QRgb-typedef">QRgb</a></span><span class="operator">&gt;</span> <span class="operator">*</span> m_watcher;</pre>
<p>Most of the members are set up in the constructor:</p>
<pre class="cpp">ImageAnalyzer<span class="operator">::</span>ImageAnalyzer(<span class="type"><a href="../qtnetwork/qnetworkdiskcache.html">QNetworkDiskCache</a></span><span class="operator">*</span> netcache<span class="operator">,</span> <span class="type"><a href="../qtcore/qobject.html">QObject</a></span><span class="operator">*</span> parent)
    : <span class="type"><a href="../qtcore/qobject.html">QObject</a></span>(parent)<span class="operator">,</span> m_cache(netcache)<span class="operator">,</span> m_outstandingFetches(<span class="number">0</span>)
{
    <span class="comment">/*  ImageAnalyzer only wants to receive http responses
        for requests that it makes, so that's why it has its own
        QNetworkAccessManager. */</span>
    m_network <span class="operator">=</span> <span class="keyword">new</span> <span class="type"><a href="../qtnetwork/qnetworkaccessmanager.html">QNetworkAccessManager</a></span>(<span class="keyword">this</span>);
    m_watcher <span class="operator">=</span> <span class="keyword">new</span> <span class="type"><a href="../qtcore/qfuturewatcher.html">QFutureWatcher</a></span><span class="operator">&lt;</span><span class="type"><a href="../qtgui/qcolor.html#QRgb-typedef">QRgb</a></span><span class="operator">&gt;</span>(<span class="keyword">this</span>);
    <span class="comment">/*  We want to share a cache with the web browser,
        in case it has some images we want: */</span>
    m_network<span class="operator">-</span><span class="operator">&gt;</span>setCache(m_cache);

    <span class="type"><a href="../qtcore/qobject.html">QObject</a></span><span class="operator">::</span>connect(m_network<span class="operator">,</span> SIGNAL(finished(<span class="type"><a href="../qtnetwork/qnetworkreply.html">QNetworkReply</a></span><span class="operator">*</span>))<span class="operator">,</span>
                     <span class="keyword">this</span><span class="operator">,</span> SLOT(handleReply(<span class="type"><a href="../qtnetwork/qnetworkreply.html">QNetworkReply</a></span><span class="operator">*</span>)));
    <span class="type"><a href="../qtcore/qobject.html">QObject</a></span><span class="operator">::</span>connect(m_watcher<span class="operator">,</span> SIGNAL(finished())<span class="operator">,</span>
                     <span class="keyword">this</span><span class="operator">,</span> SLOT(doneProcessing()));
    <span class="type"><a href="../qtcore/qobject.html">QObject</a></span><span class="operator">::</span>connect(m_watcher<span class="operator">,</span> SIGNAL(progressValueChanged(<span class="type">int</span>))<span class="operator">,</span>
                     <span class="keyword">this</span><span class="operator">,</span> SLOT(progressStatus(<span class="type">int</span>)));
}</pre>
<p>Back on the JavaScript side, we want to connect signals from this object to JavaScript functions on our web page, after the web page is loaded, but before the images are analyzed.</p>
<p>From <code>connectSlots()</code>, we can see how to connect signals from the imageAnalyzer object to regular JavaScript functions, which can also behave like slots. We use this to monitor and display progress from the C++ side.</p>
<pre class="cpp">function connectSlots()
{
    if ( !connected ) {
        connected = true;
        imageAnalyzer.finishedAnalysis.connect(this, finished);
        imageAnalyzer.updateProgress.connect(this, updateProg);
    }
}</pre>
<p>The only public slot is <code>startAnalysis()</code>, called to place a list of URLs into the image analyzer's <a href="../qtconcurrent/qtconcurrent.html">QtConcurrent</a> processing queue from JavaScript space.</p>
<pre class="cpp"><span class="type">void</span> ImageAnalyzer<span class="operator">::</span>startAnalysis(<span class="keyword">const</span> <span class="type"><a href="../qtcore/qstringlist.html">QStringList</a></span> <span class="operator">&amp;</span> urls)
{
    m_URLQueue <span class="operator">=</span> urls;
    fetchURLs();
}</pre>
<p>The images need to be loaded again now, which is why fetchURLs first checks the cache to see if we can save an extra network get.</p>
<pre class="cpp"><span class="type">void</span> ImageAnalyzer<span class="operator">::</span>fetchURLs()
{
    <span class="keyword">while</span> (<span class="operator">!</span>m_URLQueue<span class="operator">.</span>isEmpty())
    {
        <span class="type"><a href="../qtcore/qstring.html">QString</a></span> url <span class="operator">=</span> m_URLQueue<span class="operator">.</span>takeFirst();
        <span class="type"><a href="../qtcore/qurl.html">QUrl</a></span> URL <span class="operator">=</span> <span class="type"><a href="../qtcore/qurl.html">QUrl</a></span>(url);
        <span class="type"><a href="../qtcore/qiodevice.html">QIODevice</a></span> <span class="operator">*</span> pData <span class="operator">=</span> m_cache<span class="operator">-</span><span class="operator">&gt;</span>data(URL);
        <span class="comment">// Is image already loaded in cache?</span>
        <span class="keyword">if</span> (pData <span class="operator">=</span><span class="operator">=</span> <span class="number">0</span>) {
            <span class="comment">// HTTP Get image over network.</span>
            m_outstandingFetches<span class="operator">+</span><span class="operator">+</span>;
            <span class="type"><a href="../qtnetwork/qnetworkrequest.html">QNetworkRequest</a></span> request <span class="operator">=</span> <span class="type"><a href="../qtnetwork/qnetworkrequest.html">QNetworkRequest</a></span>(URL);
            request<span class="operator">.</span>setRawHeader(<span class="string">&quot;User-Agent&quot;</span><span class="operator">,</span> <span class="string">&quot;The Qt Company Ltd. - Custom Qt app&quot;</span>);
            m_network<span class="operator">-</span><span class="operator">&gt;</span>get(request);
        } <span class="keyword">else</span> {
            <span class="comment">// Get image from cache</span>
            <span class="type"><a href="../qtgui/qimage.html">QImage</a></span> image;
            image<span class="operator">.</span>load(pData<span class="operator">,</span> <span class="number">0</span>);
            <span class="keyword">if</span> (<span class="operator">!</span>image<span class="operator">.</span>isNull())
                queueImage(image);
            <span class="keyword">delete</span>(pData);
        }
    }
}</pre>
<p>For the images that were not in the cache, <code>handleReply()</code> will load them into a <a href="../qtgui/qimage.html">QImage</a> when the data is ready.</p>
<pre class="cpp"><span class="type">void</span> ImageAnalyzer<span class="operator">::</span>handleReply(<span class="type"><a href="../qtnetwork/qnetworkreply.html">QNetworkReply</a></span> <span class="operator">*</span> pReply)
{
    m_outstandingFetches<span class="operator">-</span><span class="operator">-</span>;
    <span class="keyword">if</span> (pReply<span class="operator">-</span><span class="operator">&gt;</span>error()) {
        <a href="../qtcore/qtglobal.html#qDebug">qDebug</a>() <span class="operator">&lt;</span><span class="operator">&lt;</span> <span class="string">&quot;Error code&quot;</span> <span class="operator">&lt;</span><span class="operator">&lt;</span> pReply<span class="operator">-</span><span class="operator">&gt;</span>error();
        <a href="../qtcore/qtglobal.html#qDebug">qDebug</a>() <span class="operator">&lt;</span><span class="operator">&lt;</span> <span class="string">&quot;Http code&quot;</span> <span class="operator">&lt;</span><span class="operator">&lt;</span> pReply<span class="operator">-</span><span class="operator">&gt;</span>attribute(<span class="type"><a href="../qtnetwork/qnetworkrequest.html">QNetworkRequest</a></span><span class="operator">::</span>HttpStatusCodeAttribute);
        <span class="keyword">return</span>;
    }
    <span class="type"><a href="../qtgui/qimage.html">QImage</a></span> image;
    image<span class="operator">.</span>load(pReply<span class="operator">,</span> <span class="number">0</span>);
    pReply<span class="operator">-</span><span class="operator">&gt;</span>deleteLater();
    <span class="keyword">if</span> (image<span class="operator">.</span>isNull()) {
        <a href="../qtcore/qtglobal.html#qDebug">qDebug</a>() <span class="operator">&lt;</span><span class="operator">&lt;</span> <span class="string">&quot;bad image&quot;</span>;
        <a href="../qtcore/qtglobal.html#qDebug">qDebug</a>() <span class="operator">&lt;</span><span class="operator">&lt;</span> pReply<span class="operator">-</span><span class="operator">&gt;</span>rawHeaderList();
        foreach(<span class="type"><a href="../qtcore/qbytearray.html">QByteArray</a></span> element<span class="operator">,</span> pReply<span class="operator">-</span><span class="operator">&gt;</span>rawHeaderList()) {
            <a href="../qtcore/qtglobal.html#qDebug">qDebug</a>() <span class="operator">&lt;</span><span class="operator">&lt;</span> element <span class="operator">&lt;</span><span class="operator">&lt;</span> <span class="string">&quot; = &quot;</span> <span class="operator">&lt;</span><span class="operator">&lt;</span> pReply<span class="operator">-</span><span class="operator">&gt;</span>rawHeader(element);
        }
        <span class="keyword">return</span>;
    }
    queueImage(image);
}</pre>
<p>After the images are loaded, they are queued up in preparation to be sent in a batch for analysis to a <a href="../qtcore/qfuturewatcher.html">QFutureWatcher</a>, which will distribute the processing across multiple threads and cores, depending on how many are available.</p>
<pre class="cpp"><span class="type">void</span> ImageAnalyzer<span class="operator">::</span>queueImage(<span class="type"><a href="../qtgui/qimage.html">QImage</a></span> img)
{
    <span class="keyword">if</span> (<span class="operator">!</span>img<span class="operator">.</span>isNull())
        m_imageQueue <span class="operator">&lt;</span><span class="operator">&lt;</span> img;

    <span class="keyword">if</span> (m_outstandingFetches <span class="operator">=</span><span class="operator">=</span> <span class="number">0</span> <span class="operator">&amp;</span><span class="operator">&amp;</span> m_URLQueue<span class="operator">.</span>isEmpty()) {
        m_watcher<span class="operator">-</span><span class="operator">&gt;</span>setFuture(<span class="type"><a href="../qtconcurrent/qtconcurrent.html">QtConcurrent</a></span><span class="operator">::</span>mapped(m_imageQueue<span class="operator">,</span> averageRGB));
    }
}</pre>
<p>The function that gets performed on each image is <code>averageRGB()</code>, as specified in argument 2 to the <a href="../qtconcurrent/qtconcurrent.html#mapped">QtConcurrent::mapped</a>() function. Notice it repeats the same calculations 100 times on each pixel to keep the CPU very busy. This is done only for the purposes of the demo so that the analysis takes a noticeable time to complete.</p>
<pre class="cpp"><span class="type"><a href="../qtgui/qcolor.html#QRgb-typedef">QRgb</a></span> averageRGB(<span class="keyword">const</span> <span class="type"><a href="../qtgui/qimage.html">QImage</a></span> <span class="operator">&amp;</span>img)
{
    <span class="type">int</span> pixelCount <span class="operator">=</span> img<span class="operator">.</span>width() <span class="operator">*</span> img<span class="operator">.</span>height();
    <span class="type">int</span> rAvg<span class="operator">,</span> gAvg<span class="operator">,</span> bAvg;

    <span class="comment">// We waste some time here:</span>
    <span class="keyword">for</span> (<span class="type">int</span> timeWaster<span class="operator">=</span><span class="number">0</span>; timeWaster <span class="operator">&lt;</span> <span class="number">100</span>; timeWaster<span class="operator">+</span><span class="operator">+</span>) {
        <span class="type"><a href="../qtcore/qtglobal.html#quint64-typedef">quint64</a></span> rTot <span class="operator">=</span> <span class="number">0</span>;
        <span class="type"><a href="../qtcore/qtglobal.html#quint64-typedef">quint64</a></span> gTot <span class="operator">=</span> <span class="number">0</span>;
        <span class="type"><a href="../qtcore/qtglobal.html#quint64-typedef">quint64</a></span> bTot <span class="operator">=</span> <span class="number">0</span>;
        <span class="keyword">for</span> (<span class="type">int</span> i<span class="operator">=</span><span class="number">0</span>; i <span class="operator">&lt;</span> img<span class="operator">.</span>width(); i<span class="operator">+</span><span class="operator">+</span>) {
            <span class="keyword">for</span> (<span class="type">int</span> j<span class="operator">=</span><span class="number">0</span>; j <span class="operator">&lt;</span> img<span class="operator">.</span>height(); j<span class="operator">+</span><span class="operator">+</span>) {
                <span class="type"><a href="../qtgui/qcolor.html#QRgb-typedef">QRgb</a></span> pixel <span class="operator">=</span> img<span class="operator">.</span>pixel(i<span class="operator">,</span>j);
                rTot <span class="operator">+</span><span class="operator">=</span> <a href="../qtgui/qcolor.html#qRed">qRed</a>(pixel);
                gTot <span class="operator">+</span><span class="operator">=</span> <a href="../qtgui/qcolor.html#qGreen">qGreen</a>(pixel);
                bTot <span class="operator">+</span><span class="operator">=</span> <a href="../qtgui/qcolor.html#qBlue">qBlue</a>(pixel);
            }
        }
        rAvg <span class="operator">=</span> (rTot)<span class="operator">/</span>(pixelCount);
        gAvg <span class="operator">=</span> (gTot)<span class="operator">/</span>(pixelCount);
        bAvg <span class="operator">=</span> (bTot)<span class="operator">/</span>(pixelCount);
    }
    <span class="keyword">return</span> <a href="../qtgui/qcolor.html#qRgb">qRgb</a>(rAvg<span class="operator">,</span> gAvg<span class="operator">,</span> bAvg);
}</pre>
<p>Files:</p>
<ul>
<li><a href="qtwebkitexamples-webkitwidgets-imageanalyzer-imageanalyzer-cpp.html">webkitwidgets/imageanalyzer/imageanalyzer.cpp</a></li>
<li><a href="qtwebkitexamples-webkitwidgets-imageanalyzer-imageanalyzer-h.html">webkitwidgets/imageanalyzer/imageanalyzer.h</a></li>
<li><a href="qtwebkitexamples-webkitwidgets-imageanalyzer-mainwindow-cpp.html">webkitwidgets/imageanalyzer/mainwindow.cpp</a></li>
<li><a href="qtwebkitexamples-webkitwidgets-imageanalyzer-mainwindow-h.html">webkitwidgets/imageanalyzer/mainwindow.h</a></li>
<li><a href="qtwebkitexamples-webkitwidgets-imageanalyzer-resources-index-html.html">webkitwidgets/imageanalyzer/resources/index.html</a></li>
<li><a href="qtwebkitexamples-webkitwidgets-imageanalyzer-main-cpp.html">webkitwidgets/imageanalyzer/main.cpp</a></li>
<li><a href="qtwebkitexamples-webkitwidgets-imageanalyzer-imageanalyzer-pro.html">webkitwidgets/imageanalyzer/imageanalyzer.pro</a></li>
<li><a href="qtwebkitexamples-webkitwidgets-imageanalyzer-resources-imageanalyzer-qrc.html">webkitwidgets/imageanalyzer/resources/imageanalyzer.qrc</a></li>
</ul>
</div>
<!-- @@@webkitwidgets/imageanalyzer -->
        </div>
       </div>
   </div>
   </div>
</div>
<div class="footer">
   <p>
   <acronym title="Copyright">&copy;</acronym> 2015 The Qt Company Ltd.
   Documentation contributions included herein are the copyrights of
   their respective owners.<br>    The documentation provided herein is licensed under the terms of the    <a href="http://www.gnu.org/licenses/fdl.html">GNU Free Documentation    License version 1.3</a> as published by the Free Software Foundation.<br>    Qt and respective logos are trademarks of The Qt Company Ltd.     in Finland and/or other countries worldwide. All other trademarks are property
   of their respective owners. </p>
</div>
</body>
</html>