我正在为 Ubuntu Touch 开发一个应用程序,它应该能够读取 QR 码。它依赖于自定义视频过滤器子类,但是我无法从QVideoFrame
实例中提取单个图像。将QVideoFrame::map
失败。我的研究表明,我必须使用 OpenGL 句柄来读取 2D 纹理,而不是直接访问,类似于以下情况:
- https://github.com/stephenquan/MyVideoFilterApp/blob/master/QVideoFrameToQImage.cpp
- QVideoFrame::map() 崩溃
- https://forum.qt.io/topic/103430/qvideoframe-map-is-false-in-android
- https://lists.qt-project.org/pipermail/interest/2018-June/030295.html
所以我正在尝试QVideoFrame::map
使用 OpenGL 函数来实现替换。
但是,尽管从上述示例中可以清楚地看出该方法,但我似乎无法QImage
从QVideoFrame
. 我有许多不确定性;我从未使用过 OpenGL,而且我对图像格式也不太熟悉。事实上,我并没有在自己的实现上工作,而是试图让qzxing
库在我的应用程序中工作。我已经在 SailfishOS 下工作了(QVideoFrame::map
刚刚工作),我正在将我的应用程序移植到 Ubuntu Touch。
目前我有这个:
QImage img(frame.width(), frame.height(), QImage::Format_RGBA8888);
GLuint textureId = frame.handle().toUInt();
QOpenGLContext *ctx = QOpenGLContext::currentContext();
QOpenGLFunctions *f = ctx->functions();
GLuint fbo;
f->glGenFramebuffers(1, &fbo);
GLuint prevFbo;
f->glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint *) &prevFbo);
f->glBindFramebuffer(GL_FRAMEBUFFER, fbo);
f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0);
f->glReadPixels(0, 0, frame.width(), frame.height(), GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
const QString path = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation) + "/qrtest/test.png";
qDebug() << "Saving image at:" << path << img.save(path) << " size: " << img.size() << "/" << img.sizeInBytes();
当我尝试将图像保存到磁盘时(为了检查它的外观,如果它甚至包含任何东西),QImage::save
将返回false
并打印:
Saving image at: "/home/phablet/Pictures/qrtest/test.png" false size: QSize(1920, 1088) / 8355840
输入视频流似乎是 format QVideFrame::Format_RGB32
,至少这是 frame.pixelFormat()
报告的内容。这是否重要,或者GL_RGBA
无论如何都会起作用,我只需要确保img
格式正确,所以内部缓冲区足够大吗?因此会是QImage::Format_RGBA8888
正确的吗?
为什么生成的图像看起来无效?我怎样才能解决这个问题?