~ubuntu-branches/ubuntu/quantal/digikam/quantal-proposed

« back to all changes in this revision

Viewing changes to core/libs/dimg/filters/fx/distortionfxfilter.cpp

  • Committer: Package Import Robot
  • Author(s): Rohan Garg
  • Date: 2012-06-08 00:31:19 UTC
  • mfrom: (1.2.39) (3.2.23 sid)
  • Revision ID: package-import@ubuntu.com-20120608003119-qn0l1eo3rf5jdh9w
Tags: 4:2.6.0-0ubuntu1
* Merge from debian, remaining changes (LP: #885324, #1009943)
  - keep seperate binary packages:
    + libkface1, libkface-data, libkface-dev
    + libkgeomap1, libkgeomap-data, libkgeomap-dev
    + libvkontakte1, libkvkontakte-dev
    + libmediawiki1, libmediawiki-dev
  - keep patches:
    + kubuntu_mysqld_executable_name.diff
  - don't fail on missing files in dh_install
  - install oxygen icons for kipi-plugins
  - digikam breaks/replaces kipi-plugins-common << 4:2.5.0~
  - digikam-doc breaks/replaces digikam-data << 4:2.5.0~
  - digikam-data breaks/replaces kipi-plugins << 4:2.5.0~
  - kipi-plugins-common breaks/replaces kipi-plugins << 4:2.5.0~
* Update install files

Show diffs side-by-side

added added

removed removed

Lines of Context:
6
6
 * Date        : 2005-07-18
7
7
 * Description : Distortion FX threaded image filter.
8
8
 *
9
 
 * Copyright (C) 2005-2010 by Gilles Caulier <caulier dot gilles at gmail dot com>
 
9
 * Copyright (C) 2005-2012 by Gilles Caulier <caulier dot gilles at gmail dot com>
10
10
 * Copyright (C) 2006-2010 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
11
11
 * Copyright (C) 2010      by Martin Klapetek <martin dot klapetek at gmail dot com>
12
12
 *
32
32
 
33
33
// C++ includes
34
34
 
35
 
#include <cmath>
36
35
#include <cstdlib>
37
36
 
38
37
// Qt includes
39
38
 
40
39
#include <QDateTime>
 
40
#include <qmath.h>
41
41
 
42
42
// Local includes
43
43
 
48
48
namespace Digikam
49
49
{
50
50
 
51
 
DistortionFXFilter::DistortionFXFilter(QObject* parent)
 
51
DistortionFXFilter::DistortionFXFilter(QObject* const parent)
52
52
    : DImgThreadedFilter(parent)
53
53
{
54
54
    initFilter();
55
55
}
56
56
 
57
 
DistortionFXFilter::DistortionFXFilter(DImg* orgImage, QObject* parent, int effectType,
58
 
                                       int level, int iteration, bool antialiasing)
 
57
DistortionFXFilter::DistortionFXFilter(DImg* const orgImage, QObject* const parent, int effectType,
 
58
                                       int level, int iteration, bool antialiaqSing)
59
59
    : DImgThreadedFilter(orgImage, parent, "DistortionFX")
60
60
{
61
61
    m_effectType = effectType;
62
62
    m_level      = level;
63
63
    m_iteration  = iteration;
64
 
    m_antiAlias  = antialiasing;
 
64
    m_antiAlias  = antialiaqSing;
65
65
    m_randomSeed = RandomNumberGenerator::timeSeed();
66
66
 
67
67
    initFilter();
188
188
    }
189
189
}
190
190
 
191
 
/* Function to apply the fisheye effect backported from ImageProcessing version 2
 
191
/* Function to apply the fisheye effect backported from ImageProcesqSing version 2
192
192
 *
193
193
 * data             => The image data in RGBA mode.
194
194
 * Width            => Width of image.
237
237
    }
238
238
 
239
239
    lfRadMax = (double)qMax(Height, Width) / 2.0;
240
 
    lfCoeff = lfRadMax / log(fabs(lfCoeffStep) * lfRadMax + 1.0);
 
240
    lfCoeff  = lfRadMax / qLn(qFabs(lfCoeffStep) * lfRadMax + 1.0);
241
241
 
242
242
    // main loop
243
243
 
250
250
            tw = lfXScale * (double)(w - nHalfW);
251
251
 
252
252
            // we find the distance from the center
253
 
            lfRadius = sqrt(th * th + tw * tw);
 
253
            lfRadius = qSqrt(th * th + tw * tw);
254
254
 
255
255
            if (lfRadius < lfRadMax)
256
256
            {
257
 
                lfAngle = atan2(th, tw);
 
257
                lfAngle = qAtan2(th, tw);
258
258
 
259
259
                if (Coeff > 0.0)
260
260
                {
261
 
                    lfRadius = (exp(lfRadius / lfCoeff) - 1.0) / lfCoeffStep;
 
261
                    lfRadius = (qExp(lfRadius / lfCoeff) - 1.0) / lfCoeffStep;
262
262
                }
263
263
                else
264
264
                {
265
 
                    lfRadius = lfCoeff * log(1.0 + (-1.0 * lfCoeffStep) * lfRadius);
 
265
                    lfRadius = lfCoeff * qLn(1.0 + (-1.0 * lfCoeffStep) * lfRadius);
266
266
                }
267
267
 
268
 
                nw = (double)nHalfW + (lfRadius / lfXScale) * cos(lfAngle);
269
 
                nh = (double)nHalfH + (lfRadius / lfYScale) * sin(lfAngle);
 
268
                nw = (double)nHalfW + (lfRadius / lfXScale) * qCos(lfAngle);
 
269
                nh = (double)nHalfH + (lfRadius / lfYScale) * qSin(lfAngle);
270
270
 
271
271
                setPixelFromOther(Width, Height, sixteenBit, bytesDepth, data, pResBits, w, h, nw, nh, AntiAlias);
272
272
            }
289
289
    }
290
290
}
291
291
 
292
 
/* Function to apply the twirl effect backported from ImageProcessing version 2
 
292
/* Function to apply the twirl effect backported from ImageProcesqSing version 2
293
293
 *
294
294
 * data             => The image data in RGBA mode.
295
295
 * Width            => Width of image.
353
353
            tw = lfXScale * (double)(w - nHalfW);
354
354
 
355
355
            // now, we get the distance
356
 
            lfCurrentRadius = sqrt(th * th + tw * tw);
 
356
            lfCurrentRadius = qSqrt(th * th + tw * tw);
357
357
 
358
358
            // if distance is less than maximum radius...
359
359
            if (lfCurrentRadius < lfRadMax)
360
360
            {
361
361
                // we find the angle from the center
362
 
                lfAngle = atan2(th, tw);
 
362
                lfAngle = qAtan2(th, tw);
363
363
                // we get the accumuled angle
364
364
                lfAngleSum = lfAngleStep * (-1.0 * (lfCurrentRadius - lfRadMax));
365
365
                // ok, we sum angle with accumuled to find a new angle
366
366
                lfNewAngle = lfAngle + lfAngleSum;
367
367
 
368
368
                // now we find the exact position's x and y
369
 
                nw = (double)nHalfW + cos(lfNewAngle) * (lfCurrentRadius / lfXScale);
370
 
                nh = (double)nHalfH + sin(lfNewAngle) * (lfCurrentRadius / lfYScale);
 
369
                nw = (double)nHalfW + qCos(lfNewAngle) * (lfCurrentRadius / lfXScale);
 
370
                nh = (double)nHalfH + qSin(lfNewAngle) * (lfCurrentRadius / lfYScale);
371
371
 
372
372
                setPixelFromOther(Width, Height, sixteenBit, bytesDepth, data, pResBits, w, h, nw, nh, AntiAlias);
373
373
            }
432
432
 
433
433
    if (Horizontal)
434
434
    {
435
 
        lfCoeffX = (double)nHalfW / log(fabs(lfCoeffStep) * nHalfW + 1.0);
 
435
        lfCoeffX = (double)nHalfW / qLn(qFabs(lfCoeffStep) * nHalfW + 1.0);
436
436
    }
437
437
 
438
438
    if (Vertical)
439
439
    {
440
 
        lfCoeffY = (double)nHalfH / log(fabs(lfCoeffStep) * nHalfH + 1.0);
 
440
        lfCoeffY = (double)nHalfH / qLn(qFabs(lfCoeffStep) * nHalfH + 1.0);
441
441
    }
442
442
 
443
443
    // initial copy
450
450
        for (w = 0; runningFlag() && (w < Width); ++w)
451
451
        {
452
452
            // we find the distance from the center
453
 
            nh = fabs((double)(h - nHalfH));
454
 
            nw = fabs((double)(w - nHalfW));
 
453
            nh = qFabs((double)(h - nHalfH));
 
454
            nw = qFabs((double)(w - nHalfW));
455
455
 
456
456
            if (Horizontal)
457
457
            {
458
458
                if (Coeff > 0.0)
459
459
                {
460
 
                    nw = (exp(nw / lfCoeffX) - 1.0) / lfCoeffStep;
 
460
                    nw = (qExp(nw / lfCoeffX) - 1.0) / lfCoeffStep;
461
461
                }
462
462
                else
463
463
                {
464
 
                    nw = lfCoeffX * log(1.0 + (-1.0 * lfCoeffStep) * nw);
 
464
                    nw = lfCoeffX * qLn(1.0 + (-1.0 * lfCoeffStep) * nw);
465
465
                }
466
466
            }
467
467
 
469
469
            {
470
470
                if (Coeff > 0.0)
471
471
                {
472
 
                    nh = (exp(nh / lfCoeffY) - 1.0) / lfCoeffStep;
 
472
                    nh = (qExp(nh / lfCoeffY) - 1.0) / lfCoeffStep;
473
473
                }
474
474
                else
475
475
                {
476
 
                    nh = lfCoeffY * log(1.0 + (-1.0 * lfCoeffStep) * nh);
 
476
                    nh = lfCoeffY * qLn(1.0 + (-1.0 * lfCoeffStep) * nh);
477
477
                }
478
478
            }
479
479
 
527
527
    int nHalfW = Width / 2, nHalfH = Height / 2;
528
528
    double lfAngle, lfNewRadius, lfCurrentRadius, lfRadMax;
529
529
 
530
 
    lfRadMax = sqrt(Height * Height + Width * Width) / 2.0;
 
530
    lfRadMax = qSqrt(Height * Height + Width * Width) / 2.0;
531
531
 
532
532
    // main loop
533
533
 
540
540
            nw = nHalfW - w;
541
541
 
542
542
            // now, we get the distance
543
 
            lfCurrentRadius = sqrt(nh * nh + nw * nw);
 
543
            lfCurrentRadius = qSqrt(nh * nh + nw * nw);
544
544
            // we find the angle from the center
545
 
            lfAngle = atan2(nh, nw) * (double)Factor;
 
545
            lfAngle = qAtan2(nh, nw) * (double)Factor;
546
546
 
547
547
            // ok, we sum angle with accumuled to find a new angle
548
548
            lfNewRadius = lfCurrentRadius * lfCurrentRadius / lfRadMax;
549
549
 
550
550
            // now we find the exact position's x and y
551
 
            nw = (double)nHalfW - (cos(lfAngle) * lfNewRadius);
552
 
            nh = (double)nHalfH - (sin(lfAngle) * lfNewRadius);
 
551
            nw = (double)nHalfW - (qCos(lfAngle) * lfNewRadius);
 
552
            nh = (double)nHalfH - (qSin(lfAngle) * lfNewRadius);
553
553
 
554
554
            setPixelFromOther(Width, Height, sixteenBit, bytesDepth, data, pResBits, w, h, nw, nh, AntiAlias);
555
555
        }
564
564
    }
565
565
}
566
566
 
567
 
/* Function to apply the Polar Coordinates effect backported from ImageProcessing version 2
 
567
/* Function to apply the Polar Coordinates effect backported from ImageProcesqSing version 2
568
568
 *
569
569
 * data             => The image data in RGBA mode.
570
570
 * Width            => Width of image.
616
616
            if (Type)
617
617
            {
618
618
                // now, we get the distance
619
 
                lfRadius = sqrt(th * th + tw * tw);
 
619
                lfRadius = qSqrt(th * th + tw * tw);
620
620
                // we find the angle from the center
621
 
                lfAngle = atan2(tw, th);
 
621
                lfAngle = qAtan2(tw, th);
622
622
 
623
623
                // now we find the exact position's x and y
624
624
                nh = lfRadius * (double) Height / lfRadMax;
631
631
                lfRadius = (double)(h) * lfRadMax / (double)Height;
632
632
                lfAngle  = (double)(w) * (2 * M_PI) / (double) Width;
633
633
 
634
 
                nw = (double)nHalfW - (lfRadius / lfXScale) * sin(lfAngle);
635
 
                nh = (double)nHalfH - (lfRadius / lfYScale) * cos(lfAngle);
 
634
                nw = (double)nHalfW - (lfRadius / lfXScale) * qSin(lfAngle);
 
635
                nh = (double)nHalfH - (lfRadius / lfYScale) * qCos(lfAngle);
636
636
            }
637
637
 
638
638
            setPixelFromOther(Width, Height, sixteenBit, bytesDepth, data, pResBits, w, h, nw, nh, AntiAlias);
648
648
    }
649
649
}
650
650
 
651
 
/* Function to apply the circular waves effect backported from ImageProcessing version 2
 
651
/* Function to apply the circular waves effect backported from ImageProcesqSing version 2
652
652
 *
653
653
 * data             => The image data in RGBA mode.
654
654
 * Width            => Width of image.
692
692
 
693
693
    Phase *= ANGLE_RATIO;
694
694
 
695
 
    lfRadMax = sqrt(Height * Height + Width * Width);
 
695
    lfRadMax = qSqrt(Height * Height + Width * Width);
696
696
 
697
697
    for (h = 0; runningFlag() && (h < Height); ++h)
698
698
    {
701
701
            nw = X - w;
702
702
            nh = Y - h;
703
703
 
704
 
            lfRadius = sqrt(nw * nw + nh * nh);
 
704
            lfRadius = qSqrt(nw * nw + nh * nh);
705
705
 
706
706
            if (WavesType)
707
707
            {
708
708
                lfNewAmp = Amplitude * lfRadius / lfRadMax;
709
709
            }
710
710
 
711
 
            nw = (double)w + lfNewAmp * sin(lfFreqAngle * lfRadius + Phase);
712
 
            nh = (double)h + lfNewAmp * cos(lfFreqAngle * lfRadius + Phase);
 
711
            nw = (double)w + lfNewAmp * qSin(lfFreqAngle * lfRadius + Phase);
 
712
            nh = (double)h + lfNewAmp * qCos(lfFreqAngle * lfRadius + Phase);
713
713
 
714
714
            setPixelFromOther(Width, Height, sixteenBit, bytesDepth, data, pResBits, w, h, nw, nh, AntiAlias);
715
715
        }
735
735
 * Direction        => Vertical or horizontal flag.
736
736
 *
737
737
 * Theory           => This is an amazing effect, very funny, and very simple to
738
 
 *                     understand. You just need understand how sin and cos works.
 
738
 *                     understand. You just need understand how qSin and qCos works.
739
739
 */
740
740
void DistortionFXFilter::waves(DImg* orgImage, DImg* destImage,
741
741
                               int Amplitude, int Frequency,
763
763
 
764
764
        for (h = 0; runningFlag() && (h < Height); ++h)
765
765
        {
766
 
            tx = lround(Amplitude * sin((Frequency * 2) * h * (M_PI / 180)));
 
766
            tx = lround(Amplitude * qSin((Frequency * 2) * h * (M_PI / 180)));
767
767
            destImage->bitBltImage(orgImage, 0, h,  Width, 1,  tx, h);
768
768
 
769
769
            if (FillSides)
787
787
 
788
788
        for (w = 0; runningFlag() && (w < Width); ++w)
789
789
        {
790
 
            ty = lround(Amplitude * sin((Frequency * 2) * w * (M_PI / 180)));
 
790
            ty = lround(Amplitude * qSin((Frequency * 2) * w * (M_PI / 180)));
791
791
            destImage->bitBltImage(orgImage, w, 0, 1, Height, w, ty);
792
792
 
793
793
            if (FillSides)
854
854
            nw = nHalfW - w;
855
855
            nh = nHalfH - h;
856
856
 
857
 
//            Radius = sqrt (nw * nw + nh * nh);
 
857
//            Radius = qSqrt (nw * nw + nh * nh);
858
858
 
859
859
            if (Mode)
860
860
            {
861
 
                nw = (int)(w + Amplitude * sin(Frequency * nw * (M_PI / 180)));
862
 
                nh = (int)(h + Amplitude * cos(Frequency * nh * (M_PI / 180)));
 
861
                nw = (int)(w + Amplitude * qSin(Frequency * nw * (M_PI / 180)));
 
862
                nh = (int)(h + Amplitude * qCos(Frequency * nh * (M_PI / 180)));
863
863
            }
864
864
            else
865
865
            {
866
 
                nw = (int)(w + Amplitude * sin(Frequency * w * (M_PI / 180)));
867
 
                nh = (int)(h + Amplitude * cos(Frequency * h * (M_PI / 180)));
 
866
                nw = (int)(w + Amplitude * qSin(Frequency * w * (M_PI / 180)));
 
867
                nh = (int)(h + Amplitude * qCos(Frequency * h * (M_PI / 180)));
868
868
            }
869
869
 
870
 
            offset = getOffset(Width, w, h, bytesDepth);
 
870
            offset      = getOffset(Width, w, h, bytesDepth);
871
871
            offsetOther = getOffsetAdjusted(Width, Height, (int)nw, (int)nh, bytesDepth);
872
872
 
873
873
            // read color
896
896
 * Random           => Maximum random value
897
897
 *
898
898
 * Theory           => Similar to Tile effect from Photoshop and very easy to
899
 
 *                     understand. We get a rectangular area using WSize and HSize and
 
899
 *                     understand. We get a rectangular area uqSing WSize and HSize and
900
900
 *                     replace in a position with a random distance from the original
901
901
 *                     position.
902
902
 */
951
951
    action.setDisplayableName(DisplayableName());
952
952
 
953
953
    action.addParameter("antiAlias", m_antiAlias);
954
 
    action.addParameter("type", m_effectType);
 
954
    action.addParameter("type",      m_effectType);
955
955
    action.addParameter("iteration", m_iteration);
956
 
    action.addParameter("level", m_level);
 
956
    action.addParameter("level",     m_level);
957
957
 
958
958
    if (m_effectType == Tile)
959
959
    {
960
960
        action.addParameter("randomSeed", m_randomSeed);
961
961
    }
962
962
 
963
 
 
964
963
    return action;
965
964
}
966
965
 
967
 
void DistortionFXFilter::readParameters(const Digikam::FilterAction& action)
 
966
void DistortionFXFilter::readParameters(const FilterAction& action)
968
967
{
969
 
    m_antiAlias = action.parameter("antiAlias").toBool();
 
968
    m_antiAlias  = action.parameter("antiAlias").toBool();
970
969
    m_effectType = action.parameter("type").toInt();
971
 
    m_iteration = action.parameter("iteration").toInt();
972
 
    m_level = action.parameter("level").toInt();
 
970
    m_iteration  = action.parameter("iteration").toInt();
 
971
    m_level      = action.parameter("level").toInt();
973
972
 
974
973
    if (m_effectType == Tile)
975
974
    {
977
976
    }
978
977
}
979
978
 
980
 
// UNUSED
981
 
/* Function to return the maximum radius with a determined angle
982
 
 *
983
 
 * Height           => Height of the image
984
 
 * Width            => Width of the image
985
 
 * Angle            => Angle to analyze the maximum radius
986
 
 *
987
 
 * Theory           => This function calculates the maximum radius to that angle
988
 
 *                     so, we can build an oval circumference
989
 
 */
990
 
/*
991
 
double DistortionFXFilter::maximumRadius(int Height, int Width, double Angle)
992
 
{
993
 
   double MaxRad, MinRad;
994
 
   double Radius, DegAngle = fabs (Angle * 57.295);    // Rads -> Degrees
995
 
 
996
 
   MinRad = qMin (Height, Width) / 2.0;                // Gets the minor radius
997
 
   MaxRad = qMax (Height, Width) / 2.0;                // Gets the major radius
998
 
 
999
 
   // Find the quadrant between -PI/2 and PI/2
1000
 
   if (DegAngle > 90.0)
1001
 
       Radius = proportionalValue (MinRad, MaxRad, (DegAngle * (255.0 / 90.0)));
1002
 
   else
1003
 
       Radius = proportionalValue (MaxRad, MinRad, ((DegAngle - 90.0) * (255.0 / 90.0)));
1004
 
   return (Radius);
1005
 
}
1006
 
*/
1007
 
 
1008
979
}  // namespace Digikam