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

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
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
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