模糊QImage alpha通道

时间:2016-02-08 13:29:23

标签: qt

我正在尝试模糊QImage alpha通道。我当前的实现使用了弃用的'alphaChannel'方法并且运行缓慢。

QImage blurImage(const QImage & image, double radius)
{
  QImage newImage = image.convertToFormat(QImage::Format_ARGB32);

  QImage alpha = newImage.alphaChannel();
  QImage blurredAlpha = alpha;
  for (int x = 0; x < alpha.width(); x++)
  {
    for (int y = 0; y < alpha.height(); y++)
    {
      uint color = calculateAverageAlpha(x, y, alpha, radius);
      blurredAlpha.setPixel(x, y, color);
    }
  }
  newImage.setAlphaChannel(blurredAlpha);

  return newImage;
}

我也尝试使用QGraphicsBlurEffect来实现它,但它不会影响alpha。

模糊QImage alpha通道的正确方法是什么?

1 个答案:

答案 0 :(得分:0)

我遇到了similar question about pixel read\write access

  1. 反转你的循环。图像作为连续的行布置在存储器中。所以你应该先按高度然后按宽度
  2. 进行访问
  3. 使用QImage::scanline访问数据,而不是昂贵的QImage::pixelQImage::setPixel。扫描中的像素(也称为行)保证是连续的。
  4. 您的代码如下:

    for (int ii = 0; ii < image.height(); ii++) {
        uchar* scan = image.scanLine(ii);
        int depth =4;
        for (int jj = 0; jj < image.width(); jj++) {
            //it is in fact an rgba
            QRgb* rgbpixel = reinterpret_cast<QRgb*>(scan + jj*depth);
            QColor color(*rgbpixel);
            int alpha = calculateAverageAlpha(ii, jj, color, image);
            color.setAlpha(alpha);
    
            //write
            *rgbpixel = color.rgba();
        }
    }
    

    您可以进一步优化Alpha平均值的计算。让我们看一下半径中像素的总和。半径(x,y)处的α值之和为s(x,y)。在任一方向上移动一个像素时,会在删除一行时添加一行。让我们说你水平移动。如果l(x,y)是以2*radius为中心的长度(x,y)的垂直线的总和,那么

      s(x + 1, y) = s(x, y) + l(x + r + 1, y) - l(x - r, y)
    

    允许您在第一遍中有效地计算和的矩阵(然后是平均值,除以像素数)。

    我怀疑这种优化已经在opencv这样的库中以更好的方式实现了。因此,如果您希望节省时间,我建议您使用现有的opencv函数。