【问题标题】:What is the fastest way to access a pixel in QImage?在 QImage 中访问像素的最快方法是什么?
【发布时间】:2014-04-17 23:47:37
【问题描述】:

我想知道修改 QImage 的一部分的最快方法是什么。

我有这段代码必须以 30Hz 的频率执行。它通过一种锁孔显示图像。不可能看到整个图像,只能看到圆圈内的一部分。第一个 for 循环擦除之前的“显示的钥匙孔部分”,第二个更新“显示的钥匙孔”的位置。

for (int i = (prev_y - r_y); i < (prev_y + r_y); i++){
        QRgb *line = (QRgb *)backgrd->scanLine(i);
        for(int j = (prev_x - r_x); j < (prev_x + r_x) ; j++){
            if((i >= 0 && i < this->backgrd->height()) && (j >= 0 && j < this->backgrd->width()))
                line[j] = qRgb(0,0,0);
        }
    }
    prev_x = new_x; prev_y = new_y;

    for (int i = (new_y - r_y); i < (new_y + r_y); i++){
        QRgb *line = (QRgb *)backgrd->scanLine(i);
        QRgb *line2 = (QRgb *)this->picture->scanLine(i);
        for(int j = (new_x - r_x); j < (new_x + r_x) ; j++){
            if ((((new_x - j)*(new_x - j)/(r_x*r_x) + (new_y - i)*(new_y - i)/(r_y*r_y)) <= 1) && (i >= 0) && (i < this->picture->height())&& (j >= 0) && (j < this->picture->width()))
                line[j] = line2[j];
        }
    }
    this->current_img = this->backgrd;
}
this->update(); //Display QImage* this->current_img

如果我分析程序的时间戳,我会发现每次执行时执行流程都会出现延迟...... 访问 QImage 中的像素是否非常耗时?难道我做错了什么? Qt 程序有没有比 QImage 更好的替代品?

【问题讨论】:

  • 欢迎使用每像素每帧代码。是时候进行微优化了。多少像素?您可以将方法访问移出循环吗?将条件移出循环?按顺序触摸内存且仅一次
  • 它是一个大约 80x80 像素的正方形......但我意识到大小并不重要,因为即使修改了一些像素,我也有相同的行为......我将把它移到另一个部分代码...
  • sscce.org 的时间——内部循环的细节不重要,如果它们不产生影响!
  • 最快的方法是:根本不做。将源图像的矩形部分复制到新图像,然后在其上绘画以提供锁孔效果。光栅绘制引擎可能会比您编写的任何代码快得多。代码将更容易维护。如果您所做的只是在图像上绘画,则无需使用上面显示的代码。
  • 你不能再改进它了。 IMO 首先你应该使用分析器来确保你正在优化正确的代码。即使在古老的机器上,80x80 尺寸图像的附加代码也应该比 30Hz 运行得快得多。

标签: c++ qt opengl qimage


【解决方案1】:

如何在数组/qimage 中预渲染您的“钥匙孔”并与源进行按位与?

  • 原始像素 && 黑色 => 黑色
  • 原始像素 && 白色 => 原始像素

你在最里面的循环中有很多条件(虽然有些可以移出),但是用乘法和除法计算圆半径看起来很昂贵。您可以为每一帧重复使用锁孔蒙版,因此无需执行计算。

【讨论】:

    【解决方案2】:
    • 您可以至少将一些条件移到外循环,并可能预先计算条件内的一些项,尽管这可能会被优化。
    • 仅为您修改的矩形调用更新
    • 从哪里获得时间戳?也许您会在其他地方浪费时间?

    【讨论】:

    • 耗时的操作(来自时间戳分析)是对行和像素的访问。那么这是在 Qt 中访问像素的最快方法吗?还是有最快的方法?
    【解决方案3】:

    其实我理解不是像素访问慢,而是渲染。 在我做的测试中,我使用了纯色图像,但是这些图像比从文件加载的复杂图像渲染起来要快得多。通过其他测试,我意识到渲染速度很慢。

    渲染 QImage 的最快方法是首先使用转换它

    public: static QImage QGLWidget::convertToGLFormat(const QImage &img)
    

    然后可以快速操作图像(它保留了 bits() scanline() width() 和 height() 函数) 并且可以通过openGL快速显示(无需进一步转换)

    QPainter painter(this);
    glDrawPixels(img.width(), img.height(), GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
    painter.end();
    

    【讨论】:

      【解决方案4】:

      据我所知,访问 QImage 数据的最快方法是使用 QImage::bits(),它可以让您直接访问 QImage 的数据。

      对于您的问题,更好的方法是按照 Bgie 的建议进行操作:使用代表钥匙孔的数组并仅执行按位与运算。

      这将有助于为您的图像选择正确的格式,RGB32 和 ARG32_Premultiplied_ARGB32 格式是最快的。如果不需要,请不要使用 ARGB32。

      【讨论】:

      • 他使用了scanLine(),它和bits()一样快。
      猜你喜欢
      • 1970-01-01
      • 2016-12-17
      • 2012-11-18
      • 1970-01-01
      • 2017-12-11
      • 2020-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多