如何解决QPixmap :: fromImage内存泄漏问题?

时间:2009-11-17 16:51:34

标签: qt memory-leaks opencv qimage qpixmap

我遇到Qt问题。

以下是困扰我的代码的一部分:

    void FullScreenImage::QImageIplImageCvt(IplImage *input)
{
    help=cvCreateImage(cvGetSize(input), input->depth, input->nChannels);
    cvCvtColor(input, help, CV_BGR2RGB);
    QImage tmp((uchar *)help->imageData, help->width, help->height, help->widthStep, QImage::Format_RGB888);
    this->setPixmap(QPixmap::fromImage(tmp).scaled(this->size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
    cvReleaseImage(&help);
}


void FullScreenImage::hideOnScreen() {
    this->hide();
    this->clear();
}

void FullScreenImage::showOnScreen(IplImage *slika, int delay) {
    QImageIplImageCvt(slika);
    this->showFullScreen();
    if(delay>0)
 QTimer::singleShot(delay*1000, this, SLOT(hideOnScreen()));
}

因此,方法showOnScreen使用私有方法QImageIplImageCvtQImage创建IplImage(由OpenCV使用),然后用于创建QPixmap 1}}以全屏显示图像。 FullScreenImage类继承QLabel

经过一段时间的延迟后,应该隐藏全屏图片,因此我会在延迟一段时间后使用QTimer来触发事件。事件处理程序是hideOnScreen方法,它隐藏标签并清除内存。

问题如下:

每当我调用QPixmap::fromImage时,它会为pixmap数据分配内存,并将数据从QImage内存缓冲区复制到QPixmap内存缓冲区。隐藏标签后,QPixmap数据仍然会被分配,更糟糕的是,在新的QPixmap::fromImage调用之后,新的内存块被分配给新图片,并且旧数据不会从记忆。这会导致内存泄漏(使用我的测试图片每次方法调用10 MB)。我怎样才能解决这个漏洞?

我甚至尝试创建一个私有的QPixmap变量,将QPixmap::fromImage创建的pixmap存储到它,然后尝试用hideOnScreen方法调用它的析构函数,但它没有没帮忙。

是否存在从QPixmap创建QImage的非静态方法?或者甚至更好,有没有办法直接从QPixmap创建IplImage*

提前感谢您的回答。

4 个答案:

答案 0 :(得分:1)

无法直接从QPixmap创建IplImage*(也不能从cv::Mat创建)。但是,你的解决方案是避免将所有内容写入一行,并使用一个你自己解放的指针。

e.g:

if (this->mypixmap)
    delete this->mypixmap;
this->mypixmap = new QPixmap(QPixmap::fromImage(tmp).scaled(this->size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
this->setPixmap(this->mypixmap);

不要忘记在构造函数中设置mypixmap(NULL)

答案 1 :(得分:0)

您应该可以使用QPixmap::loadFromData直接创建QPixmap。所以类似下面的内容可能会起作用:

QPixmap p;
p.loadFromData((uchar *)help->imageData, help->width * help->height);

在不了解OpenCV或IplImage的情况下,我不能保证上面的代码段是正确的,但希望它能让你走上正确的道路。

答案 2 :(得分:0)

我有类似的问题,但是我的代码不同,所以不值得我放在这里。拿你的代码并与我的方法合并会给你:

void FullScreenImage::QImageIplImageCvt(IplImage *input)
{
    help=cvCreateImage(cvGetSize(input), input->depth, input->nChannels);
    cvCvtColor(input, help, CV_BGR2RGB);
    QImage* tmp = new QImage((uchar *)help->imageData, help->width, help->height, help->widthStep, QImage::Format_RGB888);
    this->setPixmap(QPixmap::fromImage(*tmp).scaled(this->size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
    delete tmp;
    cvReleaseImage(&help);
}

答案 3 :(得分:0)

使用重载方法为我解决了这个问题:

QPixmap::fromImage(const QImage && image,..)

您可以通过以下方式调用它:

QPixmap::fromImage(std::move(tmp))