QRCodeReader (WIP)
This commit is contained in:
parent
d38e40d53f
commit
6744dce57e
5 changed files with 251 additions and 90 deletions
|
@ -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
|
||||||
|
|
|
@ -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());
|
||||||
|
|
28
client/platforms/ios/QRCodeReader.h
Normal file
28
client/platforms/ios/QRCodeReader.h
Normal 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
|
109
client/platforms/ios/QRCodeReader.mm
Normal file
109
client/platforms/ios/QRCodeReader.mm
Normal 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];
|
||||||
|
}
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
qrCodeReader.setCameraSize(Qt.rect(loader.x,
|
||||||
|
loader.y,
|
||||||
|
loader.width,
|
||||||
|
loader.height))
|
||||||
|
qrCodeReader.startReading()
|
||||||
|
}
|
||||||
|
Component.onDestruction: qrCodeReader.stopReading()
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoOutput
|
// Camera
|
||||||
{
|
// {
|
||||||
id: videoOutput
|
// id:camera
|
||||||
source: camera
|
// focus {
|
||||||
anchors.top: parent.top
|
// focusMode: CameraFocus.FocusContinuous
|
||||||
anchors.bottom: parent.bottom
|
// focusPointMode: CameraFocus.FocusPointAuto
|
||||||
anchors.left: parent.left
|
// }
|
||||||
anchors.right: parent.right
|
// }
|
||||||
autoOrientation: true
|
|
||||||
fillMode: VideoOutput.PreserveAspectFit
|
// VideoOutput
|
||||||
filters: [ zxingFilter ]
|
// {
|
||||||
|
// id: videoOutput
|
||||||
|
// source: camera
|
||||||
|
// anchors.top: parent.top
|
||||||
|
// anchors.bottom: parent.bottom
|
||||||
|
// anchors.left: parent.left
|
||||||
|
// anchors.right: parent.right
|
||||||
|
// autoOrientation: true
|
||||||
|
// fillMode: VideoOutput.PreserveAspectFit
|
||||||
|
// filters: [ zxingFilter ]
|
||||||
|
|
||||||
|
|
||||||
Rectangle {
|
// Rectangle {
|
||||||
color: "black"
|
// color: "black"
|
||||||
opacity: 0.5
|
// opacity: 0.5
|
||||||
width: videoOutput.contentRect.width *0.15
|
// width: videoOutput.contentRect.width * 0.15
|
||||||
height: videoOutput.contentRect.height
|
// height: videoOutput.contentRect.height
|
||||||
x: (videoOutput.width - videoOutput.contentRect.width)/2
|
// x: (videoOutput.width - videoOutput.contentRect.width)/2
|
||||||
anchors.verticalCenter: videoOutput.verticalCenter
|
// anchors.verticalCenter: videoOutput.verticalCenter
|
||||||
}
|
// }
|
||||||
|
|
||||||
Rectangle {
|
// Rectangle {
|
||||||
color: "black"
|
// color: "black"
|
||||||
opacity: 0.5
|
// opacity: 0.5
|
||||||
width: videoOutput.contentRect.width *0.15
|
// width: videoOutput.contentRect.width * 0.15
|
||||||
height: videoOutput.contentRect.height
|
// height: videoOutput.contentRect.height
|
||||||
x: videoOutput.width/2 + videoOutput.contentRect.width/2 - videoOutput.contentRect.width *0.15
|
// x: videoOutput.width/2 + videoOutput.contentRect.width/2 - videoOutput.contentRect.width * 0.15
|
||||||
anchors.verticalCenter: videoOutput.verticalCenter
|
// anchors.verticalCenter: videoOutput.verticalCenter
|
||||||
}
|
// }
|
||||||
|
|
||||||
Rectangle {
|
// Rectangle {
|
||||||
color: "black"
|
// color: "black"
|
||||||
opacity: 0.5
|
// opacity: 0.5
|
||||||
width: videoOutput.contentRect.width *0.7
|
// width: videoOutput.contentRect.width * 0.7
|
||||||
height: videoOutput.contentRect.height *0.15
|
// height: videoOutput.contentRect.height * 0.15
|
||||||
x: (videoOutput.width - videoOutput.contentRect.width)/2 + videoOutput.contentRect.width *0.15
|
// x: (videoOutput.width - videoOutput.contentRect.width)/2 + videoOutput.contentRect.width * 0.15
|
||||||
y: (videoOutput.height - videoOutput.contentRect.height)/2
|
// y: (videoOutput.height - videoOutput.contentRect.height)/2
|
||||||
}
|
// }
|
||||||
|
|
||||||
Rectangle {
|
// Rectangle {
|
||||||
color: "black"
|
// color: "black"
|
||||||
opacity: 0.5
|
// opacity: 0.5
|
||||||
width: videoOutput.contentRect.width *0.7
|
// width: videoOutput.contentRect.width * 0.7
|
||||||
height: videoOutput.contentRect.height *0.15
|
// height: videoOutput.contentRect.height * 0.15
|
||||||
x: (videoOutput.width - videoOutput.contentRect.width)/2 + videoOutput.contentRect.width *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
|
// y: videoOutput.height/2 + videoOutput.contentRect.height/2 - videoOutput.contentRect.height * 0.15
|
||||||
}
|
// }
|
||||||
|
|
||||||
LabelType {
|
// LabelType {
|
||||||
width: parent.width
|
// width: parent.width
|
||||||
text: qsTr("Decoded QR chunks " + QrDecoderLogic.receivedChunksCount + "/" + QrDecoderLogic.totalChunksCount)
|
// text: qsTr("Decoded QR chunks " + QrDecoderLogic.receivedChunksCount + "/" + QrDecoderLogic.totalChunksCount)
|
||||||
horizontalAlignment: Text.AlignLeft
|
// horizontalAlignment: Text.AlignLeft
|
||||||
visible: QrDecoderLogic.totalChunksCount > 0
|
// visible: QrDecoderLogic.totalChunksCount > 0
|
||||||
anchors.horizontalCenter: videoOutput.horizontalCenter
|
// anchors.horizontalCenter: videoOutput.horizontalCenter
|
||||||
y: videoOutput.height/2 + videoOutput.contentRect.height/2
|
// y: videoOutput.height/2 + videoOutput.contentRect.height/2
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
QZXingFilter
|
// QZXingFilter
|
||||||
{
|
// {
|
||||||
id: zxingFilter
|
// id: zxingFilter
|
||||||
orientation: videoOutput.orientation
|
// orientation: videoOutput.orientation
|
||||||
captureRect: {
|
// captureRect: {
|
||||||
// setup bindings
|
// // setup bindings
|
||||||
videoOutput.contentRect;
|
// videoOutput.contentRect;
|
||||||
videoOutput.sourceRect;
|
// videoOutput.sourceRect;
|
||||||
return videoOutput.mapRectToSource(videoOutput.mapNormalizedRectToItem(Qt.rect(
|
// return videoOutput.mapRectToSource(videoOutput.mapNormalizedRectToItem(Qt.rect(
|
||||||
0.15, 0.15, 0.7, 0.7 //0, 0, 1.0, 1.0
|
// 0.15, 0.15, 0.7, 0.7 //0, 0, 1.0, 1.0
|
||||||
)));
|
// )));
|
||||||
}
|
// }
|
||||||
|
|
||||||
decoder {
|
// decoder {
|
||||||
enabledDecoders: QZXing.DecoderFormat_QR_CODE
|
// enabledDecoders: QZXing.DecoderFormat_QR_CODE
|
||||||
|
|
||||||
onTagFound: {
|
// onTagFound: {
|
||||||
QrDecoderLogic.onDetectedQrCode(tag)
|
// QrDecoderLogic.onDetectedQrCode(tag)
|
||||||
}
|
// }
|
||||||
|
|
||||||
tryHarder: true
|
// tryHarder: true
|
||||||
}
|
// }
|
||||||
|
|
||||||
property int framesDecoded: 0
|
// property int framesDecoded: 0
|
||||||
property real timePerFrameDecode: 0
|
// property real timePerFrameDecode: 0
|
||||||
|
|
||||||
onDecodingFinished:
|
// onDecodingFinished:
|
||||||
{
|
// {
|
||||||
timePerFrameDecode = (decodeTime + framesDecoded * timePerFrameDecode) / (framesDecoded + 1);
|
// timePerFrameDecode = (decodeTime + framesDecoded * timePerFrameDecode) / (framesDecoded + 1);
|
||||||
framesDecoded++;
|
// framesDecoded++;
|
||||||
if(succeeded)
|
// if(succeeded)
|
||||||
console.log("frame finished: " + succeeded, decodeTime, timePerFrameDecode, framesDecoded);
|
// console.log("frame finished: " + succeeded, decodeTime, timePerFrameDecode, framesDecoded);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue