1 /****************************************************************************
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
6 ** This file is part of the examples of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:BSD$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
18 ** Alternatively, you may use this file under the terms of the BSD license
21 ** "Redistribution and use in source and binary forms, with or without
22 ** modification, are permitted provided that the following conditions are
24 ** * Redistributions of source code must retain the above copyright
25 ** notice, this list of conditions and the following disclaimer.
26 ** * Redistributions in binary form must reproduce the above copyright
27 ** notice, this list of conditions and the following disclaimer in
28 ** the documentation and/or other materials provided with the
30 ** * Neither the name of The Qt Company Ltd nor the names of its
31 ** contributors may be used to endorse or promote products derived
32 ** from this software without specific prior written permission.
35 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
49 ****************************************************************************/
51 #include "renderthread.h"
52 #include "renderthread.moc"
54 #include <QtGui/QImage>
57 RenderThread::RenderThread(QObject
* parent
)
60 for (int i
= 0; i
< ColormapSize
; ++i
)
61 m_colormap
[i
] = rgbFromWaveLength(380.0 + (i
* 400.0 / ColormapSize
));
64 RenderThread::~RenderThread()
68 m_condition
.wakeOne();
74 void RenderThread::render(double centerX
, double centerY
, double scaleFactor
, QSize resultSize
,
75 double devicePixelRatio
)
77 QMutexLocker
locker(&m_mutex
);
81 m_scaleFactor
= scaleFactor
;
82 m_devicePixelRatio
= devicePixelRatio
;
83 m_resultSize
= resultSize
;
92 m_condition
.wakeOne();
96 void RenderThread::run()
101 const double devicePixelRatio
= m_devicePixelRatio
;
102 const QSize resultSize
= m_resultSize
* devicePixelRatio
;
103 const double requestedScaleFactor
= m_scaleFactor
;
104 const double scaleFactor
= requestedScaleFactor
/ devicePixelRatio
;
105 const double centerX
= m_centerX
;
106 const double centerY
= m_centerY
;
109 int halfWidth
= resultSize
.width() / 2;
110 int halfHeight
= resultSize
.height() / 2;
111 QImage
image(resultSize
, QImage::Format_RGB32
);
112 image
.setDevicePixelRatio(devicePixelRatio
);
114 const int NumPasses
= 8;
116 while (pass
< NumPasses
)
118 const int MaxIterations
= (1 << (2 * pass
+ 6)) + 32;
120 bool allBlack
= true;
122 for (int y
= -halfHeight
; y
< halfHeight
; ++y
)
129 auto scanLine
= reinterpret_cast<uint
*>(image
.scanLine(y
+ halfHeight
));
130 const double ay
= centerY
+ (y
* scaleFactor
);
132 for (int x
= -halfWidth
; x
< halfWidth
; ++x
)
134 const double ax
= centerX
+ (x
* scaleFactor
);
137 int numIterations
= 0;
142 const double a2
= (a1
* a1
) - (b1
* b1
) + ax
;
143 const double b2
= (2 * a1
* b1
) + ay
;
144 if ((a2
* a2
) + (b2
* b2
) > Limit
)
148 a1
= (a2
* a2
) - (b2
* b2
) + ax
;
149 b1
= (2 * a2
* b2
) + ay
;
150 if ((a1
* a1
) + (b1
* b1
) > Limit
)
152 } while (numIterations
< MaxIterations
);
154 if (numIterations
< MaxIterations
)
156 *scanLine
++ = m_colormap
[numIterations
% ColormapSize
];
161 *scanLine
++ = qRgb(0, 0, 0);
166 if (allBlack
&& pass
== 0)
173 emit
renderedImage(image
, requestedScaleFactor
);
180 m_condition
.wait(&m_mutex
);
186 uint
RenderThread::rgbFromWaveLength(double wave
)
192 if (wave
>= 380.0 && wave
<= 440.0)
194 r
= -1.0 * (wave
- 440.0) / (440.0 - 380.0);
197 else if (wave
>= 440.0 && wave
<= 490.0)
199 g
= (wave
- 440.0) / (490.0 - 440.0);
202 else if (wave
>= 490.0 && wave
<= 510.0)
205 b
= -1.0 * (wave
- 510.0) / (510.0 - 490.0);
207 else if (wave
>= 510.0 && wave
<= 580.0)
209 r
= (wave
- 510.0) / (580.0 - 510.0);
212 else if (wave
>= 580.0 && wave
<= 645.0)
215 g
= -1.0 * (wave
- 645.0) / (645.0 - 580.0);
217 else if (wave
>= 645.0 && wave
<= 780.0)
224 s
= 0.3 + 0.7 * (780.0 - wave
) / (780.0 - 700.0);
225 else if (wave
< 420.0)
226 s
= 0.3 + 0.7 * (wave
- 380.0) / (420.0 - 380.0);
228 r
= std::pow(r
* s
, 0.8);
229 g
= std::pow(g
* s
, 0.8);
230 b
= std::pow(b
* s
, 0.8);
231 return qRgb(int(r
* 255), int(g
* 255), int(b
* 255));