13#include "kiconeffect.h"
15#include "kiconloader.h"
17#include <KColorScheme>
23#include <qplatformdefs.h>
27class KIconEffectPrivate
46#if KICONTHEMES_BUILD_DEPRECATED_SINCE(6, 5)
48 : d(new KIconEffectPrivate)
54KIconEffect::~KIconEffect() =
default;
56#if KICONTHEMES_BUILD_DEPRECATED_SINCE(6, 5)
63 groups += QStringLiteral(
"Desktop");
64 groups += QStringLiteral(
"Toolbar");
65 groups += QStringLiteral(
"MainToolbar");
66 groups += QStringLiteral(
"Small");
67 groups += QStringLiteral(
"Panel");
68 groups += QStringLiteral(
"Dialog");
71 states += QStringLiteral(
"Default");
72 states += QStringLiteral(
"Active");
73 states += QStringLiteral(
"Disabled");
92#if KICONTHEMES_BUILD_DEPRECATED_SINCE(6, 5)
100 return d->effect[group][state] != NoEffect;
104#if KICONTHEMES_BUILD_DEPRECATED_SINCE(6, 5)
112 QString cached = d->key[group][state];
115 cached = tmp.
setNum(d->effect[group][state]);
117 cached += tmp.
setNum(d->value[group][state]);
121 d->key[group][state] = cached;
128#if KICONTHEMES_BUILD_DEPRECATED_SINCE(6, 5)
132 qCWarning(KICONTHEMES) <<
"Invalid icon state:" << state <<
", should be one of KIconLoader::States";
136 qCWarning(KICONTHEMES) <<
"Invalid icon group:" << group <<
", should be one of KIconLoader::Group";
139 return apply(image, d->effect[group][state], d->value[group][state],
QColor(),
QColor(), d->trans[group][state]);
143#if KICONTHEMES_BUILD_DEPRECATED_SINCE(6, 5)
150#if KICONTHEMES_BUILD_DEPRECATED_SINCE(6, 5)
154 if (effect >= LastEffect) {
155 qCWarning(KICONTHEMES) <<
"Invalid icon effect:" << effect <<
", should be one of KIconLoader::Effects";
160 }
else if (value < 0.0) {
187#if KICONTHEMES_BUILD_DEPRECATED_SINCE(6, 5)
191 qCWarning(KICONTHEMES) <<
"Invalid icon state:" << state <<
", should be one of KIconLoader::States";
195 qCWarning(KICONTHEMES) <<
"Invalid icon group:" << group <<
", should be one of KIconLoader::Group";
198 return apply(pixmap, d->effect[group][state], d->value[group][state],
QColor(),
QColor(), d->trans[group][state]);
202#if KICONTHEMES_BUILD_DEPRECATED_SINCE(6, 5)
209#if KICONTHEMES_BUILD_DEPRECATED_SINCE(6, 5)
214 if (effect >= LastEffect) {
215 qCWarning(KICONTHEMES) <<
"Invalid icon effect:" << effect <<
", should be one of KIconLoader::Effects";
219 if ((trans ==
true) && (effect == NoEffect)) {
222 }
else if (effect != NoEffect) {
224 tmpImg =
apply(tmpImg, effect, value, col, col2, trans);
243 if (img.
depth() > 8) {
246 if ((img.format() != QImage::Format_ARGB32)
247 && (img.format() != QImage::Format_RGB32)) {
248 img.convertTo(QImage::Format_ARGB32);
250 data = (
unsigned int *)img.
bits();
255 data = (
unsigned int *)colors.
data();
261 if (img.
depth() <= 8) {
266 KIEImgEdit(
const KIEImgEdit &) =
delete;
267 KIEImgEdit &operator=(
const KIEImgEdit &) =
delete;
280 QRgb *data = ii.data;
281 QRgb *end = data + ii.pixels;
285 while (data != end) {
287 *data = qRgba(gray, gray, gray, qAlpha(*data));
291 unsigned char val = (
unsigned char)(255.0 * value);
292 while (data != end) {
294 *data = qRgba((val * gray + (0xFF - val) * qRed(*data)) >> 8,
295 (val * gray + (0xFF - val) * qGreen(*data)) >> 8,
296 (val * gray + (0xFF - val) * qBlue(*data)) >> 8,
310 QRgb *data = ii.data;
311 QRgb *end = data + ii.pixels;
313 float rcol = col.
red();
314 float gcol = col.
green();
315 float bcol = col.
blue();
320 unsigned char val = (
unsigned char)(255.0 * value);
321 while (data != end) {
324 red =
static_cast<unsigned char>(rcol / 128 * gray);
325 green =
static_cast<unsigned char>(gcol / 128 * gray);
326 blue =
static_cast<unsigned char>(bcol / 128 * gray);
327 }
else if (gray > 128) {
328 red =
static_cast<unsigned char>((gray - 128) * (2 - rcol / 128) + rcol - 1);
329 green =
static_cast<unsigned char>((gray - 128) * (2 - gcol / 128) + gcol - 1);
330 blue =
static_cast<unsigned char>((gray - 128) * (2 - bcol / 128) + bcol - 1);
332 red =
static_cast<unsigned char>(rcol);
333 green =
static_cast<unsigned char>(gcol);
334 blue =
static_cast<unsigned char>(bcol);
337 *data = qRgba((val * red + (0xFF - val) * qRed(*data)) >> 8,
338 (val * green + (0xFF - val) * qGreen(*data)) >> 8,
339 (val * blue + (0xFF - val) * qBlue(*data)) >> 8,
352 QRgb *data = ii.data;
353 QRgb *end = data + ii.pixels;
358 bool grayscale =
true;
359 while (data != end) {
360 sum += qGray(*data) * qAlpha(*data) + 255 * (255 - qAlpha(*data));
362 if ((qRed(*data) != qGreen(*data)) || (qGreen(*data) != qBlue(*data))) {
367 double medium = sum / values;
370 unsigned char val = (
unsigned char)(255.0 * value);
371 int rw = white.red();
372 int gw = white.green();
373 int bw = white.blue();
374 int rb = black.red();
375 int gb = black.green();
376 int bb = black.blue();
380 while (data != end) {
381 if (qRed(*data) <= medium) {
382 *data = qRgba((val * rb + (0xFF - val) * qRed(*data)) >> 8,
383 (val * gb + (0xFF - val) * qGreen(*data)) >> 8,
384 (val * bb + (0xFF - val) * qBlue(*data)) >> 8,
387 *data = qRgba((val * rw + (0xFF - val) * qRed(*data)) >> 8,
388 (val * gw + (0xFF - val) * qGreen(*data)) >> 8,
389 (val * bw + (0xFF - val) * qBlue(*data)) >> 8,
395 while (data != end) {
396 if (qGray(*data) <= medium) {
397 *data = qRgba((val * rb + (0xFF - val) * qRed(*data)) >> 8,
398 (val * gb + (0xFF - val) * qGreen(*data)) >> 8,
399 (val * bb + (0xFF - val) * qBlue(*data)) >> 8,
402 *data = qRgba((val * rw + (0xFF - val) * qRed(*data)) >> 8,
403 (val * gw + (0xFF - val) * qGreen(*data)) >> 8,
404 (val * bw + (0xFF - val) * qBlue(*data)) >> 8,
419 QRgb *data = ii.data;
420 QRgb *end = data + ii.pixels;
426 while (data != end) {
429 color.
setHsv(h, (
int)(s * (1.0 - value) + 0.5), v);
430 *data = qRgba(color.
red(), color.
green(), color.
blue(), qAlpha(*data));
438 QRgb *data = ii.data;
439 QRgb *end = data + ii.pixels;
441 float gamma = 1 / (2 * value + 0.5);
442 while (data != end) {
443 *data = qRgba(
static_cast<unsigned char>(pow(
static_cast<float>(qRed(*data)) / 255, gamma) * 255),
444 static_cast<unsigned char>(pow(
static_cast<float>(qGreen(*data)) / 255, gamma) * 255),
445 static_cast<unsigned char>(pow(
static_cast<float>(qBlue(*data)) / 255, gamma) * 255),
453 if (img.
depth() == 32) {
457 int width = img.
width();
458 int height = img.
height();
461 for (
int y = 0; y < height; ++y) {
467 for (
int x = 0; x < width; ++x) {
472 }
else if (img.
depth() == 8) {
475 for (
int i = 0; i < colorTable.
size(); ++i) {
476 colorTable[i] = (colorTable[i] & 0x00ffffff) | ((colorTable[i] & 0xfe000000) >> 1);
486 if (qAlpha(img.
color(x)) < 127) {
493 if (transColor < 0 || transColor >= img.
colorCount()) {
499 if (img.
depth() == 8) {
500 for (
int y = 0; y < img.
height(); ++y) {
502 for (
int x = (y % 2); x < img.
width(); x += 2) {
503 line[x] = transColor;
507 const bool setOn = (transColor != 0);
509 for (
int y = 0; y < img.
height(); ++y) {
511 for (
int x = (y % 2); x < img.
width(); x += 2) {
513 *(line + (x >> 3)) &= ~(1 << (x & 7));
515 *(line + (x >> 3)) |= (1 << (x & 7));
520 for (
int y = 0; y < img.
height(); ++y) {
522 for (
int x = (y % 2); x < img.
width(); x += 2) {
524 *(line + (x >> 3)) &= ~(1 << (7 - (x & 7)));
526 *(line + (x >> 3)) |= (1 << (7 - (x & 7)));
549 if (src.
depth() == 1) {
550 qWarning() <<
"image depth 1 not supported";
556 if (src.
depth() == 32) {
559 for (y = 0; y < h; ++y) {
562 for (x = 0; x < w; ++x) {
563 l2[x * 2] = l2[x * 2 + 1] = l1[x];
572 const unsigned char *l1;
574 for (y = 0; y < h; ++y) {
577 for (x = 0; x < w; ++x) {
579 l2[x * 2 + 1] = l1[x];
590 qWarning() <<
"Image depth src (" << src.
depth() <<
") != overlay "
591 <<
"(" <<
overlay.depth() <<
")!";
595 qWarning() <<
"Image size src != overlay";
603 qWarning() <<
"Overlay doesn't have alpha buffer!";
614 if (src.
depth() == 1) {
615 qWarning() <<
"1bpp not supported!";
621 if (src.
depth() == 8) {
623 qWarning() <<
"Too many colors in src + overlay!";
629 for (trans = 0; trans <
overlay.colorCount(); trans++) {
630 if (qAlpha(
overlay.color(trans)) == 0) {
631 qWarning() <<
"transparent pixel found at " << trans;
635 if (trans ==
overlay.colorCount()) {
636 qWarning() <<
"transparent pixel not found!";
643 for (i = 0; i <
overlay.colorCount(); ++i) {
648 unsigned char *oline;
649 unsigned char *sline;
650 for (i = 0; i < src.
height(); ++i) {
653 for (j = 0; j < src.
width(); ++j) {
654 if (oline[j] != trans) {
655 sline[j] = oline[j] + nc;
663 if (src.
depth() == 32) {
675 for (i = 0; i < src.
height(); ++i) {
676 oline = (QRgb *)
overlay.scanLine(i);
679 for (j = 0; j < src.
width(); ++j) {
681 g1 = qGreen(oline[j]);
682 b1 = qBlue(oline[j]);
683 a1 = qAlpha(oline[j]);
686 g2 = qGreen(sline[j]);
687 b2 = qBlue(sline[j]);
688 a2 = qAlpha(sline[j]);
690 r2 = (a1 * r1 + (0xff - a1) * r2) >> 8;
691 g2 = (a1 * g1 + (0xff - a1) * g2) >> 8;
692 b2 = (a1 * b1 + (0xff - a1) * b2) >> 8;
695 sline[j] = qRgba(r2, g2, b2, a2);
QString fingerprint(int group, int state) const
Returns a fingerprint for the effect by encoding the given group and state into a QString.
static void toDisabled(QImage &image)
Applies a disabled effect.
static void overlay(QImage &src, QImage &overlay)
Overlays an image with an other image.
QImage doublePixels(const QImage &src) const
Returns an image twice as large, consisting of 2x2 pixels.
static void toGray(QImage &image, float value)
Tints an image gray.
static void colorize(QImage &image, const QColor &col, float value)
Colorizes an image with a specific color.
static void toActive(QImage &image)
Applies an effect for an icon that is in an 'active' state.
void init()
Rereads configuration.
static void semiTransparent(QImage &image)
Renders an image semi-transparent.
KIconEffect()
Create a new KIconEffect.
static void toGamma(QImage &image, float value)
Changes the gamma value of an image.
static void toMonochrome(QImage &image, const QColor &black, const QColor &white, float value)
Produces a monochrome icon with a given foreground and background color.
bool hasEffect(int group, int state) const
Tests whether an effect has been configured for the given icon group.
QImage apply(const QImage &src, int group, int state) const
Applies an effect to an image.
static void deSaturate(QImage &image, float value)
Desaturates an image.
@ Panel
Panel (Plasma Taskbar) icons.
@ ActiveState
Icon is active.
@ DisabledState
Icon is disabled.
@ LastState
Last state (last constant)
@ DefaultState
The default state.
void getHsv(int *h, int *s, int *v, int *a) const const
void setHsv(int h, int s, int v, int a)
qsizetype bytesPerLine() const const
QRgb color(int i) const const
int colorCount() const const
QList< QRgb > colorTable() const const
void convertTo(Format format, Qt::ImageConversionFlags flags)
void setColor(int index, QRgb colorValue)
void setColorCount(int colorCount)
void setColorTable(const QList< QRgb > &colors)
const_iterator constBegin() const const
const_iterator constEnd() const const
qsizetype size() const const
QPixmap fromImage(QImage &&image, Qt::ImageConversionFlags flags)
QImage toImage() const const
bool isEmpty() const const
QString & setNum(double n, char format, int precision)