278 const QImage &srcImage,
279 const QRectF &srcRect,
280 QPainter::CompositionMode mode,
285 const QImage processImage = (srcImage.format() != QImage::Format_ARGB32_Premultiplied ) ? srcImage.convertToFormat(QImage::Format_ARGB32_Premultiplied) : srcImage;
288 std::unique_ptr<
int[]> fixedKernel(
new int[kernelWidth * kernelHeight]);
289 for(
int i = 0; i < kernelWidth*kernelHeight; i++)
291 fixedKernel[i] = (
int)(65536 * kernel[i]);
293 QRectF trect = srcRect.isNull() ? processImage.rect() : srcRect;
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());
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());
303 const uint *sourceStart = (
const uint*)processImage.scanLine(0);
304 uint *outputStart = (uint*)destImage->scanLine(0);
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++) {
317 int kernely = -kernelHeight/2;
319 int endy = kernelHeight;
320 if (yk+kernely+endy >= srcImage.height())
321 endy = kernelHeight-((yk+kernely+endy)-srcImage.height())-1;
323 starty = -(yk+kernely);
325 int kernelx = -kernelWidth/2;
327 int endx = kernelWidth;
328 if (xk+kernelx+endx >= srcImage.width())
329 endx = kernelWidth-((xk+kernelx+endx)-srcImage.width())-1;
331 startx = -(xk+kernelx);
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;
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);
352 if (mode == QPainter::CompositionMode_Source) {
353 uint color = (a<<24)+(r<<16)+(g<<8)+b;
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);
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));
377void QPixmapConvolutionFilter::draw(QPainter *painter,
const QPointF &p,
const QPixmap &src,
const QRectF& srcRect)
const
379 Q_D(
const QPixmapConvolutionFilter);
380 if (!painter->isActive())
383 if (d->kernelWidth<=0 || d->kernelHeight <= 0)
391 QImage *target =
nullptr;
392 if (painter->paintEngine()->paintDevice()->devType() == QInternal::Image) {
393 target =
static_cast<QImage *>(painter->paintEngine()->paintDevice());
395 QTransform mat = painter->combinedTransform();
397 if (mat.type() > QTransform::TxTranslate) {
401 QRasterPaintEngine *pe =
static_cast<QRasterPaintEngine *>(painter->paintEngine());
402 if (pe->clipType() == QRasterPaintEngine::ComplexClip)
406 QRectF clip = pe->clipBoundingRect();
407 QRectF rect = boundingRectFor(srcRect.isEmpty() ? src.rect() : srcRect);
408 QTransform x = painter->deviceTransform();
409 if (!clip.contains(rect.translated(x.dx() + p.x(), x.dy() + p.y()))) {
418 QTransform x = painter->deviceTransform();
419 QPointF offset(x.dx(), x.dy());
421 convolute(target, p+offset, src.toImage(), srcRect, QPainter::CompositionMode_SourceOver, d->convolutionKernel, d->kernelWidth, d->kernelHeight);
423 QRect srect = srcRect.isNull() ? src.rect() : srcRect.toRect();
424 QRect rect = boundingRectFor(srect).toRect();
425 QImage result = QImage(rect.size(), QImage::Format_ARGB32_Premultiplied);
426 QPoint offset = srect.topLeft() - rect.topLeft();
431 QPainter::CompositionMode_Source,
432 d->convolutionKernel,
435 painter->drawImage(p - offset, result);
565void QPixmapBlurFilter::draw(QPainter *painter,
const QPointF &p,
const QPixmap &src,
const QRectF &rect)
const
567 Q_D(
const QPixmapBlurFilter);
568 if (!painter->isActive())
574 QRectF srcRect = rect;
575 if (srcRect.isNull())
576 srcRect = src.rect();
578 if (d->radius <= 1) {
579 painter->drawPixmap(srcRect.translated(p), src, srcRect);
583 qreal scaledRadius = radiusScale * d->radius;
585 if (qt_scaleForTransform(painter->transform(), &scale))
586 scaledRadius /= scale;
590 if (srcRect == src.rect()) {
591 srcImage = src.toImage();
593 QRect rect = srcRect.toAlignedRect().intersected(src.rect());
594 srcImage = src.copy(rect).toImage();
597 QTransform transform = painter->worldTransform();
598 painter->translate(p);
599 qt_blurImage(painter, srcImage, scaledRadius, (d->hints & QGraphicsBlurEffect::QualityHint),
false);
600 painter->setWorldTransform(transform);
606static void grayscale(
const QImage &image, QImage &dest,
const QRect& rect = QRect())
608 QRect destRect = rect;
609 QRect srcRect = rect;
611 srcRect = dest.rect();
612 destRect = dest.rect();
614 if (&image != &dest) {
615 destRect.moveTo(QPoint(0, 0));
618 const unsigned int *data = (
const unsigned int *)image.bits();
619 unsigned int *outData = (
unsigned int *)dest.bits();
621 if (dest.size() == image.size() && image.rect() == srcRect) {
623 int pixels = dest.width() * dest.height();
624 for (
int i = 0; i < pixels; ++i) {
625 int val = qGray(data[i]);
626 outData[i] = qRgba(val, val, val, qAlpha(data[i]));
629 int yd = destRect.top();
630 for (
int y = srcRect.top(); y <= srcRect.bottom() && y < image.height(); y++) {
631 data = (
const unsigned int*)image.scanLine(y);
632 outData = (
unsigned int*)dest.scanLine(yd++);
633 int xd = destRect.left();
634 for (
int x = srcRect.left(); x <= srcRect.right() && x < image.width(); x++) {
635 int val = qGray(data[x]);
636 outData[xd++] = qRgba(val, val, val, qAlpha(data[x]));
747void QPixmapColorizeFilter::draw(QPainter *painter,
const QPointF &dest,
const QPixmap &src,
const QRectF &srcRect)
const
749 Q_D(
const QPixmapColorizeFilter);
757 painter->drawPixmap(dest, src, srcRect);
764 if (srcRect.isNull()) {
765 srcImage = src.toImage();
766 const auto format = srcImage.hasAlphaChannel() ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32;
767 srcImage = std::move(srcImage).convertToFormat(format);
768 destImage = QImage(srcImage.size(), srcImage.format());
770 QRect rect = srcRect.toAlignedRect().intersected(src.rect());
772 srcImage = src.copy(rect).toImage();
773 const auto format = srcImage.hasAlphaChannel() ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32;
774 srcImage = std::move(srcImage).convertToFormat(format);
775 destImage = QImage(rect.size(), srcImage.format());
777 destImage.setDevicePixelRatio(src.devicePixelRatio());
780 QPainter destPainter(&destImage);
781 grayscale(srcImage, destImage, srcImage.rect());
782 destPainter.setCompositionMode(QPainter::CompositionMode_Screen);
783 destPainter.fillRect(srcImage.rect(), d->color);
788 QImage buffer = srcImage;
789 QPainter bufPainter(&buffer);
790 bufPainter.setOpacity(d->strength);
791 bufPainter.drawImage(0, 0, destImage);
793 destImage = std::move(buffer);
796 if (srcImage.hasAlphaChannel()) {
797 Q_ASSERT(destImage.format() == QImage::Format_ARGB32_Premultiplied);
798 QPainter maskPainter(&destImage);
799 maskPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
800 maskPainter.drawImage(0, 0, srcImage);
803 painter->drawImage(dest, destImage);
975void QPixmapDropShadowFilter::draw(QPainter *p,
978 const QRectF &src)
const
980 Q_D(
const QPixmapDropShadowFilter);
985 QImage tmp(px.size(), QImage::Format_ARGB32_Premultiplied);
986 tmp.setDevicePixelRatio(px.devicePixelRatio());
988 QPainter tmpPainter(&tmp);
989 tmpPainter.setCompositionMode(QPainter::CompositionMode_Source);
990 tmpPainter.drawPixmap(d->offset, px);
994 QImage blurred(tmp.size(), QImage::Format_ARGB32_Premultiplied);
995 blurred.setDevicePixelRatio(px.devicePixelRatio());
997 QPainter blurPainter(&blurred);
998 qt_blurImage(&blurPainter, tmp, d->radius,
false,
true);
1001 tmp = std::move(blurred);
1004 tmpPainter.begin(&tmp);
1005 tmpPainter.setCompositionMode(QPainter::CompositionMode_SourceIn);
1006 tmpPainter.fillRect(tmp.rect(), d->color);
1010 p->drawImage(pos, tmp);
1013 p->drawPixmap(pos, px, src);
static void convolute(QImage *destImage, const QPointF &pos, const QImage &srcImage, const QRectF &srcRect, QPainter::CompositionMode mode, qreal *kernel, int kernelWidth, int kernelHeight)