简体   繁体   English

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

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

I would like to know what is the fastest way to modify a portion of a QImage. 我想知道修改QImage的一部分的最快方法。

I have this piece of code that has to be executed with a frequency of 30Hz. 我有一段必须以30Hz的频率执行的代码。 It displays an image through a sort of keyhole. 它通过某种钥匙孔显示图像。 It is not possible to see the entire image but only a portion inside a circle. 无法看到整个图像,而只能看到圆内的一部分。 The first for-loop erases the previous "keyhole portion displayed" and the second updates the position of the "displayed keyhole". 第一个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

If I analyse the timestamps of the program I find a delay in the flow of execution every time it is executed... Is it so high consuming to access a pixel in a QImage? 如果我分析程序的时间戳,每次执行时都会发现执行流程存在延迟...访问QImage中的像素是否耗费这么大的精力? Am I doing something wrong? 难道我做错了什么? Is there a better alternative to QImage for a Qt program? Qt程序是否有更好的替代QImage的方法?

How about prerendering your 'keyhole' in an array/qimage and doing a bitwise AND with the source? 如何在数组/ qimage中预渲染“锁孔”并与源进行按位与运算呢?

  • Original pixel && black => black 原始像素&&黑色=>黑色
  • Original pixel && white => original pixel 原始像素&&白色=>原始像素

You have a lot of conditions in the innermost loop (some can be moved out though), but the circle radius calculation with the multiplies and divides looks costly. 在最里面的循环中有很多条件(尽管有些条件可以移出),但是使用乘除法的圆半径计算看起来很昂贵。 You can reuse the keyhole mask for every frame, so no calculations need be performed. 您可以在每个帧中重复使用锁眼掩模,因此无需执行任何计算。

  • You could move some of the conditions at least to the outer loop, and maybe pre-compute some of the terms inside the conditions, though this may be optimized anyway. 您可以将某些条件至少移到外部循环,并可以预先计算条件中的某些项,尽管无论如何都可以对其进行优化。
  • Call update only for the rectangle(s) you modified 仅针对您修改的矩形调用更新
  • Where do you get the time stamp? 您从哪里获得时间戳记? Maybe you lose time somewhere else? 也许您在其他地方浪费时间?

Actually I understood it wasn't pixel acces that was slow , but the rendering. 实际上,我知道不是像素acces较慢 ,而是渲染。 During the tests I did I used plain color images, but these kind of images are much faster to render than complex images loaded from file. 在测试中,我确实使用了单色图像,但是与从文件加载的复杂图像相比,此类图像的渲染速度要快得多。 With other tests I realized was the rendering that was slow. 通过其他测试,我意识到渲染速度很慢。

The fastest way to render an QImage is first of all to transform it using 渲染QImage最快的方法是首先使用

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

then the image can be fastly manipulated (it preserves bits() scanline() width() and height() functions) and can be displayed very fast by openGL (no further conversions are necessary) 然后可以快速处理图像(保留bits()scanline()width()和height()函数),并可以通过openGL快速显示(无需进一步转换)

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

As far as I know the fastest way to access the data of a QImage is to use QImage::bits() which give you direct access to the data of QImage. 据我所知,访问QImage数据的最快方法是使用QImage :: bits(),它可以直接访问QImage的数据。

For your problem, A better approch will be to do as Bgie suggested : using a array representing the keyhole and doing only a bitwise AND operation. 对于您的问题,更好的方法是按照Bgie的建议进行操作:使用表示钥匙孔的数组,并仅执行按位AND操作。

it will help to choose the correct format for your Image, the format RGB32 and ARG32_Premultiplied_ARGB32 are the fastest. 它将有助于为您的图像选择正确的格式,最快的格式是RGB32和ARG32_Premultiplied_ARGB32。 Don't use ARGB32 if you don't need it. 如果不需要,请不要使用ARGB32。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM