Render QGraphicsEffect into pixmap?
-
Hello World!
I have a scene with a lot of items, all can have a custom QGraphicsEffects added.
Once an effect is rendered I would like to save the result, and add the resulting
qPixmap to a qPixmapCache.I was hoping to use the paint() function in my custom effect class, and in this do something ala
@
QPixmap im(loading the actual image);
QPainter p(&im);
QGraphicsDropShadowEffect::draw(&p);
im.save("ImageShadow.png","png");
@
BUT (and I tried a lot o variants).. yeah you know .. no.I know that scene->render() may give me a copy of the result, but the item and its effects may very well be occluded/overlapped/.. so the optimal solution would be to 'grap' it once when (OR while) rendered.
Anyone who saved effects? OR rendered effects into Qimage/pixmap/..?
A lovely one to you!
/bb -
.. thanxx for the reply .. But as I understand this, it is basically the same as scene->render(..)? Using 'grabWidget' in a view/scene setup I have to do:
pm = QPixmap::grabWidget(&view, x,y,w,h);
But this is identical (or the result is) to scene.render(..), and my scene is stuffed with items, so this gives me the same 'overlapping' problems ..
I could add a QLabel to my scene, and then use this as the widget for the 'grabWidget'. But how do I add my graphicsEffect to the widgets pixmap, and not the widget itself? .. hmm and I would really like to, not, include a QLabel in the scene ..
-
Hello i'm using QGraphicsEffect as a ThumbnailCollector here is my draw event,
@
void ThumbnailCollector::draw(QPainter *painter)
{
QPixmap pixmap = sourcePixmap(Qt::DeviceCoordinates);
//pixmap will give to you your item its own pixmap data
...
...
...
Q_EMIT thumbnailChanged(m_thumbnail);
setEnabled(false);
}
@Hope this will help, but i have some flicking problems with that trying to solve that :s
-
QWidget::grab() is again regression for graphics effect, but graphics scene's render() call works like a charm without the need to create any widgets. Here is how:
@ QImage applyEffectToImage(QImage src, QGraphicsEffect effect, int extent)
{
if(src.isNull()) return QImage(); //No need to do anything else!
if(!effect) return src; //No need to do anything else!
QGraphicsScene scene;
QGraphicsPixmapItem item;
item.setPixmap(QPixmap::fromImage(src));
item.setGraphicsEffect(effect);
scene.addItem(&item);
QImage res(src.size()+QSize(extent2, extent2), QImage::Format_ARGB32);
res.fill(Qt::transparent);
QPainter ptr(&res);
scene.render(&ptr, QRectF(), QRectF( -extent, -extent, src.width()+extent2, src.height()+extent*2 ) );
return res;
}@Them, using this function to is straightforward. Blur:
@ QGraphicsBlurEffect *blur = new QGraphicsBlurEffect;
blur->setBlurRadius(8);
QImage source("://img1.png");
QImage result = applyEffectToImage(source, blur);
result.save("final.png");@Drop shadow:
@ QGraphicsDropShadowEffect *e = new QGraphicsDropShadowEffect;
e->setColor(QColor(40,40,40,245));
e->setOffset(0,10);
e->setBlurRadius(50);
QImage p("://img3.png");
QImage res = applyEffectToImage(p, e, 40);@And note the extent parameter, it adds
extent
number of pixels to all sides of the original image, especially useful for shadows and blurs to not be cut-off. -
QWidget::grab() is again regression for graphics effect, but graphics scene's render() call works like a charm without the need to create any widgets. Here is how:
@ QImage applyEffectToImage(QImage src, QGraphicsEffect effect, int extent)
{
if(src.isNull()) return QImage(); //No need to do anything else!
if(!effect) return src; //No need to do anything else!
QGraphicsScene scene;
QGraphicsPixmapItem item;
item.setPixmap(QPixmap::fromImage(src));
item.setGraphicsEffect(effect);
scene.addItem(&item);
QImage res(src.size()+QSize(extent2, extent2), QImage::Format_ARGB32);
res.fill(Qt::transparent);
QPainter ptr(&res);
scene.render(&ptr, QRectF(), QRectF( -extent, -extent, src.width()+extent2, src.height()+extent*2 ) );
return res;
}@Them, using this function to is straightforward. Blur:
@ QGraphicsBlurEffect *blur = new QGraphicsBlurEffect;
blur->setBlurRadius(8);
QImage source("://img1.png");
QImage result = applyEffectToImage(source, blur);
result.save("final.png");@Drop shadow:
@ QGraphicsDropShadowEffect *e = new QGraphicsDropShadowEffect;
e->setColor(QColor(40,40,40,245));
e->setOffset(0,10);
e->setBlurRadius(50);
QImage p("://img3.png");
QImage res = applyEffectToImage(p, e, 40);@And note the extent parameter, it adds
extent
number of pixels to all sides of the original image, especially useful for shadows and blurs to not be cut-off. -
You should render it, to do that you should override the paint function
try this class:
DropShadow.h@
#ifndef DROPSHADOW_H
#define DROPSHADOW_H
#include <QtGui>
#include <QtCore>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsEffect>
#include <QtQuick/QQuickPaintedItem>
#include <QLabel>
#include <QPainter>
#include <QGraphicsProxyWidget>
/*!- \brief The DropShadow class, it load an Image and apply to it a DropShadow effect
*/
class DropShadow : public QQuickPaintedItem
{
Q_OBJECT
Q_PROPERTY(QString source READ getImageSource WRITE setImageSource)
Q_PROPERTY(QColor color READ getColor WRITE setColor)
Q_PROPERTY(int width READ getWidth WRITE setCustomWidth)
Q_PROPERTY(int height READ getHeight WRITE setCustomHeight)
Q_PROPERTY(double radius READ getBlurRadius WRITE setBlurRadius)
Q_PROPERTY(double horizontalOffset READ getXOffset WRITE setXOffset)
Q_PROPERTY(double verticalOffset READ getYOffset WRITE setYOffset)
public:
DropShadow(QQuickItem *parent = 0);
int getWidth();
int getHeight();
void setCustomWidth(int width);
void setCustomHeight(int height);
void setImageSource(QString myImage);
QString getImageSource() const;
QColor getColor() const;
void setColor(const QColor &color);
double getBlurRadius() const;
void setBlurRadius(const double blurRadius);
double getXOffset() const;
double getYOffset() const;
void setXOffset(double value);
void setYOffset(double value);
void paint(QPainter *painter);
~DropShadow();
signals:
void sgnSourceImageChanged();
public slots:
void sltOnsourceChanged();
private:
QImage myImage;
QString sourceImage;
QColor m_color;
double radius;
QGraphicsDropShadowEffect pShadow;
QGraphicsOpacityEffect* pOpacity;
QGraphicsView view;
QGraphicsScene *scene;
int width;
int height;
QPixmap pixmap;
QPainter * m_painter;
double horizontalOffset;
double verticalOffset;
};
#endif // DROPSHADOW_H
@dropShadow.cpp
@
#include "dropshadow.h"
DropShadow::DropShadow(QQuickItem *parent) :
QQuickPaintedItem(parent)
{connect(this,SIGNAL(sgnSourceImageChanged()),this,SLOT(sltOnsourceChanged())); myImage = new QImage; pShadow = new QGraphicsDropShadowEffect; m_color = Qt::blue; width = 0; height = 0; radius = 1.0; horizontalOffset = 8.0; verticalOffset = 8.0; scene = new QGraphicsScene; view.setScene(scene);
}
int DropShadow::getWidth()
{
return width;
}
int DropShadow::getHeight()
{
return height;
}
void DropShadow::setCustomWidth(int value)
{
width = value;
qDebug()<<"DropShadow::setCustomWidth("<<value<<")";
}
void DropShadow::setCustomHeight(int value)
{
height = value;
qDebug()<<"DropShadow::setCustomHeight("<<value<<")";
}
QColor DropShadow::getColor() const
{
return m_color;
}
void DropShadow::setColor(const QColor &color)
{
m_color = color;
}
double DropShadow::getBlurRadius() const
{
return radius;
}
double DropShadow::getXOffset() const
{
return horizontalOffset;
}
double DropShadow::getYOffset() const
{
return verticalOffset;
}
void DropShadow::setXOffset(double value)
{
horizontalOffset = value;
}
void DropShadow::setYOffset(double value)
{
verticalOffset = value;
}
void DropShadow::setBlurRadius(const double blurRadius)
{
radius = blurRadius;
}
void DropShadow::setImageSource(QString image)
{
sourceImage = image;
sgnSourceImageChanged();
}
QString DropShadow::getImageSource() const
{
return sourceImage;
}
void DropShadow::sltOnsourceChanged()
{
myImage->load(sourceImage);
if(width == 0)
{
width = myImage->width();
}
if(height == 0)
{
height = myImage->height();
}
this->setWidth(width);
this->setHeight(height);
pixmap = QPixmap::fromImage( myImage->scaled(width,height,Qt::IgnoreAspectRatio,Qt::SmoothTransformation));
}
void DropShadow::paint(QPainter *painter)
{
view.setScene(scene);
scene->setSceneRect(QRect(0,0,800,480));
pShadow->setColor(QColor(m_color));
pShadow->setBlurRadius(radius);
pShadow->setXOffset(horizontalOffset);
pShadow->setYOffset(verticalOffset);
QGraphicsPixmapItem *p = view.scene()->addPixmap(pixmap);
p->setGraphicsEffect(pShadow);
view.render(painter,QRect(0,0,800,480),QRect(0,0,800,480));
}
DropShadow::~DropShadow()
{
delete myImage;
delete pShadow;
delete scene;
}
@[edit: added missing coding tags @ SGaist]
- \brief The DropShadow class, it load an Image and apply to it a DropShadow effect
-
You should render it, to do that you should override the paint function
try this class:
DropShadow.h@
#ifndef DROPSHADOW_H
#define DROPSHADOW_H
#include <QtGui>
#include <QtCore>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsEffect>
#include <QtQuick/QQuickPaintedItem>
#include <QLabel>
#include <QPainter>
#include <QGraphicsProxyWidget>
/*!- \brief The DropShadow class, it load an Image and apply to it a DropShadow effect
*/
class DropShadow : public QQuickPaintedItem
{
Q_OBJECT
Q_PROPERTY(QString source READ getImageSource WRITE setImageSource)
Q_PROPERTY(QColor color READ getColor WRITE setColor)
Q_PROPERTY(int width READ getWidth WRITE setCustomWidth)
Q_PROPERTY(int height READ getHeight WRITE setCustomHeight)
Q_PROPERTY(double radius READ getBlurRadius WRITE setBlurRadius)
Q_PROPERTY(double horizontalOffset READ getXOffset WRITE setXOffset)
Q_PROPERTY(double verticalOffset READ getYOffset WRITE setYOffset)
public:
DropShadow(QQuickItem *parent = 0);
int getWidth();
int getHeight();
void setCustomWidth(int width);
void setCustomHeight(int height);
void setImageSource(QString myImage);
QString getImageSource() const;
QColor getColor() const;
void setColor(const QColor &color);
double getBlurRadius() const;
void setBlurRadius(const double blurRadius);
double getXOffset() const;
double getYOffset() const;
void setXOffset(double value);
void setYOffset(double value);
void paint(QPainter *painter);
~DropShadow();
signals:
void sgnSourceImageChanged();
public slots:
void sltOnsourceChanged();
private:
QImage myImage;
QString sourceImage;
QColor m_color;
double radius;
QGraphicsDropShadowEffect pShadow;
QGraphicsOpacityEffect* pOpacity;
QGraphicsView view;
QGraphicsScene *scene;
int width;
int height;
QPixmap pixmap;
QPainter * m_painter;
double horizontalOffset;
double verticalOffset;
};
#endif // DROPSHADOW_H
@dropShadow.cpp
@
#include "dropshadow.h"
DropShadow::DropShadow(QQuickItem *parent) :
QQuickPaintedItem(parent)
{connect(this,SIGNAL(sgnSourceImageChanged()),this,SLOT(sltOnsourceChanged())); myImage = new QImage; pShadow = new QGraphicsDropShadowEffect; m_color = Qt::blue; width = 0; height = 0; radius = 1.0; horizontalOffset = 8.0; verticalOffset = 8.0; scene = new QGraphicsScene; view.setScene(scene);
}
int DropShadow::getWidth()
{
return width;
}
int DropShadow::getHeight()
{
return height;
}
void DropShadow::setCustomWidth(int value)
{
width = value;
qDebug()<<"DropShadow::setCustomWidth("<<value<<")";
}
void DropShadow::setCustomHeight(int value)
{
height = value;
qDebug()<<"DropShadow::setCustomHeight("<<value<<")";
}
QColor DropShadow::getColor() const
{
return m_color;
}
void DropShadow::setColor(const QColor &color)
{
m_color = color;
}
double DropShadow::getBlurRadius() const
{
return radius;
}
double DropShadow::getXOffset() const
{
return horizontalOffset;
}
double DropShadow::getYOffset() const
{
return verticalOffset;
}
void DropShadow::setXOffset(double value)
{
horizontalOffset = value;
}
void DropShadow::setYOffset(double value)
{
verticalOffset = value;
}
void DropShadow::setBlurRadius(const double blurRadius)
{
radius = blurRadius;
}
void DropShadow::setImageSource(QString image)
{
sourceImage = image;
sgnSourceImageChanged();
}
QString DropShadow::getImageSource() const
{
return sourceImage;
}
void DropShadow::sltOnsourceChanged()
{
myImage->load(sourceImage);
if(width == 0)
{
width = myImage->width();
}
if(height == 0)
{
height = myImage->height();
}
this->setWidth(width);
this->setHeight(height);
pixmap = QPixmap::fromImage( myImage->scaled(width,height,Qt::IgnoreAspectRatio,Qt::SmoothTransformation));
}
void DropShadow::paint(QPainter *painter)
{
view.setScene(scene);
scene->setSceneRect(QRect(0,0,800,480));
pShadow->setColor(QColor(m_color));
pShadow->setBlurRadius(radius);
pShadow->setXOffset(horizontalOffset);
pShadow->setYOffset(verticalOffset);
QGraphicsPixmapItem *p = view.scene()->addPixmap(pixmap);
p->setGraphicsEffect(pShadow);
view.render(painter,QRect(0,0,800,480),QRect(0,0,800,480));
}
DropShadow::~DropShadow()
{
delete myImage;
delete pShadow;
delete scene;
}
@[edit: added missing coding tags @ SGaist]
- \brief The DropShadow class, it load an Image and apply to it a DropShadow effect
-
this is a link to my project , hope it could help you :
https://github.com/alhajjar/QmlEffects -
this is a link to my project , hope it could help you :
https://github.com/alhajjar/QmlEffects