QGLWidget::convertToGLFormat(); Qt 崩溃;
Qt Crash with QGLWidget::convertToGLFormat();
我想在具有 QGLWidget 视口的 QGraphicsScene 中显示视频纹理。
我用 openCV 读取视频,抓取每一帧,将其转换为 QImage,然后我这样做:
QImage img=QGLWidget::convertToGLFormat(videoFrame);//videoFrame is the frame got from openCV video reading and converted to QImage
我的问题是它适用于很多视频(我使用 .mp4),但适用于其他视频(仍然是 .mp4),那行代码使我的应用程序崩溃,我找不到原因。
我的问题是如何在不知道确切原因的情况下防止崩溃?我试过 :
QImage img;
try{
img=QGLWidget::convertToGLFormat(videoFrame);
}
catch(...)
{
img=QImage("defaultImg.jpg");
}
但它仍然在
崩溃
img=QGLWidget::convertToGLFormat(videoFrame);
并且没有执行catch部分。
编辑:
我得到了这样的图像:
QImage VideoPlayer::getVideoFrame()
{
IplImage* frame= cvQueryFrame( capture );
m=cv::Mat(frame);//m is a member of class VideoPlayer
return cvMatToQImage(m);
}
QImage VideoPlayer::cvMatToQImage(cv::Mat inMat)
{
cv::Mat temp;
cv::cvtColor(inMat, temp,CV_BGR2RGB);
QImage cvMatToQImg((uchar*) temp.data, temp.cols, temp.rows, temp.step, QImage::Format_RGB888);
return QImage(cvMatToQImg);
}
在我的 QgraphicsScene 子类中:
QImage videoFrame = videoPlayerInstance->getVideoFrame();
QImage img=QGLWidget::convertToGLFormat(videoFrame);//crashes here
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.width(), img.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
Qt 文档说:
QImage QGLWidget::convertToGLFormat(const QImage & img) Converts the
image img into the unnamed format expected by OpenGL functions such as
glTexImage2D(). The returned image is not usable as a QImage, but
QImage::width(), QImage::height() and QImage::bits() may be used with
OpenGL. The GL format used is GL_RGBA.
确实,因为在 glTexImage2D 中使用了 width()、height() 和 bits()。我得到并可以毫无问题地从 videoFrame 输出它们并且崩溃。
同样,它适用于一些 .mp4。
Qt 代码不会抛出异常,所以 try...catch
块是多余的。它崩溃是因为 videoFrame
为空或指向已释放的数据等。这就是问题所在。 convertToGLFormat
崩溃是向其传递垃圾图像的症状。
具体来说,您在 cvMatToQImage
中使用的 QImage
构造函数正在构造一个使用临时缓冲区的图像。构造函数的文档指出:
The buffer must remain valid throughout the life of the QImage and all copies that have not been modified or otherwise detached from the original buffer.
你应该强制图像保留矩阵。您可能也不会通过强制复制矩阵参数来过早地悲观——而是传递一个 const 引用。
static void cvMatQImageCleanup(void *info) {
delete reinterpret_cast<cv::Mat*>(info);
}
QImage VideoPlayer::cvMatToQImage(const cv::Mat & inMat)
{
auto temp = new cv::Mat;
cv::cvtColor(inMat, *temp, CV_BGR2RGB);
return QImage((uchar*) temp->data, temp->cols, temp->rows, temp->step,
QImage::Format_RGB888, &cvMatQImageCleanup, temp);
}
我想在具有 QGLWidget 视口的 QGraphicsScene 中显示视频纹理。
我用 openCV 读取视频,抓取每一帧,将其转换为 QImage,然后我这样做:
QImage img=QGLWidget::convertToGLFormat(videoFrame);//videoFrame is the frame got from openCV video reading and converted to QImage
我的问题是它适用于很多视频(我使用 .mp4),但适用于其他视频(仍然是 .mp4),那行代码使我的应用程序崩溃,我找不到原因。
我的问题是如何在不知道确切原因的情况下防止崩溃?我试过 :
QImage img;
try{
img=QGLWidget::convertToGLFormat(videoFrame);
}
catch(...)
{
img=QImage("defaultImg.jpg");
}
但它仍然在
崩溃img=QGLWidget::convertToGLFormat(videoFrame);
并且没有执行catch部分。
编辑: 我得到了这样的图像:
QImage VideoPlayer::getVideoFrame()
{
IplImage* frame= cvQueryFrame( capture );
m=cv::Mat(frame);//m is a member of class VideoPlayer
return cvMatToQImage(m);
}
QImage VideoPlayer::cvMatToQImage(cv::Mat inMat)
{
cv::Mat temp;
cv::cvtColor(inMat, temp,CV_BGR2RGB);
QImage cvMatToQImg((uchar*) temp.data, temp.cols, temp.rows, temp.step, QImage::Format_RGB888);
return QImage(cvMatToQImg);
}
在我的 QgraphicsScene 子类中:
QImage videoFrame = videoPlayerInstance->getVideoFrame();
QImage img=QGLWidget::convertToGLFormat(videoFrame);//crashes here
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.width(), img.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
Qt 文档说:
QImage QGLWidget::convertToGLFormat(const QImage & img) Converts the image img into the unnamed format expected by OpenGL functions such as glTexImage2D(). The returned image is not usable as a QImage, but QImage::width(), QImage::height() and QImage::bits() may be used with OpenGL. The GL format used is GL_RGBA.
确实,因为在 glTexImage2D 中使用了 width()、height() 和 bits()。我得到并可以毫无问题地从 videoFrame 输出它们并且崩溃。 同样,它适用于一些 .mp4。
Qt 代码不会抛出异常,所以 try...catch
块是多余的。它崩溃是因为 videoFrame
为空或指向已释放的数据等。这就是问题所在。 convertToGLFormat
崩溃是向其传递垃圾图像的症状。
具体来说,您在 cvMatToQImage
中使用的 QImage
构造函数正在构造一个使用临时缓冲区的图像。构造函数的文档指出:
The buffer must remain valid throughout the life of the QImage and all copies that have not been modified or otherwise detached from the original buffer.
你应该强制图像保留矩阵。您可能也不会通过强制复制矩阵参数来过早地悲观——而是传递一个 const 引用。
static void cvMatQImageCleanup(void *info) {
delete reinterpret_cast<cv::Mat*>(info);
}
QImage VideoPlayer::cvMatToQImage(const cv::Mat & inMat)
{
auto temp = new cv::Mat;
cv::cvtColor(inMat, *temp, CV_BGR2RGB);
return QImage((uchar*) temp->data, temp->cols, temp->rows, temp->step,
QImage::Format_RGB888, &cvMatQImageCleanup, temp);
}