Пример #1
0
/** This method apply grain adjustment on a pixel color channel from YCrCb color space.
    NRand is the lead uniform noise set from matrix used to scan whole image step by step.
    Additionally noise is applied on pixel using Poisson or Gaussian distribution.
 */
void FilmGrainFilter::adjustYCbCr(DColor& col, double range, double nRand, int channel)
{
    double y, cb, cr, n2;
    col.getYCbCr(&y, &cb, &cr);

    if (d->settings.photoDistribution)
    {
        n2 = randomizePoisson((d->settings.grainSize / 2.0) * (range / 1.414));
    }
    else
    {
        n2 = randomizeGauss((d->settings.grainSize / 2.0) * (range / 1.414));
    }

    switch (channel)
    {
        case Private::Luma:
            y  = CLAMP(y  + (nRand + n2) / d->div, 0.0, 1.0);
            break;

        case Private::ChromaBlue:
            cb = CLAMP(cb + (nRand + n2) / d->div, 0.0, 1.0);
            break;

        default:       // ChromaRed
            cr = CLAMP(cr + (nRand + n2) / d->div, 0.0, 1.0);
            break;
    }

    col.setYCbCr(y, cb, cr, col.sixteenBit());
}
Пример #2
0
/*
    This code is shared by six methods.
    Write value of pixel w|h in data to pixel nw|nh in pResBits.
    Antialias if requested.
*/
void DistortionFXFilter::setPixelFromOther(int Width, int Height, bool sixteenBit, int bytesDepth,
                                           uchar* data, uchar* pResBits,
                                           int w, int h, double nw, double nh, bool AntiAlias)
{
    DColor color;
    int offset = getOffset(Width, w, h, bytesDepth);

    if (AntiAlias)
    {
        uchar* const ptr = pResBits + offset;

        if (sixteenBit)
        {
            unsigned short* ptr16 = reinterpret_cast<unsigned short*>(ptr);
            PixelsAliasFilter().pixelAntiAliasing16(reinterpret_cast<unsigned short*>(data), Width, Height, nw, nh,
                                                    ptr16 + 3, ptr16 + 2, ptr16 + 1, ptr16);
        }
        else
        {
            PixelsAliasFilter().pixelAntiAliasing(data, Width, Height, nw, nh,
                                                  ptr + 3, ptr + 2, ptr + 1, ptr);
        }
    }
    else
    {
        // we get the position adjusted
        int offsetOther = getOffsetAdjusted(Width, Height, (int)nw, (int)nh, bytesDepth);
        // read color
        color.setColor(data + offsetOther, sixteenBit);
        // write color to destination
        color.setPixel(pResBits + offset);
    }
}
Пример #3
0
void EditorTool::slotUpdateSpotInfo(const DColor& col, const QPoint& point)
{
    DColor color = col;
    setToolInfoMessage(i18n("(%1,%2) RGBA:%3,%4,%5,%6",
                            point.x(), point.y(),
                            color.red(), color.green(),
                            color.blue(), color.alpha()));
}
	D3DCOLOR D3D9Translator::getD3DColor( DColor c )
	{
		DColor	clamped = c;
		clamped.clamp();

		return D3DCOLOR_ARGB(	static_cast<uint8>(clamped.a * 255),
			static_cast<uint8>(clamped.r * 255),
			static_cast<uint8>(clamped.g * 255),
			static_cast<uint8>(clamped.b * 255));
	}
Пример #5
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);
    }
}
Пример #6
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()));
    }
}
Пример #7
0
void WhiteBalanceTool::slotColorSelectedFromOriginal(const DColor& color)
{
    if ( d->settingsView->pickTemperatureIsOn() )
    {
        WBContainer settings = d->settingsView->settings();
        DColor dc            = color;
        QColor tc            = dc.getQColor();

        WBFilter::autoWBAdjustementFromColor(tc, settings.temperature, settings.green);
        d->settingsView->setSettings(settings);

        d->settingsView->setOnPickTemperature(false);
    }
    else
    {
        return;
    }

    d->previewWidget->setCapturePointMode(false);
    slotTimer();
}
Пример #8
0
void DImageFilterActionTest::testActions()
{
    QStringList files = QDir(imagePath()).entryList(QDir::Files);
    files.removeOne(originalImage());

    DImg original(imagePath() + originalImage());
    QVERIFY(!original.isNull());

    foreach (const QString& fileName, files)
    {
        DImg ref(imagePath() + fileName);
        QVERIFY(!ref.isNull());
        DImageHistory history = ref.getImageHistory();

        FilterActionFilter filter;
        filter.setFilterActions(history.allActions());
        QVERIFY(filter.isReproducible() || filter.isComplexAction());

        filter.setupFilter(original.copy());
        filter.startFilterDirectly();
        qDebug() << filter.filterActions().size();

        DImg img = filter.getTargetImage();

        QVERIFY(ref.size() == img.size());

        bool isEqual = true;
        DImg diff(ref.width(), ref.height(), ref.sixteenBit());
        diff.fill(DColor(Qt::black));

        for (uint x=0; x<ref.width(); x++)
        {
            for (uint y=0; y<ref.height(); y++)
            {
                DColor cref = ref.getPixelColor(x,y);
                DColor cres = img.getPixelColor(x,y);

                if (cref.red() != cres.red() || cref.green() != cres.green() || cref.blue() != cres.blue())
                {
                    //qDebug() << x << y;
                    diff.setPixelColor(x,y, DColor(Qt::white));
                    isEqual = false;
                }
            }
        }

        if (!isEqual)
        {
            showDiff(original, ref, img, diff);
        }

        QVERIFY(isEqual);
    }
Пример #9
0
/** This method interpolate gain adjustments to apply grain on shadows, midtones and highlights colors.
    The output value is a coefficient computed between 0.0 and 1.0.
 */
double FilmGrainFilter::interpolate(int shadows, int midtones, int highlights, const DColor& col)
{
    double s = (shadows    + 100.0) / 200.0;
    double m = (midtones   + 100.0) / 200.0;
    double h = (highlights + 100.0) / 200.0;

    double y, cb, cr;
    col.getYCbCr(&y, &cb, &cr);

    if (y >= 0.0 && y <= 0.5)
    {
        return (s + 2 * (m - s) * y);
    }
    else if (y >= 0.5 && y <= 1.0)
    {
        return (2 * (h - m) * y + 2 * m - h);
    }
    else
    {
        return 1.0;
    }
}
Пример #10
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 );
            }
        }
    }
}
Пример #11
0
void CurvesSettings::slotSpotColorChanged(const DColor& color)
{
    DColor sc = color;

    switch (d->curvesBox->picker())
    {
        case CurvesBox::BlackTonal:
        {
            // Black tonal curves point.
            d->curvesBox->curves()->setCurvePoint(LuminosityChannel, 1,
                                                  QPoint(qMax(qMax(sc.red(), sc.green()), sc.blue()), 42 * d->histoSegments / 256));
            d->curvesBox->curves()->setCurvePoint(RedChannel, 1, QPoint(sc.red(), 42 * d->histoSegments / 256));
            d->curvesBox->curves()->setCurvePoint(GreenChannel, 1, QPoint(sc.green(), 42 * d->histoSegments / 256));
            d->curvesBox->curves()->setCurvePoint(BlueChannel, 1, QPoint(sc.blue(), 42 * d->histoSegments / 256));
            d->curvesBox->resetPickers();
            break;
        }

        case CurvesBox::GrayTonal:
        {
            // Gray tonal curves point.
            d->curvesBox->curves()->setCurvePoint(LuminosityChannel, 8,
                                                  QPoint(qMax(qMax(sc.red(), sc.green()), sc.blue()), 128 * d->histoSegments / 256));
            d->curvesBox->curves()->setCurvePoint(RedChannel, 8, QPoint(sc.red(), 128 * d->histoSegments / 256));
            d->curvesBox->curves()->setCurvePoint(GreenChannel, 8, QPoint(sc.green(), 128 * d->histoSegments / 256));
            d->curvesBox->curves()->setCurvePoint(BlueChannel, 8, QPoint(sc.blue(), 128 * d->histoSegments / 256));
            d->curvesBox->resetPickers();
            break;
        }

        case CurvesBox::WhiteTonal:
        {
            // White tonal curves point.
            d->curvesBox->curves()->setCurvePoint(LuminosityChannel, 15,
                                                  QPoint(qMax(qMax(sc.red(), sc.green()), sc.blue()), 213 * d->histoSegments / 256));
            d->curvesBox->curves()->setCurvePoint(RedChannel, 15, QPoint(sc.red(), 213 * d->histoSegments / 256));
            d->curvesBox->curves()->setCurvePoint(GreenChannel, 15, QPoint(sc.green(), 213 * d->histoSegments / 256));
            d->curvesBox->curves()->setCurvePoint(BlueChannel, 15, QPoint(sc.blue(), 213 * d->histoSegments / 256));
            d->curvesBox->resetPickers();
            break;
        }

        default:
        {
            d->curvesBox->setCurveGuide(color);
            return;
        }
    }

    // Calculate Red, green, blue curves.

    for (int i = LuminosityChannel ; i <= BlueChannel ; ++i)
    {
        d->curvesBox->curves()->curvesCalculateCurve(i);
    }

    d->curvesBox->repaint();
    d->curvesBox->resetPickers();

    emit signalSpotColorChanged();
}
Пример #12
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);
        }
    }
}
Пример #13
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);
        }
    }
}
Пример #14
0
void NRFilter::filterImage()
{
    DColor col;
    int    progress;

    int width  = m_orgImage.width();
    int height = m_orgImage.height();
    float clip = m_orgImage.sixteenBit() ? 65535.0 : 255.0;

    // Allocate buffers.

    for (int c = 0; c < 3; ++c)
    {
        d->fimg[c] = new float[width * height];
    }

    d->buffer[1] = new float[width * height];
    d->buffer[2] = new float[width * height];

    // Read the full image and convert pixel values to float [0,1].

    int j = 0;

    for (int y = 0; runningFlag() && (y < height); ++y)
    {
        for (int x = 0; runningFlag() && (x < width); ++x)
        {
            col           = m_orgImage.getPixelColor(x, y);
            d->fimg[0][j] = col.red()   / clip;
            d->fimg[1][j] = col.green() / clip;
            d->fimg[2][j] = col.blue()  / clip;
            ++j;
        }
    }

    postProgress(10);

    // do colour model conversion sRGB[0,1] -> YCrCb.

    if (runningFlag())
    {
        srgb2ycbcr(d->fimg, width * height);
    }

    postProgress(20);

    // denoise the channels individually

    for (int c = 0; runningFlag() && (c < 3); ++c)
    {
        d->buffer[0] = d->fimg[c];

        if (d->settings.thresholds[c] > 0.0)
        {
            waveletDenoise(d->buffer, width, height, d->settings.thresholds[c], d->settings.softness[c]);

            progress = (int)(30.0 + ((double)c * 60.0) / 4);

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

    // Retransform the image data to sRGB[0,1].

    if (runningFlag())
    {
        ycbcr2srgb(d->fimg, width * height);
    }

    postProgress(80);

    // clip the values

    for (int c = 0; runningFlag() && (c < 3); ++c)
    {
        for (int i = 0; i < width * height; ++i)
        {
            d->fimg[c][i] = qBound(0.0F, d->fimg[c][i] * clip, clip);
        }
    }

    postProgress(90);

    // Write back the full image and convert pixel values from float [0,1].

    j = 0;

    for (int y = 0; runningFlag() && (y < height); ++y)
    {
        for (int x = 0; x < width; ++x)
        {
            col.setRed((int)(d->fimg[0][j] + 0.5));
            col.setGreen((int)(d->fimg[1][j] + 0.5));
            col.setBlue((int)(d->fimg[2][j] + 0.5));
            col.setAlpha(m_orgImage.getPixelColor(x, y).alpha());
            ++j;

            m_destImage.setPixelColor(x, y, col);
        }
    }

    postProgress(100);

    // Free buffers.

    for (int c = 0; c < 3; ++c)
    {
        delete [] d->fimg[c];
    }

    delete [] d->buffer[1];
    delete [] d->buffer[2];
}