模糊QI法师阿尔法通道



我试图模糊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。

模糊QI法师阿尔法通道的正确方法是什么?

我遇到了关于像素读写访问的类似问题:

  1. 反转循环。图像在内存中作为一系列行进行布局。所以你应该先按高度然后按宽度访问
  2. 使用QImage::scanline来访问数据,而不是昂贵的QImage::pixelQImage::setPixel。扫描(又称行(中的像素保证是连续的。

您的代码将如下所示:

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( 处的 alpha 值之和为 s(x,y(。向任一方向移动一个像素时,将添加一条线,同时删除一条线。假设您水平移动。如果 L(x,y( 是以 (x,y) 为中心的长度2*radius垂直线的总和,则有

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

这使您可以在第一次传递中有效地计算总和矩阵(然后通过除以像素数来求平均值(。

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

最新更新