[英]QImage: How to destroy pointer to pixels data properly?
在控制窗口的主类中,我具有以下功能,其中pixmapItem
是在类头中定义的QGraphicsPixmapItem*
:
void updateDisplay() {
uchar *data = new ...; // array of pixel data
...
QImage image = QImage(data, width, height,
width, QImage::Format_Indexed8);
pixmapItem->setPixmap(QPixmap::fromImage(image));
}
我的问题是:如何在不再需要data
时销毁data
? “不再需要”表示上面的函数或类中的另一个函数将像素图设置为另一个图像。
我已经看到QImage具有清理功能,该功能可能会有所帮助,但是关于如何使用它们以及如何传递参数(例如要删除的图像数据指针)的文档尚不清楚。
当QImage
被销毁时,您可以删除数据。 如上面的@JeremyFriesner所示,可以通过在内部范围内定义QImage
实例并在其外部分配/取消分配数据来简单地完成此操作。
但是,为什么还要烦恼所有这些工作呢? QImage
构造函数可以适应复杂的用例,在这些用例中您已经具有来自其他来源的像素数据,或者需要在“奇怪的”生命周期内保留它。
相反,您的情况更简单,像素数据的寿命与QImage
完全相同,因此最好让它自己为像素分配内存; 这样,您可以确定它的大小和对齐方式正确,并且由QImage
实例拥有/自动销毁; 构造完QImage
对象后,您可以使用bits
方法使用一个指向像素数据的指针,并对其进行任何操作。
这样,您的代码将变成:
void updateDisplay() {
QImage image = QImage(width, height,
width, QImage::Format_Indexed8);
uchar *data = image.bits();
...
pixmapItem->setPixmap(QPixmap::fromImage(image));
}
更简单,更安全,内存泄漏风险为零。
从Qt文档
构造具有给定宽度,高度和格式的图像,该图像使用现有的内存缓冲区数据。 宽度和高度必须以像素为单位指定,数据必须是32位对齐的,并且图像中数据的每条扫描线也必须是32位对齐的。
缓冲区必须在QImage的整个生命周期内保持有效。 映像不会删除销毁的缓冲区。
您需要实现自己的方式来删除该缓冲区
因此,您需要自己删除data
,但是当然,诀窍不是不要过早删除它-特别是,当QImage对象可能仍在使用它时,您不想删除它。 在您的情况下,最简单的方法是仅在销毁QImage对象之后将其删除:
void updateDisplay() {
uchar *data = new ...; // array of pixel data
...
{
QImage image = QImage(data, width, height,
width, QImage::Format_Indexed8);
pixmapItem->setPixmap(QPixmap::fromImage(image));
}
delete [] data;
}
(请注意使用花括号创建内部范围,从而确保在执行delete [] data
行之前 ,将QImage对象从堆栈中弹出并销毁!)
当然,更简单,更安全的方法是完全不必首先删除数组,从而避免了何时删除的问题。 相反,让QImage对象分配其自己的数据数组,然后直接写入该数据数组:
QImage image(width, height, QImage::Format_Indexed8);
char * data = image.bits();
// write into (data) here if you want to, but don't delete [] data, ever!
// instead, the QImage destructor will do any necessary deletes for you
您可以使用自己的析构函数对QImage
进行子类化,以进行清理。
class NativeBufferQImage : public QImage {
uchar *data;
// other stuff
public:
~NativeBufferQImage() {
delete[] this->data;
}
};
还要注意,由于QImage
是从QPaintDevice
派生的,并且QPaintDevice
具有虚拟析构函数 ,因此,如果有人通过指向其基类的指针(即QImage
) delete
NativeBufferQImage
,那么也会调用您的析构函数。
最好的方法是不要这样做:
void updateDisplay() {
QImage image(width, height, QImage::Format_Indexed8);
auto const data = image.bits();
// you can modify the data here
pixmapItem->setPixmap(QPixmap::fromImage(image));
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.