最近在开发一个摄像头扫描二维码的功能,在网上找了下相关的库发现有Qt接口的QZXing库,可是它不能用,因为这个这个库只能解析规规矩矩的二维码,这种从摄像头中获取的不可以!我也不知道为什么会这样。不过发现java的zxing是可以在摄像头获取的图片中识别出正确的二维码信息,任务急,只好
思路是这样的:
开始编码了, 劈里啪啦的干起来~~
- 解析每一帧的图像要去继承QAbstractVideoSurface类,overload虚函数supportedPixelFormats和虚函数present
QList<QVideoFrame::PixelFormat>
MyVideoSurface::supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const
{
Q_UNUSED(handleType);
static QList<QVideoFrame::PixelFormat> pixelFormats{};
if(pixelFormats.isEmpty()) {
pixelFormats << QVideoFrame::Format_ARGB32;
//.....other formats
pixelFormats << QVideoFrame::Format_AdobeDng;
}
return pixelFormats;
}
相当于告诉QCamera我要接管以上图像格式的流。
static const QString cmdf{"java -jar QR.jar \"%1\""};
static void saveImage(QRDecoder *obj, QVideoFrame cloneFrame)
{
cloneFrame.map(QAbstractVideoBuffer::ReadOnly);
QImage img{cloneFrame.bits(), cloneFrame.width(), cloneFrame.height(),
QVideoFrame::imageFormatFromPixelFormat(cloneFrame.pixelFormat())};
cloneFrame.unmap();
// TODO: It Should Have a good solution at somewhere in the world!"
/***********************************************************************/
QString filepath = QDir::tempPath() + "/" + QString::number(QDateTime::currentMSecsSinceEpoch()) + ".jpg";
img.save(filepath);
QProcess proc;
proc.setProcessEnvironment(QProcessEnvironment::systemEnvironment());
proc.setProcessChannelMode(QProcess::MergedChannels);
proc.setWorkingDirectory(QApplication::applicationDirPath());
proc.start(cmdf.arg(filepath));
proc.waitForStarted(UINT_MAX);
proc.waitForReadyRead(UINT_MAX);
proc.waitForFinished(UINT_MAX);
QByteArray origin = proc.readAll();
QTextCodec *code = QTextCodec::codecForLocale();
QString info = code->toUnicode(origin).trimmed();
QFile::remove(filepath);
/***********************************************************************/
QMetaObject::invokeMethod(obj, "decodeFinished", Qt::AutoConnection, Q_ARG(QString, info));
}
bool MyVideoSurface::present(const QVideoFrame &frame)
{
if (frame.isValid()) {
QtConcurrent::run(saveImage, qobject_cast<QRDecoder *>(parent), frame);
return true;
}
return false;
}
当有来自摄像头的图像帧时我们把它保存为本地图片并启动一个新的进程在命令行去执行java的方法。
为个提高效率,我们使用了多线程。