How to solve QPixmap::fromImage memory leak?
I have a problem with Qt.
Here is a part of code that troubles me:
void FullScreenImage::QImageIplImageCvt(IplImage *input)
{
help=cvCreateImage(cvGetSize(input), input->depth, input->nChannels);
cvCvtColor(input, help, CV_BGR2RGB);
QImage t开发者_如何转开发mp((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()));
}
So, the method showOnScreen
uses private method QImageIplImageCvt
to create QImage
from IplImage
(which is used by the OpenCV), which is then used to create QPixmap
in order to show the image in full screen. FullScreenImage
class inherits QLabel
.
After some delay, the fullscreen picture should be hidden, so I use QTimer
to trigger an event after some delay. The event handler is the hideOnScreen
method which hides the label and should clear the memory.
The problem is the following:
Whenever I call QPixmap::fromImage
, it allocates the memory for the pixmap data and copies the data from QImage
memory buffer to the QPixmap
memory buffer. After the label is hidden, the QPixmap
data still remains allocated, and even worse, after the new QPixmap::fromImage
call the new chunk of memory is allocated for the new picture, and the old data is not freed from memory. This causes a memory leak (cca 10 MB per method call with my testing pictures). How can I solve that leak?
I've even tried to create a private QPixmap
variable, store pixmap created by the QPixmap::fromImage
to it, and then tried to call its destructor in hideOnScreen
method, but it didn't help.
Is there a non-static way to create QPixmap
from QImage
? Or even better, is there a way to create QPixmap
directly from IplImage*
?
Thank you in advance for your answers.
There is no way to create QPixmap
directly from IplImage*
(and also not from cv::Mat
). However, your solution there is to refrain from writing everything into one line and work with a pointer that you free yourself.
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);
Don't forget to set mypixmap(NULL)
in the constructor.
I had a similar problem, however my code was different so its not worth me putting here. Taking your code and merging with my method would give you:
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);
}
You should be able to use QPixmap::loadFromData
to create a QPixmap
directly. So something like the following might work:
QPixmap p;
p.loadFromData((uchar *)help->imageData, help->width * help->height);
Without knowing anything about OpenCV or IplImage
, I can't guarantee that the above snippet is correct, but hopefully it starts you down the right path.
Using the overloaded method solved the issue for me:
QPixmap::fromImage(const QImage && image,..)
You can call it with:
QPixmap::fromImage(std::move(tmp))
精彩评论