133 lines
3.7 KiB
C
133 lines
3.7 KiB
C
|
#pragma once
|
||
|
|
||
|
#include "../mischelpers_global.h"
|
||
|
|
||
|
#include <QGraphicsColorizeEffect>
|
||
|
#include <QGraphicsPixmapItem>
|
||
|
#include <QGraphicsScene>
|
||
|
#include <QPainter>
|
||
|
#include "Common.h"
|
||
|
|
||
|
class MISCHELPERS_EXPORT CNeonEffect : public QGraphicsColorizeEffect
|
||
|
{
|
||
|
Q_OBJECT
|
||
|
public:
|
||
|
CNeonEffect(float blurRadius = 5.0, int glow = 2, QObject* parent = nullptr) : QGraphicsColorizeEffect(parent)
|
||
|
{
|
||
|
_blurRadius = blurRadius;
|
||
|
_glow = glow;
|
||
|
_hue = 0;
|
||
|
}
|
||
|
~CNeonEffect() {}
|
||
|
|
||
|
int glow() const { return _glow; }
|
||
|
float blurRadius() const { return _blurRadius; }
|
||
|
int hue() const { return _hue; }
|
||
|
QColor glowColor() const { return _color; }
|
||
|
|
||
|
public slots:
|
||
|
void setGlow(int glow) {
|
||
|
if (_glow == glow)
|
||
|
return;
|
||
|
_glow = std::max(1, std::min(glow, 10));
|
||
|
update();
|
||
|
}
|
||
|
void setBlurRadius(float radius) {
|
||
|
if (_blurRadius == radius)
|
||
|
return;
|
||
|
_blurRadius = std::max(1.0F, radius);
|
||
|
update();
|
||
|
}
|
||
|
void setHue(int hue) {
|
||
|
if (_hue == hue)
|
||
|
return;
|
||
|
_hue = hue;
|
||
|
update();
|
||
|
}
|
||
|
void setGlowColor(const QColor& color) {
|
||
|
if (_color == color)
|
||
|
return;
|
||
|
_color = color;
|
||
|
update();
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
virtual void draw(QPainter* painter)
|
||
|
{
|
||
|
QPoint offset;
|
||
|
auto pm = sourcePixmap(Qt::LogicalCoordinates, &offset, PadToEffectiveBoundingRect);
|
||
|
if (pm.isNull())
|
||
|
return;
|
||
|
|
||
|
if (!_color.isValid() && _hue != 0) {
|
||
|
QImage img = pm.toImage();
|
||
|
for (QRgb* c = (QRgb*)img.bits(); c != (QRgb*)(img.bits() + img.sizeInBytes()); c++) {
|
||
|
*c = (*c & 0xFF000000) | (change_hsv_c(*c & 0x00FFFFFF, float(_hue), 2, 1) & 0x00FFFFFF);
|
||
|
}
|
||
|
pm = QPixmap::fromImage(img);
|
||
|
}
|
||
|
|
||
|
|
||
|
// use a double sized image to increase the blur factor
|
||
|
auto scaledSize = QSize(pm.width() * 2, pm.height() * 2);
|
||
|
auto blurImage = QImage(scaledSize, QImage::Format_ARGB32_Premultiplied);
|
||
|
blurImage.fill(0);
|
||
|
QPainter blurPainter;
|
||
|
blurPainter.begin(&blurImage);
|
||
|
blurPainter.drawPixmap(0, 0, pm.scaled(scaledSize, Qt::KeepAspectRatio, Qt::SmoothTransformation));
|
||
|
blurPainter.end();
|
||
|
|
||
|
// apply the blurred effect on the image
|
||
|
QGraphicsBlurEffect* blur = new QGraphicsBlurEffect();
|
||
|
blur->setBlurRadius(_blurRadius);
|
||
|
//QGraphicsDropShadowEffect *blur = new QGraphicsDropShadowEffect;
|
||
|
//blur->setColor(QColor(40,40,40,245));
|
||
|
//blur->setOffset(0,10);
|
||
|
//blur->setBlurRadius(_blurRadius);
|
||
|
blurImage = applyEffectToImage(blurImage, blur);
|
||
|
|
||
|
if (_color.isValid()) {
|
||
|
// start the painter that will use the previous image as alpha
|
||
|
QPainter tmpPainter;
|
||
|
tmpPainter.begin(&blurImage);
|
||
|
// using SourceIn composition mode we use the existing alpha values
|
||
|
// to paint over
|
||
|
tmpPainter.setCompositionMode(tmpPainter.CompositionMode_SourceIn);
|
||
|
//auto color = this->color();
|
||
|
QColor color = _color;
|
||
|
color.setAlpha(color.alpha() * strength());
|
||
|
// fill using the color
|
||
|
tmpPainter.fillRect(QRect(pm.rect().left() * 2, pm.rect().top() * 2, pm.rect().width() * 2, pm.rect().height() * 2), color);
|
||
|
tmpPainter.end();
|
||
|
}
|
||
|
|
||
|
|
||
|
// repeat the effect which will make it more "glowing"
|
||
|
for (int g = 0; g < _glow; g++)
|
||
|
painter->drawImage(0, 0, blurImage.scaled(pm.size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
|
||
|
|
||
|
QGraphicsColorizeEffect::draw(painter);
|
||
|
}
|
||
|
|
||
|
QImage applyEffectToImage(QImage src, QGraphicsEffect* effect, int extent = 0)
|
||
|
{
|
||
|
if (src.isNull()) return QImage();
|
||
|
if (!effect) return src;
|
||
|
QGraphicsScene scene;
|
||
|
QGraphicsPixmapItem item;
|
||
|
item.setPixmap(QPixmap::fromImage(src));
|
||
|
item.setGraphicsEffect(effect);
|
||
|
scene.addItem(&item);
|
||
|
QImage res(src.size() + QSize(extent * 2, extent * 2), QImage::Format_ARGB32);
|
||
|
res.fill(Qt::transparent);
|
||
|
QPainter ptr(&res);
|
||
|
scene.render(&ptr, QRectF(), QRectF(-extent, -extent, src.width() + extent * 2, src.height() + extent * 2));
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
float _blurRadius;
|
||
|
int _glow;
|
||
|
int _hue;
|
||
|
QColor _color;
|
||
|
};
|