Commit ed81651f authored by Gilles Caulier's avatar Gilles Caulier 🗼
Browse files

Raindrop Tool : add support of multicore CPU based on QtConcurrent API.

CCBUGS: 289204
parent 5776c84b
......@@ -18,6 +18,7 @@ Editor : Blur tool support multicore CPU.
Editor : Charcoal tool support multicore CPU.
Editor : OilPaint tool support multicore CPU.
Editor : Emboss tool support multicore CPU.
Editor : Raindrop tool support multicore CPU.
Showfoto : Port of Thumbbar to Qt Model/view.
......
......@@ -29,7 +29,7 @@ filters
/emboss DONE DONE DONE TODO
/oilpaint DONE DONE DONE TODO
/blurfx DONE TODO DONE TODO
/raindrop DONE TODO NO TODO
/raindrop DONE DONE NO TODO
/filmgrain DONE TODO DONE DONE
enhance
......
......@@ -6,7 +6,7 @@
* Date : 2005-05-25
* Description : Raindrop threaded image filter.
*
* Copyright (C) 2005-2012 by Gilles Caulier <caulier dot gilles at gmail dot com>
* Copyright (C) 2005-2014 by Gilles Caulier <caulier dot gilles at gmail dot com>
* Copyright (C) 2006-2010 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
* Copyright (C) 2010 by Martin Klapetek <martin dot klapetek at gmail dot com>
*
......@@ -37,6 +37,7 @@
#include <QDateTime>
#include <QRect>
#include <qmath.h>
#include <QtConcurrentRun>
// Local includes
......@@ -109,7 +110,7 @@ void RainDropFilter::filterImage()
// Cut the original image in 4 areas without clipping region.
DImg zone1 = m_orgImage.copy(0, 0, d->selection.x(), h);
DImg zone1 = m_orgImage.copy(0, 0, d->selection.x(), h);
DImg zone2 = m_orgImage.copy(d->selection.x(), 0, d->selection.x() + d->selection.width(), d->selection.y());
DImg zone3 = m_orgImage.copy(d->selection.x(), d->selection.y() + d->selection.height(), d->selection.x() + d->selection.width(), h);
DImg zone4 = m_orgImage.copy(d->selection.x() + d->selection.width(), 0, w, h);
......@@ -140,6 +141,29 @@ void RainDropFilter::filterImage()
}
}
void RainDropFilter::rainDropsImageMultithreaded(const Args& prm)
{
int nRandSize;
int nRandX, nRandY;
bool bResp = false;
int nWidth = prm.orgImage->width();
int nHeight = prm.orgImage->height();
bool sixteenBit = prm.orgImage->sixteenBit();
int bytesDepth = prm.orgImage->bytesDepth();
uchar* data = prm.orgImage->bits();
uchar* pResBits = prm.destImage->bits();
for (uint nCounter = prm.start ; runningFlag() && (bResp == false) && (nCounter < prm.stop) ; ++nCounter)
{
nRandX = d->generator.number(0, nWidth - 1);
nRandY = d->generator.number(0, nHeight - 1);
nRandSize = d->generator.number(prm.MinDropSize, prm.MaxDropSize);
bResp = CreateRainDrop(data, nWidth, nHeight, sixteenBit, bytesDepth,
pResBits, prm.pStatusBits,
nRandX, nRandY, nRandSize, prm.Coeff, prm.bLimitRange);
}
}
/* Function to apply the RainDrops effect backported from ImageProcessing version 2
*
* orgImage => The image
......@@ -161,17 +185,6 @@ void RainDropFilter::filterImage()
void RainDropFilter::rainDropsImage(DImg* const orgImage, DImg* const destImage, int MinDropSize, int MaxDropSize,
int Amount, int Coeff, bool bLimitRange, int progressMin, int progressMax)
{
bool bResp;
int nRandSize, i;
int nRandX, nRandY;
int nCounter = 0;
int nWidth = orgImage->width();
int nHeight = orgImage->height();
bool sixteenBit = orgImage->sixteenBit();
int bytesDepth = orgImage->bytesDepth();
uchar* data = orgImage->bits();
uchar* pResBits = destImage->bits();
if (Amount <= 0)
{
return;
......@@ -187,8 +200,8 @@ void RainDropFilter::rainDropsImage(DImg* const orgImage, DImg* const destImage,
return;
}
QScopedArrayPointer<uchar> pStatusBits(new uchar[nHeight * nWidth]);
memset(pStatusBits.data(), 0, nHeight * nWidth * sizeof(uchar));
QScopedArrayPointer<uchar> pStatusBits(new uchar[orgImage->height() * orgImage->width()]);
memset(pStatusBits.data(), 0, orgImage->height() * orgImage->width() * sizeof(uchar));
// Initially, copy all pixels to destination
......@@ -196,23 +209,45 @@ void RainDropFilter::rainDropsImage(DImg* const orgImage, DImg* const destImage,
// Randomize.
for (i = 0; runningFlag() && (i < Amount); ++i)
uint nbCore = QThreadPool::globalInstance()->maxThreadCount();
float step = 10000 / nbCore;
uint vals[nbCore+1];
vals[0] = 0;
vals[nbCore] = 10000;
for (uint i = 1 ; i < nbCore ; ++i)
vals[i] = vals[i-1] + step;
Args prm;
prm.orgImage = orgImage;
prm.destImage = destImage;
prm.MinDropSize = MinDropSize;
prm.MaxDropSize = MaxDropSize;
prm.Coeff = Coeff;
prm.bLimitRange = bLimitRange;
prm.pStatusBits = pStatusBits.data();
for (int i = 0; runningFlag() && (i < Amount); ++i)
{
nCounter = 0;
QList <QFuture<void> > tasks;
do
for (uint j = 0 ; runningFlag() && (j < nbCore) ; ++j)
{
nRandX = d->generator.number(0, nWidth - 1);
nRandY = d->generator.number(0, nHeight - 1);
nRandSize = d->generator.number(MinDropSize, MaxDropSize);
bResp = CreateRainDrop(data, nWidth, nHeight, sixteenBit, bytesDepth,
pResBits, pStatusBits.data(),
nRandX, nRandY, nRandSize, Coeff, bLimitRange);
++nCounter;
prm.start = vals[j];
prm.stop = vals[j+1];
tasks.append(QtConcurrent::run(this,
&RainDropFilter::rainDropsImageMultithreaded,
prm
));
}
while ((bResp == false) && (nCounter < 10000) && runningFlag());
foreach(QFuture<void> t, tasks)
t.waitForFinished();
/*
// Update the progress bar in dialog.
if (nCounter >= 10000)
{
......@@ -221,7 +256,7 @@ void RainDropFilter::rainDropsImage(DImg* const orgImage, DImg* const destImage,
postProgress(progressMax);
break;
}
*/
postProgress((int)(progressMin + ((double)(i) *
(double)(progressMax - progressMin)) / (double)Amount));
}
......@@ -594,5 +629,4 @@ int RainDropFilter::pixelOffset(int Width, int X, int Y, int bytesDepth)
return (Y * Width * bytesDepth + X * bytesDepth);
}
} // namespace Digikam
......@@ -6,7 +6,7 @@
* Date : 2005-05-25
* Description : Raindrop threaded image filter.
*
* Copyright (C) 2005-2012 by Gilles Caulier <caulier dot gilles at gmail dot com>
* Copyright (C) 2005-2014 by Gilles Caulier <caulier dot gilles at gmail dot com>
* Copyright (C) 2006-2010 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
* Copyright (C) 2010 by Martin Klapetek <martin dot klapetek at gmail dot com>
*
......@@ -77,6 +77,21 @@ public:
void readParameters(const FilterAction& action);
private:
struct Args
{
uint start;
uint stop;
DImg* orgImage;
DImg* destImage;
int MinDropSize;
int MaxDropSize;
int Coeff;
bool bLimitRange;
uchar* pStatusBits;
};
private:
void filterImage();
......@@ -84,6 +99,8 @@ private:
void rainDropsImage(DImg* const orgImage, DImg* const destImage, int MinDropSize, int MaxDropSize,
int Amount, int Coeff, bool bLimitRange, int progressMin, int progressMax);
void rainDropsImageMultithreaded(const Args& prm);
bool CreateRainDrop(uchar* const pBits, int Width, int Height, bool sixteenBit, int bytesDepth,
uchar* const pResBits, uchar* const pStatusBits,
int X, int Y, int DropSize, double Coeff, bool bLimitRange);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment