• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

KDEUI

kiconeffect.cpp

Go to the documentation of this file.
00001 /* vi: ts=8 sts=4 sw=4
00002  *
00003  * This file is part of the KDE project, module kdecore.
00004  * Copyright (C) 2000 Geert Jansen <jansen@kde.org>
00005  * (C) 2007 Daniel M. Duley <daniel.duley@verizon.net>
00006  * with minor additions and based on ideas from
00007  * Torsten Rahn <torsten@kde.org>
00008  *
00009  * This library is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Library General Public
00011  * License version 2 as published by the Free Software Foundation.
00012  *
00013  * This library is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * Library General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Library General Public License
00019  * along with this library; see the file COPYING.LIB.  If not, write to
00020  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00021  * Boston, MA 02110-1301, USA.
00022  */
00023 
00024 #include "kiconeffect.h"
00025 
00026 #include <config.h>
00027 #include <unistd.h>
00028 #include <math.h>
00029 
00030 #include <QtCore/QSysInfo>
00031 #include <QtGui/QApplication>
00032 #include <QtGui/QPaintEngine>
00033 #include <QtGui/QDesktopWidget>
00034 #include <QtCore/QCharRef>
00035 #include <QtCore/QMutableStringListIterator>
00036 #include <QtGui/QBitmap>
00037 #include <QtGui/QPixmap>
00038 #include <QtGui/QImage>
00039 #include <QtGui/QColor>
00040 #include <QtGui/QWidget>
00041 #include <QtGui/QPainter>
00042 #include <QtGui/QPen>
00043 
00044 #include <kdebug.h>
00045 #include <kglobal.h>
00046 #include <ksharedconfig.h>
00047 #include <kglobalsettings.h>
00048 #include <kcolorscheme.h>
00049 #include <kicontheme.h>
00050 #include <kconfiggroup.h>
00051 
00052 
00053 class KIconEffectPrivate
00054 {
00055 public:
00056     int effect[6][3];
00057     float value[6][3];
00058     QColor color[6][3];
00059     bool trans[6][3];
00060     QString key[6][3];
00061     QColor color2[6][3];
00062 };
00063 
00064 KIconEffect::KIconEffect()
00065     :d(new KIconEffectPrivate)
00066 {
00067     init();
00068 }
00069 
00070 KIconEffect::~KIconEffect()
00071 {
00072     delete d;
00073 }
00074 
00075 void KIconEffect::init()
00076 {
00077     KSharedConfig::Ptr config = KGlobal::config();
00078 
00079     int i, j, effect=-1;
00080     //FIXME: this really should be using KIconLoader::metaObject() to guarantee synchronization
00081     // performance wise it's also practically guaranteed to be faster
00082     QStringList groups;
00083     groups += "Desktop";
00084     groups += "Toolbar";
00085     groups += "MainToolbar";
00086     groups += "Small";
00087     groups += "Panel";
00088     groups += "Dialog";
00089 
00090     QStringList states;
00091     states += "Default";
00092     states += "Active";
00093     states += "Disabled";
00094 
00095     QStringList::ConstIterator it, it2;
00096     QString _togray("togray");
00097     QString _colorize("colorize");
00098     QString _desaturate("desaturate");
00099     QString _togamma("togamma");
00100     QString _none("none");
00101     QString _tomonochrome("tomonochrome");
00102 
00103     for (it=groups.constBegin(), i=0; it!=groups.constEnd(); ++it, ++i)
00104     {
00105     // Default effects
00106     d->effect[i][0] = NoEffect;
00107     d->effect[i][1] =  ((i==0)||(i==4)) ? ToGamma : NoEffect;
00108     d->effect[i][2] = ToGray;
00109 
00110     d->trans[i][0] = false;
00111     d->trans[i][1] = false;
00112     d->trans[i][2] = true;
00113         d->value[i][0] = 1.0;
00114         d->value[i][1] = ((i==0)||(i==4)) ? 0.7 : 1.0;
00115         d->value[i][2] = 1.0;
00116         d->color[i][0] = QColor(144,128,248);
00117         d->color[i][1] = QColor(169,156,255);
00118         d->color[i][2] = QColor(34,202,0);
00119         d->color2[i][0] = QColor(0,0,0);
00120         d->color2[i][1] = QColor(0,0,0);
00121         d->color2[i][2] = QColor(0,0,0);
00122 
00123     KConfigGroup cg(config, *it + "Icons");
00124     for (it2=states.constBegin(), j=0; it2!=states.constEnd(); ++it2, ++j)
00125     {
00126         QString tmp = cg.readEntry(*it2 + "Effect", QString());
00127         if (tmp == _togray)
00128         effect = ToGray;
00129         else if (tmp == _colorize)
00130         effect = Colorize;
00131         else if (tmp == _desaturate)
00132         effect = DeSaturate;
00133         else if (tmp == _togamma)
00134         effect = ToGamma;
00135         else if (tmp == _tomonochrome)
00136         effect = ToMonochrome;
00137             else if (tmp == _none)
00138         effect = NoEffect;
00139         else
00140         continue;
00141         if(effect != -1)
00142                 d->effect[i][j] = effect;
00143         d->value[i][j] = cg.readEntry(*it2 + "Value", 0.0);
00144         d->color[i][j] = cg.readEntry(*it2 + "Color", QColor());
00145         d->color2[i][j] = cg.readEntry(*it2 + "Color2", QColor());
00146         d->trans[i][j] = cg.readEntry(*it2 + "SemiTransparent", false);
00147 
00148     }
00149     }
00150 }
00151 
00152 bool KIconEffect::hasEffect(int group, int state) const
00153 {
00154     if (group < 0 || group >= KIconLoader::LastGroup ||
00155         state < 0 || state >= KIconLoader::LastState) {
00156         return false;
00157     }
00158 
00159     return d->effect[group][state] != NoEffect;
00160 }
00161 
00162 QString KIconEffect::fingerprint(int group, int state) const
00163 {
00164     if (group < 0 || group >= KIconLoader::LastGroup ||
00165         state < 0 || state >= KIconLoader::LastState) {
00166         return QString();
00167     }
00168 
00169     QString cached = d->key[group][state];
00170     if (cached.isEmpty())
00171     {
00172         QString tmp;
00173         cached = tmp.setNum(d->effect[group][state]);
00174         cached += ':';
00175         cached += tmp.setNum(d->value[group][state]);
00176         cached += ':';
00177         cached += d->trans[group][state] ? QLatin1String("trans")
00178             : QLatin1String("notrans");
00179         if (d->effect[group][state] == Colorize || d->effect[group][state] == ToMonochrome)
00180         {
00181             cached += ':';
00182             cached += d->color[group][state].name();
00183         }
00184         if (d->effect[group][state] == ToMonochrome)
00185         {
00186             cached += ':';
00187             cached += d->color2[group][state].name();
00188         }
00189 
00190         d->key[group][state] = cached;
00191     }
00192 
00193     return cached;
00194 }
00195 
00196 QImage KIconEffect::apply(const QImage &image, int group, int state) const
00197 {
00198     if (state >= KIconLoader::LastState)
00199     {
00200     kDebug(265) << "Illegal icon state: " << state << "\n";
00201     return image;
00202     }
00203     if (group >= KIconLoader::LastGroup)
00204     {
00205     kDebug(265) << "Illegal icon group: " << group << "\n";
00206     return image;
00207     }
00208     return apply(image, d->effect[group][state], d->value[group][state],
00209         d->color[group][state], d->color2[group][state], d->trans[group][state]);
00210 }
00211 
00212 QImage KIconEffect::apply(const QImage &image, int effect, float value,
00213                           const QColor &col, bool trans) const
00214 {
00215     return apply(image, effect, value, col,
00216                  KColorScheme(QPalette::Active, KColorScheme::View).background().color(), trans);
00217 }
00218 
00219 QImage KIconEffect::apply(const QImage &img, int effect, float value,
00220                           const QColor &col, const QColor &col2, bool trans) const
00221 {
00222     QImage image = img;
00223     if (effect >= LastEffect )
00224     {
00225     kDebug(265) << "Illegal icon effect: " << effect << "\n";
00226     return image;
00227     }
00228     if (value > 1.0)
00229     value = 1.0;
00230     else if (value < 0.0)
00231     value = 0.0;
00232     switch (effect)
00233     {
00234     case ToGray:
00235     toGray(image, value);
00236     break;
00237     case DeSaturate:
00238     deSaturate(image, value);
00239     break;
00240     case Colorize:
00241         colorize(image, col, value);
00242         break;
00243     case ToGamma:
00244         toGamma(image, value);
00245         break;
00246     case ToMonochrome:
00247         toMonochrome(image, col, col2, value);
00248         break;
00249     }
00250     if (trans == true)
00251     {
00252     semiTransparent(image);
00253     }
00254     return image;
00255 }
00256 
00257 QPixmap KIconEffect::apply(const QPixmap &pixmap, int group, int state) const
00258 {
00259     if (state >= KIconLoader::LastState)
00260     {
00261     kDebug(265) << "Illegal icon state: " << state << "\n";
00262     return pixmap;
00263     }
00264     if (group >= KIconLoader::LastGroup)
00265     {
00266     kDebug(265) << "Illegal icon group: " << group << "\n";
00267     return pixmap;
00268     }
00269     return apply(pixmap, d->effect[group][state], d->value[group][state],
00270         d->color[group][state], d->color2[group][state], d->trans[group][state]);
00271 }
00272 
00273 QPixmap KIconEffect::apply(const QPixmap &pixmap, int effect, float value,
00274     const QColor &col, bool trans) const
00275 {
00276     return apply(pixmap, effect, value, col,
00277                  KColorScheme(QPalette::Active, KColorScheme::View).background().color(), trans);
00278 }
00279 
00280 QPixmap KIconEffect::apply(const QPixmap &pixmap, int effect, float value,
00281     const QColor &col, const QColor &col2, bool trans) const
00282 {
00283     QPixmap result;
00284 
00285     if (effect >= LastEffect )
00286     {
00287     kDebug(265) << "Illegal icon effect: " << effect << "\n";
00288     return result;
00289     }
00290 
00291     if ((trans == true) && (effect == NoEffect))
00292     {
00293         result = pixmap;
00294         semiTransparent(result);
00295     }
00296     else if ( effect != NoEffect )
00297     {
00298         QImage tmpImg = pixmap.toImage();
00299         tmpImg = apply(tmpImg, effect, value, col, col2, trans);
00300         result = QPixmap::fromImage(tmpImg);
00301     }
00302     else
00303         result = pixmap;
00304 
00305     return result;
00306 }
00307 
00308 struct KIEImgEdit
00309 {
00310     QImage& img;
00311     QVector <QRgb> colors;
00312     unsigned int*  data;
00313     unsigned int   pixels;
00314 
00315     KIEImgEdit(QImage& _img):img(_img)
00316     {
00317     if (img.depth() > 8)
00318         {
00319             //Code using data and pixels assumes that the pixels are stored
00320             //in 32bit values and that the image is not premultiplied
00321             if ((img.format() != QImage::Format_ARGB32) &&
00322                 (img.format() != QImage::Format_RGB32))
00323             {
00324                 img = img.convertToFormat(QImage::Format_ARGB32);
00325             }
00326             data   = (unsigned int*)img.bits();
00327         pixels = img.width()*img.height();
00328     }
00329     else
00330     {
00331         pixels = img.numColors();
00332         colors = img.colorTable();
00333         data   = (unsigned int*)colors.data();
00334     }
00335     }
00336 
00337     ~KIEImgEdit()
00338     {
00339     if (img.depth() <= 8)
00340         img.setColorTable(colors);
00341     }
00342 };
00343 
00344 static bool painterSupportsAntialiasing()
00345 {
00346 #ifdef Q_WS_WIN
00347    // apparently QApplication::desktop()->paintEngine() is null on windows
00348    // but we can assume the paint engine supports antialiasing there, right?
00349    return true;
00350 #else
00351    QPaintEngine* const pe = QApplication::desktop()->paintEngine();
00352    return pe && pe->hasFeature(QPaintEngine::Antialiasing);
00353 #endif
00354 }
00355 
00356 // Taken from KImageEffect. We don't want to link kdecore to kdeui! As long
00357 // as this code is not too big, it doesn't seem much of a problem to me.
00358 
00359 void KIconEffect::toGray(QImage &img, float value)
00360 {
00361     if(value == 0.0)
00362         return;
00363 
00364     KIEImgEdit ii(img);
00365     QRgb *data = ii.data;
00366     QRgb *end = data + ii.pixels;
00367 
00368     unsigned char gray;
00369     if(value == 1.0){
00370         while(data != end){
00371             gray = qGray(*data);
00372             *data = qRgba(gray, gray, gray, qAlpha(*data));
00373             ++data;
00374         }
00375     }
00376     else{
00377         unsigned char val = (unsigned char)(255.0*value);
00378         while(data != end){
00379             gray = qGray(*data);
00380             *data = qRgba((val*gray+(0xFF-val)*qRed(*data)) >> 8,
00381                           (val*gray+(0xFF-val)*qGreen(*data)) >> 8,
00382                           (val*gray+(0xFF-val)*qBlue(*data)) >> 8,
00383                           qAlpha(*data));
00384             ++data;
00385         }
00386     }
00387 }
00388 
00389 void KIconEffect::colorize(QImage &img, const QColor &col, float value)
00390 {
00391     if(value == 0.0)
00392         return;
00393 
00394     KIEImgEdit ii(img);
00395     QRgb *data = ii.data;
00396     QRgb *end = data + ii.pixels;
00397 
00398     float rcol = col.red(), gcol = col.green(), bcol = col.blue();
00399     unsigned char red, green, blue, gray;
00400     unsigned char val = (unsigned char)(255.0*value);
00401     while(data != end){
00402         gray = qGray(*data);
00403         if(gray < 128){
00404             red = static_cast<unsigned char>(rcol/128*gray);
00405             green = static_cast<unsigned char>(gcol/128*gray);
00406             blue = static_cast<unsigned char>(bcol/128*gray);
00407         }
00408         else if(gray > 128){
00409             red = static_cast<unsigned char>((gray-128)*(2-rcol/128)+rcol-1);
00410             green = static_cast<unsigned char>((gray-128)*(2-gcol/128)+gcol-1);
00411             blue = static_cast<unsigned char>((gray-128)*(2-bcol/128)+bcol-1);
00412         }
00413         else{
00414             red = static_cast<unsigned char>(rcol);
00415             green = static_cast<unsigned char>(gcol);
00416             blue = static_cast<unsigned char>(bcol);
00417         }
00418 
00419         *data = qRgba((val*red+(0xFF-val)*qRed(*data)) >> 8,
00420                       (val*green+(0xFF-val)*qGreen(*data)) >> 8,
00421                       (val*blue+(0xFF-val)*qBlue(*data)) >> 8,
00422                       qAlpha(*data));
00423         ++data;
00424     }
00425 }
00426 
00427 void KIconEffect::toMonochrome(QImage &img, const QColor &black,
00428                                const QColor &white, float value)
00429 {
00430     if(value == 0.0)
00431         return;
00432 
00433     KIEImgEdit ii(img);
00434     QRgb *data = ii.data;
00435     QRgb *end = data + ii.pixels;
00436 
00437     // Step 1: determine the average brightness
00438     double values = 0.0, sum = 0.0;
00439     bool grayscale = true;
00440     while(data != end){
00441         sum += qGray(*data)*qAlpha(*data) + 255*(255-qAlpha(*data));
00442         values += 255;
00443         if((qRed(*data) != qGreen(*data) ) || (qGreen(*data) != qBlue(*data)))
00444             grayscale = false;
00445         ++data;
00446     }
00447     double medium = sum/values;
00448 
00449     // Step 2: Modify the image
00450     unsigned char val = (unsigned char)(255.0*value);
00451     int rw = white.red(), gw = white.green(), bw = white.blue();
00452     int rb = black.red(), gb = black.green(), bb = black.blue();
00453     data = ii.data;
00454 
00455     if(grayscale){
00456         while(data != end){
00457             if(qRed(*data) <= medium)
00458                 *data = qRgba((val*rb+(0xFF-val)*qRed(*data)) >> 8,
00459                               (val*gb+(0xFF-val)*qGreen(*data)) >> 8,
00460                               (val*bb+(0xFF-val)*qBlue(*data)) >> 8,
00461                               qAlpha(*data));
00462             else
00463                 *data = qRgba((val*rw+(0xFF-val)*qRed(*data)) >> 8,
00464                               (val*gw+(0xFF-val)*qGreen(*data)) >> 8,
00465                               (val*bw+(0xFF-val)*qBlue(*data)) >> 8,
00466                               qAlpha(*data));
00467             ++data;
00468         }
00469     }
00470     else{
00471         while(data != end){
00472             if(qGray(*data) <= medium) 
00473                 *data = qRgba((val*rb+(0xFF-val)*qRed(*data)) >> 8,
00474                               (val*gb+(0xFF-val)*qGreen(*data)) >> 8,
00475                               (val*bb+(0xFF-val)*qBlue(*data)) >> 8,
00476                               qAlpha(*data));
00477             else
00478                 *data = qRgba((val*rw+(0xFF-val)*qRed(*data)) >> 8,
00479                               (val*gw+(0xFF-val)*qGreen(*data)) >> 8,
00480                               (val*bw+(0xFF-val)*qBlue(*data)) >> 8,
00481                               qAlpha(*data));
00482             ++data;
00483         }
00484     }
00485 }
00486 
00487 void KIconEffect::deSaturate(QImage &img, float value)
00488 {
00489     if(value == 0.0)
00490         return;
00491 
00492     KIEImgEdit ii(img);
00493     QRgb *data = ii.data;
00494     QRgb *end = data + ii.pixels;
00495 
00496     QColor color;
00497     int h, s, v;
00498     while(data != end){
00499         color.setRgb(*data);
00500         color.getHsv(&h, &s, &v);
00501         color.setHsv(h, (int) (s * (1.0 - value) + 0.5), v);
00502     *data = qRgba(color.red(), color.green(), color.blue(),
00503                       qAlpha(*data));
00504         ++data;
00505     }
00506 }
00507 
00508 void KIconEffect::toGamma(QImage &img, float value)
00509 {
00510     KIEImgEdit ii(img);
00511     QRgb *data = ii.data;
00512     QRgb *end = data + ii.pixels;
00513 
00514     float gamma = 1/(2*value+0.5);
00515     while(data != end){
00516         *data = qRgba(static_cast<unsigned char>
00517                       (pow(static_cast<float>(qRed(*data))/255 , gamma)*255),
00518                       static_cast<unsigned char>
00519                       (pow(static_cast<float>(qGreen(*data))/255 , gamma)*255),
00520                       static_cast<unsigned char>
00521                       (pow(static_cast<float>(qBlue(*data))/255 , gamma)*255),
00522                       qAlpha(*data));
00523         ++data;
00524     }
00525 }
00526 
00527 void KIconEffect::semiTransparent(QImage &img)
00528 {
00529     int x, y;
00530     if(img.depth() == 32){
00531         if(img.format() == QImage::Format_ARGB32_Premultiplied)
00532             img = img.convertToFormat(QImage::Format_ARGB32);
00533         int width  = img.width();
00534     int height = img.height();
00535 
00536         if(painterSupportsAntialiasing()){
00537             unsigned char *line;
00538             for(y=0; y<height; ++y){
00539                 if(QSysInfo::ByteOrder == QSysInfo::BigEndian)
00540                     line = img.scanLine(y);
00541                 else
00542                     line = img.scanLine(y) + 3;
00543                 for(x=0; x<width; ++x){
00544                     *line >>= 1;
00545                     line += 4;
00546                 }
00547             }
00548         }
00549         else{
00550             for(y=0; y<height; ++y){
00551                 QRgb* line = (QRgb*)img.scanLine(y);
00552                 for(x=(y%2); x<width; x+=2)
00553                     line[x] &= 0x00ffffff;
00554             }
00555         }
00556     }
00557     else{
00558         if (img.depth() == 8) {
00559             if (painterSupportsAntialiasing()) {
00560                 // not running on 8 bit, we can safely install a new colorTable
00561                 QVector<QRgb> colorTable = img.colorTable();
00562                 for (int i = 0; i < colorTable.size(); ++i) {
00563                     colorTable[i] = (colorTable[i] & 0x00ffffff) | ((colorTable[i] & 0xfe000000) >> 1);
00564                 }
00565                 img.setColorTable(colorTable);
00566                 return;
00567             }
00568         }
00569         // Insert transparent pixel into the clut.
00570         int transColor = -1;
00571 
00572         // search for a color that is already transparent
00573         for(x=0; x<img.numColors(); ++x){
00574             // try to find already transparent pixel
00575             if(qAlpha(img.color(x)) < 127){
00576                 transColor = x;
00577                 break;
00578             }
00579         }
00580 
00581         // FIXME: image must have transparency
00582         if(transColor < 0 || transColor >= img.numColors())
00583             return;
00584 
00585     img.setColor(transColor, 0);
00586         unsigned char *line;
00587         if(img.depth() == 8){
00588             for(y=0; y<img.height(); ++y){
00589                 line = img.scanLine(y);
00590                 for(x=(y%2); x<img.width(); x+=2)
00591                     line[x] = transColor;
00592             }
00593     }
00594         else{
00595             bool setOn = (transColor != 0);
00596             if(img.format() == QImage::Format_MonoLSB){
00597                 for(y=0; y<img.height(); ++y){
00598                     line = img.scanLine(y);
00599                     for(x=(y%2); x<img.width(); x+=2){
00600                         if(!setOn)
00601                             *(line + (x >> 3)) &= ~(1 << (x & 7));
00602                         else
00603                             *(line + (x >> 3)) |= (1 << (x & 7));
00604                     }
00605                 }
00606             }
00607             else{
00608                 for(y=0; y<img.height(); ++y){
00609                     line = img.scanLine(y);
00610                     for(x=(y%2); x<img.width(); x+=2){
00611                         if(!setOn)
00612                             *(line + (x >> 3)) &= ~(1 << (7-(x & 7)));
00613                         else
00614                             *(line + (x >> 3)) |= (1 << (7-(x & 7)));
00615                     }
00616                 }
00617             }
00618         }
00619     }
00620 }
00621 
00622 void KIconEffect::semiTransparent(QPixmap &pix)
00623 {
00624     if (painterSupportsAntialiasing()) {
00625         QImage img=pix.toImage();
00626         semiTransparent(img);
00627         pix = QPixmap::fromImage(img);
00628         return;
00629     }
00630 
00631     QImage img;
00632     if (!pix.mask().isNull())
00633       img = pix.mask().toImage();
00634     else
00635     {
00636         img = QImage(pix.size(), QImage::Format_Mono);
00637         img.fill(1);
00638     }
00639 
00640     for (int y=0; y<img.height(); y++)
00641     {
00642         QRgb* line = (QRgb*)img.scanLine(y);
00643         QRgb pattern = (y % 2) ? 0x55555555 : 0xaaaaaaaa;
00644         for (int x=0; x<(img.width()+31)/32; x++)
00645             line[x] &= pattern;
00646     }
00647     QBitmap mask;
00648     mask = QBitmap::fromImage(img);
00649     pix.setMask(mask);
00650 }
00651 
00652 QImage KIconEffect::doublePixels(const QImage &src) const
00653 {
00654     int w = src.width();
00655     int h = src.height();
00656 
00657     QImage dst( w*2, h*2, src.format() );
00658 
00659     if (src.depth() == 1)
00660     {
00661     kDebug(265) << "image depth 1 not supported\n";
00662     return QImage();
00663     }
00664 
00665     int x, y;
00666     if (src.depth() == 32)
00667     {
00668     QRgb* l1, *l2;
00669     for (y=0; y<h; ++y)
00670     {
00671         l1 = (QRgb*)src.scanLine(y);
00672         l2 = (QRgb*)dst.scanLine(y*2);
00673         for (x=0; x<w; ++x)
00674         {
00675         l2[x*2] = l2[x*2+1] = l1[x];
00676         }
00677         memcpy(dst.scanLine(y*2+1), l2, dst.bytesPerLine());
00678     }
00679     } else
00680     {
00681     for (x=0; x<src.numColors(); ++x)
00682         dst.setColor(x, src.color(x));
00683 
00684     const unsigned char *l1;
00685     unsigned char *l2;
00686     for (y=0; y<h; ++y)
00687     {
00688         l1 = src.scanLine(y);
00689         l2 = dst.scanLine(y*2);
00690         for (x=0; x<w; ++x)
00691         {
00692         l2[x*2] = l1[x];
00693         l2[x*2+1] = l1[x];
00694         }
00695         memcpy(dst.scanLine(y*2+1), l2, dst.bytesPerLine());
00696     }
00697     }
00698     return dst;
00699 }
00700 
00701 void KIconEffect::overlay(QImage &src, QImage &overlay)
00702 {
00703     if (src.depth() != overlay.depth())
00704     {
00705     kDebug(265) << "Image depth src (" << src.depth() << ") != overlay " << "(" << overlay.depth() << ")!\n";
00706     return;
00707     }
00708     if (src.size() != overlay.size())
00709     {
00710     kDebug(265) << "Image size src != overlay\n";
00711     return;
00712     }
00713     if (src.format() == QImage::Format_ARGB32_Premultiplied)
00714         src = src.convertToFormat(QImage::Format_ARGB32);
00715 
00716     if (overlay.format() == QImage::Format_RGB32)
00717     {
00718     kDebug(265) << "Overlay doesn't have alpha buffer!\n";
00719     return;
00720     }
00721     else if (overlay.format() == QImage::Format_ARGB32_Premultiplied)
00722         overlay = overlay.convertToFormat(QImage::Format_ARGB32);
00723 
00724     int i, j;
00725 
00726     // We don't do 1 bpp
00727 
00728     if (src.depth() == 1)
00729     {
00730     kDebug(265) << "1bpp not supported!\n";
00731     return;
00732     }
00733 
00734     // Overlay at 8 bpp doesn't use alpha blending
00735 
00736     if (src.depth() == 8)
00737     {
00738     if (src.numColors() + overlay.numColors() > 255)
00739     {
00740         kDebug(265) << "Too many colors in src + overlay!\n";
00741         return;
00742     }
00743 
00744     // Find transparent pixel in overlay
00745     int trans;
00746     for (trans=0; trans<overlay.numColors(); trans++)
00747     {
00748         if (qAlpha(overlay.color(trans)) == 0)
00749         {
00750         kDebug(265) << "transparent pixel found at " << trans << "\n";
00751         break;
00752         }
00753     }
00754     if (trans == overlay.numColors())
00755     {
00756         kDebug(265) << "transparent pixel not found!\n";
00757         return;
00758     }
00759 
00760     // Merge color tables
00761     int nc = src.numColors();
00762     src.setNumColors(nc + overlay.numColors());
00763     for (i=0; i<overlay.numColors(); ++i)
00764     {
00765         src.setColor(nc+i, overlay.color(i));
00766     }
00767 
00768     // Overwrite nontransparent pixels.
00769     unsigned char *oline, *sline;
00770     for (i=0; i<src.height(); ++i)
00771     {
00772         oline = overlay.scanLine(i);
00773         sline = src.scanLine(i);
00774         for (j=0; j<src.width(); ++j)
00775         {
00776         if (oline[j] != trans)
00777             sline[j] = oline[j]+nc;
00778         }
00779     }
00780     }
00781 
00782     // Overlay at 32 bpp does use alpha blending
00783 
00784     if (src.depth() == 32)
00785     {
00786     QRgb* oline, *sline;
00787     int r1, g1, b1, a1;
00788     int r2, g2, b2, a2;
00789 
00790     for (i=0; i<src.height(); ++i)
00791     {
00792         oline = (QRgb*)overlay.scanLine(i);
00793         sline = (QRgb*)src.scanLine(i);
00794 
00795         for (j=0; j<src.width(); ++j)
00796         {
00797         r1 = qRed(oline[j]);
00798         g1 = qGreen(oline[j]);
00799         b1 = qBlue(oline[j]);
00800         a1 = qAlpha(oline[j]);
00801 
00802         r2 = qRed(sline[j]);
00803         g2 = qGreen(sline[j]);
00804         b2 = qBlue(sline[j]);
00805         a2 = qAlpha(sline[j]);
00806 
00807         r2 = (a1 * r1 + (0xff - a1) * r2) >> 8;
00808         g2 = (a1 * g1 + (0xff - a1) * g2) >> 8;
00809         b2 = (a1 * b1 + (0xff - a1) * b2) >> 8;
00810         a2 = qMax(a1, a2);
00811 
00812         sline[j] = qRgba(r2, g2, b2, a2);
00813         }
00814     }
00815     }
00816 
00817     return;
00818 }
00819 

KDEUI

Skip menu "KDEUI"
  • Main Page
  • Modules
  • 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
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
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