访问QImage中像素的最快方法是什么

What is the fastest way to access a pixel in QImage?

本文关键字:方法 是什么 QImage 像素 访问      更新时间:2023-10-16

我想知道修改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更好的替代方案?

在数组/qimage中预先呈现您的"keykey",并与源进行逐位and,怎么样?

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

在最里面的循环中有很多条件(不过有些条件可以移出),但使用乘法和除法计算圆半径看起来代价高昂。可以对每个帧重复使用锁孔遮罩,因此无需执行任何计算。

  • 您可以将一些条件至少移动到外循环,并可能预先计算条件中的一些项,尽管这可能会被优化
  • 仅对您修改的矩形调用更新
  • 你在哪里得到时间戳?也许你在别的地方浪费时间了

实际上我理解不是像素加速慢,而是渲染。在测试过程中,我使用了纯彩色图像,但这类图像的渲染速度比从文件加载的复杂图像快得多。在其他测试中,我意识到渲染速度很慢。

渲染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();

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

对于你的问题,一个更好的方法是按照Bgie的建议:使用一个表示钥匙孔的数组,只进行逐位and运算。

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