Beispiel #1
0
void RefocusFilter::convolveImage(const Args& prm)
{
    int progress;

    QList<int> vals = multithreadedSteps(prm.width);

    for (int y1 = 0; runningFlag() && (y1 < prm.height); ++y1)
    {
        QList <QFuture<void> > tasks;

        for (int j = 0 ; runningFlag() && (j < vals.count()-1) ; ++j)
        {
            tasks.append(QtConcurrent::run(this,
                                           &RefocusFilter::convolveImageMultithreaded,
                                           vals[j],
                                           vals[j+1],
                                           y1,
                                           prm
                                          ));
        }

        foreach(QFuture<void> t, tasks)
            t.waitForFinished();

        // Update the progress bar in dialog.
        progress = (int)(((double)y1 * 100.0) / prm.height);

        if (progress % 5 == 0)
        {
            postProgress(progress);
        }
    }
}
Beispiel #2
0
void DistortionFXFilter::tileMultithreaded(const Args& prm)
{
    int tx, ty, progress=0, oldProgress=0;

    for (int h = prm.start; runningFlag() && (h < prm.stop); h += prm.HSize)
    {
        for (int w = 0; runningFlag() && (w < (int)prm.orgImage->width()); w += prm.WSize)
        {
            d->lock2.lock();
            tx = d->generator.number(-prm.Random / 2, prm.Random / 2);
            ty = d->generator.number(-prm.Random / 2, prm.Random / 2);
            d->lock2.unlock();
            prm.destImage->bitBltImage(prm.orgImage, w, h, prm.WSize, prm.HSize, w + tx, h + ty);
        }

        // Update the progress bar in dialog.
        progress = (int)( ( (double)h * (100.0 / QThreadPool::globalInstance()->maxThreadCount()) ) / (prm.stop - prm.start));

        if ((progress % 5 == 0) && (progress > oldProgress))
        {
            d->lock.lock();
            oldProgress       = progress;
            d->globalProgress += 5;
            postProgress(d->globalProgress);
            d->lock.unlock();
        }
    }
}
Beispiel #3
0
/* Function to apply the waves effect
 *
 * data             => The image data in RGBA mode.
 * Width            => Width of image.
 * Height           => Height of image.
 * Amplitude        => Sinoidal maximum height.
 * Frequency        => Frequency value.
 * FillSides        => Like a boolean variable.
 * Direction        => Vertical or horizontal flag.
 *
 * Theory           => This is an amazing effect, very funny, and very simple to
 *                     understand. You just need understand how qSin and qCos works.
 */
void DistortionFXFilter::waves(DImg* orgImage, DImg* destImage,
                               int Amplitude, int Frequency,
                               bool FillSides, bool Direction)
{
    if (Amplitude < 0)
    {
        Amplitude = 0;
    }

    if (Frequency < 0)
    {
        Frequency = 0;
    }

    Args prm;
    prm.orgImage  = orgImage;
    prm.destImage = destImage;
    prm.Amplitude = Amplitude;
    prm.Frequency = Frequency;
    prm.FillSides = FillSides;

    if (Direction)        // Horizontal
    {
        QList<int> vals = multithreadedSteps(orgImage->height());
        QList <QFuture<void> > tasks;

        for (int j = 0 ; runningFlag() && (j < vals.count()-1) ; ++j)
        {
            prm.start = vals[j];
            prm.stop  = vals[j+1];
            tasks.append(QtConcurrent::run(this,
                                           &DistortionFXFilter::wavesHorizontalMultithreaded,
                                           prm
                                          ));
        }

        foreach(QFuture<void> t, tasks)
            t.waitForFinished();
    }
    else
    {
        QList<int> vals = multithreadedSteps(orgImage->width());
        QList <QFuture<void> > tasks;

        for (int j = 0 ; runningFlag() && (j < vals.count()-1) ; ++j)
        {
            prm.start = vals[j];
            prm.stop  = vals[j+1];
            tasks.append(QtConcurrent::run(this,
                                           &DistortionFXFilter::wavesVerticalMultithreaded,
                                           prm
                                          ));
        }

        foreach(QFuture<void> t, tasks)
            t.waitForFinished();
    }
}
Beispiel #4
0
/* Function to apply the circular waves effect backported from ImageProcesqSing version 2
 *
 * data             => The image data in RGBA mode.
 * Width            => Width of image.
 * Height           => Height of image.
 * X, Y             => Position of circle center on the image.
 * Amplitude        => Sinoidal maximum height
 * Frequency        => Frequency value.
 * Phase            => Phase value.
 * WavesType        => If true  the amplitude is proportional to radius.
 * Antialias        => Smart bluring result.
 *
 * Theory           => Similar to Waves effect, but here I apply a senoidal function
 *                     with the angle point.
 */
void DistortionFXFilter::circularWaves(DImg* orgImage, DImg* destImage, int X, int Y, double Amplitude,
                                       double Frequency, double Phase, bool WavesType, bool AntiAlias)
{
    if (Amplitude < 0.0)
    {
        Amplitude = 0.0;
    }

    if (Frequency < 0.0)
    {
        Frequency = 0.0;
    }

    int progress;

    QList<int> vals = multithreadedSteps(orgImage->width());
    QList <QFuture<void> > tasks;

    Args prm;
    prm.orgImage  = orgImage;
    prm.destImage = destImage;
    prm.Phase     = Phase;
    prm.Frequency = Frequency;
    prm.Amplitude = Amplitude;
    prm.WavesType = WavesType;
    prm.X         = X;
    prm.Y         = Y;
    prm.AntiAlias = AntiAlias;

    for (int h = 0; runningFlag() && (h < (int)orgImage->height()); ++h)
    {
        for (int j = 0 ; runningFlag() && (j < vals.count()-1) ; ++j)
        {
            prm.start = vals[j];
            prm.stop  = vals[j+1];
            prm.h     = h;
            tasks.append(QtConcurrent::run(this,
                                           &DistortionFXFilter::circularWavesMultithreaded,
                                           prm
                                          ));
        }

        foreach(QFuture<void> t, tasks)
            t.waitForFinished();

        // Update the progress bar in dialog.
        progress = (int)(((double)h * 100.0) / orgImage->height());

        if (progress % 5 == 0)
        {
            postProgress(progress);
        }
    }
}
Beispiel #5
0
/* Function to apply the Cilindrical effect backported from ImageProcessing version 2
 *
 * data             => The image data in RGBA mode.
 * Width            => Width of image.
 * Height           => Height of image.
 * Coeff            => Cilindrical value.
 * Horizontal       => Apply horizontally.
 * Vertical         => Apply vertically.
 * Antialias        => Smart blurring result.
 *
 * Theory           => This is a great effect, similar to Spherize (Photoshop).
 *                     If you understand FishEye, you will understand Cilindrical
 *                     FishEye apply a logarithm function using a sphere radius,
 *                     Spherize use the same function but in a rectangular
 *                     environment.
 */
void DistortionFXFilter::cilindrical(DImg* orgImage, DImg* destImage, double Coeff,
                                     bool Horizontal, bool Vertical, bool AntiAlias)

{
    if ((Coeff == 0.0) || (!(Horizontal || Vertical)))
    {
        return;
    }

    int progress;

    // initial copy
    memcpy(destImage->bits(), orgImage->bits(), orgImage->numBytes());

    QList<int> vals = multithreadedSteps(orgImage->width());
    QList <QFuture<void> > tasks;

    Args prm;
    prm.orgImage   = orgImage;
    prm.destImage  = destImage;
    prm.Coeff      = Coeff;
    prm.Horizontal = Horizontal;
    prm.Vertical   = Vertical;
    prm.AntiAlias  = AntiAlias;

    // main loop

    for (int h = 0; runningFlag() && (h < (int)orgImage->height()); ++h)
    {
        for (int j = 0 ; runningFlag() && (j < vals.count()-1) ; ++j)
        {
            prm.start = vals[j];
            prm.stop  = vals[j+1];
            prm.h     = h;
            tasks.append(QtConcurrent::run(this,
                                           &DistortionFXFilter::cilindricalMultithreaded,
                                           prm
                                          ));
        }

        foreach(QFuture<void> t, tasks)
            t.waitForFinished();

        // Update the progress bar in dialog.
        progress = (int)(((double)h * 100.0) / orgImage->height());

        if (progress % 5 == 0)
        {
            postProgress(progress);
        }
    }
}
Beispiel #6
0
/* Function to apply the block waves effect
 *
 * data             => The image data in RGBA mode.
 * Width            => Width of image.
 * Height           => Height of image.
 * Amplitude        => Sinoidal maximum height
 * Frequency        => Frequency value
 * Mode             => The mode to be applied.
 *
 * Theory           => This is an amazing effect, very funny when amplitude and
 *                     frequency are small values.
 */
void DistortionFXFilter::blockWaves(DImg* orgImage, DImg* destImage,
                                    int Amplitude, int Frequency, bool Mode)
{
    if (Amplitude < 0)
    {
        Amplitude = 0;
    }

    if (Frequency < 0)
    {
        Frequency = 0;
    }

    int progress;

    QList<int> vals = multithreadedSteps(orgImage->height());
    QList <QFuture<void> > tasks;

    Args prm;
    prm.orgImage  = orgImage;
    prm.destImage = destImage;
    prm.Mode      = Mode;
    prm.Frequency = Frequency;
    prm.Amplitude = Amplitude;

    for (int w = 0; runningFlag() && (w < (int)orgImage->width()); ++w)
    {
        for (int j = 0 ; runningFlag() && (j < vals.count()-1) ; ++j)
        {
            prm.start = vals[j];
            prm.stop  = vals[j+1];
            prm.w     = w;
            tasks.append(QtConcurrent::run(this,
                                           &DistortionFXFilter::blockWavesMultithreaded,
                                           prm
                                          ));
        }

        foreach(QFuture<void> t, tasks)
            t.waitForFinished();

        // Update the progress bar in dialog.
        progress = (int)(((double)w * 100.0) / orgImage->width());

        if (progress % 5 == 0)
        {
            postProgress(progress);
        }
    }
}
Beispiel #7
0
void DistortionFXFilter::wavesVerticalMultithreaded(const Args& prm)
{
    int oldProgress=0, progress=0, ty;

    for (int w = prm.start; runningFlag() && (w < prm.stop); ++w)
    {
        ty = lround(prm.Amplitude * qSin((prm.Frequency * 2) * w * (M_PI / 180)));
        prm.destImage->bitBltImage(prm.orgImage, w, 0, 1, prm.orgImage->height(), w, ty);

        if (prm.FillSides)
        {
            prm.destImage->bitBltImage(prm.orgImage, w, prm.orgImage->height() - ty,  1, ty,  w, 0);
            prm.destImage->bitBltImage(prm.orgImage, w, 0,  1, prm.orgImage->height() - (prm.orgImage->height() - 2 * prm.Amplitude + ty),  w, prm.orgImage->height() + ty);
        }

        // Update the progress bar in dialog.
        progress = (int)( ( (double)w * (100.0 / QThreadPool::globalInstance()->maxThreadCount()) ) / (prm.stop - prm.start));

        if ((progress % 5 == 0) && (progress > oldProgress))
        {
            d->lock.lock();
            oldProgress       = progress;
            d->globalProgress += 5;
            postProgress(d->globalProgress);
            d->lock.unlock();
        }
    }
}
Beispiel #8
0
/** This method have been implemented following this report in bugzilla :
    https://bugs.kde.org/show_bug.cgi?id=148540
    We use YCbCr color space to perform noise addition. Please follow this url for
    details about this color space :
    http://en.allexperts.com/e/y/yc/ycbcr.htm
 */
void FilmGrainFilter::filterImage()
{
    if (d->settings.lumaIntensity <= 0       ||
        d->settings.chromaBlueIntensity <= 0 ||
        d->settings.chromaRedIntensity <= 0  ||
        !d->settings.isDirty())
    {
        m_destImage = m_orgImage;
        return;
    }

    d->div                 = m_orgImage.sixteenBit() ? 65535.0 : 255.0;
    d->leadLumaNoise       = d->settings.lumaIntensity       * (m_orgImage.sixteenBit() ? 256.0 : 1.0);
    d->leadChromaBlueNoise = d->settings.chromaBlueIntensity * (m_orgImage.sixteenBit() ? 256.0 : 1.0);
    d->leadChromaRedNoise  = d->settings.chromaRedIntensity  * (m_orgImage.sixteenBit() ? 256.0 : 1.0);

    d->generator.seed(1); // noise will always be the same

    QList<int> vals = multithreadedSteps(m_orgImage.width());
    QList <QFuture<void> > tasks;

    for (int j = 0 ; runningFlag() && (j < vals.count()-1) ; ++j)
    {
        tasks.append(QtConcurrent::run(this,
                                       &FilmGrainFilter::filmgrainMultithreaded,
                                       vals[j],
                                       vals[j+1]
                                      ));
    }

    foreach(QFuture<void> t, tasks)
        t.waitForFinished();
}
Beispiel #9
0
void DistortionFXFilter::wavesHorizontalMultithreaded(const Args& prm)
{
    int oldProgress=0, progress=0, tx;

    for (int h = prm.start; runningFlag() && (h < prm.stop); ++h)
    {
        tx = lround(prm.Amplitude * qSin((prm.Frequency * 2) * h * (M_PI / 180)));
        prm.destImage->bitBltImage(prm.orgImage, 0, h,  prm.orgImage->width(), 1,  tx, h);

        if (prm.FillSides)
        {
            prm.destImage->bitBltImage(prm.orgImage, prm.orgImage->width() - tx, h,  tx, 1,  0, h);
            prm.destImage->bitBltImage(prm.orgImage, 0, h, prm.orgImage->width() - (prm.orgImage->width() - 2 * prm.Amplitude + tx), 1,  prm.orgImage->width() + tx, h);
        }

        // Update the progress bar in dialog.
        progress = (int)( ( (double)h * (100.0 / QThreadPool::globalInstance()->maxThreadCount()) ) / (prm.stop - prm.start));

        if ((progress % 5 == 0) && (progress > oldProgress))
        {
            d->lock.lock();
            oldProgress       = progress;
            d->globalProgress += 5;
            postProgress(d->globalProgress);
            d->lock.unlock();
        }
    }
}
Beispiel #10
0
void DistortionFXFilter::circularWavesMultithreaded(const Args& prm)
{
    int Width       = prm.orgImage->width();
    int Height      = prm.orgImage->height();
    uchar* data     = prm.orgImage->bits();
    bool sixteenBit = prm.orgImage->sixteenBit();
    int bytesDepth  = prm.orgImage->bytesDepth();
    uchar* pResBits = prm.destImage->bits();

    double nh, nw;

    double lfRadius, lfRadMax;
    double lfNewAmp     = prm.Amplitude;
    double lfFreqAngle  = prm.Frequency * ANGLE_RATIO;
    double phase        = prm.Phase     * ANGLE_RATIO;
    lfRadMax            = qSqrt(Height * Height + Width * Width);

    for (int w = prm.start; runningFlag() && (w < prm.stop); ++w)
    {
        nw = prm.X - w;
        nh = prm.Y - prm.h;

        lfRadius = qSqrt(nw * nw + nh * nh);

        if (prm.WavesType)
        {
            lfNewAmp = prm.Amplitude * lfRadius / lfRadMax;
        }

        nw = (double)w     + lfNewAmp * qSin(lfFreqAngle * lfRadius + phase);
        nh = (double)prm.h + lfNewAmp * qCos(lfFreqAngle * lfRadius + phase);

        setPixelFromOther(Width, Height, sixteenBit, bytesDepth, data, pResBits, w, prm.h, nw, nh, prm.AntiAlias);
    }
}
Beispiel #11
0
/* Function to apply the twirl effect backported from ImageProcesqSing version 2
 *
 * data             => The image data in RGBA mode.
 * Width            => Width of image.
 * Height           => Height of image.
 * dist             => Distance value.
 * Antialias        => Smart blurring result.
 *
 * Theory           => Take spiral studies, you will understand better, I'm studying
 *                     hard on this effect, because it is not too fast.
 */
void DistortionFXFilter::twirl(DImg* orgImage, DImg* destImage, int dist, bool AntiAlias)
{
    // if dist value is zero, we do nothing

    if (dist == 0)
    {
        return;
    }

    int progress;

    QList<int> vals = multithreadedSteps(orgImage->width());
    QList <QFuture<void> > tasks;

    Args prm;
    prm.orgImage  = orgImage;
    prm.destImage = destImage;
    prm.dist      = dist;
    prm.AntiAlias = AntiAlias;

    // main loop

    for (int h = 0; runningFlag() && (h < (int)orgImage->height()); ++h)
    {
        for (int j = 0 ; runningFlag() && (j < vals.count()-1) ; ++j)
        {
            prm.start = vals[j];
            prm.stop  = vals[j+1];
            prm.h     = h;
            tasks.append(QtConcurrent::run(this,
                                           &DistortionFXFilter::twirlMultithreaded,
                                           prm
                                          ));
        }

        foreach(QFuture<void> t, tasks)
            t.waitForFinished();

        // Update the progress bar in dialog.
        progress = (int)(((double)h * 100.0) / orgImage->height());

        if (progress % 5 == 0)
        {
            postProgress(progress);
        }
    }
}
Beispiel #12
0
bool CharcoalFilter::convolveImage(const unsigned int order, const double* kernel)
{
    long kernelWidth = order;

    if ((kernelWidth % 2) == 0)
    {
        qCWarning(DIGIKAM_DIMG_LOG) << "Kernel width must be an odd number!";
        return false;
    }

    long    i;
    double  normalize = 0.0;

    QScopedArrayPointer<double> normal_kernel(new double[kernelWidth * kernelWidth]);

    if (!normal_kernel)
    {
        qCWarning(DIGIKAM_DIMG_LOG) << "Unable to allocate memory!";
        return false;
    }

    for (i = 0; i < (kernelWidth * kernelWidth); ++i)
    {
        normalize += kernel[i];
    }

    if (fabs(normalize) <= Epsilon)
    {
        normalize = 1.0;
    }

    normalize = 1.0 / normalize;

    for (i = 0; i < (kernelWidth * kernelWidth); ++i)
    {
        normal_kernel[i] = normalize * kernel[i];
    }

    // --------------------------------------------------------

    QList<int> vals = multithreadedSteps(m_orgImage.height());
    QList <QFuture<void> > tasks;

    for (int j = 0 ; runningFlag() && (j < vals.count()-1) ; ++j)
    {
        tasks.append(QtConcurrent::run(this,
                                       &CharcoalFilter::convolveImageMultithreaded,
                                       vals[j],
                                       vals[j+1],
                                       normal_kernel.data(),
                                       kernelWidth
                                      ));
    }

    foreach(QFuture<void> t, tasks)
        t.waitForFinished();

    return true;
}
Beispiel #13
0
bool RawProcessingFilter::continueQuery() const
{
    if (m_observer && !m_observer->continueQuery(0))
    {
        return false;
    }
    return runningFlag();
}
Beispiel #14
0
void DistortionFXFilter::polarCoordinatesMultithreaded(const Args& prm)
{
    int Width       = prm.orgImage->width();
    int Height      = prm.orgImage->height();
    uchar* data     = prm.orgImage->bits();
    bool sixteenBit = prm.orgImage->sixteenBit();
    int bytesDepth  = prm.orgImage->bytesDepth();
    uchar* pResBits = prm.destImage->bits();

    int nHalfW      = Width / 2;
    int nHalfH      = Height / 2;
    double lfXScale = 1.0;
    double lfYScale = 1.0;
    double lfAngle, lfRadius, lfRadMax;
    double nh, nw, tw;

    if (Width > Height)
    {
        lfYScale = (double)Width / (double)Height;
    }
    else if (Height > Width)
    {
        lfXScale = (double)Height / (double)Width;
    }

    lfRadMax = (double)qMax(Height, Width) / 2.0;

    double th = lfYScale * (double)(prm.h - nHalfH);

    for (int w = prm.start; runningFlag() && (w < prm.stop); ++w)
    {
        tw = lfXScale * (double)(w - nHalfW);

        if (prm.Type)
        {
            // now, we get the distance
            lfRadius = qSqrt(th * th + tw * tw);
            // we find the angle from the center
            lfAngle = qAtan2(tw, th);

            // now we find the exact position's x and y
            nh = lfRadius * (double) Height / lfRadMax;
            nw =  lfAngle * (double)  Width / (2 * M_PI);

            nw = (double)nHalfW + nw;
        }
        else
        {
            lfRadius = (double)(prm.h) * lfRadMax   / (double)Height;
            lfAngle  = (double)(w)     * (2 * M_PI) / (double) Width;

            nw = (double)nHalfW - (lfRadius / lfXScale) * qSin(lfAngle);
            nh = (double)nHalfH - (lfRadius / lfYScale) * qCos(lfAngle);
        }

        setPixelFromOther(Width, Height, sixteenBit, bytesDepth, data, pResBits, w, prm.h, nw, nh, prm.AntiAlias);
    }
}
Beispiel #15
0
void SharpenFilter::convolveImageMultithreaded(const Args& prm)
{
    double  maxClamp = m_destImage.sixteenBit() ? 16777215.0 : 65535.0;
    double* k        = 0;
    double  red, green, blue, alpha;
    int     mx, my, sx, sy, mcx, mcy;
    DColor  color;

    for (uint x = prm.start ; runningFlag() && (x < prm.stop) ; ++x)
    {
        k   = prm.normal_kernel;
        red = green = blue = alpha = 0;
        sy  = prm.y - prm.halfKernelWidth;

        for (mcy = 0 ; runningFlag() && (mcy < prm.kernelWidth) ; ++mcy, ++sy)
        {
            my = sy < 0 ? 0 : sy > (int)m_destImage.height() - 1 ? m_destImage.height() - 1 : sy;
            sx = x + (-prm.halfKernelWidth);

            for (mcx = 0 ; runningFlag() && (mcx < prm.kernelWidth) ; ++mcx, ++sx)
            {
                mx     = sx < 0 ? 0 : sx > (int)m_destImage.width() - 1 ? m_destImage.width() - 1 : sx;
                color  = m_orgImage.getPixelColor(mx, my);
                red   += (*k) * (color.red()   * 257.0);
                green += (*k) * (color.green() * 257.0);
                blue  += (*k) * (color.blue()  * 257.0);
                alpha += (*k) * (color.alpha() * 257.0);
                ++k;
            }
        }

        red   =   red < 0.0 ? 0.0 :   red > maxClamp ? maxClamp :   red + 0.5;
        green = green < 0.0 ? 0.0 : green > maxClamp ? maxClamp : green + 0.5;
        blue  =  blue < 0.0 ? 0.0 :  blue > maxClamp ? maxClamp :  blue + 0.5;
        alpha = alpha < 0.0 ? 0.0 : alpha > maxClamp ? maxClamp : alpha + 0.5;

        m_destImage.setPixelColor(x, prm.y, DColor((int)(red  / 257UL), (int)(green / 257UL),
                                                   (int)(blue / 257UL), (int)(alpha / 257UL),
                                                   m_destImage.sixteenBit()));
    }
}
Beispiel #16
0
void NRFilter::thresholdingMultithreaded(const Args& prm)
{
    for (uint i = prm.start; runningFlag() && (i < prm.stop); ++i)
    {
        if (prm.fimg[*prm.lpass][i] > 0.8)
        {
            *prm.thold = prm.threshold * prm.stdev[4];
        }
        else if (prm.fimg[*prm.lpass][i] > 0.6)
        {
            *prm.thold = prm.threshold * prm.stdev[3];
        }
        else if (prm.fimg[*prm.lpass][i] > 0.4)
        {
            *prm.thold = prm.threshold * prm.stdev[2];
        }
        else if (prm.fimg[*prm.lpass][i] > 0.2)
        {
            *prm.thold = prm.threshold * prm.stdev[1];
        }
        else
        {
            *prm.thold = prm.threshold * prm.stdev[0];
        }

        if (prm.fimg[*prm.hpass][i] < -*prm.thold)
        {
            prm.fimg[*prm.hpass][i] += *prm.thold - *prm.thold * prm.softness;
        }
        else if (prm.fimg[*prm.hpass][i] > *prm.thold)
        {
            prm.fimg[*prm.hpass][i] -= *prm.thold - *prm.thold * prm.softness;
        }
        else
        {
            prm.fimg[*prm.hpass][i] *= prm.softness;
        }

        if (*prm.hpass)
        {
            prm.fimg[0][i] += prm.fimg[*prm.hpass][i];
        }
    }
}
Beispiel #17
0
/* Function to apply the tile effect
 *
 * data             => The image data in RGBA mode.
 * Width            => Width of image.
 * Height           => Height of image.
 * WSize            => Tile Width
 * HSize            => Tile Height
 * Random           => Maximum random value
 *
 * Theory           => Similar to Tile effect from Photoshop and very easy to
 *                     understand. We get a rectangular area uqSing WSize and HSize and
 *                     replace in a position with a random distance from the original
 *                     position.
 */
void DistortionFXFilter::tile(DImg* orgImage, DImg* destImage,
                              int WSize, int HSize, int Random)
{
    if (WSize < 1)
    {
        WSize = 1;
    }

    if (HSize < 1)
    {
        HSize = 1;
    }

    if (Random < 1)
    {
        Random = 1;
    }

    Args prm;
    prm.orgImage  = orgImage;
    prm.destImage = destImage;
    prm.WSize     = WSize;
    prm.HSize     = HSize;
    prm.Random    = Random;

    d->generator.seed(d->randomSeed);

    QList<int> vals = multithreadedSteps(orgImage->height());
    QList <QFuture<void> > tasks;

    for (int j = 0 ; runningFlag() && (j < vals.count()-1) ; ++j)
    {
        prm.start = vals[j];
        prm.stop  = vals[j+1];
        tasks.append(QtConcurrent::run(this,
                                       &DistortionFXFilter::tileMultithreaded,
                                       prm
                                      ));
    }

    foreach(QFuture<void> t, tasks)
        t.waitForFinished();
}
Beispiel #18
0
void DistortionFXFilter::blockWavesMultithreaded(const Args& prm)
{
    int Width       = prm.orgImage->width();
    int Height      = prm.orgImage->height();
    uchar* data     = prm.orgImage->bits();
    bool sixteenBit = prm.orgImage->sixteenBit();
    int bytesDepth  = prm.orgImage->bytesDepth();
    uchar* pResBits = prm.destImage->bits();

    int nw, nh;

    DColor color;
    int offset, offsetOther;

    int nHalfW = Width  / 2;
    int nHalfH = Height / 2;

    for (int h = prm.start; runningFlag() && (h < prm.stop); ++h)
    {
        nw = nHalfW - prm.w;
        nh = nHalfH - h;

        if (prm.Mode)
        {
            nw = (int)(prm.w + prm.Amplitude * qSin(prm.Frequency * nw * (M_PI / 180)));
            nh = (int)(h     + prm.Amplitude * qCos(prm.Frequency * nh * (M_PI / 180)));
        }
        else
        {
            nw = (int)(prm.w + prm.Amplitude * qSin(prm.Frequency * prm.w * (M_PI / 180)));
            nh = (int)(h     + prm.Amplitude * qCos(prm.Frequency * h     * (M_PI / 180)));
        }

        offset      = getOffset(Width, prm.w, h, bytesDepth);
        offsetOther = getOffsetAdjusted(Width, Height, (int)nw, (int)nh, bytesDepth);

        // read color
        color.setColor(data + offsetOther, sixteenBit);
        // write color to destination
        color.setPixel(pResBits + offset);
    }
}
Beispiel #19
0
void DistortionFXFilter::multipleCornersMultithreaded(const Args& prm)
{
    int Width       = prm.orgImage->width();
    int Height      = prm.orgImage->height();
    uchar* data     = prm.orgImage->bits();
    bool sixteenBit = prm.orgImage->sixteenBit();
    int bytesDepth  = prm.orgImage->bytesDepth();
    uchar* pResBits = prm.destImage->bits();

    double nh, nw;

    int    nHalfW   = Width / 2;
    int    nHalfH   = Height / 2;
    double lfRadMax = qSqrt(Height * Height + Width * Width) / 2.0;
    double lfAngle, lfNewRadius, lfCurrentRadius;

    for (int w = prm.start; runningFlag() && (w < prm.stop); ++w)
    {
        // we find the distance from the center
        nh = nHalfH - prm.h;
        nw = nHalfW - w;

        // now, we get the distance
        lfCurrentRadius = qSqrt(nh * nh + nw * nw);
        // we find the angle from the center
        lfAngle = qAtan2(nh, nw) * (double)prm.Factor;

        // ok, we sum angle with accumuled to find a new angle
        lfNewRadius = lfCurrentRadius * lfCurrentRadius / lfRadMax;

        // now we find the exact position's x and y
        nw = (double)nHalfW - (qCos(lfAngle) * lfNewRadius);
        nh = (double)nHalfH - (qSin(lfAngle) * lfNewRadius);

        setPixelFromOther(Width, Height, sixteenBit, bytesDepth, data, pResBits, w, prm.h, nw, nh, prm.AntiAlias);
    }
}
Beispiel #20
0
void NRFilter::calculteStdevMultithreaded(const Args& prm)
{
    for (uint i = prm.start; runningFlag() && (i < prm.stop); ++i)
    {
        prm.fimg[*prm.hpass][i] -= prm.fimg[*prm.lpass][i];

        if (prm.fimg[*prm.hpass][i] < *prm.thold && prm.fimg[*prm.hpass][i] > -*prm.thold)
        {
            if (prm.fimg[*prm.lpass][i] > 0.8)
            {
                prm.stdev[4] += prm.fimg[*prm.hpass][i] * prm.fimg[*prm.hpass][i];
                prm.samples[4]++;
            }
            else if (prm.fimg[*prm.lpass][i] > 0.6)
            {
                prm.stdev[3] += prm.fimg[*prm.hpass][i] * prm.fimg[*prm.hpass][i];
                prm.samples[3]++;
            }
            else if (prm.fimg[*prm.lpass][i] > 0.4)
            {
                prm.stdev[2] += prm.fimg[*prm.hpass][i] * prm.fimg[*prm.hpass][i];
                prm.samples[2]++;
            }
            else if (prm.fimg[*prm.lpass][i] > 0.2)
            {
                prm.stdev[1] += prm.fimg[*prm.hpass][i] * prm.fimg[*prm.hpass][i];
                prm.samples[1]++;
            }
            else
            {
                prm.stdev[0] += prm.fimg[*prm.hpass][i] * prm.fimg[*prm.hpass][i];
                prm.samples[0]++;
            }
        }
    }
}
Beispiel #21
0
void LoadSaveThread::run()
{
    while (runningFlag())
    {
        {
            QMutexLocker lock(threadMutex());

            delete d->lastTask;
            d->lastTask = 0;
            delete m_currentTask;
            m_currentTask = 0;

            if (!m_todo.isEmpty())
            {
                m_currentTask = m_todo.takeFirst();

                if (m_notificationPolicy == NotificationPolicyTimeLimited)
                {
                    // set timing values so that first event is sent only
                    // after an initial time span.
                    d->notificationTime  = QTime::currentTime();
                    d->blockNotification = true;
                }
            }
            else
            {
                stop(lock);
            }
        }

        if (m_currentTask)
        {
            m_currentTask->execute();
        }
    }
}
Beispiel #22
0
void CharcoalFilter::convolveImageMultithreaded(uint start, uint stop, double* normal_kernel, double kernelWidth)
{
    int     mx, my, sx, sy, mcx, mcy, oldProgress=0, progress=0;
    double  red, green, blue, alpha;
    double* k = 0;

    uint height     = m_destImage.height();
    uint width      = m_destImage.width();
    bool sixteenBit = m_destImage.sixteenBit();
    uchar* ddata    = m_destImage.bits();
    int ddepth      = m_destImage.bytesDepth();
    uchar* sdata    = m_orgImage.bits();
    int sdepth      = m_orgImage.bytesDepth();
    double maxClamp = m_destImage.sixteenBit() ? 16777215.0 : 65535.0;

    for (uint y = start ; runningFlag() && (y < stop) ; ++y)
    {
        sy = y - (kernelWidth / 2);

        for (uint x = 0; runningFlag() && (x < width); ++x)
        {
            k   = normal_kernel;
            red = green = blue = alpha = 0;
            sy  = y - (kernelWidth / 2);

            for (mcy = 0; runningFlag() && (mcy < kernelWidth); ++mcy, ++sy)
            {
                my = sy < 0 ? 0 : sy > (int) height - 1 ? height - 1 : sy;
                sx = x + (-kernelWidth / 2);

                for (mcx = 0; runningFlag() && (mcx < kernelWidth); ++mcx, ++sx)
                {
                    mx = sx < 0 ? 0 : sx > (int) width - 1 ? width - 1 : sx;
                    DColor color(sdata + mx * sdepth + (width * my * sdepth), sixteenBit);
                    red += (*k) * (color.red() * 257.0);
                    green += (*k) * (color.green() * 257.0);
                    blue += (*k) * (color.blue() * 257.0);
                    alpha += (*k) * (color.alpha() * 257.0);
                    ++k;
                }
            }

            red   =   red < 0.0 ? 0.0 :   red > maxClamp ? maxClamp :   red + 0.5;
            green = green < 0.0 ? 0.0 : green > maxClamp ? maxClamp : green + 0.5;
            blue  =  blue < 0.0 ? 0.0 :  blue > maxClamp ? maxClamp :  blue + 0.5;
            alpha = alpha < 0.0 ? 0.0 : alpha > maxClamp ? maxClamp : alpha + 0.5;

            DColor color((int)(red / 257UL), (int)(green / 257UL),
                         (int)(blue / 257UL), (int)(alpha / 257UL), sixteenBit);
            color.setPixel((ddata + x * ddepth + (width * y * ddepth)));
        }

        progress = (int)( ( (double)y * (80.0 / QThreadPool::globalInstance()->maxThreadCount()) ) / (stop-start));

        if ((progress % 5 == 0) && (progress > oldProgress))
        {
            d->lock.lock();
            oldProgress       = progress;
            d->globalProgress += 5;
            postProgress(d->globalProgress);
            d->lock.unlock();
        }
    }
}
Beispiel #23
0
bool SharpenFilter::convolveImage(const unsigned int order, const double* const kernel)
{
    uint    y;
    int     progress;
    long    i;
    double  normalize = 0.0;

    Args prm;
    prm.kernelWidth     = order;
    prm.halfKernelWidth = prm.kernelWidth / 2;;

    if ((prm.kernelWidth % 2) == 0)
    {
        qCWarning(DIGIKAM_DIMG_LOG) << "Kernel width must be an odd number!";
        return false;
    }

    QScopedArrayPointer<double> normal_kernel(new double[prm.kernelWidth * prm.kernelWidth]);

    if (normal_kernel.isNull())
    {
        qCWarning(DIGIKAM_DIMG_LOG) << "Unable to allocate memory!";
        return false;
    }

    for (i = 0 ; i < (prm.kernelWidth * prm.kernelWidth) ; ++i)
    {
        normalize += kernel[i];
    }

    if (fabs(normalize) <= Epsilon)
    {
        normalize = 1.0;
    }

    normalize = 1.0 / normalize;

    for (i = 0 ; i < (prm.kernelWidth * prm.kernelWidth) ; ++i)
    {
        normal_kernel[i] = normalize * kernel[i];
    }

    prm.normal_kernel = normal_kernel.data();
    QList<int> vals = multithreadedSteps(m_destImage.width());

    for (y = 0 ; runningFlag() && (y < m_destImage.height()) ; ++y)
    {
        QList <QFuture<void> > tasks;

        for (int j = 0 ; runningFlag() && (j < vals.count()-1) ; ++j)
        {
            prm.start = vals[j];
            prm.stop  = vals[j+1];
            prm.y     = y;

            tasks.append(QtConcurrent::run(this,
                                           &SharpenFilter::convolveImageMultithreaded,
                                           prm
                                          ));
        }

        foreach(QFuture<void> t, tasks)
            t.waitForFinished();

        progress = (int)(((double)y * 100.0) / m_destImage.height());

        if (progress % 5 == 0)
        {
            postProgress(progress);
        }
    }

    return true;
}
Beispiel #24
0
void TextureFilter::filterImage()
{
    // Texture tile.

    int w           = m_orgImage.width();
    int h           = m_orgImage.height();
    int bytesDepth  = m_orgImage.bytesDepth();
    bool sixteenBit = m_orgImage.sixteenBit();

    kDebug() << "Texture File: " << m_texturePath;
    DImg texture(m_texturePath);

    if ( texture.isNull() )
    {
        return;
    }

    DImg textureImg(w, h, m_orgImage.sixteenBit(), m_orgImage.hasAlpha());

    texture.convertToDepthOfImage(&textureImg);

    for (int x = 0 ; x < w ; x+=texture.width())
    {
        for (int y = 0 ; y < h ; y+=texture.height())
        {
            textureImg.bitBltImage(&texture, x, y);
        }
    }

    // Apply texture.

    uchar* data     = m_orgImage.bits();
    uchar* pTeData  = textureImg.bits();
    uchar* pOutBits = m_destImage.bits();
    uint offset;

    DColor teData, transData, inData, outData;
    uchar* ptr, *dptr, *tptr;
    int progress;

    int blendGain;

    if (sixteenBit)
    {
        blendGain = (m_blendGain + 1) * 256 - 1;
    }
    else
    {
        blendGain = m_blendGain;
    }

    // Make textured transparent layout.

    for (int x = 0; runningFlag() && x < w; ++x)
    {
        for (int y = 0; runningFlag() && y < h; ++y)
        {
            offset = x * bytesDepth + (y * w * bytesDepth);
            ptr    = data + offset;
            tptr   = pTeData + offset;

            // Read color
            teData.setColor(tptr, sixteenBit);

            // in the old algorithm, this was
            //teData.channel.red   = (teData.channel.red * (255 - m_blendGain) +
            //      transData.channel.red * m_blendGain) >> 8;
            // but transdata was uninitialized, its components were apparently 0,
            // so I removed the part after the "+".

            if (sixteenBit)
            {
                teData.blendInvAlpha16(blendGain);
            }
            else
            {
                teData.blendInvAlpha8(blendGain);
            }

            // Overwrite RGB.
            teData.setPixel(tptr);
        }

        // Update progress bar in dialog.
        progress = (int) (((double) x * 50.0) / w);

        if (progress % 5 == 0)
        {
            postProgress(progress);
        }
    }

    // Merge layout and image using overlay method.

    for (int x = 0; runningFlag() && x < w; ++x)
    {
        for (int y = 0; runningFlag() && y < h; ++y)
        {
            offset = x * bytesDepth + (y * w * bytesDepth);
            ptr    = data + offset;
            dptr   = pOutBits + offset;
            tptr   = pTeData + offset;

            inData.setColor(ptr, sixteenBit);
            outData.setColor(dptr, sixteenBit);
            teData.setColor(tptr, sixteenBit);

            if (sixteenBit)
            {
                outData.setRed(intMult16(inData.red(), inData.red() + intMult16(2 * teData.red(), 65535 - inData.red())));
                outData.setGreen(intMult16(inData.green(), inData.green() + intMult16(2 * teData.green(), 65535 - inData.green())));
                outData.setBlue(intMult16(inData.blue(), inData.blue() + intMult16(2 * teData.blue(), 65535 - inData.blue())));
            }
            else
            {
                outData.setRed(intMult8(inData.red(), inData.red() + intMult8(2 * teData.red(), 255 - inData.red())));
                outData.setGreen(intMult8(inData.green(), inData.green() + intMult8(2 * teData.green(), 255 - inData.green())));
                outData.setBlue(intMult8(inData.blue(), inData.blue() + intMult8(2 * teData.blue(), 255 - inData.blue())));
            }

            outData.setAlpha(inData.alpha());
            outData.setPixel(dptr);
        }

        // Update progress bar in dialog.
        progress = (int) (50.0 + ((double) x * 50.0) / w);

        if (progress%5 == 0)
        {
            postProgress(progress);
        }
    }
}
Beispiel #25
0
/** Performs an histogram equalization of the image.
    this method adjusts the brightness of colors across the
    active image so that the histogram for the value channel
    is as nearly as possible flat, that is, so that each possible
    brightness value appears at about the same number of pixels
    as each other value. Sometimes Equalize works wonderfully at
    enhancing the contrasts in an image. Other times it gives
    garbage. It is a very powerful operation, which can either work
    miracles on an image or destroy it.*/
void EqualizeFilter::equalizeImage()
{
    struct double_packet  high, low, intensity;
    struct double_packet* map;
    struct int_packet*    equalize_map;
    register int          i;
    int                   progress;

    if (m_orgImage.sixteenBit() != m_refImage.sixteenBit())
    {
        kDebug() << "Ref. image and Org. has different bits depth";
        return;
    }

    // Create an histogram of the reference image.
    ImageHistogram* histogram = new ImageHistogram(m_refImage.bits(), m_refImage.width(),
            m_refImage.height(), m_refImage.sixteenBit());
    histogram->calculate();

    // Memory allocation.
    map          = new double_packet[histogram->getHistogramSegments()];
    equalize_map = new int_packet[histogram->getHistogramSegments()];

    if ( !histogram || !map || !equalize_map )
    {
        delete histogram;
        if (map)
        {
            delete [] map;
        }

        if (equalize_map)
        {
            delete [] equalize_map;
        }

        kWarning() << ("Unable to allocate memory!");
        return;
    }

    // Integrate the histogram to get the equalization map.

    memset(&intensity, 0, sizeof(struct double_packet));
    memset(&high,      0, sizeof(struct double_packet));
    memset(&low,       0, sizeof(struct double_packet));

    for (i = 0 ; runningFlag() && (i < histogram->getHistogramSegments()) ; ++i)
    {
        intensity.red   += histogram->getValue(RedChannel, i);
        intensity.green += histogram->getValue(GreenChannel, i);
        intensity.blue  += histogram->getValue(BlueChannel, i);
        intensity.alpha += histogram->getValue(AlphaChannel, i);
        map[i]           = intensity;
    }

    // Stretch the histogram.

    low  = map[0];
    high = map[histogram->getHistogramSegments()-1];
    memset(equalize_map, 0, histogram->getHistogramSegments()*sizeof(int_packet));

    // TODO magic number 256
    for (i = 0 ; runningFlag() && (i < histogram->getHistogramSegments()) ; ++i)
    {
        if (high.red != low.red)
            equalize_map[i].red = (uint)(((256*histogram->getHistogramSegments() -1) *
                                          (map[i].red-low.red))/(high.red-low.red));

        if (high.green != low.green)
            equalize_map[i].green = (uint)(((256*histogram->getHistogramSegments() -1) *
                                            (map[i].green-low.green))/(high.green-low.green));

        if (high.blue != low.blue)
            equalize_map[i].blue = (uint)(((256*histogram->getHistogramSegments() -1) *
                                           (map[i].blue-low.blue))/(high.blue-low.blue));

        if (high.alpha != low.alpha)
            equalize_map[i].alpha = (uint)(((256*histogram->getHistogramSegments() -1) *
                                            (map[i].alpha-low.alpha))/(high.alpha-low.alpha));
    }

    delete histogram;
    delete [] map;

    uchar* data     = m_orgImage.bits();
    int w           = m_orgImage.width();
    int h           = m_orgImage.height();
    bool sixteenBit = m_orgImage.sixteenBit();
    int size        = w*h;

    // Apply results to image.
    // TODO magic number 257
    if (!sixteenBit)        // 8 bits image.
    {
        uchar  red, green, blue, alpha;
        uchar* ptr = data;

        for (i = 0 ; runningFlag() && (i < size) ; ++i)
        {
            blue  = ptr[0];
            green = ptr[1];
            red   = ptr[2];
            alpha = ptr[3];

            if (low.red != high.red)
            {
                red = (equalize_map[red].red)/257;
            }

            if (low.green != high.green)
            {
                green = (equalize_map[green].green)/257;
            }

            if (low.blue != high.blue)
            {
                blue = (equalize_map[blue].blue)/257;
            }

            if (low.alpha != high.alpha)
            {
                alpha = (equalize_map[alpha].alpha)/257;
            }

            ptr[0] = blue;
            ptr[1] = green;
            ptr[2] = red;
            ptr[3] = alpha;
            ptr   += 4;

            progress = (int)(((double)i * 100.0) / size);

            if ( progress%5 == 0 )
            {
                postProgress( progress );
            }
        }
    }
    else               // 16 bits image.
    {
        unsigned short  red, green, blue, alpha;
        unsigned short* ptr = (unsigned short*)data;

        for (i = 0 ; runningFlag() && (i < size) ; ++i)
        {
            blue  = ptr[0];
            green = ptr[1];
            red   = ptr[2];
            alpha = ptr[3];

            if (low.red != high.red)
            {
                red = (equalize_map[red].red)/257;
            }

            if (low.green != high.green)
            {
                green = (equalize_map[green].green)/257;
            }

            if (low.blue != high.blue)
            {
                blue = (equalize_map[blue].blue)/257;
            }

            if (low.alpha != high.alpha)
            {
                alpha = (equalize_map[alpha].alpha)/257;
            }

            ptr[0] = blue;
            ptr[1] = green;
            ptr[2] = red;
            ptr[3] = alpha;
            ptr   += 4;

            progress = (int)(((double)i * 100.0) / size);

            if ( progress%5 == 0 )
            {
                postProgress( progress );
            }
        }
    }

    delete [] equalize_map;
}
Beispiel #26
0
void DistortionFXFilter::twirlMultithreaded(const Args& prm)
{
    int Width       = prm.orgImage->width();
    int Height      = prm.orgImage->height();
    uchar* data     = prm.orgImage->bits();
    bool sixteenBit = prm.orgImage->sixteenBit();
    int bytesDepth  = prm.orgImage->bytesDepth();
    uchar* pResBits = prm.destImage->bits();

    DColor color;
    int offset;

    int    nHalfW   = Width / 2;
    int    nHalfH   = Height / 2;
    double lfXScale = 1.0;
    double lfYScale = 1.0;
    double lfAngle, lfNewAngle, lfAngleSum, lfCurrentRadius;
    double tw, nh, nw;

    if (Width > Height)
    {
        lfYScale = (double)Width / (double)Height;
    }
    else if (Height > Width)
    {
        lfXScale = (double)Height / (double)Width;
    }

    // the angle step is dist divided by 10000
    double lfAngleStep = prm.dist / 10000.0;
    // now, we get the minimum radius
    double lfRadMax    = (double)qMax(Width, Height) / 2.0;

    double th          = lfYScale * (double)(prm.h - nHalfH);

    for (int w = prm.start; runningFlag() && (w < prm.stop); ++w)
    {
        tw = lfXScale * (double)(w - nHalfW);

        // now, we get the distance
        lfCurrentRadius = qSqrt(th * th + tw * tw);

        // if distance is less than maximum radius...
        if (lfCurrentRadius < lfRadMax)
        {
            // we find the angle from the center
            lfAngle = qAtan2(th, tw);
            // we get the accumuled angle
            lfAngleSum = lfAngleStep * (-1.0 * (lfCurrentRadius - lfRadMax));
            // ok, we sum angle with accumuled to find a new angle
            lfNewAngle = lfAngle + lfAngleSum;

            // now we find the exact position's x and y
            nw = (double)nHalfW + qCos(lfNewAngle) * (lfCurrentRadius / lfXScale);
            nh = (double)nHalfH + qSin(lfNewAngle) * (lfCurrentRadius / lfYScale);

            setPixelFromOther(Width, Height, sixteenBit, bytesDepth, data, pResBits, w, prm.h, nw, nh, prm.AntiAlias);
        }
        else
        {
            // copy pixel
            offset = getOffset(Width, w, prm.h, bytesDepth);
            color.setColor(data + offset, sixteenBit);
            color.setPixel(pResBits + offset);
        }
    }
}
Beispiel #27
0
void CharcoalFilter::filterImage()
{
    if (m_orgImage.isNull())
    {
        qCWarning(DIGIKAM_DIMG_LOG) << "No image data available!";
        return;
    }

    if (d->pencil <= 0.0)
    {
        m_destImage = m_orgImage;
        return;
    }

    // -- Applying Edge effect -----------------------------------------------

    register long i = 0;
    int kernelWidth = getOptimalKernelWidth(d->pencil, d->smooth);

    if ((int)m_orgImage.width() < kernelWidth)
    {
        qCWarning(DIGIKAM_DIMG_LOG) << "Image is smaller than radius!";
        return;
    }

    QScopedArrayPointer<double> kernel(new double[kernelWidth * kernelWidth]);

    if (kernel.isNull())
    {
        qCWarning(DIGIKAM_DIMG_LOG) << "Unable to allocate memory!";
        return;
    }

    for (i = 0 ; i < (kernelWidth * kernelWidth) ; ++i)
    {
        kernel[i] = (-1.0);
    }

    kernel[i / 2] = kernelWidth * kernelWidth - 1.0;
    convolveImage(kernelWidth, kernel.data());

    // -- Applying Gaussian blur effect ---------------------------------------

    BlurFilter(this, m_destImage, m_destImage, 80, 85, (int)(d->smooth / 10.0));

    if (!runningFlag())
    {
        return;
    }

    // -- Applying stretch contrast color effect -------------------------------

    StretchFilter stretch(&m_destImage, &m_destImage);
    stretch.startFilterDirectly();
    m_destImage.putImageData(stretch.getTargetImage().bits());

    postProgress(90);

    if (!runningFlag())
    {
        return;
    }

    // -- Inverting image color -----------------------------------------------

    InvertFilter invert(&m_destImage);
    invert.startFilterDirectly();
    m_destImage.putImageData(invert.getTargetImage().bits());

    postProgress(95);

    if (!runningFlag())
    {
        return;
    }

    // -- Convert to neutral black & white ------------------------------------

    MixerContainer settings;
    settings.bMonochrome    = true;
    settings.blackRedGain   = 0.3;
    settings.blackGreenGain = 0.59;
    settings.blackBlueGain  = 0.11;
    MixerFilter mixer(&m_destImage, 0L, settings);
    mixer.startFilterDirectly();
    m_destImage.putImageData(mixer.getTargetImage().bits());

    postProgress(100);

    if (!runningFlag())
    {
        return;
    }
}
Beispiel #28
0
void DistortionFXFilter::cilindricalMultithreaded(const Args& prm)
{
    int Width       = prm.orgImage->width();
    int Height      = prm.orgImage->height();
    uchar* data     = prm.orgImage->bits();
    bool sixteenBit = prm.orgImage->sixteenBit();
    int bytesDepth  = prm.orgImage->bytesDepth();
    uchar* pResBits = prm.destImage->bits();

    double nh, nw;

    int    nHalfW      = Width / 2;
    int    nHalfH      = Height / 2;
    double lfCoeffX    = 1.0;
    double lfCoeffY    = 1.0;
    double lfCoeffStep = prm.Coeff / 1000.0;

    if (prm.Horizontal)
    {
        lfCoeffX = (double)nHalfW / qLn(qFabs(lfCoeffStep) * nHalfW + 1.0);
    }

    if (prm.Vertical)
    {
        lfCoeffY = (double)nHalfH / qLn(qFabs(lfCoeffStep) * nHalfH + 1.0);
    }

    for (int w = prm.start; runningFlag() && (w < prm.stop); ++w)
    {
        // we find the distance from the center
        nh = qFabs((double)(prm.h - nHalfH));
        nw = qFabs((double)(w - nHalfW));

        if (prm.Horizontal)
        {
            if (prm.Coeff > 0.0)
            {
                nw = (qExp(nw / lfCoeffX) - 1.0) / lfCoeffStep;
            }
            else
            {
                nw = lfCoeffX * qLn(1.0 + (-1.0 * lfCoeffStep) * nw);
            }
        }

        if (prm.Vertical)
        {
            if (prm.Coeff > 0.0)
            {
                nh = (qExp(nh / lfCoeffY) - 1.0) / lfCoeffStep;
            }
            else
            {
                nh = lfCoeffY * qLn(1.0 + (-1.0 * lfCoeffStep) * nh);
            }
        }

        nw = (double)nHalfW + ((w >= nHalfW)     ? nw : -nw);
        nh = (double)nHalfH + ((prm.h >= nHalfH) ? nh : -nh);

        setPixelFromOther(Width, Height, sixteenBit, bytesDepth, data, pResBits, w, prm.h, nw, nh, prm.AntiAlias);
    }
}
Beispiel #29
0
void HSLFilter::applyHSL(DImg& image)
{
    if (image.isNull())
    {
        return;
    }

    bool   sixteenBit     = image.sixteenBit();
    uint   numberOfPixels = image.numPixels();
    int    progress;
    int    hue, sat, lig;
    double vib = d->settings.vibrance;
    DColor color;

    if (sixteenBit)                   // 16 bits image.
    {
        unsigned short* data = (unsigned short*) image.bits();

        for (uint i=0; runningFlag() && (i<numberOfPixels); ++i)
        {
            color = DColor(data[2], data[1], data[0], 0, sixteenBit);

            // convert RGB to HSL
            color.getHSL(&hue, &sat, &lig);

            // convert HSL to RGB
            color.setHSL(d->htransfer16[hue], vibranceBias(d->stransfer16[sat], hue, vib, sixteenBit), d->ltransfer16[lig], sixteenBit);

            data[2] = color.red();
            data[1] = color.green();
            data[0] = color.blue();

            data += 4;

            progress = (int)(((double)i * 100.0) / numberOfPixels);

            if ( progress%5 == 0 )
            {
                postProgress( progress );
            }
        }
    }
    else                                      // 8 bits image.
    {
        uchar* data = image.bits();

        for (uint i=0; runningFlag() && (i<numberOfPixels); ++i)
        {
            color = DColor(data[2], data[1], data[0], 0, sixteenBit);

            // convert RGB to HSL
            color.getHSL(&hue, &sat, &lig);

            // convert HSL to RGB
            color.setHSL(d->htransfer[hue], vibranceBias(d->stransfer[sat],hue,vib,sixteenBit), d->ltransfer[lig], sixteenBit);

            data[2] = color.red();
            data[1] = color.green();
            data[0] = color.blue();

            data += 4;

            progress = (int)(((double)i * 100.0) / numberOfPixels);

            if ( progress%5 == 0 )
            {
                postProgress( progress );
            }
        }
    }
}
Beispiel #30
0
void DistortionFXFilter::fisheyeMultithreaded(const Args& prm)
{
    int Width       = prm.orgImage->width();
    int Height      = prm.orgImage->height();
    uchar* data     = prm.orgImage->bits();
    bool sixteenBit = prm.orgImage->sixteenBit();
    int bytesDepth  = prm.orgImage->bytesDepth();
    uchar* pResBits = prm.destImage->bits();

    double nh, nw, tw;

    DColor color;
    int offset;

    int nHalfW         = Width  / 2;
    int nHalfH         = Height / 2;
    double lfXScale    = 1.0;
    double lfYScale    = 1.0;
    double lfCoeffStep = prm.Coeff / 1000.0;
    double lfRadius, lfAngle;

    if (Width > Height)
    {
        lfYScale = (double)Width / (double)Height;
    }
    else if (Height > Width)
    {
        lfXScale = (double)Height / (double)Width;
    }

    double lfRadMax = (double)qMax(Height, Width) / 2.0;
    double lfCoeff  = lfRadMax / qLn(qFabs(lfCoeffStep) * lfRadMax + 1.0);
    double th       = lfYScale * (double)(prm.h - nHalfH);

    for (int w = prm.start; runningFlag() && (w < prm.stop); ++w)
    {
        tw = lfXScale * (double)(w - nHalfW);

        // we find the distance from the center
        lfRadius = qSqrt(th * th + tw * tw);

        if (lfRadius < lfRadMax)
        {
            lfAngle = qAtan2(th, tw);

            if (prm.Coeff > 0.0)
            {
                lfRadius = (qExp(lfRadius / lfCoeff) - 1.0) / lfCoeffStep;
            }
            else
            {
                lfRadius = lfCoeff * qLn(1.0 + (-1.0 * lfCoeffStep) * lfRadius);
            }

            nw = (double)nHalfW + (lfRadius / lfXScale) * qCos(lfAngle);
            nh = (double)nHalfH + (lfRadius / lfYScale) * qSin(lfAngle);

            setPixelFromOther(Width, Height, sixteenBit, bytesDepth, data, pResBits, w, prm.h, nw, nh, prm.AntiAlias);
        }
        else
        {
            // copy pixel
            offset = getOffset(Width, w, prm.h, bytesDepth);
            color.setColor(data + offset, sixteenBit);
            color.setPixel(pResBits + offset);
        }
    }
}