qimage:如何正确破坏指向像素数据的指针

QImage: How to destroy pointer to pixels data properly?

本文关键字:像素数 像素 数据 指针 何正确 qimage      更新时间:2023-10-16

在控制一个窗口的主要类中,我有此功能,其中 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销毁CC_3?"不再需要"是指上面的功能或我的类中的其他功能将pixmap设置为另一个图像。

我已经看到qimage具有可能有帮助的清理功能,但是文档对如何使用它们以及如何传递参数(例如图像的数据指针删除)并不清楚。

QImage被破坏时,您可以删除数据;如上所述,这可以简单地通过在内部范围中定义 QImage实例,然后分配/dealsloge laste以外的数据来完成。

但是,为什么要打扰所有工作呢?QImage构造函数可以适应复杂的用例,其中您已经从其他来源获得了像素数据,或者您需要将其保留为"奇怪"的寿命。

您的情况更简单,像素数据的寿命与QImage完全相同,因此,让它本身分配内存是一个更好的主意。这样,您可以确定它的尺寸和对齐正确,并且由QImage实例拥有/自动销毁;构建QImage对象后,您可以使用bits方法将指针指向Pixel数据,然后对其进行任何操作。

以这种方式,您的代码只会变成:

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;
}

(请注意使用卷曲括号来创建内部范围,从而确保qimage对象从堆栈中弹出并在 delete [] data行执行!)

之前!)

当然,一种更容易,更安全的方法是完全避免通过首先手动分配阵列来完全避免使用何时删除的问题。相反,让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

您可以使用自己的销毁器进行清理。

class NativeBufferQImage : public QImage {
    uchar *data;
    // other stuff
public:
    ~NativeBufferQImage() {
        delete[] this->data; 
    }
};

还要注意,由于QImage是从QPaintDevice派生的,QPaintDevice具有虚拟破坏者,因此,如果某人通过delete您的NativeBufferQImage通过指针到其基类的指针(即QImage),则您的销毁器也将被称为。Div>

最好的方法不是这样做:

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));
}