Commit 458eb50b3163bca241916e93bd6a21dc598d6b6f
- Diff rendering mode:
- inline
- side by side
examples/mandelbrot/main.cpp
(1 / 1)
|   | |||
| 4 | 4 | ** All rights reserved. | |
| 5 | 5 | ** Contact: Nokia Corporation (qt-info@nokia.com) | |
| 6 | 6 | ** | |
| 7 | ** This file is part of the examples of the Qt Toolkit. | ||
| 7 | ** Modified 2010 by HostileFork to use http://hostilefork.com/thinker-qt/ | ||
| 8 | 8 | ** | |
| 9 | 9 | ** $QT_BEGIN_LICENSE:LGPL$ | |
| 10 | 10 | ** No Commercial Usage |
|   | |||
| 4 | 4 | ** All rights reserved. | |
| 5 | 5 | ** Contact: Nokia Corporation (qt-info@nokia.com) | |
| 6 | 6 | ** | |
| 7 | ** This file is part of the examples of the Qt Toolkit. | ||
| 7 | ** Modified 2010 by HostileFork to use http://hostilefork.com/thinker-qt/ | ||
| 8 | 8 | ** | |
| 9 | 9 | ** $QT_BEGIN_LICENSE:LGPL$ | |
| 10 | 10 | ** No Commercial Usage | |
| … | … | ||
| 54 | 54 | pixmapScale = DefaultScale; | |
| 55 | 55 | curScale = DefaultScale; | |
| 56 | 56 | ||
| 57 | qRegisterMetaType<QImage>("QImage"); | ||
| 58 | connect(&thread, SIGNAL(renderedImage(const QImage &, double)), | ||
| 59 | this, SLOT(updatePixmap(const QImage &, double))); | ||
| 57 | for (int i = 0; i < ColormapSize; ++i) | ||
| 58 | colormap[i] = rgbFromWaveLength(380.0 + (i * 400.0 / ColormapSize)); | ||
| 60 | 59 | ||
| 60 | connect(&watcher, SIGNAL(written()), this, SLOT(updatePixmap())); | ||
| 61 | watcher.setThrottleTime(400); | ||
| 62 | |||
| 61 | 63 | setWindowTitle(tr("Mandelbrot")); | |
| 62 | 64 | #ifndef QT_NO_CURSOR | |
| 63 | 65 | setCursor(Qt::CrossCursor); | |
| … | … | ||
| 67 | 67 | resize(550, 400); | |
| 68 | 68 | } | |
| 69 | 69 | ||
| 70 | MandelbrotWidget::~MandelbrotWidget() | ||
| 71 | { | ||
| 72 | watcher.cancel(); | ||
| 73 | } | ||
| 74 | |||
| 75 | void MandelbrotWidget::resetThinker(double centerX, double centerY, | ||
| 76 | double scaleFactor, QSize resultSize) | ||
| 77 | { | ||
| 78 | watcher.cancel(); | ||
| 79 | |||
| 80 | RenderThinker* thinker = new RenderThinker(centerX, centerY, | ||
| 81 | scaleFactor, resultSize, colormap); | ||
| 82 | watcher.setPresent(ThinkerQt::run(thinker)); | ||
| 83 | } | ||
| 84 | |||
| 70 | 85 | void MandelbrotWidget::paintEvent(QPaintEvent * /* event */) | |
| 71 | 86 | { | |
| 72 | 87 | QPainter painter(this); | |
| … | … | ||
| 127 | 127 | ||
| 128 | 128 | void MandelbrotWidget::resizeEvent(QResizeEvent * /* event */) | |
| 129 | 129 | { | |
| 130 | thread.render(centerX, centerY, curScale, size()); | ||
| 130 | resetThinker(centerX, centerY, curScale, size()); | ||
| 131 | 131 | } | |
| 132 | 132 | ||
| 133 | 133 | void MandelbrotWidget::keyPressEvent(QKeyEvent *event) | |
| … | … | ||
| 190 | 190 | } | |
| 191 | 191 | } | |
| 192 | 192 | ||
| 193 | void MandelbrotWidget::updatePixmap(const QImage &image, double scaleFactor) | ||
| 193 | void MandelbrotWidget::updatePixmap() | ||
| 194 | 194 | { | |
| 195 | 195 | if (!lastDragPos.isNull()) | |
| 196 | 196 | return; | |
| 197 | 197 | ||
| 198 | pixmap = QPixmap::fromImage(image); | ||
| 199 | pixmapOffset = QPoint(); | ||
| 200 | lastDragPos = QPoint(); | ||
| 201 | pixmapScale = scaleFactor; | ||
| 202 | update(); | ||
| 198 | RenderThinker::SnapshotPointer snap = watcher.createSnapshot(); | ||
| 199 | if (snap->hasImage()) { | ||
| 200 | pixmap = QPixmap::fromImage(snap->getImage()); | ||
| 201 | pixmapScale = snap->getScaleFactor(); | ||
| 202 | snap.clear(); | ||
| 203 | pixmapOffset = QPoint(); | ||
| 204 | lastDragPos = QPoint(); | ||
| 205 | update(); | ||
| 206 | } | ||
| 203 | 207 | } | |
| 204 | 208 | ||
| 205 | 209 | void MandelbrotWidget::zoom(double zoomFactor) | |
| 206 | 210 | { | |
| 207 | 211 | curScale *= zoomFactor; | |
| 208 | 212 | update(); | |
| 209 | thread.render(centerX, centerY, curScale, size()); | ||
| 213 | resetThinker(centerX, centerY, curScale, size()); | ||
| 210 | 214 | } | |
| 211 | 215 | ||
| 212 | 216 | void MandelbrotWidget::scroll(int deltaX, int deltaY) | |
| … | … | ||
| 218 | 218 | centerX += deltaX * curScale; | |
| 219 | 219 | centerY += deltaY * curScale; | |
| 220 | 220 | update(); | |
| 221 | thread.render(centerX, centerY, curScale, size()); | ||
| 221 | resetThinker(centerX, centerY, curScale, size()); | ||
| 222 | } | ||
| 223 | |||
| 224 | uint MandelbrotWidget::rgbFromWaveLength(double wave) | ||
| 225 | { | ||
| 226 | double r = 0.0; | ||
| 227 | double g = 0.0; | ||
| 228 | double b = 0.0; | ||
| 229 | |||
| 230 | if (wave >= 380.0 && wave <= 440.0) { | ||
| 231 | r = -1.0 * (wave - 440.0) / (440.0 - 380.0); | ||
| 232 | b = 1.0; | ||
| 233 | } else if (wave >= 440.0 && wave <= 490.0) { | ||
| 234 | g = (wave - 440.0) / (490.0 - 440.0); | ||
| 235 | b = 1.0; | ||
| 236 | } else if (wave >= 490.0 && wave <= 510.0) { | ||
| 237 | g = 1.0; | ||
| 238 | b = -1.0 * (wave - 510.0) / (510.0 - 490.0); | ||
| 239 | } else if (wave >= 510.0 && wave <= 580.0) { | ||
| 240 | r = (wave - 510.0) / (580.0 - 510.0); | ||
| 241 | g = 1.0; | ||
| 242 | } else if (wave >= 580.0 && wave <= 645.0) { | ||
| 243 | r = 1.0; | ||
| 244 | g = -1.0 * (wave - 645.0) / (645.0 - 580.0); | ||
| 245 | } else if (wave >= 645.0 && wave <= 780.0) { | ||
| 246 | r = 1.0; | ||
| 247 | } | ||
| 248 | |||
| 249 | double s = 1.0; | ||
| 250 | if (wave > 700.0) | ||
| 251 | s = 0.3 + 0.7 * (780.0 - wave) / (780.0 - 700.0); | ||
| 252 | else if (wave < 420.0) | ||
| 253 | s = 0.3 + 0.7 * (wave - 380.0) / (420.0 - 380.0); | ||
| 254 | |||
| 255 | r = pow(r * s, 0.8); | ||
| 256 | g = pow(g * s, 0.8); | ||
| 257 | b = pow(b * s, 0.8); | ||
| 258 | return qRgb(int(r * 255), int(g * 255), int(b * 255)); | ||
| 222 | 259 | } |
|   | |||
| 4 | 4 | ** All rights reserved. | |
| 5 | 5 | ** Contact: Nokia Corporation (qt-info@nokia.com) | |
| 6 | 6 | ** | |
| 7 | ** This file is part of the examples of the Qt Toolkit. | ||
| 7 | ** Modified 2010 by HostileFork to use http://hostilefork.com/thinker-qt/ | ||
| 8 | 8 | ** | |
| 9 | 9 | ** $QT_BEGIN_LICENSE:LGPL$ | |
| 10 | 10 | ** No Commercial Usage | |
| … | … | ||
| 37 | 37 | ||
| 38 | 38 | #include <QPixmap> | |
| 39 | 39 | #include <QWidget> | |
| 40 | #include "thinkerqt/thinkerqt.h" | ||
| 40 | 41 | ||
| 41 | 42 | #include "renderthread.h" | |
| 42 | 43 | ||
| … | … | ||
| 47 | 47 | ||
| 48 | 48 | public: | |
| 49 | 49 | MandelbrotWidget(QWidget *parent = 0); | |
| 50 | ~MandelbrotWidget(); | ||
| 50 | 51 | ||
| 51 | 52 | protected: | |
| 52 | 53 | void paintEvent(QPaintEvent *event); | |
| … | … | ||
| 59 | 59 | void mouseReleaseEvent(QMouseEvent *event); | |
| 60 | 60 | ||
| 61 | 61 | private slots: | |
| 62 | void updatePixmap(const QImage &image, double scaleFactor); | ||
| 62 | void updatePixmap(); /* makes snapshot to get image & scaleFactor */ | ||
| 63 | 63 | ||
| 64 | 64 | private: | |
| 65 | 65 | void zoom(double zoomFactor); | |
| 66 | 66 | void scroll(int deltaX, int deltaY); | |
| 67 | uint rgbFromWaveLength(double wave); | ||
| 67 | 68 | ||
| 68 | RenderThread thread; | ||
| 69 | RenderThinker::PresentWatcher watcher; | ||
| 70 | void resetThinker(double centerX, double centerY, double scaleFactor, | ||
| 71 | QSize resultSize); | ||
| 72 | |||
| 69 | 73 | QPixmap pixmap; | |
| 70 | 74 | QPoint pixmapOffset; | |
| 71 | 75 | QPoint lastDragPos; | |
| … | … | ||
| 77 | 77 | double centerY; | |
| 78 | 78 | double pixmapScale; | |
| 79 | 79 | double curScale; | |
| 80 | Colormap colormap; | ||
| 80 | 81 | }; | |
| 81 | 82 | ||
| 82 | 83 | #endif |
examples/mandelbrot/renderthread.cpp
(15 / 94)
|   | |||
| 4 | 4 | ** All rights reserved. | |
| 5 | 5 | ** Contact: Nokia Corporation (qt-info@nokia.com) | |
| 6 | 6 | ** | |
| 7 | ** This file is part of the examples of the Qt Toolkit. | ||
| 7 | ** Modified 2010 by HostileFork to use http://hostilefork.com/thinker-qt/ | ||
| 8 | 8 | ** | |
| 9 | 9 | ** $QT_BEGIN_LICENSE:LGPL$ | |
| 10 | 10 | ** No Commercial Usage | |
| … | … | ||
| 38 | 38 | ||
| 39 | 39 | #include "renderthread.h" | |
| 40 | 40 | ||
| 41 | RenderThread::RenderThread(QObject *parent) | ||
| 42 | : QThread(parent) | ||
| 41 | RenderThinker::RenderThinker(double centerX, double centerY, double scaleFactor, | ||
| 42 | QSize resultSize, const Colormap& colormap) | ||
| 43 | : centerX (centerX), | ||
| 44 | centerY (centerY), | ||
| 45 | scaleFactor (scaleFactor), | ||
| 46 | resultSize (resultSize), | ||
| 47 | colormap (colormap) | ||
| 43 | 48 | { | |
| 44 | restart = false; | ||
| 45 | abort = false; | ||
| 46 | |||
| 47 | for (int i = 0; i < ColormapSize; ++i) | ||
| 48 | colormap[i] = rgbFromWaveLength(380.0 + (i * 400.0 / ColormapSize)); | ||
| 49 | 49 | } | |
| 50 | 50 | ||
| 51 | RenderThread::~RenderThread() | ||
| 51 | void RenderThinker::start() | ||
| 52 | 52 | { | |
| 53 | mutex.lock(); | ||
| 54 | abort = true; | ||
| 55 | condition.wakeOne(); | ||
| 56 | mutex.unlock(); | ||
| 57 | |||
| 58 | wait(); | ||
| 59 | } | ||
| 60 | |||
| 61 | void RenderThread::render(double centerX, double centerY, double scaleFactor, | ||
| 62 | QSize resultSize) | ||
| 63 | { | ||
| 64 | QMutexLocker locker(&mutex); | ||
| 65 | |||
| 66 | this->centerX = centerX; | ||
| 67 | this->centerY = centerY; | ||
| 68 | this->scaleFactor = scaleFactor; | ||
| 69 | this->resultSize = resultSize; | ||
| 70 | |||
| 71 | if (!isRunning()) { | ||
| 72 | start(LowPriority); | ||
| 73 | } else { | ||
| 74 | restart = true; | ||
| 75 | condition.wakeOne(); | ||
| 76 | } | ||
| 77 | } | ||
| 78 | |||
| 79 | void RenderThread::run() | ||
| 80 | { | ||
| 81 | forever { | ||
| 82 | mutex.lock(); | ||
| 83 | QSize resultSize = this->resultSize; | ||
| 84 | double scaleFactor = this->scaleFactor; | ||
| 85 | double centerX = this->centerX; | ||
| 86 | double centerY = this->centerY; | ||
| 87 | mutex.unlock(); | ||
| 88 | |||
| 89 | 53 | int halfWidth = resultSize.width() / 2; | |
| 90 | 54 | int halfHeight = resultSize.height() / 2; | |
| 91 | 55 | QImage image(resultSize, QImage::Format_RGB32); | |
| … | … | ||
| 62 | 62 | bool allBlack = true; | |
| 63 | 63 | ||
| 64 | 64 | for (int y = -halfHeight; y < halfHeight; ++y) { | |
| 65 | if (restart) | ||
| 66 | break; | ||
| 67 | if (abort) | ||
| 65 | if (wasPauseRequested()) | ||
| 68 | 66 | return; | |
| 69 | 67 | ||
| 70 | 68 | uint *scanLine = | |
| … | … | ||
| 101 | 101 | if (allBlack && pass == 0) { | |
| 102 | 102 | pass = 4; | |
| 103 | 103 | } else { | |
| 104 | if (!restart) | ||
| 105 | emit renderedImage(image, scaleFactor); | ||
| 104 | lockForWrite(); | ||
| 105 | writable().image = image; | ||
| 106 | writable().scaleFactor = scaleFactor; | ||
| 107 | unlock(); | ||
| 106 | 108 | ++pass; | |
| 107 | 109 | } | |
| 108 | 110 | } | |
| 109 | |||
| 110 | mutex.lock(); | ||
| 111 | if (!restart) | ||
| 112 | condition.wait(&mutex); | ||
| 113 | restart = false; | ||
| 114 | mutex.unlock(); | ||
| 115 | } | ||
| 116 | } | ||
| 117 | |||
| 118 | uint RenderThread::rgbFromWaveLength(double wave) | ||
| 119 | { | ||
| 120 | double r = 0.0; | ||
| 121 | double g = 0.0; | ||
| 122 | double b = 0.0; | ||
| 123 | |||
| 124 | if (wave >= 380.0 && wave <= 440.0) { | ||
| 125 | r = -1.0 * (wave - 440.0) / (440.0 - 380.0); | ||
| 126 | b = 1.0; | ||
| 127 | } else if (wave >= 440.0 && wave <= 490.0) { | ||
| 128 | g = (wave - 440.0) / (490.0 - 440.0); | ||
| 129 | b = 1.0; | ||
| 130 | } else if (wave >= 490.0 && wave <= 510.0) { | ||
| 131 | g = 1.0; | ||
| 132 | b = -1.0 * (wave - 510.0) / (510.0 - 490.0); | ||
| 133 | } else if (wave >= 510.0 && wave <= 580.0) { | ||
| 134 | r = (wave - 510.0) / (580.0 - 510.0); | ||
| 135 | g = 1.0; | ||
| 136 | } else if (wave >= 580.0 && wave <= 645.0) { | ||
| 137 | r = 1.0; | ||
| 138 | g = -1.0 * (wave - 645.0) / (645.0 - 580.0); | ||
| 139 | } else if (wave >= 645.0 && wave <= 780.0) { | ||
| 140 | r = 1.0; | ||
| 141 | } | ||
| 142 | |||
| 143 | double s = 1.0; | ||
| 144 | if (wave > 700.0) | ||
| 145 | s = 0.3 + 0.7 * (780.0 - wave) / (780.0 - 700.0); | ||
| 146 | else if (wave < 420.0) | ||
| 147 | s = 0.3 + 0.7 * (wave - 380.0) / (420.0 - 380.0); | ||
| 148 | |||
| 149 | r = pow(r * s, 0.8); | ||
| 150 | g = pow(g * s, 0.8); | ||
| 151 | b = pow(b * s, 0.8); | ||
| 152 | return qRgb(int(r * 255), int(g * 255), int(b * 255)); | ||
| 111 | emit done(); | ||
| 153 | 112 | } |
examples/mandelbrot/renderthread.h
(34 / 20)
|   | |||
| 4 | 4 | ** All rights reserved. | |
| 5 | 5 | ** Contact: Nokia Corporation (qt-info@nokia.com) | |
| 6 | 6 | ** | |
| 7 | ** This file is part of the examples of the Qt Toolkit. | ||
| 7 | ** Modified 2010 by HostileFork to use http://hostilefork.com/thinker-qt/ | ||
| 8 | 8 | ** | |
| 9 | 9 | ** $QT_BEGIN_LICENSE:LGPL$ | |
| 10 | 10 | ** No Commercial Usage | |
| … | … | ||
| 39 | 39 | #include <QSize> | |
| 40 | 40 | #include <QThread> | |
| 41 | 41 | #include <QWaitCondition> | |
| 42 | #include <QImage> | ||
| 43 | #include "thinkerqt/thinkerqt.h" | ||
| 42 | 44 | ||
| 43 | class QImage; | ||
| 45 | class RenderThinker; | ||
| 44 | 46 | ||
| 45 | class RenderThread : public QThread | ||
| 47 | class RenderThinkerData : public SnapshottableData | ||
| 46 | 48 | { | |
| 47 | Q_OBJECT | ||
| 49 | private: | ||
| 50 | friend class RenderThinker; | ||
| 51 | QImage image; | ||
| 52 | double scaleFactor; | ||
| 48 | 53 | ||
| 49 | 54 | public: | |
| 50 | RenderThread(QObject *parent = 0); | ||
| 51 | ~RenderThread(); | ||
| 55 | RenderThinkerData () | ||
| 56 | { } | ||
| 52 | 57 | ||
| 53 | void render(double centerX, double centerY, double scaleFactor, | ||
| 54 | QSize resultSize); | ||
| 58 | RenderThinkerData (const RenderThinkerData& other) | ||
| 59 | : image (other.image), | ||
| 60 | scaleFactor(other.scaleFactor) | ||
| 61 | { } | ||
| 55 | 62 | ||
| 56 | signals: | ||
| 57 | void renderedImage(const QImage &image, double scaleFactor); | ||
| 63 | bool hasImage() const { return !image.isNull(); } | ||
| 58 | 64 | ||
| 65 | const QImage& getImage() const { return image; } | ||
| 66 | |||
| 67 | double getScaleFactor() const { return scaleFactor; } | ||
| 68 | }; | ||
| 69 | |||
| 70 | const int ColormapSize = 512; | ||
| 71 | typedef uint Colormap[ColormapSize]; | ||
| 72 | |||
| 73 | class RenderThinker : public Thinker<RenderThinkerData> | ||
| 74 | { | ||
| 75 | Q_OBJECT | ||
| 76 | |||
| 77 | public: | ||
| 78 | RenderThinker(double centerX, double centerY, double scaleFactor, | ||
| 79 | QSize resultSize, const Colormap& colormap); | ||
| 80 | |||
| 59 | 81 | protected: | |
| 60 | void run(); | ||
| 82 | /* virtual*/ void start(); | ||
| 61 | 83 | ||
| 62 | 84 | private: | |
| 63 | uint rgbFromWaveLength(double wave); | ||
| 64 | |||
| 65 | QMutex mutex; | ||
| 66 | QWaitCondition condition; | ||
| 67 | 85 | double centerX; | |
| 68 | 86 | double centerY; | |
| 69 | 87 | double scaleFactor; | |
| 70 | 88 | QSize resultSize; | |
| 71 | bool restart; | ||
| 72 | bool abort; | ||
| 73 | |||
| 74 | enum { ColormapSize = 512 }; | ||
| 75 | uint colormap[ColormapSize]; | ||
| 89 | const Colormap& colormap; | ||
| 76 | 90 | }; | |
| 77 | 91 | ||
| 78 | 92 | #endif |

