• Skip to content
  • Skip to link menu
KDE 4.4 API Reference
  • KDE API Reference
  • KDE Support
  • Sitemap
  • Contact Us
 

qimageblitz

blitz.cpp

Go to the documentation of this file.
00001 /* 
00002  Copyright (C) 1998, 1999, 2001, 2002, 2004, 2005, 2007
00003       Daniel M. Duley <daniel.duley@verizon.net>
00004  (C) 2004 Zack Rusin <zack@kde.org>
00005  (C) 2000 Josef Weidendorfer <weidendo@in.tum.de>
00006  (C) 1999 Geert Jansen <g.t.jansen@stud.tue.nl>
00007  (C) 1998, 1999 Christian Tibirna <ctibirna@total.net>
00008  (C) 1998, 1999 Dirk Mueller <mueller@kde.org>
00009 
00010 Redistribution and use in source and binary forms, with or without
00011 modification, are permitted provided that the following conditions
00012 are met:
00013 
00014 1. Redistributions of source code must retain the above copyright
00015    notice, this list of conditions and the following disclaimer.
00016 2. Redistributions in binary form must reproduce the above copyright
00017    notice, this list of conditions and the following disclaimer in the
00018    documentation and/or other materials provided with the distribution.
00019 
00020 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00021 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00022 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00023 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00024 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00025 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00026 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00027 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00028 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00029 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00030 
00031 */
00032 
00033 /*
00034  Portions of this software are were originally based on ImageMagick's
00035  algorithms. ImageMagick is copyrighted under the following conditions:
00036 
00037 Copyright (C) 2003 ImageMagick Studio, a non-profit organization dedicated to
00038 making software imaging solutions freely available.
00039 
00040 Permission is hereby granted, free of charge, to any person obtaining a copy
00041 of this software and associated documentation files ("ImageMagick"), to deal
00042 in ImageMagick without restriction, including without limitation the rights
00043 to use, copy, modify, merge, publish, distribute, sublicense,  and/or sell
00044 copies of ImageMagick, and to permit persons to whom the ImageMagick is
00045 furnished to do so, subject to the following conditions:
00046 
00047 The above copyright notice and this permission notice shall be included in all
00048 copies or substantial portions of ImageMagick.
00049 
00050 The software is provided "as is", without warranty of any kind, express or
00051 implied, including but not limited to the warranties of merchantability,
00052 fitness for a particular purpose and noninfringement.  In no event shall
00053 ImageMagick Studio be liable for any claim, damages or other liability,
00054 whether in an action of contract, tort or otherwise, arising from, out of or
00055 in connection with ImageMagick or the use or other dealings in ImageMagick.
00056 
00057 Except as contained in this notice, the name of the ImageMagick Studio shall
00058 not be used in advertising or otherwise to promote the sale, use or other
00059 dealings in ImageMagick without prior written authorization from the
00060 ImageMagick Studio.
00061 */
00062 
00063 #define _USE_MATH_DEFINES   // for msvc
00064 
00065 #include "qimageblitz.h"
00066 #include "private/blitz_p.h"
00067 #include <config-processor.h>
00068 #include "blitzcpu.h"
00069 #include "private/interpolate.h"
00070 #include "private/inlinehsv.h"
00071 #include <cmath>
00072 #ifndef M_PI
00073 // Some cmath doesn't define it, try from the older source
00074 #include "math.h"
00075 #endif
00076 #include <string.h>
00077 #include <QVector>
00078 #include <QColor>
00079 
00080 #if defined(__i386__) && ( defined(__GNUC__) || defined(__INTEL_COMPILER) )
00081 #  if defined(HAVE_MMX )
00082 #    define USE_MMX_INLINE_ASM
00083 #  endif
00084 #endif
00085 
00086 QImage& Blitz::despeckle(QImage &img)
00087 {
00088     if(img.isNull())
00089         return(img);
00090 
00091     int length, x, y, j, i;
00092     QRgb *src, *dest;
00093     unsigned char *buffer, *pixels;
00094     int w = img.width();
00095     int h = img.height();
00096 
00097     static const int
00098         X[4]= {0, 1, 1,-1},
00099         Y[4]= {1, 0, 1, 1};
00100 
00101     length = (img.width()+2)*(img.height()+2);
00102     pixels = new unsigned char[length];
00103     buffer = new unsigned char[length];
00104 
00105     if(img.depth() != 32){
00106         img = img.convertToFormat(img.hasAlphaChannel() ?
00107                                   QImage::Format_ARGB32 :
00108                                   QImage::Format_RGB32);
00109     }
00110     else if(img.format() == QImage::Format_ARGB32_Premultiplied)
00111         img = img.convertToFormat(QImage::Format_ARGB32);
00112 
00113     // Do each channel. This originally was in one loop with an "if" statement
00114     // for each channel, but I unrolled it because a lot goes on and it needs
00115     // any speed help it can get >:/ (mosfet)
00116 
00117     // Red
00118     (void)memset(pixels, 0, length);
00119     j = w+2;
00120     for(y=0; y < h; ++y, ++j){
00121         src = (QRgb *)img.scanLine(y);
00122         ++j;
00123         for(x=w-1; x >= 0; --x, ++src, ++j)
00124             pixels[j] = qRed(*src);
00125     }
00126     (void)memset(buffer, 0, length);
00127     for(i=0; i < 4; ++i){
00128         BlitzPrivate::hull(X[i], Y[i], w, h, pixels, buffer, 1);
00129         BlitzPrivate::hull(-X[i], -Y[i], w, h, pixels, buffer, 1);
00130         BlitzPrivate::hull(-X[i], -Y[i], w, h, pixels, buffer, -1);
00131         BlitzPrivate::hull(X[i], Y[i], w, h, pixels, buffer, -1);
00132     }
00133     j = w+2;
00134     for(y=0; y < h; ++y, ++j){
00135         dest = (QRgb *)img.scanLine(y);
00136         ++j;
00137         for(x=w-1; x >= 0; --x, ++dest, ++j)
00138             *dest = qRgba(pixels[j], qGreen(*dest), qBlue(*dest),
00139                           qAlpha(*dest));
00140     }
00141 
00142     // Green
00143     (void)memset(pixels, 0, length);
00144     j = w+2;
00145     for(y=0; y < h; ++y, ++j){
00146         src = (QRgb *)img.scanLine(y);
00147         ++j;
00148         for(x=w-1; x >= 0; --x, ++src, ++j)
00149             pixels[j] = qGreen(*src);
00150     }
00151     (void)memset(buffer, 0, length);
00152     for(i=0; i < 4; ++i){
00153         BlitzPrivate::hull(X[i], Y[i], w, h, pixels, buffer, 1);
00154         BlitzPrivate::hull(-X[i], -Y[i], w, h, pixels, buffer, 1);
00155         BlitzPrivate::hull(-X[i], -Y[i], w, h, pixels, buffer, -1);
00156         BlitzPrivate::hull(X[i], Y[i], w, h, pixels, buffer, -1);
00157     }
00158     j = w+2;
00159     for(y=0; y < h; ++y, ++j){
00160         dest = (QRgb *)img.scanLine(y);
00161         ++j;
00162         for(x=w-1; x >= 0; --x, ++dest, ++j)
00163             *dest = qRgba(qRed(*dest), pixels[j], qBlue(*dest),
00164                           qAlpha(*dest));
00165     }
00166 
00167     // Blue
00168     (void)memset(pixels, 0, length);
00169     j = w+2;
00170     for(y=0; y < h; ++y, ++j){
00171         src = (QRgb *)img.scanLine(y);
00172         ++j;
00173         for(x=w-1; x >= 0; --x, ++src, ++j)
00174             pixels[j] = qBlue(*src);
00175     }
00176     (void)memset(buffer, 0, length);
00177     for(i=0; i < 4; ++i){
00178         BlitzPrivate::hull(X[i], Y[i], w, h, pixels, buffer, 1);
00179         BlitzPrivate::hull(-X[i], -Y[i], w, h, pixels, buffer, 1);
00180         BlitzPrivate::hull(-X[i], -Y[i], w, h, pixels, buffer, -1);
00181         BlitzPrivate::hull(X[i], Y[i], w, h, pixels, buffer, -1);
00182     }
00183     j = w+2;
00184     for(y=0; y < h; ++y, ++j){
00185         dest = (QRgb *)img.scanLine(y);
00186         ++j;
00187         for(x=w-1; x >= 0; --x, ++dest, ++j)
00188             *dest = qRgba(qRed(*dest), qGreen(*dest), pixels[j],
00189                           qAlpha(*dest));
00190     }
00191 
00192     delete[] pixels;
00193     delete[] buffer;
00194     return(img);
00195 }
00196 
00197 QImage Blitz::blur(QImage &img, int radius)
00198 {
00199     QRgb *p1, *p2;
00200     int x, y, w, h, mx, my, mw, mh, mt, xx, yy;
00201     int a, r, g, b;
00202     int *as, *rs, *gs, *bs;
00203 
00204     if(radius < 1 || img.isNull() || img.width() < (radius << 1))
00205         return(img);
00206 
00207     w = img.width();
00208     h = img.height();
00209 
00210     if(img.depth() < 8)
00211         img = img.convertToFormat(QImage::Format_Indexed8);
00212     QImage buffer(w, h, img.hasAlphaChannel() ?
00213                   QImage::Format_ARGB32 : QImage::Format_RGB32);
00214 
00215     as = new int[w];
00216     rs = new int[w];
00217     gs = new int[w];
00218     bs = new int[w];
00219 
00220     QVector<QRgb> colorTable;
00221     if(img.format() == QImage::Format_Indexed8)
00222         colorTable = img.colorTable();
00223 
00224     for(y = 0; y < h; y++){
00225         my = y - radius;
00226         mh = (radius << 1) + 1;
00227         if(my < 0){
00228             mh += my;
00229             my = 0;
00230         }
00231         if((my + mh) > h)
00232             mh = h - my;
00233 
00234         p1 = (QRgb *)buffer.scanLine(y);
00235         memset(as, 0, w * sizeof(int));
00236         memset(rs, 0, w * sizeof(int));
00237         memset(gs, 0, w * sizeof(int));
00238         memset(bs, 0, w * sizeof(int));
00239 
00240         if(img.format() == QImage::Format_ARGB32_Premultiplied){
00241             QRgb pixel;
00242             for(yy = 0; yy < mh; yy++){
00243                 p2 = (QRgb *)img.scanLine(yy + my);
00244                 for(x = 0; x < w; x++, p2++){
00245                     pixel = BlitzPrivate::convertFromPremult(*p2);
00246                     as[x] += qAlpha(pixel);
00247                     rs[x] += qRed(pixel);
00248                     gs[x] += qGreen(pixel);
00249                     bs[x] += qBlue(pixel);
00250                 }
00251             }
00252         }
00253         else if(img.format() == QImage::Format_Indexed8){
00254             QRgb pixel;
00255             unsigned char *ptr;
00256             for(yy = 0; yy < mh; yy++){
00257                 ptr = (unsigned char *)img.scanLine(yy + my);
00258                 for(x = 0; x < w; x++, ptr++){
00259                     pixel = colorTable[*ptr];
00260                     as[x] += qAlpha(pixel);
00261                     rs[x] += qRed(pixel);
00262                     gs[x] += qGreen(pixel);
00263                     bs[x] += qBlue(pixel);
00264                 }
00265             }
00266         }
00267         else{
00268             for(yy = 0; yy < mh; yy++){
00269                 p2 = (QRgb *)img.scanLine(yy + my);
00270                 for(x = 0; x < w; x++, p2++){
00271                     as[x] += qAlpha(*p2);
00272                     rs[x] += qRed(*p2);
00273                     gs[x] += qGreen(*p2);
00274                     bs[x] += qBlue(*p2);
00275                 }
00276             }
00277         }
00278 
00279         for(x = 0; x < w; x++){
00280             a = r = g = b = 0;
00281             mx = x - radius;
00282             mw = (radius << 1) + 1;
00283             if(mx < 0){
00284                 mw += mx;
00285                 mx = 0;
00286                 }
00287             if((mx + mw) > w)
00288                 mw = w - mx;
00289             mt = mw * mh;
00290             for(xx = mx; xx < (mw + mx); xx++){
00291                 a += as[xx];
00292                 r += rs[xx];
00293                 g += gs[xx];
00294                 b += bs[xx];
00295             }
00296             a = a / mt;
00297             r = r / mt;
00298             g = g / mt;
00299             b = b / mt;
00300             *p1++ = qRgba(r, g, b, a);
00301         }
00302     }
00303     delete[] as;
00304     delete[] rs;
00305     delete[] gs;
00306     delete[] bs;
00307 
00308     return(buffer);
00309 }
00310 
00311 QImage Blitz::sharpen(QImage &img, int radius)
00312 {
00313     if(img.isNull() || radius < 1)
00314         return(img);
00315     if(img.depth() != 32){
00316         img = img.convertToFormat(img.hasAlphaChannel() ?
00317                                   QImage::Format_ARGB32 :
00318                                   QImage::Format_RGB32);
00319     }
00320     else if(img.format() == QImage::Format_ARGB32_Premultiplied)
00321         img = img.convertToFormat(QImage::Format_ARGB32);
00322 
00323     QImage buffer(img.width(), img.height(), img.format());
00324     int a, r, g, b, x, y;
00325     int w = img.width();
00326     int h = img.height();
00327     QRgb *src, *dest;
00328 
00329     memcpy(buffer.scanLine(0), img.scanLine(0), img.bytesPerLine());
00330     for(y=1; y < h-1; ++y){
00331         src = (QRgb *)img.scanLine(y);
00332         dest = (QRgb *)buffer.scanLine(y);
00333         *dest++ = *src++;
00334         for(x=1; x < w-1; ++x){
00335             r = qRed(*src)*5;
00336             g = qGreen(*src)*5;
00337             b = qBlue(*src)*5;
00338             a = qAlpha(*src)*5;
00339 
00340             r -= qRed(*(src-1));
00341             g -= qGreen(*(src-1));
00342             b -= qBlue(*(src-1));
00343             a -= qAlpha(*(src-1));
00344             r -= qRed(*(src+1));
00345             g -= qGreen(*(src+1));
00346             b -= qBlue(*(src+1));
00347             a -= qAlpha(*(src+1));
00348 
00349             r -= qRed(*(src-w));
00350             g -= qGreen(*(src-w));
00351             b -= qBlue(*(src-w));
00352             a -= qAlpha(*(src-w));
00353             r -= qRed(*(src+w));
00354             g -= qGreen(*(src+w));
00355             b -= qBlue(*(src+w));
00356             a -= qAlpha(*(src+w));
00357 
00358             r = (r & ((~r) >> 16));
00359             r = ((r | ((r & 256) - ((r & 256) >> 8))));
00360             g = (g & ((~g) >> 16));
00361             g = ((g | ((g & 256) - ((g & 256) >> 8))));
00362             b = (b & ((~b) >> 16));
00363             b = ((b | ((b & 256) - ((b & 256) >> 8))));
00364             a = (a & ((~a) >> 16));
00365             a = ((a | ((a & 256) - ((a & 256) >> 8))));
00366 
00367             *dest = qRgba(r, g, b, a);
00368             ++src; ++dest;
00369         }
00370         *dest++ = *src++;
00371     }
00372     memcpy(buffer.scanLine(h-1), img.scanLine(h-1), img.bytesPerLine());
00373     return(buffer);
00374 }
00375 
00376 /*
00377  * I was looking for a quick way to do edge detection and found
00378  * the Sobel method. This is a gradient method that applies two 3x3
00379  * matrixes. These matrixes are:
00380  *
00381  * x:  -1, 0, 1      y:  1,  2,  1
00382  *     -2, 0, 2          0,  0,  0
00383  *     -1, 0, 1         -1, -2, -1
00384  *
00385  * After the matrix is applied you simply calculate the magnitude by
00386  * |x| + |y|.
00387  *
00388  * The one problem w/ this is most descriptions of the algorithm I've
00389  * seen assume grayscale data so your working with the intensity of the
00390  * pixel. We do each color channel separately. This is probably wrong,
00391  * but all the implementations I've seen do this...
00392  * (mosfet)
00393  */
00394 
00395 // Accumulates the results of applying x and y Sobel masks
00396 #define SOBEL(xm, ym, pixel) \
00397     xR += qRed((pixel))*(xm); xG += qGreen((pixel))*(xm); \
00398     xB += qBlue((pixel))*(xm); \
00399     yR += qRed((pixel))*(ym); yG += qGreen((pixel))*(ym); \
00400     yB += qBlue((pixel))*(ym);
00401 
00402 QImage Blitz::edge(QImage &img)
00403 {
00404 
00405     int x, y, w = img.width(), h = img.height();
00406     if(w < 3 || h < 3){
00407         qWarning("Blitz::edge(): Image is too small!");
00408         return(img);
00409     }
00410     if(img.isNull())
00411         return(img);
00412 
00413     if(img.depth() != 32){
00414         img = img.convertToFormat(img.hasAlphaChannel() ?
00415                                   QImage::Format_ARGB32 :
00416                                   QImage::Format_RGB32);
00417     }
00418     else if(img.format() == QImage::Format_ARGB32_Premultiplied)
00419         img = img.convertToFormat(QImage::Format_ARGB32);
00420 
00421     QImage buffer(w, h, QImage::Format_RGB32);
00422     QRgb *dest;
00423     QRgb *s, *scanblock[3];
00424 
00425 
00426 #ifdef USE_MMX_INLINE_ASM
00427 #ifdef __GNUC__
00428 #warning Using MMX sobel edge
00429 #endif
00430     if(BlitzCPUInfo::haveExtension(BlitzCPUInfo::MMX)){
00431         int xmatrix[] = {-1, 0, 1, -2, 0, 2, -1, 0, 1};
00432         int ymatrix[] = {1, 2, 1, 0, 0, 0, -1, -2, -1};
00433         int i, *xm, *ym;
00434 
00435         for(y=0; y < h; ++y){
00436             scanblock[1] = (QRgb *)img.scanLine(y);
00437             dest = (QRgb *)buffer.scanLine(y);
00438             if(y == 0){
00439                 scanblock[0] = (QRgb *)img.scanLine(y);
00440                 scanblock[2] = (QRgb *)img.scanLine(y+1);
00441             }
00442             else if(y == h-1){
00443                 scanblock[0] = (QRgb *)img.scanLine(y-1);
00444                 scanblock[2]  = (QRgb *)img.scanLine(y);
00445             }
00446             else{
00447                 scanblock[0] = (QRgb *)img.scanLine(y-1);
00448                 scanblock[2] = (QRgb *)img.scanLine(y+1);
00449             }
00450             //
00451             // x == 0, double over first pixel
00452             //
00453             __asm__ __volatile__
00454                 ("pxor %%mm7, %%mm7\n\t" // used for unpacking
00455                  "pxor %%mm5, %%mm5\n\t" // clear accumulator
00456                  "pxor %%mm6, %%mm6\n\t" // ""
00457                  : : );
00458             for(i=0, xm=xmatrix, ym=ymatrix; i < 3; ++i, xm+=3, ym+=3){
00459                 s = scanblock[i];
00460                 __asm__ __volatile__
00461                     (// first pixel
00462                      "movd (%0), %%mm0\n\t" // load pixel into mm0
00463                      "punpcklbw %%mm7, %%mm0\n\t" // upgrade to quad
00464                      "movq %%mm0, %%mm1\n\t" // copy pixel to mm1
00465                      "movq %%mm0, %%mm4\n\t" // and mm4 since we are doubling over
00466                      "movd 0(%1), %%mm2\n\t" // load x matrix into mm2
00467                      "punpckldq %%mm2, %%mm2\n\t" // expand to all words
00468                      "packssdw %%mm2, %%mm2\n\t"
00469                      "movd 0(%2), %%mm3\n\t" // load y matrix into mm3
00470                      "punpckldq %%mm3, %%mm3\n\t" // expand
00471                      "packssdw %%mm3, %%mm3\n\t"
00472                      "pmullw %%mm2, %%mm0\n\t" // multiply pixel w/ x matrix
00473                      "pmullw %%mm3, %%mm1\n\t" // and multiply copy w/ y matrix
00474                      "paddw %%mm0, %%mm5\n\t"  // add to accumulators
00475                      "paddw %%mm1, %%mm6\n\t"
00476                      // second pixel (doubled over)
00477                      "movq %%mm4, %%mm1\n\t" // copy saved pixel to mm1
00478                      "movd 4(%1), %%mm2\n\t" // load x matrix into mm2
00479                      "punpckldq %%mm2, %%mm2\n\t" // expand to all words
00480                      "packssdw %%mm2, %%mm2\n\t"
00481                      "movd 4(%2), %%mm3\n\t" // load y matrix into mm3
00482                      "punpckldq %%mm3, %%mm3\n\t" // expand
00483                      "packssdw %%mm3, %%mm3\n\t"
00484                      "pmullw %%mm2, %%mm4\n\t" // multiply pixel w/ x matrix
00485                      "pmullw %%mm3, %%mm1\n\t" // and multiply copy w/ y matrix
00486                      "paddw %%mm4, %%mm5\n\t"  // add to accumulators
00487                      "paddw %%mm1, %%mm6\n\t"
00488                      // third pixel
00489                      "movd 4(%0), %%mm0\n\t" // load pixel into mm0
00490                      "punpcklbw %%mm7, %%mm0\n\t" // upgrade to quad
00491                      "movq %%mm0, %%mm1\n\t" // copy pixel to mm1
00492                      "movd 8(%1), %%mm2\n\t" // load x matrix into mm2
00493                      "punpckldq %%mm2, %%mm2\n\t" // expand to all words
00494                      "packssdw %%mm2, %%mm2\n\t"
00495                      "movd 8(%2), %%mm3\n\t" // load y matrix into mm3
00496                      "punpckldq %%mm3, %%mm3\n\t" // expand
00497                      "packssdw %%mm3, %%mm3\n\t"
00498                      "pmullw %%mm2, %%mm0\n\t" // multiply pixel w/ x matrix
00499                      "pmullw %%mm3, %%mm1\n\t" // and multiply copy w/ y matrix
00500                      "paddw %%mm0, %%mm5\n\t"  // add to accumulators
00501                      "paddw %%mm1, %%mm6\n\t"
00502                      : : "r"(s), "r"(xm), "r"(ym));
00503             }
00504             __asm__ __volatile__
00505                 (// calculate abs, sum, and write
00506                  "movq %%mm5, %%mm0\n\t" // calculate abs of x accumulator
00507                  "psraw $15, %%mm0\n\t"
00508                  "pxor %%mm0, %%mm5\n\t"
00509                  "psubw %%mm0, %%mm5\n\t"
00510                  "movq %%mm6, %%mm0\n\t" // calculate abs of y accumulator
00511                  "psraw $15, %%mm0\n\t"
00512                  "pxor %%mm0, %%mm6\n\t"
00513                  "psubw %%mm0, %%mm6\n\t"
00514                  "paddw %%mm5, %%mm6\n\t" // add together
00515                  "packuswb %%mm6, %%mm6\n\t" // and write
00516                  "movd %%mm6, (%0)\n\t"
00517                  : : "r"(dest));
00518             dest++;
00519 
00520             //
00521             // Now x == 1, process middle of image
00522             //
00523 
00524             for(x=1; x < w-1; ++x){
00525                 __asm__ __volatile__
00526                     ("pxor %%mm5, %%mm5\n\t" // clear accumulator
00527                      "pxor %%mm6, %%mm6\n\t"
00528                      : : );
00529                 for(i=0, xm=xmatrix, ym=ymatrix; i < 3; ++i, xm+=3, ym+=3){
00530                     s = scanblock[i];
00531                     __asm__ __volatile__
00532                         (// first pixel
00533                          "movd (%0), %%mm0\n\t" // load pixel into mm0
00534                          "punpcklbw %%mm7, %%mm0\n\t" // upgrade to quad
00535                          "movq %%mm0, %%mm1\n\t" // copy pixel to mm1
00536                          "movd (%1), %%mm2\n\t" // load x matrix into mm2
00537                          "punpckldq %%mm2, %%mm2\n\t" // expand to all words
00538                          "packssdw %%mm2, %%mm2\n\t"
00539                          "movd (%2), %%mm3\n\t" // load y matrix into mm3
00540                          "punpckldq %%mm3, %%mm3\n\t" // expand
00541                          "packssdw %%mm3, %%mm3\n\t"
00542                          "pmullw %%mm2, %%mm0\n\t" // multiply pixel w/ x matrix
00543                          "pmullw %%mm3, %%mm1\n\t" // and multiply copy w/ y matrix
00544                          "paddw %%mm0, %%mm5\n\t"  // add to accumulators
00545                          "paddw %%mm1, %%mm6\n\t"
00546                          // second pixel
00547                          "movd 4(%0), %%mm0\n\t" // load pixel into mm0
00548                          "punpcklbw %%mm7, %%mm0\n\t" // upgrade to quad
00549                          "movq %%mm0, %%mm1\n\t" // copy pixel to mm1
00550                          "movd 4(%1), %%mm2\n\t" // load x matrix into mm2
00551                          "punpckldq %%mm2, %%mm2\n\t" // expand to all words
00552                          "packssdw %%mm2, %%mm2\n\t"
00553                          "movd 4(%2), %%mm3\n\t" // load y matrix into mm3
00554                          "punpckldq %%mm3, %%mm3\n\t" // expand
00555                          "packssdw %%mm3, %%mm3\n\t"
00556                          "pmullw %%mm2, %%mm0\n\t" // multiply pixel w/ x matrix
00557                          "pmullw %%mm3, %%mm1\n\t" // and multiply copy w/ y matrix
00558                          "paddw %%mm0, %%mm5\n\t"  // add to accumulators
00559                          "paddw %%mm1, %%mm6\n\t"
00560                          // third pixel
00561                          "movd 8(%0), %%mm0\n\t" // load pixel into mm0
00562                          "punpcklbw %%mm7, %%mm0\n\t" // upgrade to quad
00563                          "movq %%mm0, %%mm1\n\t" // copy pixel to mm1
00564                          "movd 8(%1), %%mm2\n\t" // load x matrix into mm2
00565                          "punpckldq %%mm2, %%mm2\n\t" // expand to all words
00566                          "packssdw %%mm2, %%mm2\n\t"
00567                          "movd 8(%2), %%mm3\n\t" // load y matrix into mm3
00568                          "punpckldq %%mm3, %%mm3\n\t" // expand
00569                          "packssdw %%mm3, %%mm3\n\t"
00570                          "pmullw %%mm2, %%mm0\n\t" // multiply pixel w/ x matrix
00571                          "pmullw %%mm3, %%mm1\n\t" // and multiply copy w/ y matrix
00572                          "paddw %%mm0, %%mm5\n\t"  // add to accumulators
00573                          "paddw %%mm1, %%mm6\n\t"
00574                          : : "r"(s), "r"(xm), "r"(ym));
00575                 }
00576                 __asm__ __volatile__
00577                     (// calculate abs, sum, and write
00578                      "movq %%mm5, %%mm0\n\t" // calculate abs of x accumulator
00579                      "psraw $15, %%mm0\n\t"
00580                      "pxor %%mm0, %%mm5\n\t"
00581                      "psubw %%mm0, %%mm5\n\t"
00582                      "movq %%mm6, %%mm0\n\t" // calculate abs of y accumulator
00583                      "psraw $15, %%mm0\n\t"
00584                      "pxor %%mm0, %%mm6\n\t"
00585                      "psubw %%mm0, %%mm6\n\t"
00586                      "paddw %%mm5, %%mm6\n\t" // add together
00587                      "packuswb %%mm6, %%mm6\n\t" // and write
00588                      "movd %%mm6, (%0)\n\t"
00589                      : : "r"(dest));
00590                 dest++;
00591                 ++scanblock[0], ++scanblock[1], ++scanblock[2];
00592             }
00593 
00594             //
00595             // x = w-1, double over last pixel
00596             //
00597 
00598             __asm__ __volatile__
00599                 ("pxor %%mm5, %%mm5\n\t" // clear accumulator
00600                  "pxor %%mm6, %%mm6\n\t"
00601                  : : );
00602             for(i=0, xm=xmatrix, ym=ymatrix; i < 3; ++i, xm+=3, ym+=3){
00603                 s = scanblock[i];
00604                 __asm__ __volatile__
00605                     (// first pixel
00606                      "movd (%0), %%mm0\n\t" // load pixel into mm0
00607                      "punpcklbw %%mm7, %%mm0\n\t" // upgrade to quad
00608                      "movq %%mm0, %%mm1\n\t" // copy pixel to mm1
00609                      "movd (%1), %%mm2\n\t" // load x matrix into mm2
00610                      "punpckldq %%mm2, %%mm2\n\t" // expand to all words
00611                      "packssdw %%mm2, %%mm2\n\t"
00612                      "movd (%2), %%mm3\n\t" // load y matrix into mm3
00613                      "punpckldq %%mm3, %%mm3\n\t" // expand
00614                      "packssdw %%mm3, %%mm3\n\t"
00615                      "pmullw %%mm2, %%mm0\n\t" // multiply pixel w/ x matrix
00616                      "pmullw %%mm3, %%mm1\n\t" // and multiply copy w/ y matrix
00617                      "paddw %%mm0, %%mm5\n\t"  // add to accumulators
00618                      "paddw %%mm1, %%mm6\n\t"
00619                      // second pixel
00620                      "movd 4(%0), %%mm0\n\t" // load pixel into mm0
00621                      "punpcklbw %%mm7, %%mm0\n\t" // upgrade to quad
00622                      "movq %%mm0, %%mm1\n\t" // copy pixel to mm1
00623                      "movd 4(%1), %%mm2\n\t" // load x matrix into mm2
00624                      "punpckldq %%mm2, %%mm2\n\t" // expand to all words
00625                      "packssdw %%mm2, %%mm2\n\t"
00626                      "movd 4(%2), %%mm3\n\t" // load y matrix into mm3
00627                      "punpckldq %%mm3, %%mm3\n\t" // expand
00628                      "packssdw %%mm3, %%mm3\n\t"
00629                      "pmullw %%mm2, %%mm0\n\t" // multiply pixel w/ x matrix
00630                      "pmullw %%mm3, %%mm1\n\t" // and multiply copy w/ y matrix
00631                      "paddw %%mm0, %%mm5\n\t"  // add to accumulators
00632                      "paddw %%mm1, %%mm6\n\t"
00633                      // third pixel
00634                      "movd 4(%0), %%mm0\n\t" // load pixel into mm0
00635                      "punpcklbw %%mm7, %%mm0\n\t" // upgrade to quad
00636                      "movq %%mm0, %%mm1\n\t" // copy pixel to mm1
00637                      "movd 8(%1), %%mm2\n\t" // load x matrix into mm2
00638                      "punpckldq %%mm2, %%mm2\n\t" // expand to all words
00639                      "packssdw %%mm2, %%mm2\n\t"
00640                      "movd 8(%2), %%mm3\n\t" // load y matrix into mm3
00641                      "punpckldq %%mm3, %%mm3\n\t" // expand
00642                      "packssdw %%mm3, %%mm3\n\t"
00643                      "pmullw %%mm2, %%mm0\n\t" // multiply pixel w/ x matrix
00644                      "pmullw %%mm3, %%mm1\n\t" // and multiply copy w/ y matrix
00645                      "paddw %%mm0, %%mm5\n\t"  // add to accumulators
00646                      "paddw %%mm1, %%mm6\n\t"
00647                      : : "r"(s), "r"(xm), "r"(ym));
00648             }
00649             __asm__ __volatile__
00650                 (// calculate abs, sum, and write
00651                  "movq %%mm5, %%mm0\n\t" // calculate abs of x accumulator
00652                  "psraw $15, %%mm0\n\t"
00653                  "pxor %%mm0, %%mm5\n\t"
00654                  "psubw %%mm0, %%mm5\n\t"
00655                  "movq %%mm6, %%mm0\n\t" // calculate abs of y accumulator
00656                  "psraw $15, %%mm0\n\t"
00657                  "pxor %%mm0, %%mm6\n\t"
00658                  "psubw %%mm0, %%mm6\n\t"
00659                  "paddw %%mm5, %%mm6\n\t" // add together
00660                  "packuswb %%mm6, %%mm6\n\t" // and write
00661                  "movd %%mm6, (%0)\n\t"
00662                  : : "r"(dest));
00663             dest++;
00664         }
00665         __asm__ __volatile__ ("emms\n\t" : :);
00666     }
00667     else
00668 #endif
00669     {
00670         int xR, xG, xB, yR, yG, yB;
00671         for(y=0; y < h; ++y){
00672             scanblock[1] = (QRgb *)img.scanLine(y);
00673             dest = (QRgb *)buffer.scanLine(y);
00674             if(y == 0){
00675                 scanblock[0] = (QRgb *)img.scanLine(y);
00676                 scanblock[2] = (QRgb *)img.scanLine(y+1);
00677             }
00678             else if(y == h-1){
00679                 scanblock[0] = (QRgb *)img.scanLine(y-1);
00680                 scanblock[2]  = (QRgb *)img.scanLine(y);
00681             }
00682             else{
00683                 scanblock[0] = (QRgb *)img.scanLine(y-1);
00684                 scanblock[2] = (QRgb *)img.scanLine(y+1);
00685             }
00686 
00687             // x == 0, double over first pixel
00688             xR = xG = xB = yR = yG = yB = 0;
00689             s = scanblock[0];
00690             SOBEL(-1, 1, *s); SOBEL(0, 2, *s); ++s; SOBEL(1, 1, *s);
00691             s = scanblock[1];
00692             SOBEL(-2, 0, *s); SOBEL(0, 0, *s); ++s; SOBEL(2, 0, *s);
00693             s = scanblock[2];
00694             SOBEL(-1, -1, *s); SOBEL(0, -2, *s); ++s; SOBEL(1, -1, *s);
00695             xR = qAbs(xR)+qAbs(yR); xG = qAbs(xG)+qAbs(yG);
00696             xB = qAbs(xB)+qAbs(yB);
00697             *dest++ = qRgb(qMin(xR, 255), qMin(xG, 255), qMin(xB, 255));
00698 
00699             // x == 1, process middle of image
00700             for(x=1; x < w-1; ++x){
00701                 xR = xG = xB = yR = yG = yB = 0;
00702                 s = scanblock[0];
00703                 SOBEL(-1, 1, *s); ++s; SOBEL(0, 2, *s); ++s; SOBEL(1, 1, *s);
00704                 s = scanblock[1];
00705                 SOBEL(-2, 0, *s); ++s; SOBEL(0, 0, *s); ++s; SOBEL(2, 0, *s);
00706                 s = scanblock[2];
00707                 SOBEL(-1, -1, *s); ++s; SOBEL(0, -2, *s); ++s; SOBEL(1, -1, *s);
00708                 ++scanblock[0]; ++scanblock[1]; ++scanblock[2];
00709                 xR = qAbs(xR)+qAbs(yR); xG = qAbs(xG)+qAbs(yG);
00710                 xB = qAbs(xB)+qAbs(yB);
00711                 *dest++ = qRgb(qMin(xR, 255), qMin(xG, 255), qMin(xB, 255));
00712             }
00713 
00714             // x == w-1, double over last pixel
00715             xR = xG = xB = yR = yG = yB = 0;
00716             s = scanblock[0];
00717             SOBEL(-1, 1, *s); ++s; SOBEL(0, 2, *s); SOBEL(1, 1, *s);
00718             s = scanblock[1];
00719             SOBEL(-2, 0, *s); ++s; SOBEL(0, 0, *s); SOBEL(2, 0, *s);
00720             s = scanblock[2];
00721             SOBEL(-1, -1, *s); ++s; SOBEL(0, -2, *s); SOBEL(1, -1, *s);
00722             xR = qAbs(xR)+qAbs(yR); xG = qAbs(xG)+qAbs(yG);
00723             xB = qAbs(xB)+qAbs(yB);
00724             *dest++ = qRgb(qMin(xR, 255), qMin(xG, 255), qMin(xB, 255));
00725         }
00726     }
00727     return(buffer);
00728 }
00729 
00730 QImage Blitz::charcoal(QImage &img)
00731 {
00732     QImage buffer(edge(img));
00733     buffer = blur(buffer, 1);
00734     normalize(buffer);
00735     buffer.invertPixels();
00736     grayscale(buffer, true);
00737     return(buffer);
00738 }
00739 
00740 QImage Blitz::swirl(QImage &img, float degrees)
00741 {
00742     float sine, cosine, distance, radius, factor;
00743     float x_center, x_distance, x_scale;
00744     float y_center, y_distance, y_scale;
00745     int x, y, w, h;
00746     QRgb *dest;
00747 
00748     w = img.width();
00749     h = img.height();
00750 
00751     if(img.format() == QImage::Format_ARGB32_Premultiplied)
00752         img = img.convertToFormat(QImage::Format_ARGB32);
00753     else if(img.depth() < 8)
00754         img = img.convertToFormat(QImage::Format_Indexed8);
00755 
00756     QImage buffer(w, h, img.hasAlphaChannel() ?
00757                   QImage::Format_ARGB32 : QImage::Format_RGB32);
00758 
00759     x_center = w/2.0;
00760     y_center = h/2.0;
00761     radius = qMax(x_center, y_center);
00762     x_scale = y_scale = 1.0;
00763     if(w > h)
00764         y_scale = (float)(w/h);
00765     else if(w < h)
00766         x_scale = (float)(h/w);
00767     degrees = (M_PI*degrees)/180.0;
00768 
00769     InlineInterpolate interpolate(&img, 0);
00770     if(img.depth() > 8){
00771         QRgb *src;
00772         for(y=0; y < h; ++y){
00773             src = (QRgb *)img.scanLine(y);
00774             dest = (QRgb *)buffer.scanLine(y);
00775             y_distance = y_scale*(y-y_center);
00776             for(x=0; x < w; ++x){
00777                 x_distance = x_scale*(x-x_center);
00778                 distance = x_distance*x_distance + y_distance*y_distance;
00779                 if(distance >= (radius*radius))
00780                     *dest = src[x];
00781                 else{
00782                     factor = 1.0-std::sqrt(distance)/radius;
00783                     sine = std::sin(degrees*factor*factor);
00784                     cosine = std::cos(degrees*factor*factor);
00785                     *dest = interpolate.
00786                         interpolate((cosine*x_distance-sine*y_distance)/
00787                                     x_scale+x_center,
00788                                     (sine*x_distance+cosine*y_distance)/
00789                                     y_scale+y_center);
00790                 }
00791                 ++dest;
00792             }
00793         }
00794     }
00795     else{
00796         QVector<QRgb> cTable(img.colorTable());
00797         unsigned char *src;
00798         for(y=0; y < h; ++y){
00799             src = img.scanLine(y);
00800             dest = (QRgb *)buffer.scanLine(y);
00801             y_distance = y_scale*(y-y_center);
00802             for(x=0; x < w; ++x){
00803                 x_distance = x_scale*(x-x_center);
00804                 distance = x_distance*x_distance + y_distance*y_distance;
00805                 if(distance >= (radius*radius))
00806                     *dest = cTable.at(src[x]);
00807                 else{
00808                     factor = 1.0-std::sqrt(distance)/radius;
00809                     sine = std::sin(degrees*factor*factor);
00810                     cosine = std::cos(degrees*factor*factor);
00811                     *dest = interpolate.
00812                         interpolate((cosine*x_distance-sine*y_distance)/
00813                                     x_scale+x_center,
00814                                     (sine*x_distance+cosine*y_distance)/
00815                                     y_scale+y_center);
00816                 }
00817                 ++dest;
00818             }
00819         }
00820     }
00821     return(buffer);
00822 }
00823 
00824 QImage Blitz::implode(QImage &img, float amount)
00825 {
00826     float distance, radius, factor;
00827     float x_center, x_distance, x_scale;
00828     float y_center, y_distance, y_scale;
00829     int x, y, w, h;
00830     QRgb *dest;
00831 
00832     w = img.width();
00833     h = img.height();
00834 
00835     if(img.format() == QImage::Format_ARGB32_Premultiplied)
00836         img = img.convertToFormat(QImage::Format_ARGB32);
00837     else if(img.depth() < 8)
00838         img = img.convertToFormat(QImage::Format_Indexed8);
00839 
00840     QImage buffer(w, h, img.hasAlphaChannel() ?
00841                   QImage::Format_ARGB32 : QImage::Format_RGB32);
00842 
00843     x_scale = y_scale = 1.0;
00844     x_center = 0.5*w;
00845     y_center = 0.5*h;
00846     radius = x_center;
00847     if(w > h)
00848         y_scale = (float)(w/h);
00849     else if(w < h){
00850         x_scale = (float)(h/w);
00851         radius = y_center;
00852     }
00853 
00854     InlineInterpolate interpolate(&img, 0);
00855     if(img.depth() > 8){
00856         QRgb *src;
00857         for(y=0; y < h; ++y){
00858             src = (QRgb *)img.scanLine(y);
00859             dest = (QRgb *)buffer.scanLine(y);
00860             y_distance = y_scale*(y-y_center);
00861             for(x=0; x < w; ++x){
00862                 x_distance = x_scale*(x-x_center);
00863                 distance = x_distance*x_distance + y_distance*y_distance;
00864                 if(distance >= (radius*radius))
00865                     *dest = src[x];
00866                 else{
00867                     factor = 1.0;
00868                     if(distance > 0.0)
00869                         factor = std::pow(std::sin(((float)M_PI)*
00870                                                    std::sqrt(distance)/
00871                                                    radius/2), -amount);
00872                     *dest = interpolate.
00873                         interpolate(factor*x_distance/x_scale+x_center,
00874                                     factor*y_distance/y_scale+y_center);
00875                 }
00876                 ++dest;
00877             }
00878         }
00879     }
00880     else{
00881         QVector<QRgb> cTable(img.colorTable());
00882         unsigned char *src;
00883         for(y=0; y < h; ++y){
00884             src = img.scanLine(y);
00885             dest = (QRgb *)buffer.scanLine(y);
00886             y_distance = y_scale*(y-y_center);
00887             for(x=0; x < w; ++x){
00888                 x_distance = x_scale*(x-x_center);
00889                 distance = x_distance*x_distance + y_distance*y_distance;
00890                 if(distance >= (radius*radius))
00891                     *dest = cTable.at(src[x]);
00892                 else{
00893                     factor = 1.0;
00894                     if(distance > 0.0)
00895                         factor = std::pow(std::sin(((float)M_PI)*
00896                                                    std::sqrt(distance)/
00897                                                    radius/2), -amount);
00898                     *dest = interpolate.
00899                         interpolate(factor*x_distance/x_scale+x_center,
00900                                     factor*y_distance/y_scale+y_center);
00901                 }
00902                 ++dest;
00903             }
00904         }
00905     }
00906     return(buffer);
00907 }
00908 
00909 QImage Blitz::wave(QImage &img, float amplitude, float length,
00910                    unsigned int background)
00911 {
00912     int x, y, w, h;
00913     QRgb *dest;
00914     float *sine_map;
00915 
00916     if(img.format() == QImage::Format_ARGB32_Premultiplied)
00917         img = img.convertToFormat(QImage::Format_ARGB32);
00918     else if(img.depth() < 8)
00919         img = img.convertToFormat(QImage::Format_Indexed8);
00920 
00921     QImage buffer(img.width(), (int)(img.height()+2.0*std::abs(amplitude)),
00922                   QImage::Format_RGB32);
00923     w = buffer.width();
00924     h = buffer.height();
00925 
00926     sine_map = new float[w];
00927     for(x=0; x < w; ++x)
00928         sine_map[x] = std::abs(amplitude)+amplitude*std::sin((2*M_PI*x)/length);
00929 
00930     InlineInterpolate interpolate(&img, background);
00931     for(y=0; y < h; ++y){
00932         dest = (QRgb *)buffer.scanLine(y);
00933         for(x=0; x < w; ++x)
00934             *dest++ = interpolate.
00935                 interpolateBackground(x, y-sine_map[x]);
00936     }
00937     delete[] sine_map;
00938     return(buffer);
00939 }
00940 
00941 QImage& Blitz::modulate(QImage &img, QImage &modImg, bool reverse,
00942                         ModulationType type, int factor, RGBChannel channel)
00943 {
00944     if(img.isNull() || modImg.isNull())
00945         return(img);
00946 
00947     // for image, we handle only depth 32
00948     if(img.depth() < 32 || img.format() == QImage::Format_ARGB32_Premultiplied)
00949         img = img.convertToFormat(img.hasAlphaChannel() ?
00950                                   QImage::Format_ARGB32 :
00951                                   QImage::Format_RGB32);
00952 
00953     // for modImage, we handle depth 8 and 32
00954     if(modImg.depth() < 8)
00955         modImg = modImg.convertToFormat(QImage::Format_Indexed8);
00956     else if(modImg.format() == QImage::Format_ARGB32_Premultiplied)
00957         modImg = modImg.convertToFormat(QImage::Format_ARGB32);
00958 
00959     unsigned int x1 = img.width(),  y1 = img.height();
00960     unsigned int x2 = modImg.width(), y2 = modImg.height();
00961     unsigned int x, y;
00962     unsigned int *src, *modulation_colorTable;
00963     unsigned char *modulation_src;
00964     int r, g, b, mod = 0;
00965     QRgb color1, color2;
00966     InlineHSV hsv;
00967 
00968     QVector<QRgb> cTable;
00969     if(modImg.format() == QImage::Format_Indexed8){
00970         cTable = modImg.colorTable();
00971         modulation_colorTable = cTable.data();
00972     }
00973     else
00974         modulation_colorTable = NULL;
00975 
00976     for(y=0; y < y1; ++y){
00977         src = (QRgb *)img.scanLine(y);
00978         modulation_src = modImg.scanLine(y%y2);
00979         x=0;
00980         while(x < x1){
00981             color2 = (!modulation_colorTable) ?
00982                 *((QRgb *)modulation_src) :
00983                 modulation_colorTable[*modulation_src];
00984             if(reverse){
00985                 color1 = color2;
00986                 color2 = *src;
00987             }
00988             else
00989                 color1 = *src;
00990 
00991             if(type == Intensity || type == Contrast){
00992                 r = qRed(color1); g = qGreen(color1); b = qBlue(color1);
00993                 if(channel != All){
00994                     mod = (channel == Red) ? qRed(color2) :
00995                         (channel == Green) ? qGreen(color2) :
00996                         (channel == Blue) ? qBlue(color2) :
00997                         (channel == Grayscale) ? qGray(color2) : 0;
00998                     mod = mod*factor/50;
00999                 }
01000 
01001                 if(type == Intensity){
01002                     if(channel == All){
01003                         r += r * factor/50 * qRed(color2)/256;
01004                         g += g * factor/50 * qGreen(color2)/256;
01005                         b += b * factor/50 * qBlue(color2)/256;
01006                     }
01007                     else{
01008                         r += r * mod/256;
01009                         g += g * mod/256;
01010                         b += b * mod/256;
01011                     }
01012                 }
01013                 else{ // Contrast
01014                     if(channel == All){
01015                         r += (r-128) * factor/50 * qRed(color2)/128;
01016                         g += (g-128) * factor/50 * qGreen(color2)/128;
01017                         b += (b-128) * factor/50 * qBlue(color2)/128;
01018                     }
01019                     else{
01020                         r += (r-128) * mod/128;
01021                         g += (g-128) * mod/128;
01022                         b += (b-128) * mod/128;
01023                     }
01024                 }
01025                 *src = qRgba(qBound(0, r, 255), qBound(0, g, 255),
01026                              qBound(0, b, 255), qAlpha(*src));
01027             }
01028             else if(type == Saturation || type == HueShift){
01029                 mod = (channel == Red) ? qRed(color2) :
01030                     (channel == Green) ? qGreen(color2) :
01031                     (channel == Blue) ? qBlue(color2) :
01032                     (channel == Grayscale||channel == All) ? qGray(color2) : 0;
01033                 mod = mod*factor/50;
01034                 hsv.convertRGB2HSV(color1);
01035                 if(type == Saturation)
01036                     hsv.setSaturation(qBound(0, hsv.saturation()-
01037                                              hsv.saturation()*mod/256, 255));
01038                 else{
01039                     int h = hsv.hue() + mod;
01040                     while(h<0) h+=360;
01041                     hsv.setHue(h %= 360);
01042                 }
01043                 hsv.convertHSV2RGB();
01044                 *src = qRgba(hsv.red(), hsv.green(), hsv.blue(), qAlpha(*src));
01045             }
01046             ++src; ++x;
01047             modulation_src += (!modulation_colorTable) ? 4 : 1;
01048 
01049             if((x%x2) == 0)
01050                 modulation_src -= (!modulation_colorTable) ? x2*4 : x2;
01051         }
01052     }
01053     return(img);
01054 }
01055 
01056 

qimageblitz

Skip menu "qimageblitz"
  • Main Page
  • Namespace List
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

KDE Support

Skip menu "KDE Support"
  • akonadi
  • Decibel
  • grantlee
  • kdewin
  • phonon
  •     Backend
  • polkit-qt
  • qca
  • qimageblitz
  • soprano
  • strigi
  •     searchclient
  •     streamanalyzer
  •     streams
Generated for KDE Support by doxygen 1.5.9-20090814
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