source: trunk/examples/threads/mandelbrot/renderthread.cpp@ 987

Last change on this file since 987 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 6.5 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the examples of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:BSD$
10** You may use this file under the terms of the BSD license as follows:
11**
12** "Redistribution and use in source and binary forms, with or without
13** modification, are permitted provided that the following conditions are
14** met:
15** * Redistributions of source code must retain the above copyright
16** notice, this list of conditions and the following disclaimer.
17** * Redistributions in binary form must reproduce the above copyright
18** notice, this list of conditions and the following disclaimer in
19** the documentation and/or other materials provided with the
20** distribution.
21** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
22** the names of its contributors may be used to endorse or promote
23** products derived from this software without specific prior written
24** permission.
25**
26** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
37** $QT_END_LICENSE$
38**
39****************************************************************************/
40
41#include <QtGui>
42
43#include <math.h>
44
45#include "renderthread.h"
46
47//! [0]
48RenderThread::RenderThread(QObject *parent)
49 : QThread(parent)
50{
51 restart = false;
52 abort = false;
53
54 for (int i = 0; i < ColormapSize; ++i)
55 colormap[i] = rgbFromWaveLength(380.0 + (i * 400.0 / ColormapSize));
56}
57//! [0]
58
59//! [1]
60RenderThread::~RenderThread()
61{
62 mutex.lock();
63 abort = true;
64 condition.wakeOne();
65 mutex.unlock();
66
67 wait();
68}
69//! [1]
70
71//! [2]
72void RenderThread::render(double centerX, double centerY, double scaleFactor,
73 QSize resultSize)
74{
75 QMutexLocker locker(&mutex);
76
77 this->centerX = centerX;
78 this->centerY = centerY;
79 this->scaleFactor = scaleFactor;
80 this->resultSize = resultSize;
81
82 if (!isRunning()) {
83 start(LowPriority);
84 } else {
85 restart = true;
86 condition.wakeOne();
87 }
88}
89//! [2]
90
91//! [3]
92void RenderThread::run()
93{
94 forever {
95 mutex.lock();
96 QSize resultSize = this->resultSize;
97 double scaleFactor = this->scaleFactor;
98 double centerX = this->centerX;
99 double centerY = this->centerY;
100 mutex.unlock();
101//! [3]
102
103//! [4]
104 int halfWidth = resultSize.width() / 2;
105//! [4] //! [5]
106 int halfHeight = resultSize.height() / 2;
107 QImage image(resultSize, QImage::Format_RGB32);
108
109 const int NumPasses = 8;
110 int pass = 0;
111 while (pass < NumPasses) {
112 const int MaxIterations = (1 << (2 * pass + 6)) + 32;
113 const int Limit = 4;
114 bool allBlack = true;
115
116 for (int y = -halfHeight; y < halfHeight; ++y) {
117 if (restart)
118 break;
119 if (abort)
120 return;
121
122 uint *scanLine =
123 reinterpret_cast<uint *>(image.scanLine(y + halfHeight));
124 double ay = centerY + (y * scaleFactor);
125
126 for (int x = -halfWidth; x < halfWidth; ++x) {
127 double ax = centerX + (x * scaleFactor);
128 double a1 = ax;
129 double b1 = ay;
130 int numIterations = 0;
131
132 do {
133 ++numIterations;
134 double a2 = (a1 * a1) - (b1 * b1) + ax;
135 double b2 = (2 * a1 * b1) + ay;
136 if ((a2 * a2) + (b2 * b2) > Limit)
137 break;
138
139 ++numIterations;
140 a1 = (a2 * a2) - (b2 * b2) + ax;
141 b1 = (2 * a2 * b2) + ay;
142 if ((a1 * a1) + (b1 * b1) > Limit)
143 break;
144 } while (numIterations < MaxIterations);
145
146 if (numIterations < MaxIterations) {
147 *scanLine++ = colormap[numIterations % ColormapSize];
148 allBlack = false;
149 } else {
150 *scanLine++ = qRgb(0, 0, 0);
151 }
152 }
153 }
154
155 if (allBlack && pass == 0) {
156 pass = 4;
157 } else {
158 if (!restart)
159 emit renderedImage(image, scaleFactor);
160//! [5] //! [6]
161 ++pass;
162 }
163//! [6] //! [7]
164 }
165//! [7]
166
167//! [8]
168 mutex.lock();
169//! [8] //! [9]
170 if (!restart)
171 condition.wait(&mutex);
172 restart = false;
173 mutex.unlock();
174 }
175}
176//! [9]
177
178//! [10]
179uint RenderThread::rgbFromWaveLength(double wave)
180{
181 double r = 0.0;
182 double g = 0.0;
183 double b = 0.0;
184
185 if (wave >= 380.0 && wave <= 440.0) {
186 r = -1.0 * (wave - 440.0) / (440.0 - 380.0);
187 b = 1.0;
188 } else if (wave >= 440.0 && wave <= 490.0) {
189 g = (wave - 440.0) / (490.0 - 440.0);
190 b = 1.0;
191 } else if (wave >= 490.0 && wave <= 510.0) {
192 g = 1.0;
193 b = -1.0 * (wave - 510.0) / (510.0 - 490.0);
194 } else if (wave >= 510.0 && wave <= 580.0) {
195 r = (wave - 510.0) / (580.0 - 510.0);
196 g = 1.0;
197 } else if (wave >= 580.0 && wave <= 645.0) {
198 r = 1.0;
199 g = -1.0 * (wave - 645.0) / (645.0 - 580.0);
200 } else if (wave >= 645.0 && wave <= 780.0) {
201 r = 1.0;
202 }
203
204 double s = 1.0;
205 if (wave > 700.0)
206 s = 0.3 + 0.7 * (780.0 - wave) / (780.0 - 700.0);
207 else if (wave < 420.0)
208 s = 0.3 + 0.7 * (wave - 380.0) / (420.0 - 380.0);
209
210 r = pow(r * s, 0.8);
211 g = pow(g * s, 0.8);
212 b = pow(b * s, 0.8);
213 return qRgb(int(r * 255), int(g * 255), int(b * 255));
214}
215//! [10]
Note: See TracBrowser for help on using the repository browser.