Skip to content
Permalink
Browse files

Mandelbrot sample changes to use Thinker-Qt. (Submitted in a single d…

…iff for easy review on gitorious)
  • Loading branch information
hostilefork committed Jan 21, 2010
1 parent ae5205f commit 458eb50b3163bca241916e93bd6a21dc598d6b6f
@@ -4,7 +4,7 @@
** All rights reserved. ** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com) ** Contact: Nokia Corporation (qt-info@nokia.com)
** **
** This file is part of the examples of the Qt Toolkit. ** Modified 2010 by HostileFork to use http://hostilefork.com/thinker-qt/
** **
** $QT_BEGIN_LICENSE:LGPL$ ** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage ** No Commercial Usage
@@ -42,4 +42,4 @@ int main(int argc, char *argv[])
MandelbrotWidget widget; MandelbrotWidget widget;
widget.show(); widget.show();
return app.exec(); return app.exec();
} }
@@ -4,7 +4,7 @@
** All rights reserved. ** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com) ** Contact: Nokia Corporation (qt-info@nokia.com)
** **
** This file is part of the examples of the Qt Toolkit. ** Modified 2010 by HostileFork to use http://hostilefork.com/thinker-qt/
** **
** $QT_BEGIN_LICENSE:LGPL$ ** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage ** No Commercial Usage
@@ -54,9 +54,11 @@ MandelbrotWidget::MandelbrotWidget(QWidget *parent)
pixmapScale = DefaultScale; pixmapScale = DefaultScale;
curScale = DefaultScale; curScale = DefaultScale;


qRegisterMetaType<QImage>("QImage"); for (int i = 0; i < ColormapSize; ++i)
connect(&thread, SIGNAL(renderedImage(const QImage &, double)), colormap[i] = rgbFromWaveLength(380.0 + (i * 400.0 / ColormapSize));
this, SLOT(updatePixmap(const QImage &, double)));
connect(&watcher, SIGNAL(written()), this, SLOT(updatePixmap()));
watcher.setThrottleTime(400);


setWindowTitle(tr("Mandelbrot")); setWindowTitle(tr("Mandelbrot"));
#ifndef QT_NO_CURSOR #ifndef QT_NO_CURSOR
@@ -65,6 +67,21 @@ MandelbrotWidget::MandelbrotWidget(QWidget *parent)
resize(550, 400); resize(550, 400);
} }


MandelbrotWidget::~MandelbrotWidget()
{
watcher.cancel();
}

void MandelbrotWidget::resetThinker(double centerX, double centerY,
double scaleFactor, QSize resultSize)
{
watcher.cancel();

RenderThinker* thinker = new RenderThinker(centerX, centerY,
scaleFactor, resultSize, colormap);
watcher.setPresent(ThinkerQt::run(thinker));
}

void MandelbrotWidget::paintEvent(QPaintEvent * /* event */) void MandelbrotWidget::paintEvent(QPaintEvent * /* event */)
{ {
QPainter painter(this); QPainter painter(this);
@@ -110,7 +127,7 @@ void MandelbrotWidget::paintEvent(QPaintEvent * /* event */)


void MandelbrotWidget::resizeEvent(QResizeEvent * /* event */) void MandelbrotWidget::resizeEvent(QResizeEvent * /* event */)
{ {
thread.render(centerX, centerY, curScale, size()); resetThinker(centerX, centerY, curScale, size());
} }


void MandelbrotWidget::keyPressEvent(QKeyEvent *event) void MandelbrotWidget::keyPressEvent(QKeyEvent *event)
@@ -173,29 +190,70 @@ void MandelbrotWidget::mouseReleaseEvent(QMouseEvent *event)
} }
} }


void MandelbrotWidget::updatePixmap(const QImage &image, double scaleFactor) void MandelbrotWidget::updatePixmap()
{ {
if (!lastDragPos.isNull()) if (!lastDragPos.isNull())
return; return;


pixmap = QPixmap::fromImage(image); RenderThinker::SnapshotPointer snap = watcher.createSnapshot();
pixmapOffset = QPoint(); if (snap->hasImage()) {
lastDragPos = QPoint(); pixmap = QPixmap::fromImage(snap->getImage());
pixmapScale = scaleFactor; pixmapScale = snap->getScaleFactor();
update(); snap.clear();
pixmapOffset = QPoint();
lastDragPos = QPoint();
update();
}
} }


void MandelbrotWidget::zoom(double zoomFactor) void MandelbrotWidget::zoom(double zoomFactor)
{ {
curScale *= zoomFactor; curScale *= zoomFactor;
update(); update();
thread.render(centerX, centerY, curScale, size()); resetThinker(centerX, centerY, curScale, size());
} }


void MandelbrotWidget::scroll(int deltaX, int deltaY) void MandelbrotWidget::scroll(int deltaX, int deltaY)
{ {
centerX += deltaX * curScale; centerX += deltaX * curScale;
centerY += deltaY * curScale; centerY += deltaY * curScale;
update(); update();
thread.render(centerX, centerY, curScale, size()); resetThinker(centerX, centerY, curScale, size());
} }

uint MandelbrotWidget::rgbFromWaveLength(double wave)
{
double r = 0.0;
double g = 0.0;
double b = 0.0;

if (wave >= 380.0 && wave <= 440.0) {
r = -1.0 * (wave - 440.0) / (440.0 - 380.0);
b = 1.0;
} else if (wave >= 440.0 && wave <= 490.0) {
g = (wave - 440.0) / (490.0 - 440.0);
b = 1.0;
} else if (wave >= 490.0 && wave <= 510.0) {
g = 1.0;
b = -1.0 * (wave - 510.0) / (510.0 - 490.0);
} else if (wave >= 510.0 && wave <= 580.0) {
r = (wave - 510.0) / (580.0 - 510.0);
g = 1.0;
} else if (wave >= 580.0 && wave <= 645.0) {
r = 1.0;
g = -1.0 * (wave - 645.0) / (645.0 - 580.0);
} else if (wave >= 645.0 && wave <= 780.0) {
r = 1.0;
}

double s = 1.0;
if (wave > 700.0)
s = 0.3 + 0.7 * (780.0 - wave) / (780.0 - 700.0);
else if (wave < 420.0)
s = 0.3 + 0.7 * (wave - 380.0) / (420.0 - 380.0);

r = pow(r * s, 0.8);
g = pow(g * s, 0.8);
b = pow(b * s, 0.8);
return qRgb(int(r * 255), int(g * 255), int(b * 255));
}
@@ -4,7 +4,7 @@
** All rights reserved. ** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com) ** Contact: Nokia Corporation (qt-info@nokia.com)
** **
** This file is part of the examples of the Qt Toolkit. ** Modified 2010 by HostileFork to use http://hostilefork.com/thinker-qt/
** **
** $QT_BEGIN_LICENSE:LGPL$ ** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage ** No Commercial Usage
@@ -37,6 +37,7 @@


#include <QPixmap> #include <QPixmap>
#include <QWidget> #include <QWidget>
#include "thinkerqt/thinkerqt.h"


#include "renderthread.h" #include "renderthread.h"


@@ -46,6 +47,7 @@ class MandelbrotWidget : public QWidget


public: public:
MandelbrotWidget(QWidget *parent = 0); MandelbrotWidget(QWidget *parent = 0);
~MandelbrotWidget();


protected: protected:
void paintEvent(QPaintEvent *event); void paintEvent(QPaintEvent *event);
@@ -57,20 +59,25 @@ class MandelbrotWidget : public QWidget
void mouseReleaseEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event);


private slots: private slots:
void updatePixmap(const QImage &image, double scaleFactor); void updatePixmap(); /* makes snapshot to get image & scaleFactor */


private: private:
void zoom(double zoomFactor); void zoom(double zoomFactor);
void scroll(int deltaX, int deltaY); void scroll(int deltaX, int deltaY);
uint rgbFromWaveLength(double wave);

RenderThinker::PresentWatcher watcher;
void resetThinker(double centerX, double centerY, double scaleFactor,
QSize resultSize);


RenderThread thread;
QPixmap pixmap; QPixmap pixmap;
QPoint pixmapOffset; QPoint pixmapOffset;
QPoint lastDragPos; QPoint lastDragPos;
double centerX; double centerX;
double centerY; double centerY;
double pixmapScale; double pixmapScale;
double curScale; double curScale;
Colormap colormap;
}; };


#endif #endif
@@ -4,7 +4,7 @@
** All rights reserved. ** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com) ** Contact: Nokia Corporation (qt-info@nokia.com)
** **
** This file is part of the examples of the Qt Toolkit. ** Modified 2010 by HostileFork to use http://hostilefork.com/thinker-qt/
** **
** $QT_BEGIN_LICENSE:LGPL$ ** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage ** No Commercial Usage
@@ -38,54 +38,18 @@


#include "renderthread.h" #include "renderthread.h"


RenderThread::RenderThread(QObject *parent) RenderThinker::RenderThinker(double centerX, double centerY, double scaleFactor,
: QThread(parent) QSize resultSize, const Colormap& colormap)
: centerX (centerX),
centerY (centerY),
scaleFactor (scaleFactor),
resultSize (resultSize),
colormap (colormap)
{ {
restart = false;
abort = false;

for (int i = 0; i < ColormapSize; ++i)
colormap[i] = rgbFromWaveLength(380.0 + (i * 400.0 / ColormapSize));
}

RenderThread::~RenderThread()
{
mutex.lock();
abort = true;
condition.wakeOne();
mutex.unlock();

wait();
} }


void RenderThread::render(double centerX, double centerY, double scaleFactor, void RenderThinker::start()
QSize resultSize)
{ {
QMutexLocker locker(&mutex);

this->centerX = centerX;
this->centerY = centerY;
this->scaleFactor = scaleFactor;
this->resultSize = resultSize;

if (!isRunning()) {
start(LowPriority);
} else {
restart = true;
condition.wakeOne();
}
}

void RenderThread::run()
{
forever {
mutex.lock();
QSize resultSize = this->resultSize;
double scaleFactor = this->scaleFactor;
double centerX = this->centerX;
double centerY = this->centerY;
mutex.unlock();

int halfWidth = resultSize.width() / 2; int halfWidth = resultSize.width() / 2;
int halfHeight = resultSize.height() / 2; int halfHeight = resultSize.height() / 2;
QImage image(resultSize, QImage::Format_RGB32); QImage image(resultSize, QImage::Format_RGB32);
@@ -98,9 +62,7 @@ void RenderThread::run()
bool allBlack = true; bool allBlack = true;


for (int y = -halfHeight; y < halfHeight; ++y) { for (int y = -halfHeight; y < halfHeight; ++y) {
if (restart) if (wasPauseRequested())
break;
if (abort)
return; return;


uint *scanLine = uint *scanLine =
@@ -139,53 +101,12 @@ void RenderThread::run()
if (allBlack && pass == 0) { if (allBlack && pass == 0) {
pass = 4; pass = 4;
} else { } else {
if (!restart) lockForWrite();
emit renderedImage(image, scaleFactor); writable().image = image;
writable().scaleFactor = scaleFactor;
unlock();
++pass; ++pass;
} }
} }

emit done();
mutex.lock();
if (!restart)
condition.wait(&mutex);
restart = false;
mutex.unlock();
}
} }

uint RenderThread::rgbFromWaveLength(double wave)
{
double r = 0.0;
double g = 0.0;
double b = 0.0;

if (wave >= 380.0 && wave <= 440.0) {
r = -1.0 * (wave - 440.0) / (440.0 - 380.0);
b = 1.0;
} else if (wave >= 440.0 && wave <= 490.0) {
g = (wave - 440.0) / (490.0 - 440.0);
b = 1.0;
} else if (wave >= 490.0 && wave <= 510.0) {
g = 1.0;
b = -1.0 * (wave - 510.0) / (510.0 - 490.0);
} else if (wave >= 510.0 && wave <= 580.0) {
r = (wave - 510.0) / (580.0 - 510.0);
g = 1.0;
} else if (wave >= 580.0 && wave <= 645.0) {
r = 1.0;
g = -1.0 * (wave - 645.0) / (645.0 - 580.0);
} else if (wave >= 645.0 && wave <= 780.0) {
r = 1.0;
}

double s = 1.0;
if (wave > 700.0)
s = 0.3 + 0.7 * (780.0 - wave) / (780.0 - 700.0);
else if (wave < 420.0)
s = 0.3 + 0.7 * (wave - 380.0) / (420.0 - 380.0);

r = pow(r * s, 0.8);
g = pow(g * s, 0.8);
b = pow(b * s, 0.8);
return qRgb(int(r * 255), int(g * 255), int(b * 255));
}

0 comments on commit 458eb50

Please sign in to comment.
You can’t perform that action at this time.