30 #include <QtCore/QSysInfo>
31 #include <QtGui/QApplication>
32 #include <QtGui/QPaintEngine>
33 #include <QtGui/QDesktopWidget>
34 #include <QtCore/QCharRef>
35 #include <QtCore/QMutableStringListIterator>
36 #include <QtGui/QBitmap>
37 #include <QtGui/QPixmap>
38 #include <QtGui/QImage>
39 #include <QtGui/QColor>
40 #include <QtGui/QWidget>
41 #include <QtGui/QPainter>
53 class KIconEffectPrivate
65 :d(new KIconEffectPrivate)
85 groups +=
"MainToolbar";
95 QStringList::ConstIterator it, it2;
98 QString _desaturate(
"desaturate");
101 QString _tomonochrome(
"tomonochrome");
103 for (it=groups.constBegin(), i=0; it!=groups.constEnd(); ++it, ++i)
110 d->trans[i][0] =
false;
111 d->trans[i][1] =
false;
112 d->trans[i][2] =
true;
113 d->value[i][0] = 1.0;
114 d->value[i][1] = ((i==0)||(i==4)) ? 0.7 : 1.0;
115 d->value[i][2] = 1.0;
116 d->color[i][0] =
QColor(144,128,248);
117 d->color[i][1] =
QColor(169,156,255);
118 d->color[i][2] =
QColor(34,202,0);
119 d->color2[i][0] =
QColor(0,0,0);
120 d->color2[i][1] =
QColor(0,0,0);
121 d->color2[i][2] =
QColor(0,0,0);
124 for (it2=states.constBegin(), j=0; it2!=states.constEnd(); ++it2, ++j)
129 else if (tmp == _colorize)
131 else if (tmp == _desaturate)
133 else if (tmp == _togamma)
135 else if (tmp == _tomonochrome)
137 else if (tmp == _none)
142 d->effect[i][j] = effect;
143 d->value[i][j] = cg.
readEntry(*it2 +
"Value", 0.0);
146 d->trans[i][j] = cg.
readEntry(*it2 +
"SemiTransparent",
false);
159 return d->effect[group][state] !=
NoEffect;
169 QString cached = d->key[group][state];
170 if (cached.isEmpty())
173 cached = tmp.setNum(d->effect[group][state]);
175 cached += tmp.setNum(d->value[group][state]);
177 cached += d->trans[group][state] ? QLatin1String(
"trans")
178 : QLatin1String(
"notrans");
182 cached += d->color[group][state].name();
187 cached += d->color2[group][state].name();
190 d->key[group][state] = cached;
200 kDebug(265) <<
"Illegal icon state: " << state <<
"\n";
205 kDebug(265) <<
"Illegal icon group: " << group <<
"\n";
208 return apply(image, d->effect[group][state], d->value[group][state],
209 d->color[group][state], d->color2[group][state], d->trans[group][state]);
213 const QColor &col,
bool trans)
const
215 return apply(image, effect, value, col,
220 const QColor &col,
const QColor &col2,
bool trans)
const
225 kDebug(265) <<
"Illegal icon effect: " << effect <<
"\n";
230 else if (value < 0.0)
261 kDebug(265) <<
"Illegal icon state: " << state <<
"\n";
266 kDebug(265) <<
"Illegal icon group: " << group <<
"\n";
269 return apply(pixmap, d->effect[group][state], d->value[group][state],
270 d->color[group][state], d->color2[group][state], d->trans[group][state]);
274 const QColor &col,
bool trans)
const
276 return apply(pixmap, effect, value, col,
281 const QColor &col,
const QColor &col2,
bool trans)
const
287 kDebug(265) <<
"Illegal icon effect: " << effect <<
"\n";
291 if ((trans ==
true) && (effect ==
NoEffect))
298 QImage tmpImg = pixmap.toImage();
299 tmpImg =
apply(tmpImg, effect, value, col, col2, trans);
300 result = QPixmap::fromImage(tmpImg);
311 QVector <QRgb> colors;
315 KIEImgEdit(QImage& _img):img(_img)
321 if ((img.format() != QImage::Format_ARGB32) &&
322 (img.format() != QImage::Format_RGB32))
324 img = img.convertToFormat(QImage::Format_ARGB32);
326 data = (
unsigned int*)img.bits();
327 pixels = img.width()*img.height();
331 pixels = img.numColors();
332 colors = img.colorTable();
333 data = (
unsigned int*)colors.data();
339 if (img.depth() <= 8)
340 img.setColorTable(colors);
351 QPaintEngine*
const pe = QApplication::desktop()->paintEngine();
352 return pe && pe->hasFeature(QPaintEngine::Antialiasing);
365 QRgb *data = ii.data;
366 QRgb *
end = data + ii.pixels;
372 *data = qRgba(gray, gray, gray, qAlpha(*data));
377 unsigned char val = (
unsigned char)(255.0*value);
380 *data = qRgba((val*gray+(0xFF-val)*qRed(*data)) >> 8,
381 (val*gray+(0xFF-val)*qGreen(*data)) >> 8,
382 (val*gray+(0xFF-val)*qBlue(*data)) >> 8,
395 QRgb *data = ii.data;
396 QRgb *
end = data + ii.pixels;
398 float rcol = col.red(), gcol = col.green(), bcol = col.blue();
399 unsigned char red, green, blue, gray;
400 unsigned char val = (
unsigned char)(255.0*value);
404 red =
static_cast<unsigned char>(rcol/128*gray);
405 green =
static_cast<unsigned char>(gcol/128*gray);
406 blue =
static_cast<unsigned char>(bcol/128*gray);
409 red =
static_cast<unsigned char>((gray-128)*(2-rcol/128)+rcol-1);
410 green =
static_cast<unsigned char>((gray-128)*(2-gcol/128)+gcol-1);
411 blue =
static_cast<unsigned char>((gray-128)*(2-bcol/128)+bcol-1);
414 red =
static_cast<unsigned char>(rcol);
415 green =
static_cast<unsigned char>(gcol);
416 blue =
static_cast<unsigned char>(bcol);
419 *data = qRgba((val*red+(0xFF-val)*qRed(*data)) >> 8,
420 (val*green+(0xFF-val)*qGreen(*data)) >> 8,
421 (val*blue+(0xFF-val)*qBlue(*data)) >> 8,
428 const QColor &white,
float value)
434 QRgb *data = ii.data;
435 QRgb *
end = data + ii.pixels;
438 double values = 0.0, sum = 0.0;
439 bool grayscale =
true;
441 sum += qGray(*data)*qAlpha(*data) + 255*(255-qAlpha(*data));
443 if((qRed(*data) != qGreen(*data) ) || (qGreen(*data) != qBlue(*data)))
447 double medium = sum/values;
450 unsigned char val = (
unsigned char)(255.0*value);
451 int rw = white.red(), gw = white.green(), bw = white.blue();
452 int rb = black.red(), gb = black.green(), bb = black.blue();
457 if(qRed(*data) <= medium)
458 *data = qRgba((val*rb+(0xFF-val)*qRed(*data)) >> 8,
459 (val*gb+(0xFF-val)*qGreen(*data)) >> 8,
460 (val*bb+(0xFF-val)*qBlue(*data)) >> 8,
463 *data = qRgba((val*rw+(0xFF-val)*qRed(*data)) >> 8,
464 (val*gw+(0xFF-val)*qGreen(*data)) >> 8,
465 (val*bw+(0xFF-val)*qBlue(*data)) >> 8,
472 if(qGray(*data) <= medium)
473 *data = qRgba((val*rb+(0xFF-val)*qRed(*data)) >> 8,
474 (val*gb+(0xFF-val)*qGreen(*data)) >> 8,
475 (val*bb+(0xFF-val)*qBlue(*data)) >> 8,
478 *data = qRgba((val*rw+(0xFF-val)*qRed(*data)) >> 8,
479 (val*gw+(0xFF-val)*qGreen(*data)) >> 8,
480 (val*bw+(0xFF-val)*qBlue(*data)) >> 8,
493 QRgb *data = ii.data;
494 QRgb *
end = data + ii.pixels;
500 color.getHsv(&h, &s, &v);
501 color.setHsv(h, (
int) (s * (1.0 - value) + 0.5), v);
502 *data = qRgba(color.red(), color.green(), color.blue(),
511 QRgb *data = ii.data;
512 QRgb *
end = data + ii.pixels;
514 float gamma = 1/(2*value+0.5);
516 *data = qRgba(static_cast<unsigned char>
517 (pow(static_cast<float>(qRed(*data))/255 , gamma)*255),
518 static_cast<unsigned char>
519 (pow(static_cast<float>(qGreen(*data))/255 , gamma)*255),
520 static_cast<unsigned char>
521 (pow(static_cast<float>(qBlue(*data))/255 , gamma)*255),
530 if(img.depth() == 32){
531 if(img.format() == QImage::Format_ARGB32_Premultiplied)
532 img = img.convertToFormat(QImage::Format_ARGB32);
533 int width = img.width();
534 int height = img.height();
538 for(y=0; y<height; ++y){
539 if(QSysInfo::ByteOrder == QSysInfo::BigEndian)
540 line = img.scanLine(y);
542 line = img.scanLine(y) + 3;
543 for(x=0; x<width; ++x){
550 for(y=0; y<height; ++y){
551 QRgb* line = (QRgb*)img.scanLine(y);
552 for(x=(y%2); x<width; x+=2)
553 line[x] &= 0x00ffffff;
558 if (img.depth() == 8) {
561 QVector<QRgb> colorTable = img.colorTable();
562 for (
int i = 0; i < colorTable.size(); ++i) {
563 colorTable[i] = (colorTable[i] & 0x00ffffff) | ((colorTable[i] & 0xfe000000) >> 1);
565 img.setColorTable(colorTable);
573 for(x=0; x<img.numColors(); ++x){
575 if(qAlpha(img.color(x)) < 127){
582 if(transColor < 0 || transColor >= img.numColors())
585 img.setColor(transColor, 0);
587 if(img.depth() == 8){
588 for(y=0; y<img.height(); ++y){
589 line = img.scanLine(y);
590 for(x=(y%2); x<img.width(); x+=2)
591 line[x] = transColor;
595 bool setOn = (transColor != 0);
596 if(img.format() == QImage::Format_MonoLSB){
597 for(y=0; y<img.height(); ++y){
598 line = img.scanLine(y);
599 for(x=(y%2); x<img.width(); x+=2){
601 *(line + (x >> 3)) &= ~(1 << (x & 7));
603 *(line + (x >> 3)) |= (1 << (x & 7));
608 for(y=0; y<img.height(); ++y){
609 line = img.scanLine(y);
610 for(x=(y%2); x<img.width(); x+=2){
612 *(line + (x >> 3)) &= ~(1 << (7-(x & 7)));
614 *(line + (x >> 3)) |= (1 << (7-(x & 7)));
625 QImage img=pix.toImage();
627 pix = QPixmap::fromImage(img);
632 if (!pix.mask().isNull())
633 img = pix.mask().toImage();
636 img = QImage(pix.size(), QImage::Format_Mono);
640 for (
int y=0; y<img.height(); y++)
642 QRgb* line = (QRgb*)img.scanLine(y);
643 QRgb pattern = (y % 2) ? 0x55555555 : 0xaaaaaaaa;
644 for (
int x=0; x<(img.width()+31)/32; x++)
648 mask = QBitmap::fromImage(img);
655 int h = src.height();
657 QImage dst( w*2, h*2, src.format() );
659 if (src.depth() == 1)
661 kDebug(265) <<
"image depth 1 not supported\n";
666 if (src.depth() == 32)
671 l1 = (QRgb*)src.scanLine(y);
672 l2 = (QRgb*)dst.scanLine(y*2);
675 l2[x*2] = l2[x*2+1] = l1[x];
677 memcpy(dst.scanLine(y*2+1), l2, dst.bytesPerLine());
681 for (x=0; x<src.numColors(); ++x)
682 dst.setColor(x, src.color(x));
684 const unsigned char *l1;
688 l1 = src.scanLine(y);
689 l2 = dst.scanLine(y*2);
695 memcpy(dst.scanLine(y*2+1), l2, dst.bytesPerLine());
703 if (src.depth() != overlay.depth())
705 kDebug(265) <<
"Image depth src (" << src.depth() <<
") != overlay " <<
"(" << overlay.depth() <<
")!\n";
708 if (src.size() != overlay.size())
710 kDebug(265) <<
"Image size src != overlay\n";
713 if (src.format() == QImage::Format_ARGB32_Premultiplied)
714 src = src.convertToFormat(QImage::Format_ARGB32);
716 if (overlay.format() == QImage::Format_RGB32)
718 kDebug(265) <<
"Overlay doesn't have alpha buffer!\n";
721 else if (overlay.format() == QImage::Format_ARGB32_Premultiplied)
722 overlay = overlay.convertToFormat(QImage::Format_ARGB32);
728 if (src.depth() == 1)
730 kDebug(265) <<
"1bpp not supported!\n";
736 if (src.depth() == 8)
738 if (src.numColors() + overlay.numColors() > 255)
740 kDebug(265) <<
"Too many colors in src + overlay!\n";
746 for (trans=0; trans<overlay.numColors(); trans++)
748 if (qAlpha(overlay.color(trans)) == 0)
750 kDebug(265) <<
"transparent pixel found at " << trans <<
"\n";
754 if (trans == overlay.numColors())
756 kDebug(265) <<
"transparent pixel not found!\n";
761 int nc = src.numColors();
762 src.setNumColors(nc + overlay.numColors());
763 for (i=0; i<overlay.numColors(); ++i)
765 src.setColor(nc+i, overlay.color(i));
769 unsigned char *oline, *sline;
770 for (i=0; i<src.height(); ++i)
772 oline = overlay.scanLine(i);
773 sline = src.scanLine(i);
774 for (j=0; j<src.width(); ++j)
776 if (oline[j] != trans)
777 sline[j] = oline[j]+nc;
784 if (src.depth() == 32)
790 for (i=0; i<src.height(); ++i)
792 oline = (QRgb*)overlay.scanLine(i);
793 sline = (QRgb*)src.scanLine(i);
795 for (j=0; j<src.width(); ++j)
798 g1 = qGreen(oline[j]);
799 b1 = qBlue(oline[j]);
800 a1 = qAlpha(oline[j]);
803 g2 = qGreen(sline[j]);
804 b2 = qBlue(sline[j]);
805 a2 = qAlpha(sline[j]);
807 r2 = (a1 * r1 + (0xff - a1) * r2) >> 8;
808 g2 = (a1 * g1 + (0xff - a1) * g2) >> 8;
809 b2 = (a1 * b1 + (0xff - a1) * b2) >> 8;
812 sline[j] = qRgba(r2, g2, b2, a2);
static void semiTransparent(QImage &image)
Renders an image semi-transparent.
static QDebug kDebug(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
static void toMonochrome(QImage &image, const QColor &black, const QColor &white, float value)
Produces a monochrome icon with a given foreground and background color.
KSharedConfigPtr config()
static void overlay(QImage &src, QImage &overlay)
Overlays an image with an other image.
KIconEffect()
Create a new KIconEffect.
static void colorize(QImage &image, const QColor &col, float value)
Colorizes an image with a specific color.
static void deSaturate(QImage &image, float value)
Desaturates an image.
void init()
Rereads configuration.
static void toGamma(QImage &image, float value)
Changes the gamma value of an image.
Views; for example, frames, input fields, etc.
Last state (last constant)
A set of methods used to work with colors.
QString fingerprint(int group, int state) const
Returns a fingerprint for the effect by encoding the given group and state into a QString...
static bool painterSupportsAntialiasing()
bool hasEffect(int group, int state) const
Tests whether an effect has been configured for the given icon group.
static void toGray(QImage &image, float value)
Tints an image gray.
QImage apply(const QImage &src, int group, int state) const
Applies an effect to an image.
const KShortcut & end()
Goto end of the document.
T readEntry(const QString &key, const T &aDefault) const
QImage doublePixels(const QImage &src) const
Returns an image twice as large, consisting of 2x2 pixels.