什么时候我们可以在从它构造QImage时删除一个帧缓冲区并且可能是浅层复制的?

时间:2012-11-11 16:29:32

标签: qt object-lifetime qimage

在这个问题中,我想知道维护与QImage对象关联的外部缓冲区对象的生命周期的最佳实践。

背景

我正在使用QT开发一个未压缩的图像文件查看器。它从文件中读取YV12数据,将其转换为RGB帧缓冲区,构造QImage对象,并将其传递到UI层进行渲染。

YV12文件阅读器看起来像这样。

class YV12Frame
{
public:
    YV12Frame(std::string const& fileName)
    {
        // Initialize m_frameBuffer
        // ... (Omitted for brevity)
    }

    QImage GetQImage()
    {
        // Build QImage object
        return QImage(m_frameBuffer, WIDTH, HEIGHT, QImage::Format_RGB32); 
    }

private:
    unsigned char m_frameBuffer[WIDTH * HEIGHT * 4];
};

正如QT文档所说,我们需要在QImage对象的整个生命周期中保持YV12Frame对象的有效性。

UI层可以通过浅拷贝或深拷贝复制QImage对象。换句话说,可能存在未知数量的QImage对象,它们一次引用帧缓冲区。

问题

我们如何安全地知道何时删除YV12Frame对象?

预期答案

有一个通知(回调或其他)告诉“嘿,我是最后一个引用帧缓冲区的QImage对象,我即将被删除。你现在可以安全地删除帧缓冲区。”

但是,我找不到这样的通知。

1 个答案:

答案 0 :(得分:0)

以下解决方法可能符合您的需求。

将实际的QImage对象存储为YV12Frame的私有成员(使用正确的宽度和高度初始化),而不是数组。这是您需要从GetQtImage()函数返回的对象。由于QImage隐式共享,您可以随时安全地删除YV12Frame,因为任何其他QImage实例在发生时都会分离自己的像素数据。

在帧解码中,通过常用的setPixel()函数更改QImage的内容。

如果速度很关键,那么就不能使用setPixel,因此需要直接操作像素数据。这里的技巧是防止QImage分离像素数据。因此,您需要使用constBits()constScanLine(),将其强制转换为非常量指针,然后直接访问它(丑陋,我知道)。