【问题标题】:QT4 How to blur QPixmap image?QT4 如何模糊 QPixmap 图像?
【发布时间】:2010-10-11 02:42:29
【问题描述】:

QT4如何模糊QPixmap图像?

我正在寻找类似以下内容之一的内容:

Blur(pixmap); 
painter.Blur(); 
painter.Blur(rect);

最好的方法是什么?

【问题讨论】:

  • 我认为 liuyanghejerry 已经等待了足够长的时间来获得最佳答案。

标签: qt graphics qt4 effects


【解决方案1】:

1st) 声明外部 QT 例程:

QT_BEGIN_NAMESPACE
  extern Q_WIDGETS_EXPORT void qt_blurImage( QPainter *p, QImage &blurImage, qreal radius, bool quality, bool alphaOnly, int transposed = 0 );
QT_END_NAMESPACE

第二)使用:

  extern QImage srcImg;//source image
  QPixmap pxDst( srcImg.size() );//blurred destination
  pxDst.fill( Qt::transparent );
  {
    QPainter painter( &pxDst );
    qt_blurImage( &painter, srcImg, 2, true, false );//blur radius: 2px
  }

【讨论】:

  • 有时我想知道为什么质量较低的问题会出现而不是好的问题。到目前为止,你的答案是这个问题的最佳答案。 +1
【解决方案2】:

让我们为这个主题做出贡献。从 Qt 5.3 开始,以下函数将帮助您将 QGraphicsEffect 应用于 QImage(并且不会丢失 alpha)

QImage applyEffectToImage(QImage src, QGraphicsEffect *effect, int extent = 0)
{
    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(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;
}

他们,使用这个功能来模糊你的图像很简单:

QGraphicsBlurEffect *blur = new QGraphicsBlurEffect;
blur->setBlurRadius(8);
QImage source("://img1.png");
QImage result = applyEffectToImage(source, blur);
result.save("final.png");

当然,你不需要保存它,这只是一个有用的例子。 你甚至可以投下阴影:

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);

注意extent参数,它将extent像素数添加到原始图像的所有边,特别适用于阴影和模糊不被切断。

【讨论】:

    【解决方案3】:

    看看这个:

    #include <QtGui/QApplication>
    #include <QImage>
    #include <QPixmap>
    #include <QLabel>
    
    QImage blurred(const QImage& image, const QRect& rect, int radius, bool alphaOnly = false)
    {
        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;
    
        int i1 = 0;
        int i2 = 3;
    
        if (alphaOnly)
            i1 = i2 = (QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 3);
    
        for (int col = c1; col <= c2; col++) {
            p = result.scanLine(r1) + col * 4;
            for (int i = i1; i <= i2; i++)
                rgba[i] = p[i] << 4;
    
            p += bpl;
            for (int j = r1; j < r2; j++, p += bpl)
                for (int i = i1; i <= i2; 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 = i1; i <= i2; i++)
                rgba[i] = p[i] << 4;
    
            p += 4;
            for (int j = c1; j < c2; j++, p += 4)
                for (int i = i1; i <= i2; 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 = i1; i <= i2; i++)
                rgba[i] = p[i] << 4;
    
            p -= bpl;
            for (int j = r1; j < r2; j++, p -= bpl)
                for (int i = i1; i <= i2; 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 = i1; i <= i2; i++)
                rgba[i] = p[i] << 4;
    
            p -= 4;
            for (int j = c1; j < c2; j++, p -= 4)
                for (int i = i1; i <= i2; i++)
                    p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4;
        }
    
        return result;
    }
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        QLabel label;
        QImage image("image.png");
        image =  blurred(image,image.rect(),10,false);
        label.setPixmap(QPixmap::fromImage(image));
        label.show();
    
        return a.exec();
    }
    

    【讨论】:

      【解决方案4】:

      方法 1a:获取原始数据并自己动手。您需要充分熟悉位图和模糊算法才能自己实现模糊。如果您想要那种精确度,这就是要走的路。

      QImage image = pixmap.toImage();
      if (image.format() != QImage::Format_RGB32)
           image = image.convertToFormat(QImage::Format_RGB32);
      uchar* bits = image.bits();
      int rowBytes = image.bytesPerLine();
      DoMyOwnBlurAlgorithm(bits, image.width(), image.height(), rowBytes);
      return QPixmap::fromImage(image);
      

      方法 1b:谁需要原始数据?您可以改用 image.pixel(x,y) 和 image.setPixel(x,y,color) 。这不会像 1a 那样快,但应该更容易理解和编码。

      QImage image = pixmap.toImage();
      QImage output(image.width(), image.height(), image.format());
      for (int y=0; y<image.height(); ++y)
         for (int x=0; x<image.width(); ++x)
            output.setPixel(getBlurredColor(image, x, y));
      return output;
      

      方法2:使用QGraphicsBlurEffect,通过小部件或场景。这里的代码使用了一个标签小部件:

      QPixmap BlurAPixmap(const QPixmap& inPixmap)
      {
          QLabel* label = new QLabel();
          label->setPixmap(inPixmap);
          label->setGraphicsEffect(new QGraphicsBlurEffect());
          QPixmap output(inPixmap.width(), inPixmap.height());
          QPainter painter(&output);
          label->render(&painter);
          return output;
      }
      

      根据需要进行调整。例如,我假设默认的图形模糊效果是可以接受的。我在我的项目中使用方法 2。

      【讨论】:

        【解决方案5】:

        Gaussian blur 是一种创建模糊效果的简单方法。

        编辑: 瞧,我遇到了 Qt 的 QGraphicsBlurEffect。在 Qt 4.6 中引入,它似乎完全符合您的要求。

        【讨论】:

        • QGraphicsEffects 旨在应用于图形视图,而不是像素图。但是,高斯模糊的一般概念是要走的路。你只需要在像素图上自己实现算法。 (不过,转换为 QImage 可能更快/更容易。)
        • 每个人都知道这些算法。但是要自己实现它们,我必须有办法: 1. 将 QPixmap 转换为 2d 数组 2. 从 2d 数组转换回 pixmap 的方法。如果您的建议是自己实现它,那么请告诉如何在 QPixmap 和 2d 数组之间进行转换
        • 先转换成QImage,这样你就可以直接访问像素,然后再创建一个QImage,应用卷积核就可以了:)文档会进一步帮助你
        【解决方案6】:

        根据@Петър Петров 对 QT 5 的回答添加 python 代码。

        def applyEffectToImage(src, effect):
            scene = QGraphicsScene()
            item = QGraphicsPixmapItem()
            item.setPixmap(QPixmap.fromImage(src))
            item.setGraphicsEffect(effect)
            scene.addItem(item)
            res = QImage(src.size(), QImage.Format_ARGB32)
            res.fill(Qt.transparent)
            ptr = QPainter(res)
            scene.render(ptr, QRectF(), QRectF(0,0, src.width(), src.height()) )
            return res
        
        blur = QGraphicsBlurEffect()
        blur.setBlurRadius(8)
        source = QImage(r"C:\Users\fran\Desktop\test.png")
        result = applyEffectToImage(source, blur)
        result.save(r"C:\Users\fran\Desktop\result.png")
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-06-10
          • 2010-12-08
          • 1970-01-01
          • 2014-12-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-07-26
          相关资源
          最近更新 更多