QRCodeReader (WIP)

This commit is contained in:
eugenyorbitsoftcom 2022-07-06 11:04:46 +06:00
parent d38e40d53f
commit 6744dce57e
5 changed files with 251 additions and 90 deletions

View file

@ -296,7 +296,8 @@ ios {
platforms/ios/bigint.h \ platforms/ios/bigint.h \
platforms/ios/bigintipv6addr.h \ platforms/ios/bigintipv6addr.h \
platforms/ios/ipaddress.h \ platforms/ios/ipaddress.h \
platforms/ios/ipaddressrange.h platforms/ios/ipaddressrange.h \
platforms/ios/QRCodeReader.h
SOURCES += \ SOURCES += \
protocols/ios_vpnprotocol.mm \ protocols/ios_vpnprotocol.mm \
@ -304,7 +305,8 @@ ios {
platforms/ios/json.cpp \ platforms/ios/json.cpp \
platforms/ios/iosglue.mm \ platforms/ios/iosglue.mm \
platforms/ios/ipaddress.cpp \ platforms/ios/ipaddress.cpp \
platforms/ios/ipaddressrange.cpp platforms/ios/ipaddressrange.cpp \
platforms/ios/QRCodeReader.mm
Q_ENABLE_BITCODE.value = NO Q_ENABLE_BITCODE.value = NO
Q_ENABLE_BITCODE.name = ENABLE_BITCODE Q_ENABLE_BITCODE.name = ENABLE_BITCODE

View file

@ -37,6 +37,8 @@
#include "QZXing.h" #include "QZXing.h"
#include "platforms/ios/QRCodeReader.h"
#include "debug.h" #include "debug.h"
#include "defines.h" #include "defines.h"
@ -167,6 +169,7 @@ int main(int argc, char *argv[])
declareQmlContainerEnum(); declareQmlContainerEnum();
qmlRegisterType<PageType>("PageType", 1, 0, "PageType"); qmlRegisterType<PageType>("PageType", 1, 0, "PageType");
qmlRegisterType<QRCodeReader>("QRCodeReader", 1, 0, "QRCodeReader");
QScopedPointer<ContainerProps> containerProps(new ContainerProps); QScopedPointer<ContainerProps> containerProps(new ContainerProps);
qmlRegisterSingletonInstance("ContainerProps", 1, 0, "ContainerProps", containerProps.get()); qmlRegisterSingletonInstance("ContainerProps", 1, 0, "ContainerProps", containerProps.get());

View file

@ -0,0 +1,28 @@
#ifndef QRCODEREADER_H
#define QRCODEREADER_H
#include <QObject>
#include <QRect>
class QRCodeReader: public QObject {
Q_OBJECT
public:
QRCodeReader();
QRect cameraSize();
public slots:
void startReading();
void stopReading();
void setCameraSize(QRect value);
signals:
void codeReaded(QString code);
private:
void* m_qrCodeReader;
QRect m_cameraSize;
};
#endif // QRCODEREADER_H

View file

@ -0,0 +1,109 @@
#include "QRCodeReader.h"
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
@interface QRCodeReaderImpl : UIViewController
@end
@interface QRCodeReaderImpl () <AVCaptureMetadataOutputObjectsDelegate>
@property (nonatomic) QRCodeReader* qrCodeReader;
@property (nonatomic, strong) AVCaptureSession *captureSession;
@property (nonatomic, strong) AVCaptureVideoPreviewLayer *videoPreviewPlayer;
@end
@implementation QRCodeReaderImpl
- (void)viewDidLoad {
[super viewDidLoad];
_captureSession = nil;
}
- (void)setQrCodeReader: (QRCodeReader*)value {
_qrCodeReader = value;
}
- (BOOL)startReading {
NSError *error;
AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType: AVMediaTypeVideo];
AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput deviceInputWithDevice: captureDevice error: &error];
if(!deviceInput) {
NSLog(@"Error %@", error.localizedDescription);
return NO;
}
_captureSession = [[AVCaptureSession alloc]init];
[_captureSession addInput:deviceInput];
AVCaptureMetadataOutput *capturedMetadataOutput = [[AVCaptureMetadataOutput alloc] init];
[_captureSession addOutput:capturedMetadataOutput];
dispatch_queue_t dispatchQueue;
dispatchQueue = dispatch_queue_create("myQueue", NULL);
[capturedMetadataOutput setMetadataObjectsDelegate: self queue: dispatchQueue];
[capturedMetadataOutput setMetadataObjectTypes: [NSArray arrayWithObject:AVMetadataObjectTypeQRCode]];
_videoPreviewPlayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession: _captureSession];
CGFloat tabBarHeight = 20.0;
QRect cameraRect = _qrCodeReader->cameraSize();
CGRect cameraCGRect = CGRectMake(cameraRect.x(),
cameraRect.y() + tabBarHeight,
cameraRect.width(),
cameraRect.height());
[_videoPreviewPlayer setVideoGravity: AVLayerVideoGravityResizeAspect];
[_videoPreviewPlayer setFrame: cameraCGRect];
CALayer* layer = [UIApplication sharedApplication].keyWindow.layer;
[layer addSublayer: _videoPreviewPlayer];
[_captureSession startRunning];
return YES;
}
- (void)stopReading {
[_captureSession stopRunning];
_captureSession = nil;
[_videoPreviewPlayer removeFromSuperlayer];
}
- (void)captureOutput:(AVCaptureOutput *)output didOutputMetadataObjects:(NSArray<__kindof AVMetadataObject *> *)metadataObjects fromConnection:(AVCaptureConnection *)connection {
if (metadataObjects != nil && metadataObjects.count > 0) {
AVMetadataMachineReadableCodeObject *metadataObject = [metadataObjects objectAtIndex:0];
if ([[metadataObject type] isEqualToString: AVMetadataObjectTypeQRCode]) {
_qrCodeReader->emit codeReaded([metadataObject stringValue].UTF8String);
}
}
}
@end
QRCodeReader::QRCodeReader() {
m_qrCodeReader = [[QRCodeReaderImpl alloc] init];
[m_qrCodeReader setQrCodeReader: this];
}
QRect QRCodeReader::cameraSize() {
return m_cameraSize;
}
void QRCodeReader::setCameraSize(QRect value) {
m_cameraSize = value;
}
void QRCodeReader::startReading() {
[m_qrCodeReader startReading];
}
void QRCodeReader::stopReading() {
[m_qrCodeReader stopReading];
}

View file

@ -3,6 +3,7 @@ import QtQuick.Controls 2.12
import PageEnum 1.0 import PageEnum 1.0
import QtMultimedia 5.5 import QtMultimedia 5.5
import QZXing 3.2 import QZXing 3.2
import QRCodeReader 1.0
import "./" import "./"
import "../Controls" import "../Controls"
@ -51,108 +52,126 @@ PageBase {
Item { Item {
anchors.fill: parent anchors.fill: parent
Camera
{ QRCodeReader {
id:camera id: qrCodeReader
focus {
focusMode: CameraFocus.FocusContinuous onCodeReaded: {
focusPointMode: CameraFocus.FocusPointAuto QrDecoderLogic.onDetectedQrCode(code)
}
} }
VideoOutput Component.onCompleted: {
{ qrCodeReader.setCameraSize(Qt.rect(loader.x,
id: videoOutput loader.y,
source: camera loader.width,
anchors.top: parent.top loader.height))
anchors.bottom: parent.bottom qrCodeReader.startReading()
anchors.left: parent.left }
anchors.right: parent.right Component.onDestruction: qrCodeReader.stopReading()
autoOrientation: true
fillMode: VideoOutput.PreserveAspectFit
filters: [ zxingFilter ]
Rectangle {
color: "black"
opacity: 0.5
width: videoOutput.contentRect.width *0.15
height: videoOutput.contentRect.height
x: (videoOutput.width - videoOutput.contentRect.width)/2
anchors.verticalCenter: videoOutput.verticalCenter
} }
Rectangle { // Camera
color: "black" // {
opacity: 0.5 // id:camera
width: videoOutput.contentRect.width *0.15 // focus {
height: videoOutput.contentRect.height // focusMode: CameraFocus.FocusContinuous
x: videoOutput.width/2 + videoOutput.contentRect.width/2 - videoOutput.contentRect.width *0.15 // focusPointMode: CameraFocus.FocusPointAuto
anchors.verticalCenter: videoOutput.verticalCenter // }
} // }
Rectangle { // VideoOutput
color: "black" // {
opacity: 0.5 // id: videoOutput
width: videoOutput.contentRect.width *0.7 // source: camera
height: videoOutput.contentRect.height *0.15 // anchors.top: parent.top
x: (videoOutput.width - videoOutput.contentRect.width)/2 + videoOutput.contentRect.width *0.15 // anchors.bottom: parent.bottom
y: (videoOutput.height - videoOutput.contentRect.height)/2 // anchors.left: parent.left
} // anchors.right: parent.right
// autoOrientation: true
// fillMode: VideoOutput.PreserveAspectFit
// filters: [ zxingFilter ]
Rectangle {
color: "black"
opacity: 0.5
width: videoOutput.contentRect.width *0.7
height: videoOutput.contentRect.height *0.15
x: (videoOutput.width - videoOutput.contentRect.width)/2 + videoOutput.contentRect.width *0.15
y: videoOutput.height/2 + videoOutput.contentRect.height/2 - videoOutput.contentRect.height *0.15
}
LabelType { // Rectangle {
width: parent.width // color: "black"
text: qsTr("Decoded QR chunks " + QrDecoderLogic.receivedChunksCount + "/" + QrDecoderLogic.totalChunksCount) // opacity: 0.5
horizontalAlignment: Text.AlignLeft // width: videoOutput.contentRect.width * 0.15
visible: QrDecoderLogic.totalChunksCount > 0 // height: videoOutput.contentRect.height
anchors.horizontalCenter: videoOutput.horizontalCenter // x: (videoOutput.width - videoOutput.contentRect.width)/2
y: videoOutput.height/2 + videoOutput.contentRect.height/2 // anchors.verticalCenter: videoOutput.verticalCenter
} // }
}
QZXingFilter // Rectangle {
{ // color: "black"
id: zxingFilter // opacity: 0.5
orientation: videoOutput.orientation // width: videoOutput.contentRect.width * 0.15
captureRect: { // height: videoOutput.contentRect.height
// setup bindings // x: videoOutput.width/2 + videoOutput.contentRect.width/2 - videoOutput.contentRect.width * 0.15
videoOutput.contentRect; // anchors.verticalCenter: videoOutput.verticalCenter
videoOutput.sourceRect; // }
return videoOutput.mapRectToSource(videoOutput.mapNormalizedRectToItem(Qt.rect(
0.15, 0.15, 0.7, 0.7 //0, 0, 1.0, 1.0
)));
}
decoder { // Rectangle {
enabledDecoders: QZXing.DecoderFormat_QR_CODE // color: "black"
// opacity: 0.5
// width: videoOutput.contentRect.width * 0.7
// height: videoOutput.contentRect.height * 0.15
// x: (videoOutput.width - videoOutput.contentRect.width)/2 + videoOutput.contentRect.width * 0.15
// y: (videoOutput.height - videoOutput.contentRect.height)/2
// }
onTagFound: { // Rectangle {
QrDecoderLogic.onDetectedQrCode(tag) // color: "black"
} // opacity: 0.5
// width: videoOutput.contentRect.width * 0.7
// height: videoOutput.contentRect.height * 0.15
// x: (videoOutput.width - videoOutput.contentRect.width)/2 + videoOutput.contentRect.width * 0.15
// y: videoOutput.height/2 + videoOutput.contentRect.height/2 - videoOutput.contentRect.height * 0.15
// }
tryHarder: true // LabelType {
} // width: parent.width
// text: qsTr("Decoded QR chunks " + QrDecoderLogic.receivedChunksCount + "/" + QrDecoderLogic.totalChunksCount)
// horizontalAlignment: Text.AlignLeft
// visible: QrDecoderLogic.totalChunksCount > 0
// anchors.horizontalCenter: videoOutput.horizontalCenter
// y: videoOutput.height/2 + videoOutput.contentRect.height/2
// }
// }
property int framesDecoded: 0 // QZXingFilter
property real timePerFrameDecode: 0 // {
// id: zxingFilter
// orientation: videoOutput.orientation
// captureRect: {
// // setup bindings
// videoOutput.contentRect;
// videoOutput.sourceRect;
// return videoOutput.mapRectToSource(videoOutput.mapNormalizedRectToItem(Qt.rect(
// 0.15, 0.15, 0.7, 0.7 //0, 0, 1.0, 1.0
// )));
// }
onDecodingFinished: // decoder {
{ // enabledDecoders: QZXing.DecoderFormat_QR_CODE
timePerFrameDecode = (decodeTime + framesDecoded * timePerFrameDecode) / (framesDecoded + 1);
framesDecoded++; // onTagFound: {
if(succeeded) // QrDecoderLogic.onDetectedQrCode(tag)
console.log("frame finished: " + succeeded, decodeTime, timePerFrameDecode, framesDecoded); // }
}
} // tryHarder: true
// }
// property int framesDecoded: 0
// property real timePerFrameDecode: 0
// onDecodingFinished:
// {
// timePerFrameDecode = (decodeTime + framesDecoded * timePerFrameDecode) / (framesDecoded + 1);
// framesDecoded++;
// if(succeeded)
// console.log("frame finished: " + succeeded, decodeTime, timePerFrameDecode, framesDecoded);
// }
// }
} }