Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qpixmapfilter.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <qglobal.h>
5
6#include <QDebug>
7
8#include "qpainter.h"
9#include "qpixmap.h"
10#include "qpixmapfilter_p.h"
11#include "qvarlengtharray.h"
12
13#include "private/qguiapplication_p.h"
14#include "private/qpaintengineex_p.h"
15#include "private/qpaintengine_raster_p.h"
16#include "qmath.h"
17#include "private/qmath_p.h"
18#include "private/qmemrotate_p.h"
19#include "private/qdrawhelper_p.h"
20
21#include <memory>
22
24
26{
27 Q_DECLARE_PUBLIC(QPixmapFilter)
28public:
30};
31
82{
83 d_func()->type = type;
84}
85
86
87
92 : QObject(d, parent)
93{
94 d_func()->type = type;
95}
96
97
104{
105}
106
114{
115 Q_D(const QPixmapFilter);
116 return d->type;
117}
118
126{
127 return rect;
128}
129
173{
174public:
177 delete[] convolutionKernel;
178 }
179
184};
185
186
195 : QPixmapFilter(*new QPixmapConvolutionFilterPrivate, ConvolutionFilter, parent)
196{
198 d->convoluteAlpha = true;
199}
200
207{
208}
209
222{
224 delete [] d->convolutionKernel;
225 d->convolutionKernel = new qreal[rows * columns];
226 memcpy(d->convolutionKernel, kernel, sizeof(qreal) * rows * columns);
227 d->kernelWidth = columns;
228 d->kernelHeight = rows;
229}
230
236const qreal *QPixmapConvolutionFilter::convolutionKernel() const
237{
238 Q_D(const QPixmapConvolutionFilter);
239 return d->convolutionKernel;
240}
241
247int QPixmapConvolutionFilter::rows() const
248{
249 Q_D(const QPixmapConvolutionFilter);
250 return d->kernelHeight;
251}
252
258int QPixmapConvolutionFilter::columns() const
259{
260 Q_D(const QPixmapConvolutionFilter);
261 return d->kernelWidth;
262}
263
264
269{
270 Q_D(const QPixmapConvolutionFilter);
271 return rect.adjusted(-d->kernelWidth / 2, -d->kernelHeight / 2, (d->kernelWidth - 1) / 2, (d->kernelHeight - 1) / 2);
272}
273
274// Convolutes the image
275static void convolute(
276 QImage *destImage,
277 const QPointF &pos,
278 const QImage &srcImage,
279 const QRectF &srcRect,
281 qreal *kernel,
282 int kernelWidth,
283 int kernelHeight )
284{
285 const QImage processImage = (srcImage.format() != QImage::Format_ARGB32_Premultiplied ) ? srcImage.convertToFormat(QImage::Format_ARGB32_Premultiplied) : srcImage;
286 // TODO: support also other formats directly without copying
287
288 std::unique_ptr<int[]> fixedKernel(new int[kernelWidth * kernelHeight]);
289 for(int i = 0; i < kernelWidth*kernelHeight; i++)
290 {
291 fixedKernel[i] = (int)(65536 * kernel[i]);
292 }
293 QRectF trect = srcRect.isNull() ? processImage.rect() : srcRect;
294 trect.moveTo(pos);
295 QRectF bounded = trect.adjusted(-kernelWidth / 2, -kernelHeight / 2, (kernelWidth - 1) / 2, (kernelHeight - 1) / 2);
296 QRect rect = bounded.toAlignedRect();
297 QRect targetRect = rect.intersected(destImage->rect());
298
299 QRectF srect = srcRect.isNull() ? processImage.rect() : srcRect;
300 QRectF sbounded = srect.adjusted(-kernelWidth / 2, -kernelHeight / 2, (kernelWidth - 1) / 2, (kernelHeight - 1) / 2);
301 QPoint srcStartPoint = sbounded.toAlignedRect().topLeft()+(targetRect.topLeft()-rect.topLeft());
302
303 const uint *sourceStart = (const uint*)processImage.scanLine(0);
304 uint *outputStart = (uint*)destImage->scanLine(0);
305
306 int yk = srcStartPoint.y();
307 for (int y = targetRect.top(); y <= targetRect.bottom(); y++) {
308 uint* output = outputStart + (destImage->bytesPerLine()/sizeof(uint))*y+targetRect.left();
309 int xk = srcStartPoint.x();
310 for(int x = targetRect.left(); x <= targetRect.right(); x++) {
311 int r = 0;
312 int g = 0;
313 int b = 0;
314 int a = 0;
315
316 // some out of bounds pre-checking to avoid inner-loop ifs
317 int kernely = -kernelHeight/2;
318 int starty = 0;
319 int endy = kernelHeight;
320 if (yk+kernely+endy >= srcImage.height())
321 endy = kernelHeight-((yk+kernely+endy)-srcImage.height())-1;
322 if (yk+kernely < 0)
323 starty = -(yk+kernely);
324
325 int kernelx = -kernelWidth/2;
326 int startx = 0;
327 int endx = kernelWidth;
328 if (xk+kernelx+endx >= srcImage.width())
329 endx = kernelWidth-((xk+kernelx+endx)-srcImage.width())-1;
330 if (xk+kernelx < 0)
331 startx = -(xk+kernelx);
332
333 for (int ys = starty; ys < endy; ys ++) {
334 const uint *pix = sourceStart + (processImage.bytesPerLine()/sizeof(uint))*(yk+kernely+ys) + ((xk+kernelx+startx));
335 const uint *endPix = pix+endx-startx;
336 int kernelPos = ys*kernelWidth+startx;
337 while (pix < endPix) {
338 int factor = fixedKernel[kernelPos++];
339 a += (((*pix) & 0xff000000)>>24) * factor;
340 r += (((*pix) & 0x00ff0000)>>16) * factor;
341 g += (((*pix) & 0x0000ff00)>>8 ) * factor;
342 b += (((*pix) & 0x000000ff) ) * factor;
343 pix++;
344 }
345 }
346
347 r = qBound((int)0, r >> 16, (int)255);
348 g = qBound((int)0, g >> 16, (int)255);
349 b = qBound((int)0, b >> 16, (int)255);
350 a = qBound((int)0, a >> 16, (int)255);
351 // composition mode checking could be moved outside of loop
353 uint color = (a<<24)+(r<<16)+(g<<8)+b;
354 *output++ = color;
355 } else {
356 uint current = *output;
357 uchar ca = (current&0xff000000)>>24;
358 uchar cr = (current&0x00ff0000)>>16;
359 uchar cg = (current&0x0000ff00)>>8;
360 uchar cb = (current&0x000000ff);
361 uint color =
362 (((ca*(255-a) >> 8)+a) << 24)+
363 (((cr*(255-a) >> 8)+r) << 16)+
364 (((cg*(255-a) >> 8)+g) << 8)+
365 (((cb*(255-a) >> 8)+b));
366 *output++ = color;;
367 }
368 xk++;
369 }
370 yk++;
371 }
372}
373
377void QPixmapConvolutionFilter::draw(QPainter *painter, const QPointF &p, const QPixmap &src, const QRectF& srcRect) const
378{
379 Q_D(const QPixmapConvolutionFilter);
380 if (!painter->isActive())
381 return;
382
383 if (d->kernelWidth<=0 || d->kernelHeight <= 0)
384 return;
385
386 if (src.isNull())
387 return;
388
389 // raster implementation
390
391 QImage *target = nullptr;
393 target = static_cast<QImage *>(painter->paintEngine()->paintDevice());
394
396
397 if (mat.type() > QTransform::TxTranslate) {
398 // Disabled because of transformation...
399 target = nullptr;
400 } else {
403 // disabled because of complex clipping...
404 target = nullptr;
405 else {
406 QRectF clip = pe->clipBoundingRect();
407 QRectF rect = boundingRectFor(srcRect.isEmpty() ? src.rect() : srcRect);
409 if (!clip.contains(rect.translated(x.dx() + p.x(), x.dy() + p.y()))) {
410 target = nullptr;
411 }
412
413 }
414 }
415 }
416
417 if (target) {
419 QPointF offset(x.dx(), x.dy());
420
421 convolute(target, p+offset, src.toImage(), srcRect, QPainter::CompositionMode_SourceOver, d->convolutionKernel, d->kernelWidth, d->kernelHeight);
422 } else {
423 QRect srect = srcRect.isNull() ? src.rect() : srcRect.toRect();
424 QRect rect = boundingRectFor(srect).toRect();
426 QPoint offset = srect.topLeft() - rect.topLeft();
428 offset,
429 src.toImage(),
430 srect,
432 d->convolutionKernel,
433 d->kernelWidth,
434 d->kernelHeight);
436 }
437}
438
464{
465public:
467
469 QGraphicsBlurEffect::BlurHints hints;
470};
471
472
480{
481}
482
489{
490}
491
498{
500 d->radius = radius;
501}
502
509{
510 Q_D(const QPixmapBlurFilter);
511 return d->radius;
512}
513
529void QPixmapBlurFilter::setBlurHints(QGraphicsBlurEffect::BlurHints hints)
530{
532 d->hints = hints;
533}
534
540QGraphicsBlurEffect::BlurHints QPixmapBlurFilter::blurHints() const
541{
542 Q_D(const QPixmapBlurFilter);
543 return d->hints;
544}
545
547
552{
553 Q_D(const QPixmapBlurFilter);
554 const qreal delta = radiusScale * d->radius + 1;
555 return rect.adjusted(-delta, -delta, delta, delta);
556}
557
558template <int shift>
559inline int qt_static_shift(int value)
560{
561 if (shift == 0)
562 return value;
563 else if (shift > 0)
564 return value << (uint(shift) & 0x1f);
565 else
566 return value >> (uint(-shift) & 0x1f);
567}
568
569template<int aprec, int zprec>
570inline void qt_blurinner(uchar *bptr, int &zR, int &zG, int &zB, int &zA, int alpha)
571{
572 QRgb *pixel = (QRgb *)bptr;
573
574#define Z_MASK (0xff << zprec)
575 const int A_zprec = qt_static_shift<zprec - 24>(*pixel) & Z_MASK;
576 const int R_zprec = qt_static_shift<zprec - 16>(*pixel) & Z_MASK;
577 const int G_zprec = qt_static_shift<zprec - 8>(*pixel) & Z_MASK;
578 const int B_zprec = qt_static_shift<zprec>(*pixel) & Z_MASK;
579#undef Z_MASK
580
581 const int zR_zprec = zR >> aprec;
582 const int zG_zprec = zG >> aprec;
583 const int zB_zprec = zB >> aprec;
584 const int zA_zprec = zA >> aprec;
585
586 zR += alpha * (R_zprec - zR_zprec);
587 zG += alpha * (G_zprec - zG_zprec);
588 zB += alpha * (B_zprec - zB_zprec);
589 zA += alpha * (A_zprec - zA_zprec);
590
591#define ZA_MASK (0xff << (zprec + aprec))
592 *pixel =
593 qt_static_shift<24 - zprec - aprec>(zA & ZA_MASK)
594 | qt_static_shift<16 - zprec - aprec>(zR & ZA_MASK)
595 | qt_static_shift<8 - zprec - aprec>(zG & ZA_MASK)
596 | qt_static_shift<-zprec - aprec>(zB & ZA_MASK);
597#undef ZA_MASK
598}
599
601
602template<int aprec, int zprec>
603inline void qt_blurinner_alphaOnly(uchar *bptr, int &z, int alpha)
604{
605 const int A_zprec = int(*(bptr)) << zprec;
606 const int z_zprec = z >> aprec;
607 z += alpha * (A_zprec - z_zprec);
608 *(bptr) = z >> (zprec + aprec);
609}
610
611template<int aprec, int zprec, bool alphaOnly>
612inline void qt_blurrow(QImage & im, int line, int alpha)
613{
614 uchar *bptr = im.scanLine(line);
615
616 int zR = 0, zG = 0, zB = 0, zA = 0;
617
618 if (alphaOnly && im.format() != QImage::Format_Indexed8)
619 bptr += alphaIndex;
620
621 const int stride = im.depth() >> 3;
622 const int im_width = im.width();
623 for (int index = 0; index < im_width; ++index) {
624 if (alphaOnly)
625 qt_blurinner_alphaOnly<aprec, zprec>(bptr, zA, alpha);
626 else
627 qt_blurinner<aprec, zprec>(bptr, zR, zG, zB, zA, alpha);
628 bptr += stride;
629 }
630
631 bptr -= stride;
632
633 for (int index = im_width - 2; index >= 0; --index) {
634 bptr -= stride;
635 if (alphaOnly)
636 qt_blurinner_alphaOnly<aprec, zprec>(bptr, zA, alpha);
637 else
638 qt_blurinner<aprec, zprec>(bptr, zR, zG, zB, zA, alpha);
639 }
640}
641
642/*
643* expblur(QImage &img, int radius)
644*
645* Based on exponential blur algorithm by Jani Huhtanen
646*
647* In-place blur of image 'img' with kernel
648* of approximate radius 'radius'.
649*
650* Blurs with two sided exponential impulse
651* response.
652*
653* aprec = precision of alpha parameter
654* in fixed-point format 0.aprec
655*
656* zprec = precision of state parameters
657* zR,zG,zB and zA in fp format 8.zprec
658*/
659template <int aprec, int zprec, bool alphaOnly>
660void expblur(QImage &img, qreal radius, bool improvedQuality = false, int transposed = 0)
661{
662 // halve the radius if we're using two passes
663 if (improvedQuality)
664 radius *= qreal(0.5);
665
667 || img.format() == QImage::Format_RGB32
668 || img.format() == QImage::Format_Indexed8
669 || img.format() == QImage::Format_Grayscale8);
670
671 // choose the alpha such that pixels at radius distance from a fully
672 // saturated pixel will have an alpha component of no greater than
673 // the cutOffIntensity
674 const qreal cutOffIntensity = 2;
675 int alpha = radius <= qreal(1e-5)
676 ? ((1 << aprec)-1)
677 : qRound((1<<aprec)*(1 - qPow(cutOffIntensity * (1 / qreal(255)), 1 / radius)));
678
679 int img_height = img.height();
680 for (int row = 0; row < img_height; ++row) {
681 for (int i = 0; i <= int(improvedQuality); ++i)
682 qt_blurrow<aprec, zprec, alphaOnly>(img, row, alpha);
683 }
684
685 QImage temp(img.height(), img.width(), img.format());
686 temp.setDevicePixelRatio(img.devicePixelRatio());
687 if (transposed >= 0) {
688 if (img.depth() == 8) {
689 qt_memrotate270(reinterpret_cast<const quint8*>(img.bits()),
690 img.width(), img.height(), img.bytesPerLine(),
691 reinterpret_cast<quint8*>(temp.bits()),
692 temp.bytesPerLine());
693 } else {
694 qt_memrotate270(reinterpret_cast<const quint32*>(img.bits()),
695 img.width(), img.height(), img.bytesPerLine(),
696 reinterpret_cast<quint32*>(temp.bits()),
697 temp.bytesPerLine());
698 }
699 } else {
700 if (img.depth() == 8) {
701 qt_memrotate90(reinterpret_cast<const quint8*>(img.bits()),
702 img.width(), img.height(), img.bytesPerLine(),
703 reinterpret_cast<quint8*>(temp.bits()),
704 temp.bytesPerLine());
705 } else {
706 qt_memrotate90(reinterpret_cast<const quint32*>(img.bits()),
707 img.width(), img.height(), img.bytesPerLine(),
708 reinterpret_cast<quint32*>(temp.bits()),
709 temp.bytesPerLine());
710 }
711 }
712
713 img_height = temp.height();
714 for (int row = 0; row < img_height; ++row) {
715 for (int i = 0; i <= int(improvedQuality); ++i)
716 qt_blurrow<aprec, zprec, alphaOnly>(temp, row, alpha);
717 }
718
719 if (transposed == 0) {
720 if (img.depth() == 8) {
721 qt_memrotate90(reinterpret_cast<const quint8*>(temp.bits()),
722 temp.width(), temp.height(), temp.bytesPerLine(),
723 reinterpret_cast<quint8*>(img.bits()),
724 img.bytesPerLine());
725 } else {
726 qt_memrotate90(reinterpret_cast<const quint32*>(temp.bits()),
727 temp.width(), temp.height(), temp.bytesPerLine(),
728 reinterpret_cast<quint32*>(img.bits()),
729 img.bytesPerLine());
730 }
731 } else {
732 img = temp;
733 }
734}
735#define AVG(a,b) ( ((((a)^(b)) & 0xfefefefeUL) >> 1) + ((a)&(b)) )
736#define AVG16(a,b) ( ((((a)^(b)) & 0xf7deUL) >> 1) + ((a)&(b)) )
737
738Q_WIDGETS_EXPORT QImage qt_halfScaled(const QImage &source)
739{
740 if (source.width() < 2 || source.height() < 2)
741 return QImage();
742
743 QImage srcImage = source;
744
745 if (source.format() == QImage::Format_Indexed8 || source.format() == QImage::Format_Grayscale8) {
746 // assumes grayscale
747 QImage dest(source.width() / 2, source.height() / 2, srcImage.format());
748 dest.setDevicePixelRatio(source.devicePixelRatio());
749
750 const uchar *src = reinterpret_cast<const uchar*>(const_cast<const QImage &>(srcImage).bits());
751 qsizetype sx = srcImage.bytesPerLine();
752 qsizetype sx2 = sx << 1;
753
754 uchar *dst = reinterpret_cast<uchar*>(dest.bits());
755 qsizetype dx = dest.bytesPerLine();
756 int ww = dest.width();
757 int hh = dest.height();
758
759 for (int y = hh; y; --y, dst += dx, src += sx2) {
760 const uchar *p1 = src;
761 const uchar *p2 = src + sx;
762 uchar *q = dst;
763 for (int x = ww; x; --x, ++q, p1 += 2, p2 += 2)
764 *q = ((int(p1[0]) + int(p1[1]) + int(p2[0]) + int(p2[1])) + 2) >> 2;
765 }
766
767 return dest;
768 } else if (source.format() == QImage::Format_ARGB8565_Premultiplied) {
769 QImage dest(source.width() / 2, source.height() / 2, srcImage.format());
770 dest.setDevicePixelRatio(source.devicePixelRatio());
771
772 const uchar *src = reinterpret_cast<const uchar*>(const_cast<const QImage &>(srcImage).bits());
773 qsizetype sx = srcImage.bytesPerLine();
774 qsizetype sx2 = sx << 1;
775
776 uchar *dst = reinterpret_cast<uchar*>(dest.bits());
777 qsizetype dx = dest.bytesPerLine();
778 int ww = dest.width();
779 int hh = dest.height();
780
781 for (int y = hh; y; --y, dst += dx, src += sx2) {
782 const uchar *p1 = src;
783 const uchar *p2 = src + sx;
784 uchar *q = dst;
785 for (int x = ww; x; --x, q += 3, p1 += 6, p2 += 6) {
786 // alpha
787 q[0] = AVG(AVG(p1[0], p1[3]), AVG(p2[0], p2[3]));
788 // rgb
789 const quint16 p16_1 = (p1[2] << 8) | p1[1];
790 const quint16 p16_2 = (p1[5] << 8) | p1[4];
791 const quint16 p16_3 = (p2[2] << 8) | p2[1];
792 const quint16 p16_4 = (p2[5] << 8) | p2[4];
793 const quint16 result = AVG16(AVG16(p16_1, p16_2), AVG16(p16_3, p16_4));
794 q[1] = result & 0xff;
795 q[2] = result >> 8;
796 }
797 }
798
799 return dest;
800 } else if (source.format() != QImage::Format_ARGB32_Premultiplied
801 && source.format() != QImage::Format_RGB32)
802 {
804 }
805
806 QImage dest(source.width() / 2, source.height() / 2, srcImage.format());
807 dest.setDevicePixelRatio(source.devicePixelRatio());
808
809 const quint32 *src = reinterpret_cast<const quint32*>(const_cast<const QImage &>(srcImage).bits());
810 qsizetype sx = srcImage.bytesPerLine() >> 2;
811 qsizetype sx2 = sx << 1;
812
813 quint32 *dst = reinterpret_cast<quint32*>(dest.bits());
814 qsizetype dx = dest.bytesPerLine() >> 2;
815 int ww = dest.width();
816 int hh = dest.height();
817
818 for (int y = hh; y; --y, dst += dx, src += sx2) {
819 const quint32 *p1 = src;
820 const quint32 *p2 = src + sx;
821 quint32 *q = dst;
822 for (int x = ww; x; --x, q++, p1 += 2, p2 += 2)
823 *q = AVG(AVG(p1[0], p1[1]), AVG(p2[0], p2[1]));
824 }
825
826 return dest;
827}
828
829Q_WIDGETS_EXPORT void qt_blurImage(QPainter *p, QImage &blurImage, qreal radius, bool quality, bool alphaOnly, int transposed = 0)
830{
832 && blurImage.format() != QImage::Format_RGB32)
833 {
835 }
836
837 qreal scale = 1;
838 if (radius >= 4 && blurImage.width() >= 2 && blurImage.height() >= 2) {
839 blurImage = qt_halfScaled(blurImage);
840 scale = 2;
841 radius *= qreal(0.5);
842 }
843
844 if (alphaOnly)
845 expblur<12, 10, true>(blurImage, radius, quality, transposed);
846 else
847 expblur<12, 10, false>(blurImage, radius, quality, transposed);
848
849 if (p) {
850 p->scale(scale, scale);
851 p->setRenderHint(QPainter::SmoothPixmapTransform);
852 p->drawImage(QRect(QPoint(0, 0), blurImage.deviceIndependentSize().toSize()), blurImage);
853 }
854}
855
856Q_WIDGETS_EXPORT void qt_blurImage(QImage &blurImage, qreal radius, bool quality, int transposed = 0)
857{
858 if (blurImage.format() == QImage::Format_Indexed8 || blurImage.format() == QImage::Format_Grayscale8)
859 expblur<12, 10, true>(blurImage, radius, quality, transposed);
860 else
861 expblur<12, 10, false>(blurImage, radius, quality, transposed);
862}
863
864Q_GUI_EXPORT extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale);
865
870{
871 Q_D(const QPixmapBlurFilter);
872 if (!painter->isActive())
873 return;
874
875 if (src.isNull())
876 return;
877
878 QRectF srcRect = rect;
879 if (srcRect.isNull())
880 srcRect = src.rect();
881
882 if (d->radius <= 1) {
883 painter->drawPixmap(srcRect.translated(p), src, srcRect);
884 return;
885 }
886
887 qreal scaledRadius = radiusScale * d->radius;
888 qreal scale;
890 scaledRadius /= scale;
891
892 QImage srcImage;
893
894 if (srcRect == src.rect()) {
895 srcImage = src.toImage();
896 } else {
897 QRect rect = srcRect.toAlignedRect().intersected(src.rect());
898 srcImage = src.copy(rect).toImage();
899 }
900
903 qt_blurImage(painter, srcImage, scaledRadius, (d->hints & QGraphicsBlurEffect::QualityHint), false);
905}
906
907// grayscales the image to dest (could be same). If rect isn't defined
908// destination image size is used to determine the dimension of grayscaling
909// process.
910static void grayscale(const QImage &image, QImage &dest, const QRect& rect = QRect())
911{
912 QRect destRect = rect;
913 QRect srcRect = rect;
914 if (rect.isNull()) {
915 srcRect = dest.rect();
916 destRect = dest.rect();
917 }
918 if (&image != &dest) {
919 destRect.moveTo(QPoint(0, 0));
920 }
921
922 const unsigned int *data = (const unsigned int *)image.bits();
923 unsigned int *outData = (unsigned int *)dest.bits();
924
925 if (dest.size() == image.size() && image.rect() == srcRect) {
926 // a bit faster loop for grayscaling everything
927 int pixels = dest.width() * dest.height();
928 for (int i = 0; i < pixels; ++i) {
929 int val = qGray(data[i]);
930 outData[i] = qRgba(val, val, val, qAlpha(data[i]));
931 }
932 } else {
933 int yd = destRect.top();
934 for (int y = srcRect.top(); y <= srcRect.bottom() && y < image.height(); y++) {
935 data = (const unsigned int*)image.scanLine(y);
936 outData = (unsigned int*)dest.scanLine(yd++);
937 int xd = destRect.left();
938 for (int x = srcRect.left(); x <= srcRect.right() && x < image.width(); x++) {
939 int val = qGray(data[x]);
940 outData[xd++] = qRgba(val, val, val, qAlpha(data[x]));
941 }
942 }
943 }
944}
945
967{
968 Q_DECLARE_PUBLIC(QPixmapColorizeFilter)
969public:
975};
976
985 : QPixmapFilter(*new QPixmapColorizeFilterPrivate, ColorizeFilter, parent)
986{
988 d->color = QColor(0, 0, 192);
989 d->strength = qreal(1);
990 d->opaque = true;
991 d->alphaBlend = false;
992}
993
998{
999}
1000
1007{
1008 Q_D(const QPixmapColorizeFilter);
1009 return d->color;
1010}
1011
1018{
1020 d->color = color;
1021}
1022
1030{
1031 Q_D(const QPixmapColorizeFilter);
1032 return d->strength;
1033}
1034
1041{
1043 d->strength = qBound(qreal(0), strength, qreal(1));
1044 d->opaque = !qFuzzyIsNull(d->strength);
1045 d->alphaBlend = !qFuzzyIsNull(d->strength - 1);
1046}
1047
1051void QPixmapColorizeFilter::draw(QPainter *painter, const QPointF &dest, const QPixmap &src, const QRectF &srcRect) const
1052{
1053 Q_D(const QPixmapColorizeFilter);
1054
1055 if (src.isNull())
1056 return;
1057
1058 // raster implementation
1059
1060 if (!d->opaque) {
1061 painter->drawPixmap(dest, src, srcRect);
1062 return;
1063 }
1064
1065 QImage srcImage;
1066 QImage destImage;
1067
1068 if (srcRect.isNull()) {
1069 srcImage = src.toImage();
1071 srcImage = std::move(srcImage).convertToFormat(format);
1072 destImage = QImage(srcImage.size(), srcImage.format());
1073 } else {
1074 QRect rect = srcRect.toAlignedRect().intersected(src.rect());
1075
1076 srcImage = src.copy(rect).toImage();
1078 srcImage = std::move(srcImage).convertToFormat(format);
1079 destImage = QImage(rect.size(), srcImage.format());
1080 }
1081 destImage.setDevicePixelRatio(src.devicePixelRatio());
1082
1083 // do colorizing
1084 QPainter destPainter(&destImage);
1085 grayscale(srcImage, destImage, srcImage.rect());
1087 destPainter.fillRect(srcImage.rect(), d->color);
1088 destPainter.end();
1089
1090 if (d->alphaBlend) {
1091 // alpha blending srcImage and destImage
1092 QImage buffer = srcImage;
1093 QPainter bufPainter(&buffer);
1094 bufPainter.setOpacity(d->strength);
1095 bufPainter.drawImage(0, 0, destImage);
1096 bufPainter.end();
1097 destImage = std::move(buffer);
1098 }
1099
1100 if (srcImage.hasAlphaChannel()) {
1102 QPainter maskPainter(&destImage);
1104 maskPainter.drawImage(0, 0, srcImage);
1105 }
1106
1107 painter->drawImage(dest, destImage);
1108}
1109
1111{
1112public:
1114 : offset(8, 8), color(63, 63, 63, 180), radius(1) {}
1115
1119};
1120
1160 : QPixmapFilter(*new QPixmapDropShadowFilterPrivate, DropShadowFilter, parent)
1161{
1162}
1163
1170{
1171}
1172
1183{
1184 Q_D(const QPixmapDropShadowFilter);
1185 return d->radius;
1186}
1187
1198{
1200 d->radius = radius;
1201}
1202
1211{
1212 Q_D(const QPixmapDropShadowFilter);
1213 return d->color;
1214}
1215
1224{
1226 d->color = color;
1227}
1228
1237{
1238 Q_D(const QPixmapDropShadowFilter);
1239 return d->offset;
1240}
1241
1250{
1252 d->offset = offset;
1253}
1254
1271{
1272 Q_D(const QPixmapDropShadowFilter);
1273 return rect.united(rect.translated(d->offset).adjusted(-d->radius, -d->radius, d->radius, d->radius));
1274}
1275
1280 const QPointF &pos,
1281 const QPixmap &px,
1282 const QRectF &src) const
1283{
1284 Q_D(const QPixmapDropShadowFilter);
1285
1286 if (px.isNull())
1287 return;
1288
1291 tmp.fill(0);
1292 QPainter tmpPainter(&tmp);
1294 tmpPainter.drawPixmap(d->offset, px);
1295 tmpPainter.end();
1296
1297 // blur the alpha channel
1300 blurred.fill(0);
1301 QPainter blurPainter(&blurred);
1302 qt_blurImage(&blurPainter, tmp, d->radius, false, true);
1303 blurPainter.end();
1304
1305 tmp = std::move(blurred);
1306
1307 // blacken the image...
1308 tmpPainter.begin(&tmp);
1310 tmpPainter.fillRect(tmp.rect(), d->color);
1311 tmpPainter.end();
1312
1313 // draw the blurred drop shadow...
1314 p->drawImage(pos, tmp);
1315
1316 // Draw the actual pixmap...
1317 p->drawPixmap(pos, px, src);
1318}
1319
1321
1322#include "moc_qpixmapfilter_p.cpp"
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition qcolor.h:31
The QGraphicsBlurEffect class provides a blur effect.
\inmodule QtGui
Definition qimage.h:37
bool hasAlphaChannel() const
Returns true if the image has a format that respects the alpha channel, otherwise returns false.
Definition qimage.cpp:4571
qsizetype bytesPerLine() const
Returns the number of bytes per image scanline.
Definition qimage.cpp:1538
uchar * scanLine(int)
Returns a pointer to the pixel data at the scanline with index i.
Definition qimage.cpp:1615
QImage copy(const QRect &rect=QRect()) const
Returns a sub-area of the image as a new image.
QSize size() const
Returns the size of the image, i.e.
int width() const
Returns the width of the image.
uchar * bits()
Returns a pointer to the first pixel data.
Definition qimage.cpp:1677
int height() const
Returns the height of the image.
@ Format_RGB32
Definition qimage.h:46
@ Format_ARGB8565_Premultiplied
Definition qimage.h:50
@ Format_Indexed8
Definition qimage.h:45
@ Format_ARGB32_Premultiplied
Definition qimage.h:48
@ Format_Grayscale8
Definition qimage.h:66
void fill(uint pixel)
Fills the entire image with the given pixelValue.
Definition qimage.cpp:1738
Format format() const
Returns the format of the image.
Definition qimage.cpp:2146
QRect rect() const
Returns the enclosing rectangle (0, 0, width(), height()) of the image.
void setDevicePixelRatio(qreal scaleFactor)
Sets the device pixel ratio for the image.
Definition qimage.cpp:1488
QSizeF deviceIndependentSize() const
Returns the size of the image in device independent pixels.
Definition qimage.cpp:1511
QImage convertToFormat(Format f, Qt::ImageConversionFlags flags=Qt::AutoColor) const &
Definition qimage.h:124
int depth() const
\inmodule QtCore
Definition qobject.h:90
virtual int devType() const
QPaintDevice * paintDevice() const
Returns the device that this engine is painting on, if painting is active; otherwise returns \nullptr...
The QPainter class performs low-level painting on widgets and other paint devices.
Definition qpainter.h:46
QPaintEngine * paintEngine() const
Returns the paint engine that the painter is currently operating on if the painter is active; otherwi...
QTransform combinedTransform() const
Returns the transformation matrix combining the current window/viewport and world transformation.
bool begin(QPaintDevice *)
Begins painting the paint device and returns true if successful; otherwise returns false.
const QTransform & worldTransform() const
Returns the world transformation matrix.
void setOpacity(qreal opacity)
void setCompositionMode(CompositionMode mode)
Sets the composition mode to the given mode.
void setWorldTransform(const QTransform &matrix, bool combine=false)
Sets the world transformation matrix.
void drawImage(const QRectF &targetRect, const QImage &image, const QRectF &sourceRect, Qt::ImageConversionFlags flags=Qt::AutoColor)
Draws the rectangular portion source of the given image into the target rectangle in the paint device...
const QTransform & deviceTransform() const
Returns the matrix that transforms from logical coordinates to device coordinates of the platform dep...
void drawPixmap(const QRectF &targetRect, const QPixmap &pixmap, const QRectF &sourceRect)
Draws the rectangular portion source of the given pixmap into the given target in the paint device.
@ SmoothPixmapTransform
Definition qpainter.h:54
bool end()
Ends painting.
const QTransform & transform() const
Alias for worldTransform().
CompositionMode
Defines the modes supported for digital image compositing.
Definition qpainter.h:97
@ CompositionMode_SourceOver
Definition qpainter.h:98
@ CompositionMode_Source
Definition qpainter.h:101
@ CompositionMode_DestinationIn
Definition qpainter.h:104
@ CompositionMode_Screen
Definition qpainter.h:114
@ CompositionMode_SourceIn
Definition qpainter.h:103
bool isActive() const
Returns true if begin() has been called and end() has not yet been called; otherwise returns false.
void translate(const QPointF &offset)
Translates the coordinate system by the given offset; i.e.
void fillRect(const QRectF &, const QBrush &)
Fills the given rectangle with the brush specified.
QGraphicsBlurEffect::BlurHints hints
The QPixmapBlurFilter class provides blur filtering for pixmaps.
void setBlurHints(QGraphicsBlurEffect::BlurHints hints)
Setting the blur hints to PerformanceHint causes the implementation to trade off visual quality to bl...
QPixmapBlurFilter(QObject *parent=nullptr)
Constructs a pixmap blur filter.
void setRadius(qreal radius)
Sets the radius of the blur filter.
QGraphicsBlurEffect::BlurHints blurHints() const
Gets the blur hints of the blur filter.
QRectF boundingRectFor(const QRectF &rect) const override
qreal radius() const
Gets the radius of the blur filter.
~QPixmapBlurFilter()
Destructor of pixmap blur filter.
void draw(QPainter *painter, const QPointF &dest, const QPixmap &src, const QRectF &srcRect=QRectF()) const override
The QPixmapColorizeFilter class provides colorizing filtering for pixmaps.
QColor color() const
Gets the color of the colorize filter.
qreal strength() const
Gets the strength of the colorize filter, 1.0 means full colorized while 0.0 equals to no filtering a...
void draw(QPainter *painter, const QPointF &dest, const QPixmap &src, const QRectF &srcRect=QRectF()) const override
QPixmapColorizeFilter(QObject *parent=nullptr)
Constructs an pixmap colorize filter.
void setStrength(qreal strength)
Sets the strength of the colorize filter to strength.
void setColor(const QColor &color)
Sets the color of the colorize filter to the color specified.
The QPixmapConvolutionFilter class provides convolution filtering for pixmaps.
void draw(QPainter *painter, const QPointF &dest, const QPixmap &src, const QRectF &srcRect=QRectF()) const override
QPixmapConvolutionFilter(QObject *parent=nullptr)
Constructs a pixmap convolution filter.
void setConvolutionKernel(const qreal *matrix, int rows, int columns)
Sets convolution kernel with the given number of rows and columns.
~QPixmapConvolutionFilter()
Destructor of pixmap convolution filter.
QRectF boundingRectFor(const QRectF &rect) const override
The QPixmapDropShadowFilter class is a convenience class for drawing pixmaps with drop shadows.
void setOffset(const QPointF &offset)
Sets the shadow offset in pixels to the offset specified.
qreal blurRadius() const
Returns the radius in pixels of the blur on the drop shadow.
QPixmapDropShadowFilter(QObject *parent=nullptr)
Constructs drop shadow filter.
QColor color() const
Returns the color of the drop shadow.
QRectF boundingRectFor(const QRectF &rect) const override
void draw(QPainter *p, const QPointF &pos, const QPixmap &px, const QRectF &src=QRectF()) const override
void setColor(const QColor &color)
Sets the color of the drop shadow to the color specified.
QPointF offset() const
Returns the shadow offset in pixels.
~QPixmapDropShadowFilter()
Destroys drop shadow filter.
void setBlurRadius(qreal radius)
Sets the radius in pixels of the blur on the drop shadow to the radius specified.
QPixmapFilter::FilterType type
The QPixmapFilter class provides the basic functionality for pixmap filter classes....
virtual QRectF boundingRectFor(const QRectF &rect) const
Returns the bounding rectangle that is affected by the pixmap filter if the filter is applied to the ...
virtual ~QPixmapFilter()=0
Destroys the pixmap filter.
FilterType type() const
Returns the type of the filter.
QPixmapFilter(QPixmapFilterPrivate &d, FilterType type, QObject *parent)
Returns a copy of the pixmap that is transformed using the given transformation transform and transfo...
Definition qpixmap.h:27
QSize size() const
Returns the size of the pixmap.
Definition qpixmap.cpp:497
bool isNull() const
Returns true if this is a null pixmap; otherwise returns false.
Definition qpixmap.cpp:460
qreal devicePixelRatio() const
Returns the device pixel ratio for the pixmap.
Definition qpixmap.cpp:580
\inmodule QtCore\reentrant
Definition qpoint.h:214
\inmodule QtCore\reentrant
Definition qpoint.h:23
constexpr int x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:127
constexpr int y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:132
The QRasterPaintEngine class enables hardware acceleration of painting operations in Qt for Embedded ...
\inmodule QtCore\reentrant
Definition qrect.h:483
constexpr bool isEmpty() const noexcept
Returns true if the rectangle is empty, otherwise returns false.
Definition qrect.h:647
constexpr void moveTo(qreal x, qreal y) noexcept
Moves the rectangle, leaving the top-left corner at the given position (x, y).
Definition qrect.h:736
QRect toAlignedRect() const noexcept
Definition qrect.cpp:2330
constexpr QRectF translated(qreal dx, qreal dy) const noexcept
Returns a copy of the rectangle that is translated dx along the x axis and dy along the y axis,...
Definition qrect.h:748
bool contains(const QRectF &r) const noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qrect.cpp:1985
constexpr QRectF adjusted(qreal x1, qreal y1, qreal x2, qreal y2) const noexcept
Returns a new rectangle with dx1, dy1, dx2 and dy2 added respectively to the existing coordinates of ...
Definition qrect.h:799
constexpr bool isNull() const noexcept
Returns true if the rectangle is a null rectangle, otherwise returns false.
Definition qrect.h:644
constexpr QRect toRect() const noexcept
Returns a QRect based on the values of this rectangle.
Definition qrect.h:845
\inmodule QtCore\reentrant
Definition qrect.h:30
QRect intersected(const QRect &other) const noexcept
Definition qrect.h:414
constexpr int bottom() const noexcept
Returns the y-coordinate of the rectangle's bottom edge.
Definition qrect.h:181
constexpr QPoint topLeft() const noexcept
Returns the position of the rectangle's top-left corner.
Definition qrect.h:220
constexpr int top() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:175
constexpr int left() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:172
constexpr void moveTo(int x, int t) noexcept
Moves the rectangle, leaving the top-left corner at the given position (x, y).
Definition qrect.h:269
constexpr int right() const noexcept
Returns the x-coordinate of the rectangle's right edge.
Definition qrect.h:178
constexpr QSize toSize() const noexcept
Returns an integer based copy of this size.
Definition qsize.h:390
@ BigEndian
Definition qsysinfo.h:29
@ ByteOrder
Definition qsysinfo.h:34
The QTransform class specifies 2D transformations of a coordinate system.
Definition qtransform.h:20
TransformationType type() const
Returns the transformation type of this matrix.
QPixmap p2
QPixmap p1
[0]
double e
rect
[4]
QPixmap pix
Combined button and popup list for selecting options.
Definition image.cpp:4
static QT_WARNING_DISABLE_FLOAT_COMPARE ShiftResult shift(const QBezier *orig, QBezier *shifted, qreal offset, qreal threshold)
Definition qbezier.cpp:309
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
bool qFuzzyIsNull(qfloat16 f) noexcept
Definition qfloat16.h:303
int qRound(qfloat16 d) noexcept
Definition qfloat16.h:281
auto qPow(T1 x, T2 y)
Definition qmath.h:180
constexpr const T & qBound(const T &min, const T &val, const T &max)
Definition qminmax.h:44
GLboolean GLboolean GLboolean b
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat z
GLint GLint GLint GLint GLint x
[0]
GLenum mode
GLboolean GLboolean GLboolean GLboolean a
[7]
GLuint index
[2]
GLboolean r
[2]
GLenum src
const void GLsizei GLsizei stride
GLenum GLuint buffer
GLenum type
GLenum GLenum dst
GLenum target
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint GLintptr offset
GLboolean GLboolean g
GLint GLenum GLsizei GLsizei GLsizei GLint GLenum GLenum const void * pixels
GLint GLsizei GLsizei GLenum format
GLint y
GLsizei GLsizei GLchar * source
GLuint GLenum GLenum transform
GLuint GLfloat * val
GLint void * img
Definition qopenglext.h:233
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const void * bits
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLenum GLenum GLsizei void * row
GLuint64EXT * result
[6]
GLfloat GLfloat p
[1]
GLfloat GLfloat GLfloat alpha
Definition qopenglext.h:418
GLenum GLenum GLenum GLenum GLenum scale
Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale)
void qt_blurrow(QImage &im, int line, int alpha)
#define ZA_MASK
const qreal radiusScale
Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale)
void qt_blurinner_alphaOnly(uchar *bptr, int &z, int alpha)
static void grayscale(const QImage &image, QImage &dest, const QRect &rect=QRect())
#define AVG(a, b)
const int alphaIndex
void expblur(QImage &img, qreal radius, bool improvedQuality=false, int transposed=0)
Q_WIDGETS_EXPORT void qt_blurImage(QPainter *p, QImage &blurImage, qreal radius, bool quality, bool alphaOnly, int transposed=0)
static void convolute(QImage *destImage, const QPointF &pos, const QImage &srcImage, const QRectF &srcRect, QPainter::CompositionMode mode, qreal *kernel, int kernelWidth, int kernelHeight)
int qt_static_shift(int value)
#define Z_MASK
Q_WIDGETS_EXPORT QImage qt_halfScaled(const QImage &source)
#define AVG16(a, b)
void qt_blurinner(uchar *bptr, int &zR, int &zG, int &zB, int &zA, int alpha)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QT_BEGIN_NAMESPACE typedef unsigned int QRgb
Definition qrgb.h:13
constexpr int qGray(int r, int g, int b)
Definition qrgb.h:36
constexpr QRgb qRgba(int r, int g, int b, int a)
Definition qrgb.h:33
constexpr int qAlpha(QRgb rgb)
Definition qrgb.h:27
SSL_CTX int(* cb)(SSL *ssl, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
unsigned int quint32
Definition qtypes.h:45
unsigned char uchar
Definition qtypes.h:27
unsigned short quint16
Definition qtypes.h:43
ptrdiff_t qsizetype
Definition qtypes.h:70
unsigned int uint
Definition qtypes.h:29
double qreal
Definition qtypes.h:92
unsigned char quint8
Definition qtypes.h:41
QT_BEGIN_NAMESPACE typedef uchar * output
QObject::connect nullptr
QPainter painter(this)
[7]
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent