File indexing completed on 2024-05-19 04:22:56

0001 /*
0002    Copyright (c) 2003-2007 Clarence Dang <dang@kde.org>
0003    All rights reserved.
0004 
0005    Redistribution and use in source and binary forms, with or without
0006    modification, are permitted provided that the following conditions
0007    are met:
0008 
0009    1. Redistributions of source code must retain the above copyright
0010       notice, this list of conditions and the following disclaimer.
0011    2. Redistributions in binary form must reproduce the above copyright
0012       notice, this list of conditions and the following disclaimer in the
0013       documentation and/or other materials provided with the distribution.
0014 
0015    THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
0016    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0017    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
0018    IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
0019    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
0020    NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0021    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0022    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0023    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
0024    THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0025 */
0026 
0027 
0028 #define DEBUG_KP_EFFECT_BLUR_SHARPEN 0
0029 
0030 
0031 #include "kpEffectBlurSharpen.h"
0032 #include "blitz.h"
0033 
0034 #include "kpLogCategories.h"
0035 
0036 #include "pixmapfx/kpPixmapFX.h"
0037 
0038 
0039 #if DEBUG_KP_EFFECT_BLUR_SHARPEN
0040     #include <QTime>
0041 #endif
0042 
0043 
0044 //---------------------------------------------------------------------
0045 
0046 //
0047 // For info on "radius" and "sigma", see https://redskiesatnight.com/2005/04/06/sharpening-using-image-magick/
0048 //
0049 // Daniel Duley says:
0050 //
0051 // <quote>
0052 // I don't think I can describe it any better than the article: The radius
0053 // controls many how pixels are taken into account when determining the value
0054 // of the center pixel. This controls the quality [and speed] of the result but not
0055 // necessarily the strength. The sigma controls how those neighboring pixels
0056 // are weighted depending on how far the are from the center one. This is
0057 // closer to strength, but not exactly >:)
0058 // </quote>
0059 //
0060 
0061 
0062 static QImage BlurQImage(const QImage &qimage, int strength)
0063 {
0064     if (strength == 0) {
0065         return qimage;
0066     }
0067 
0068     // The numbers that follow were picked by experimentation to try to get
0069     // an effect linearly proportional to <strength> and at the same time,
0070     // be fast enough.
0071     //
0072     // I still have no idea what "radius" means.
0073 
0074     const double RadiusMin = 1;
0075     const double RadiusMax = 10;
0076     const double radius = RadiusMin +
0077         (strength - 1) *
0078         (RadiusMax - RadiusMin) /
0079         (kpEffectBlurSharpen::MaxStrength - 1);
0080 
0081 #if DEBUG_KP_EFFECT_BLUR_SHARPEN
0082     qCDebug(kpLogImagelib) << "kpEffectBlurSharpen.cpp:BlurQImage(strength=" << strength << ")"
0083                << " radius=" << radius;
0084 #endif
0085 
0086     QImage img(qimage);
0087     return Blitz::blur(img, qRound(radius));
0088 }
0089 
0090 //---------------------------------------------------------------------
0091 
0092 static QImage SharpenQImage (const QImage &qimage_, int strength)
0093 {
0094     QImage qimage = qimage_;
0095     if (strength == 0) {
0096         return qimage;
0097     }
0098 
0099 
0100     // The numbers that follow were picked by experimentation to try to get
0101     // an effect linearly proportional to <strength> and at the same time,
0102     // be fast enough.
0103     //
0104     // I still have no idea what "radius" and "sigma" mean.
0105 
0106     const double RadiusMin = 0.1;
0107     const double RadiusMax = 2.5;
0108     const double radius = RadiusMin +
0109        (strength - 1) *
0110        (RadiusMax - RadiusMin) /
0111        (kpEffectBlurSharpen::MaxStrength - 1);
0112 
0113     const double SigmaMin = 0.5;
0114     const double SigmaMax = 3.0;
0115     const double sigma = SigmaMin +
0116         (strength - 1) *
0117         (SigmaMax - SigmaMin) /
0118         (kpEffectBlurSharpen::MaxStrength - 1);
0119 
0120     const double RepeatMin = 1;
0121     const double RepeatMax = 2;
0122     const double repeat = qRound (RepeatMin +
0123         (strength - 1) *
0124         (RepeatMax - RepeatMin) /
0125         (kpEffectBlurSharpen::MaxStrength - 1));
0126 
0127 
0128 #if DEBUG_KP_EFFECT_BLUR_SHARPEN
0129     qCDebug(kpLogImagelib) << "kpEffectBlurSharpen.cpp:SharpenQImage(strength=" << strength << ")"
0130                << " radius=" << radius
0131                << " sigma=" << sigma
0132                << " repeat=" << repeat;
0133 #endif
0134 
0135 
0136     for (int i = 0; i < repeat; i++)
0137     {
0138     #if DEBUG_KP_EFFECT_BLUR_SHARPEN
0139         QTime timer; timer.start ();
0140     #endif
0141         qimage = Blitz::gaussianSharpen (qimage, static_cast<float> (radius),
0142                                          static_cast<float> (sigma));
0143     #if DEBUG_KP_EFFECT_BLUR_SHARPEN
0144         qCDebug(kpLogImagelib) << "\titeration #" + QString::number (i)
0145                   << ": " + QString::number (timer.elapsed ()) << "ms";
0146     #endif
0147     }
0148 
0149 
0150     return qimage;
0151 }
0152 
0153 //---------------------------------------------------------------------
0154 
0155 // public static
0156 kpImage kpEffectBlurSharpen::applyEffect (const kpImage &image,
0157         Type type, int strength)
0158 {
0159 #if DEBUG_KP_EFFECT_BLUR_SHARPEN
0160     qCDebug(kpLogImagelib) << "kpEffectBlurSharpen::applyEffect(image.rect=" << image.rect ()
0161               << ",type=" << int (type)
0162               << ",strength=" << strength
0163               << ")";
0164 #endif
0165 
0166     Q_ASSERT (strength >= MinStrength && strength <= MaxStrength);
0167 
0168     if (type == Blur) {
0169         return ::BlurQImage (image, strength);
0170     }
0171 
0172     if (type == Sharpen) {
0173         return ::SharpenQImage (image, strength);
0174     }
0175 
0176     if (type == MakeConfidential) {
0177         QImage img(image);
0178         return Blitz::blur(img, qMin(20, img.width() / 2));
0179     }
0180 
0181     return kpImage();
0182 }
0183 
0184 //---------------------------------------------------------------------