• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KIO

imagefilter.cpp

Go to the documentation of this file.
00001 //krazy:exclude=copyright (email of Maxim is missing)
00002 /*
00003     This file is a part of the KDE project
00004 
00005     Copyright © 2006 Zack Rusin <zack@kde.org>
00006     Copyright © 2006-2007, 2008 Fredrik Höglund <fredrik@kde.org>
00007 
00008     The stack blur algorithm was invented by Mario Klingemann <mario@quasimondo.com>
00009 
00010     This implementation is based on the version in Anti-Grain Geometry Version 2.4,
00011     Copyright © 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
00012 
00013     Redistribution and use in source and binary forms, with or without
00014     modification, are permitted provided that the following conditions
00015     are met:
00016 
00017     1. Redistributions of source code must retain the above copyright
00018        notice, this list of conditions and the following disclaimer.
00019     2. Redistributions in binary form must reproduce the above copyright
00020        notice, this list of conditions and the following disclaimer in the
00021        documentation and/or other materials provided with the distribution.
00022 
00023     THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00024     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00025     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00026     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00027     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00028     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00029     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00030     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00031     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00032     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00033 */
00034 
00035 #include "imagefilter_p.h"
00036 
00037 #include <QPainter>
00038 #include <QImage>
00039 #include <QColor>
00040 #include <QDebug>
00041 
00042 #include <cmath>
00043 #include <string.h>
00044 
00045 using namespace KIO;
00046 
00047 static const quint32 stack_blur8_mul[255] =
00048 {
00049     512,512,456,512,328,456,335,512,405,328,271,456,388,335,292,512,
00050     454,405,364,328,298,271,496,456,420,388,360,335,312,292,273,512,
00051     482,454,428,405,383,364,345,328,312,298,284,271,259,496,475,456,
00052     437,420,404,388,374,360,347,335,323,312,302,292,282,273,265,512,
00053     497,482,468,454,441,428,417,405,394,383,373,364,354,345,337,328,
00054     320,312,305,298,291,284,278,271,265,259,507,496,485,475,465,456,
00055     446,437,428,420,412,404,396,388,381,374,367,360,354,347,341,335,
00056     329,323,318,312,307,302,297,292,287,282,278,273,269,265,261,512,
00057     505,497,489,482,475,468,461,454,447,441,435,428,422,417,411,405,
00058     399,394,389,383,378,373,368,364,359,354,350,345,341,337,332,328,
00059     324,320,316,312,309,305,301,298,294,291,287,284,281,278,274,271,
00060     268,265,262,259,257,507,501,496,491,485,480,475,470,465,460,456,
00061     451,446,442,437,433,428,424,420,416,412,408,404,400,396,392,388,
00062     385,381,377,374,370,367,363,360,357,354,350,347,344,341,338,335,
00063     332,329,326,323,320,318,315,312,310,307,304,302,299,297,294,292,
00064     289,287,285,282,280,278,275,273,271,269,267,265,263,261,259
00065 };
00066 
00067 static const quint32 stack_blur8_shr[255] =
00068 {
00069     9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17,
00070     17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19,
00071     19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20,
00072     20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21,
00073     21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
00074     21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22,
00075     22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
00076     22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23,
00077     23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
00078     23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
00079     23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
00080     23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
00081     24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
00082     24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
00083     24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
00084     24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24
00085 };
00086 
00087 inline static void blurHorizontal(QImage &image, unsigned int *stack, int div, int radius)
00088 {
00089     int stackindex;
00090     int stackstart;
00091 
00092     quint32 * const pixels = reinterpret_cast<quint32 *>(image.bits());
00093     quint32 pixel;
00094 
00095     int w = image.width();
00096     int h = image.height();
00097     int wm = w - 1;
00098 
00099     unsigned int mul_sum = stack_blur8_mul[radius];
00100     unsigned int shr_sum = stack_blur8_shr[radius];
00101 
00102     unsigned int sum, sum_in, sum_out;
00103 
00104     for (int y = 0; y < h; y++)
00105     {
00106         sum     = 0;
00107         sum_in  = 0;
00108         sum_out = 0;
00109 
00110         const int yw = y * w;
00111         pixel = pixels[yw];
00112         for (int i = 0; i <= radius; i++)
00113         {
00114             stack[i] = qAlpha(pixel);
00115 
00116             sum += stack[i] * (i + 1);
00117             sum_out += stack[i];
00118         }
00119 
00120         for (int i = 1; i <= radius; i++)
00121         {
00122             pixel = pixels[yw + qMin(i, wm)];
00123 
00124             unsigned int *stackpix = &stack[i + radius];
00125             *stackpix = qAlpha(pixel);
00126 
00127             sum    += *stackpix * (radius + 1 - i);
00128             sum_in += *stackpix;
00129         }
00130 
00131         stackindex = radius;
00132         for (int x = 0, i = yw; x < w; x++)
00133         {
00134             pixels[i++] = (((sum * mul_sum) >> shr_sum) << 24) & 0xff000000;
00135 
00136             sum -= sum_out;
00137 
00138             stackstart = stackindex + div - radius;
00139             if (stackstart >= div)
00140                 stackstart -= div;
00141 
00142             unsigned int *stackpix = &stack[stackstart];
00143 
00144             sum_out -= *stackpix;
00145 
00146             pixel = pixels[yw + qMin(x + radius + 1, wm)];
00147 
00148             *stackpix = qAlpha(pixel);
00149 
00150             sum_in += *stackpix;
00151             sum    += sum_in;
00152 
00153             if (++stackindex >= div)
00154                 stackindex = 0;
00155 
00156             stackpix = &stack[stackindex];
00157 
00158             sum_out += *stackpix;
00159             sum_in  -= *stackpix;
00160         } // for (x = 0, ...)
00161     } // for (y = 0, ...)
00162 }
00163 
00164 inline static void blurVertical(QImage &image, unsigned int *stack, int div, int radius)
00165 {
00166     int stackindex;
00167     int stackstart;
00168 
00169     quint32 * const pixels = reinterpret_cast<quint32 *>(image.bits());
00170     quint32 pixel;
00171 
00172     int w = image.width();
00173     int h = image.height();
00174     int hm = h - 1;
00175 
00176     int mul_sum = stack_blur8_mul[radius];
00177     int shr_sum = stack_blur8_shr[radius];
00178 
00179     unsigned int sum, sum_in, sum_out;
00180 
00181     for (int x = 0; x < w; x++)
00182     {
00183         sum     = 0;
00184         sum_in  = 0;
00185         sum_out = 0;
00186 
00187         pixel = pixels[x];
00188         for (int i = 0; i <= radius; i++)
00189         {
00190             stack[i] = qAlpha(pixel);
00191 
00192             sum += stack[i] * (i + 1);
00193             sum_out += stack[i];
00194         }
00195 
00196         for (int i = 1; i <= radius; i++)
00197         {
00198             pixel = pixels[qMin(i, hm) * w + x];
00199 
00200             unsigned int *stackpix = &stack[i + radius];
00201             *stackpix = qAlpha(pixel);
00202 
00203             sum    += *stackpix * (radius + 1 - i);
00204             sum_in += *stackpix;
00205         }
00206 
00207         stackindex = radius;
00208         for (int y = 0, i = x; y < h; y++, i += w)
00209         {
00210             pixels[i] = (((sum * mul_sum) >> shr_sum) << 24) & 0xff000000;
00211 
00212             sum -= sum_out;
00213 
00214             stackstart = stackindex + div - radius;
00215             if (stackstart >= div)
00216                 stackstart -= div;
00217 
00218             unsigned int *stackpix = &stack[stackstart];
00219 
00220             sum_out -= *stackpix;
00221 
00222             pixel = pixels[qMin(y + radius + 1, hm) * w + x];
00223 
00224             *stackpix = qAlpha(pixel);
00225 
00226             sum_in += *stackpix;
00227             sum    += sum_in;
00228 
00229             if (++stackindex >= div)
00230                 stackindex = 0;
00231 
00232             stackpix = &stack[stackindex];
00233 
00234             sum_out += *stackpix;
00235             sum_in  -= *stackpix;
00236         } // for (y = 0, ...)
00237     } // for (x = 0, ...)
00238 }
00239 
00240 static void stackBlur(QImage &image, float radius)
00241 {
00242     radius = qRound(radius);
00243 
00244     int div = int(radius * 2) + 1;
00245     unsigned int *stack  = new unsigned int[div];
00246 
00247     blurHorizontal(image, stack, div, radius);
00248     blurVertical(image, stack, div, radius);
00249 
00250     delete [] stack;
00251 }
00252 
00253 void ImageFilter::shadowBlur(QImage &image, float radius, const QColor &color)
00254 {
00255     if (radius < 0)
00256         return;
00257 
00258     if (radius > 0)
00259         stackBlur(image, radius);
00260 
00261     // Correct the color and opacity of the shadow
00262     QPainter p(&image);
00263     p.setCompositionMode(QPainter::CompositionMode_SourceIn);
00264     p.fillRect(image.rect(), color);
00265 }
00266 
00267 // kate: space-indent on; indent-width 4; replace-tabs on;

KIO

Skip menu "KIO"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal