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 //---------------------------------------------------------------------