diff options
author | Samuel Rødal <sroedal@trolltech.com> | 2009-07-28 10:25:55 (GMT) |
---|---|---|
committer | Samuel Rødal <sroedal@trolltech.com> | 2009-07-28 12:19:18 (GMT) |
commit | dbdc54791e585f3c6bf62c1a091ef844a66483ba (patch) | |
tree | 75b5f14c4b1a8176b53b23d93f0b6f7dcc688365 /src/gui/image | |
parent | 610aa1737a206fe97628a3375a543400ea0761fa (diff) | |
parent | 0431548ddffc56f74cc60e7d341ade3920adefb1 (diff) | |
download | Qt-dbdc54791e585f3c6bf62c1a091ef844a66483ba.zip Qt-dbdc54791e585f3c6bf62c1a091ef844a66483ba.tar.gz Qt-dbdc54791e585f3c6bf62c1a091ef844a66483ba.tar.bz2 |
Merge commit 'qt-graphics-team/pixmapfilters-redux' into kinetic-graphicseffect
Conflicts:
src/opengl/gl2paintengineex/qglengineshadermanager.cpp
src/opengl/gl2paintengineex/qglengineshadermanager_p.h
src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
Merge custom shader / GL blur pixmap filter implementation from graphics
team repo with implementation from kinetic graphics-team repo.
Diffstat (limited to 'src/gui/image')
-rw-r--r-- | src/gui/image/qpixmapfilter.cpp | 450 | ||||
-rw-r--r-- | src/gui/image/qpixmapfilter_p.h | 51 |
2 files changed, 243 insertions, 258 deletions
diff --git a/src/gui/image/qpixmapfilter.cpp b/src/gui/image/qpixmapfilter.cpp index 2b275a3..b7b3733 100644 --- a/src/gui/image/qpixmapfilter.cpp +++ b/src/gui/image/qpixmapfilter.cpp @@ -478,6 +478,225 @@ void QPixmapConvolutionFilter::draw(QPainter *painter, const QPointF &p, const Q } } +/*! + \class QPixmapBlurFilter + \since 4.6 + \ingroup multimedia + + \brief The QPixmapBlurFilter class provides blur filtering + for pixmaps. + + QPixmapBlurFilter implements a blur pixmap filter, + which is applied when \l{QPixmapFilter::}{draw()} is called. + + The filter lets you specialize the radius of the blur as well + as the quality. + + By default, the blur effect is produced by applying an exponential + filter generated from the specified blurRadius(). Paint engines + may override this with a custom blur that is faster on the + underlying hardware. + + \sa {Pixmap Filters Example}, QPixmapConvolutionFilter, QPixmapDropShadowFilter + + \internal +*/ + +class QPixmapBlurFilterPrivate : public QPixmapFilterPrivate +{ +public: + QPixmapBlurFilterPrivate() : radius(5), quality(Qt::FastTransformation) {} + + int radius; + Qt::TransformationMode quality; +}; + + +/*! + Constructs a pixmap blur filter. + + \internal +*/ +QPixmapBlurFilter::QPixmapBlurFilter(QObject *parent) + : QPixmapFilter(*new QPixmapBlurFilterPrivate, BlurFilter, parent) +{ +} + +/*! + Destructor of pixmap blur filter. + + \internal +*/ +QPixmapBlurFilter::~QPixmapBlurFilter() +{ +} + +/*! + Sets the radius of the blur filter. Higher radius produces increased blurriness. + + \internal +*/ +void QPixmapBlurFilter::setRadius(int radius) +{ + Q_D(QPixmapBlurFilter); + d->radius = radius; +} + +/*! + Gets the radius of the blur filter. + + \internal +*/ +int QPixmapBlurFilter::radius() const +{ + Q_D(const QPixmapBlurFilter); + return d->radius; +} + +/*! + Setting the quality to FastTransformation causes the implementation + to trade off visual quality to blur the image faster. Setting the + quality to SmoothTransformation causes the implementation to improve + visual quality at the expense of speed. The implementation is free + to ignore this value if it only has a single blur algorithm. + + \internal +*/ +void QPixmapBlurFilter::setQuality(Qt::TransformationMode quality) +{ + Q_D(QPixmapBlurFilter); + d->quality = quality; +} + +/*! + Gets the quality of the blur filter. + + \internal +*/ +Qt::TransformationMode QPixmapBlurFilter::quality() const +{ + Q_D(const QPixmapBlurFilter); + return d->quality; +} + +/*! + \reimp + + \internal +*/ +QRectF QPixmapBlurFilter::boundingRectFor(const QRectF &rect) const +{ + return rect; +} + +// Blur the image according to the blur radius +// Based on exponential blur algorithm by Jani Huhtanen +// (maximum radius is set to 16) +static QImage blurred(const QImage& image, const QRect& rect, int radius) +{ + int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 }; + int alpha = (radius < 1) ? 16 : (radius > 17) ? 1 : tab[radius-1]; + + QImage result = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); + int r1 = rect.top(); + int r2 = rect.bottom(); + int c1 = rect.left(); + int c2 = rect.right(); + + int bpl = result.bytesPerLine(); + int rgba[4]; + unsigned char* p; + + for (int col = c1; col <= c2; col++) { + p = result.scanLine(r1) + col * 4; + for (int i = 0; i < 4; i++) + rgba[i] = p[i] << 4; + + p += bpl; + for (int j = r1; j < r2; j++, p += bpl) + for (int i = 0; i < 4; i++) + p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; + } + + for (int row = r1; row <= r2; row++) { + p = result.scanLine(row) + c1 * 4; + for (int i = 0; i < 4; i++) + rgba[i] = p[i] << 4; + + p += 4; + for (int j = c1; j < c2; j++, p += 4) + for (int i = 0; i < 4; i++) + p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; + } + + for (int col = c1; col <= c2; col++) { + p = result.scanLine(r2) + col * 4; + for (int i = 0; i < 4; i++) + rgba[i] = p[i] << 4; + + p -= bpl; + for (int j = r1; j < r2; j++, p -= bpl) + for (int i = 0; i < 4; i++) + p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; + } + + for (int row = r1; row <= r2; row++) { + p = result.scanLine(row) + c2 * 4; + for (int i = 0; i < 4; i++) + rgba[i] = p[i] << 4; + + p -= 4; + for (int j = c1; j < c2; j++, p -= 4) + for (int i = 0; i < 4; i++) + p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; + } + + return result; +} + +/*! + \reimp + + \internal +*/ +void QPixmapBlurFilter::draw(QPainter *painter, const QPointF &p, const QPixmap &src, const QRectF &srcRect) const +{ + Q_D(const QPixmapBlurFilter); + if (!painter->isActive()) + return; + + if (d->radius == 0) { + painter->drawPixmap(srcRect.translated(p), src, srcRect); + return; + } + + QPixmapFilter *filter = painter->paintEngine() && painter->paintEngine()->isExtended() ? + static_cast<QPaintEngineEx *>(painter->paintEngine())->createPixmapFilter(type()) : 0; + QPixmapBlurFilter *blurFilter = static_cast<QPixmapBlurFilter*>(filter); + if (blurFilter) { + blurFilter->setRadius(d->radius); + blurFilter->setQuality(d->quality); + blurFilter->draw(painter, p, src, srcRect); + delete blurFilter; + return; + } + + QImage srcImage; + QImage destImage; + + if (srcRect.isNull()) { + srcImage = src.toImage(); + destImage = blurred(srcImage, srcImage.rect(), d->radius); + } else { + QRect rect = srcRect.toAlignedRect().intersected(src.rect()); + + srcImage = src.copy(rect).toImage(); + destImage = blurred(srcImage, srcImage.rect(), d->radius); + } + + painter->drawImage(p, destImage); +} + // grayscales the image to dest (could be same). If rect isn't defined // destination image size is used to determine the dimension of grayscaling // process. @@ -841,235 +1060,4 @@ void QPixmapDropShadowFilter::draw(QPainter *p, p->drawPixmap(pos, px, src); } -/*! - \class QPixmapBlurFilter - \since 4.6 - \ingroup multimedia - - \brief The QPixmapBlurFilter class is a convenience class - for drawing pixmaps with blur effects. - - By default, the blur effect is produced by applying an exponential - filter generated from the specified blurRadius(). Paint engines - may override this with a custom blur that is faster on the - underlying hardware. - - \sa QPixmapConvolutionFilter - - \internal - */ - -class QPixmapBlurFilterPrivate : public QPixmapFilterPrivate -{ -public: - QPixmapBlurFilterPrivate() - : quality(QPixmapBlurFilter::High), radius(1) {} - - QPixmapBlurFilter::BlurQuality quality; - qreal radius; -}; - -/*! - Constructs blur filter and attaches it to \a parent. - - \internal -*/ -QPixmapBlurFilter::QPixmapBlurFilter(QObject *parent) - : QPixmapFilter(*new QPixmapBlurFilterPrivate, BlurFilter, parent) -{ - Q_D(QPixmapBlurFilter); - setBlurRadius(4); -} - -/*! - Destroys blur filter. - - \internal -*/ -QPixmapBlurFilter::~QPixmapBlurFilter() -{ -} - -/*! - \enum QPixmapFilter::BlurQuality - \since 4.6 - \ingroup multimedia - This enum describes the quality of blur to apply to pixmaps. - - \value Fast Blur faster, potentially losing some quality. - \value High Produce the best high-quality blur possible, even if slower. - - \internal -*/ - -/*! - Returns the quality of the blur. The default value is High. - - \sa blurRadius() - \internal -*/ -QPixmapBlurFilter::BlurQuality QPixmapBlurFilter::blurQuality() const -{ - Q_D(const QPixmapBlurFilter); - return d->quality; -} - -/*! - Sets the quality of the blur to the \a blurQuality specified. - - Setting the quality to Faster causes the implementation to trade - off visual quality to blur the image faster. Setting the quality - to High causes the implementation to improve visual quality - at the expense of speed. The implementation is free to ignore - this value if it only has a single blur algorithm. - - \sa setBlurRadius() - \internal -*/ -void QPixmapBlurFilter::setBlurQuality(BlurQuality blurQuality) -{ - Q_D(QPixmapBlurFilter); - d->quality = blurQuality; -} - -/*! - Returns the radius in pixels of the blur. The default value is 4. - - A smaller radius results in a sharper image. - - \sa blurQuality() - \internal -*/ -qreal QPixmapBlurFilter::blurRadius() const -{ - Q_D(const QPixmapBlurFilter); - return d->radius; -} - -/*! - Sets the radius in pixels of the blur to the \a radius specified. - - Using a smaller radius results in a sharper image. - - \sa setBlurQuality() - \internal -*/ -void QPixmapBlurFilter::setBlurRadius(qreal blurRadius) -{ - Q_D(QPixmapBlurFilter); - d->radius = blurRadius; -} - -/*! - \internal - */ -QRectF QPixmapBlurFilter::boundingRectFor(const QRectF &rect) const -{ - Q_D(const QPixmapBlurFilter); - qreal delta = d->radius * 3; - QRectF blurRect(rect); - blurRect.adjust(-delta, -delta, delta, delta); - return blurRect; -} - -// Blur the image according to the blur radius -// Based on exponential blur algorithm by Jani Huhtanen -// (maximum radius is set to 16) -static QImage blurred(const QImage& image, const QRect& rect, int radius) -{ - int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 }; - int alpha = (radius < 1) ? 16 : (radius > 17) ? 1 : tab[radius-1]; - - QImage result = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); - int r1 = rect.top(); - int r2 = rect.bottom(); - int c1 = rect.left(); - int c2 = rect.right(); - - int bpl = result.bytesPerLine(); - int rgba[4]; - unsigned char* p; - - for (int col = c1; col <= c2; col++) { - p = result.scanLine(r1) + col * 4; - for (int i = 0; i < 4; i++) - rgba[i] = p[i] << 4; - - p += bpl; - for (int j = r1; j < r2; j++, p += bpl) - for (int i = 0; i < 4; i++) - p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; - } - - for (int row = r1; row <= r2; row++) { - p = result.scanLine(row) + c1 * 4; - for (int i = 0; i < 4; i++) - rgba[i] = p[i] << 4; - - p += 4; - for (int j = c1; j < c2; j++, p += 4) - for (int i = 0; i < 4; i++) - p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; - } - - for (int col = c1; col <= c2; col++) { - p = result.scanLine(r2) + col * 4; - for (int i = 0; i < 4; i++) - rgba[i] = p[i] << 4; - - p -= bpl; - for (int j = r1; j < r2; j++, p -= bpl) - for (int i = 0; i < 4; i++) - p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; - } - - for (int row = r1; row <= r2; row++) { - p = result.scanLine(row) + c2 * 4; - for (int i = 0; i < 4; i++) - rgba[i] = p[i] << 4; - - p -= 4; - for (int j = c1; j < c2; j++, p -= 4) - for (int i = 0; i < 4; i++) - p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; - } - - return result; -} - -/*! - \internal - */ -void QPixmapBlurFilter::draw(QPainter *painter, const QPointF &dest, const QPixmap &src, const QRectF &srcRect) const -{ - Q_D(const QPixmapBlurFilter); - - QPixmapFilter *filter = painter->paintEngine() && painter->paintEngine()->isExtended() ? - static_cast<QPaintEngineEx *>(painter->paintEngine())->createPixmapFilter(type()) : 0; - QPixmapBlurFilter *blurFilter = static_cast<QPixmapBlurFilter*>(filter); - if (blurFilter) { - blurFilter->setBlurQuality(d->quality); - blurFilter->setBlurRadius(d->radius); - blurFilter->draw(painter, dest, src, srcRect); - delete blurFilter; - return; - } - - QImage srcImage; - QImage destImage; - - if (srcRect.isNull()) { - srcImage = src.toImage(); - destImage = blurred(srcImage, srcImage.rect(), int(d->radius + 0.5)); - } else { - QRect rect = srcRect.toAlignedRect().intersected(src.rect()); - - srcImage = src.copy(rect).toImage(); - destImage = blurred(srcImage, srcImage.rect(), int(d->radius + 0.5)); - } - - qreal delta = d->radius * 3; - painter->drawImage(dest - QPointF(delta, delta), destImage); -} - QT_END_NAMESPACE diff --git a/src/gui/image/qpixmapfilter_p.h b/src/gui/image/qpixmapfilter_p.h index ca27cbf..ac393a1 100644 --- a/src/gui/image/qpixmapfilter_p.h +++ b/src/gui/image/qpixmapfilter_p.h @@ -118,6 +118,30 @@ private: int columns() const; }; +class QPixmapBlurFilterPrivate; + +class Q_GUI_EXPORT QPixmapBlurFilter : public QPixmapFilter +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QPixmapBlurFilter) + +public: + QPixmapBlurFilter(QObject *parent = 0); + ~QPixmapBlurFilter(); + + void setRadius(int radius); + void setQuality(Qt::TransformationMode mode); + + int radius() const; + Qt::TransformationMode quality() const; + + QRectF boundingRectFor(const QRectF &rect) const; + void draw(QPainter *painter, const QPointF &dest, const QPixmap &src, const QRectF &srcRect = QRectF()) const; + +private: + friend class QGLPixmapBlurFilter; +}; + class QPixmapColorizeFilterPrivate; class Q_GUI_EXPORT QPixmapColorizeFilter : public QPixmapFilter @@ -159,33 +183,6 @@ public: inline void setOffset(qreal dx, qreal dy) { setOffset(QPointF(dx, dy)); } }; -class QPixmapBlurFilterPrivate; - -class Q_GUI_EXPORT QPixmapBlurFilter : public QPixmapFilter -{ - Q_OBJECT - Q_DECLARE_PRIVATE(QPixmapBlurFilter) - -public: - QPixmapBlurFilter(QObject *parent = 0); - ~QPixmapBlurFilter(); - - enum BlurQuality - { - Fast, - High - }; - - BlurQuality blurQuality() const; - void setBlurQuality(BlurQuality blurQuality); - - qreal blurRadius() const; - void setBlurRadius(qreal blurRadius); - - QRectF boundingRectFor(const QRectF &rect) const; - void draw(QPainter *painter, const QPointF &dest, const QPixmap &src, const QRectF &srcRect = QRectF()) const; -}; - QT_END_NAMESPACE QT_END_HEADER |