簡體   English   中英

QImage:如何正確銷毀指向像素數據的指針?

[英]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具有虛擬析構函數 ,因此,如果有人通過指向其基類的指針(即QImagedelete 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM