@xbone-3/cordova-plugin-mlkit-barcodescanner 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +51 -0
- package/LICENSE.md +21 -0
- package/README.md +260 -0
- package/package.json +67 -0
- package/plugin.xml +133 -0
- package/src/android/build-extras.gradle +14 -0
- package/src/android/res/assets/beep.ogg +0 -0
- package/src/android/res/drawable/flashlight.png +0 -0
- package/src/android/res/drawable/torch_active.xml +12 -0
- package/src/android/res/drawable/torch_inactive.xml +12 -0
- package/src/android/res/layout/capture_activity.xml +97 -0
- package/src/android/res/values/strings-de.xml +20 -0
- package/src/android/res/values/strings-en.xml +20 -0
- package/src/android/src/CaptureActivity.java +762 -0
- package/src/android/src/MLKitBarcodeScanner.java +221 -0
- package/src/android/src/utils/BitmapUtils.java +286 -0
- package/src/android/src/utils/FrameMetadata.java +69 -0
- package/src/ios/CDViOSScanner.h +21 -0
- package/src/ios/CDViOSScanner.m +183 -0
- package/src/ios/CameraViewController.h +36 -0
- package/src/ios/CameraViewController.m +503 -0
- package/src/ios/Sounds/beep.caf +0 -0
- package/src/ios/de.lproj/Localizable.strings +8 -0
- package/src/ios/en.lproj/Localizable.strings +8 -0
- package/www/BarcodeScanner.contract.d.ts +10 -0
- package/www/BarcodeScanner.contract.js +10 -0
- package/www/BarcodeScanner.plugin.d.ts +8 -0
- package/www/BarcodeScanner.plugin.js +145 -0
- package/www/Detector.d.ts +29 -0
- package/www/Interface.d.ts +65 -0
- package/www/Options.d.ts +2 -0
- package/www/util/Object.d.ts +3 -0
|
@@ -0,0 +1,503 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2016-present Google Inc. All Rights Reserved.
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
@import AVFoundation;
|
|
18
|
+
@import MLKitBarcodeScanning;
|
|
19
|
+
@import MLKitVision;
|
|
20
|
+
|
|
21
|
+
#import "CameraViewController.h"
|
|
22
|
+
|
|
23
|
+
@interface CameraViewController ()<AVCaptureVideoDataOutputSampleBufferDelegate>
|
|
24
|
+
|
|
25
|
+
@property(nonatomic, weak) IBOutlet UIView *placeHolderView;
|
|
26
|
+
@property(nonatomic, weak) IBOutlet UIView *overlayView;
|
|
27
|
+
@property(nonatomic, strong) UIImageView *imageView;
|
|
28
|
+
|
|
29
|
+
@property(nonatomic, strong) AVCaptureSession *session;
|
|
30
|
+
@property(nonatomic, strong) AVCaptureVideoDataOutput *videoDataOutput;
|
|
31
|
+
@property(nonatomic, strong) dispatch_queue_t videoDataOutputQueue;
|
|
32
|
+
@property(nonatomic, strong) AVCaptureVideoPreviewLayer *previewLayer;
|
|
33
|
+
|
|
34
|
+
@property(nonatomic, strong) MLKBarcodeScanner *barcodeDetector;
|
|
35
|
+
@property(nonatomic, strong) UIButton *torchButton;
|
|
36
|
+
|
|
37
|
+
@end
|
|
38
|
+
|
|
39
|
+
@implementation CameraViewController
|
|
40
|
+
@synthesize delegate;
|
|
41
|
+
|
|
42
|
+
- (BOOL)prefersStatusBarHidden
|
|
43
|
+
{
|
|
44
|
+
return YES;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
- (BOOL)prefersHomeIndicatorAutoHidden
|
|
48
|
+
{
|
|
49
|
+
return YES;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
- (BOOL) shouldAutorotate
|
|
53
|
+
{
|
|
54
|
+
return NO;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
|
|
58
|
+
return UIInterfaceOrientationMaskPortrait;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
- (id)initWithCoder:(NSCoder *)aDecoder {
|
|
62
|
+
self = [super initWithCoder:aDecoder];
|
|
63
|
+
if (self) {
|
|
64
|
+
_videoDataOutputQueue = dispatch_queue_create("VideoDataOutputQueue",
|
|
65
|
+
DISPATCH_QUEUE_SERIAL);
|
|
66
|
+
}
|
|
67
|
+
return self;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
- (void)viewDidLoad {
|
|
71
|
+
[super viewDidLoad];
|
|
72
|
+
|
|
73
|
+
// Set up camera.
|
|
74
|
+
self.session = [[AVCaptureSession alloc] init];
|
|
75
|
+
self.session.sessionPreset = AVCaptureSessionPresetHigh;
|
|
76
|
+
|
|
77
|
+
_videoDataOutputQueue = dispatch_queue_create("VideoDataOutputQueue",
|
|
78
|
+
DISPATCH_QUEUE_SERIAL);
|
|
79
|
+
|
|
80
|
+
[self updateCameraSelection];
|
|
81
|
+
|
|
82
|
+
// Set up video processing pipeline.
|
|
83
|
+
[self setUpVideoProcessing];
|
|
84
|
+
|
|
85
|
+
// Set up camera preview.
|
|
86
|
+
[self setUpCameraPreview];
|
|
87
|
+
|
|
88
|
+
//Parse Cordova settings.
|
|
89
|
+
NSNumber *formats = 0;
|
|
90
|
+
//If barcodeFormats == 0 then process as a VIN with VIN verifications.
|
|
91
|
+
if([_barcodeFormats isEqual: @0]) {
|
|
92
|
+
NSLog(@"Running VIN style");
|
|
93
|
+
formats = @(MLKBarcodeFormatCode39|MLKBarcodeFormatDataMatrix);
|
|
94
|
+
} else if([_barcodeFormats isEqual: @1234]) {
|
|
95
|
+
// @todo: investigating what should be done here
|
|
96
|
+
} else {
|
|
97
|
+
formats = _barcodeFormats;
|
|
98
|
+
}
|
|
99
|
+
NSLog(@"_barcodeFormats %@, %@", _barcodeFormats, formats);
|
|
100
|
+
|
|
101
|
+
// Initialize barcode detector.
|
|
102
|
+
MLKBarcodeScannerOptions *options = [[MLKBarcodeScannerOptions alloc] initWithFormats: [formats intValue]];
|
|
103
|
+
self.barcodeDetector = [MLKBarcodeScanner barcodeScannerWithOptions:options];
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
- (void)viewDidLayoutSubviews {
|
|
107
|
+
[super viewDidLayoutSubviews];
|
|
108
|
+
|
|
109
|
+
self.previewLayer.frame = self.view.layer.bounds;
|
|
110
|
+
self.previewLayer.position = CGPointMake(CGRectGetMidX(self.previewLayer.frame),
|
|
111
|
+
CGRectGetMidY(self.previewLayer.frame));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
- (void)dealloc {
|
|
115
|
+
[self cleanupCaptureSession];
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
- (void)viewDidAppear:(BOOL)animated {
|
|
119
|
+
[super viewDidAppear:animated];
|
|
120
|
+
|
|
121
|
+
AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
|
|
122
|
+
if (authStatus == AVAuthorizationStatusDenied) {
|
|
123
|
+
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Camera permission required" message:@"Access to the camera has been prohibited, please enable it in the settings to continue." preferredStyle:UIAlertControllerStyleAlert];
|
|
124
|
+
|
|
125
|
+
UIAlertAction *primaryAction = [UIAlertAction actionWithTitle:@"Settings" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
|
|
126
|
+
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString] options:@{} completionHandler:nil];
|
|
127
|
+
[self.delegate closeScanner];
|
|
128
|
+
}];
|
|
129
|
+
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {
|
|
130
|
+
[self.delegate closeScanner];
|
|
131
|
+
}];
|
|
132
|
+
[alert addAction:cancelAction];
|
|
133
|
+
[alert addAction:primaryAction];
|
|
134
|
+
alert.preferredAction = primaryAction;
|
|
135
|
+
[self presentViewController:alert animated:YES completion:nil];
|
|
136
|
+
} else {
|
|
137
|
+
//Force portrait orientation.
|
|
138
|
+
[[UIDevice currentDevice] setValue:
|
|
139
|
+
[NSNumber numberWithInteger: UIInterfaceOrientationPortrait]
|
|
140
|
+
forKey:@"orientation"];
|
|
141
|
+
|
|
142
|
+
[self.session startRunning];
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
- (void)viewDidDisappear:(BOOL)animated {
|
|
147
|
+
[super viewDidDisappear:animated];
|
|
148
|
+
[self.session stopRunning];
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
#pragma mark - AVCaptureVideoDataOutputSampleBufferDelegate
|
|
152
|
+
|
|
153
|
+
- (void)captureOutput:(AVCaptureOutput *)captureOutput
|
|
154
|
+
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
|
|
155
|
+
fromConnection:(AVCaptureConnection *)connection {
|
|
156
|
+
|
|
157
|
+
//Convert sampleBuffer into an image.
|
|
158
|
+
//MLKVisionImage *image = [[MLKVisionImage alloc] initWithBuffer:sampleBuffer];
|
|
159
|
+
CVImageBufferRef imageBuffer =
|
|
160
|
+
CMSampleBufferGetImageBuffer(sampleBuffer);
|
|
161
|
+
CIImage *ciImage = [CIImage imageWithCVPixelBuffer:imageBuffer];
|
|
162
|
+
CIContext *temporaryContext = [CIContext contextWithOptions:nil];
|
|
163
|
+
CGImageRef videoImage = [temporaryContext
|
|
164
|
+
createCGImage:ciImage
|
|
165
|
+
fromRect:CGRectMake(0, 0,
|
|
166
|
+
CVPixelBufferGetWidth(imageBuffer),
|
|
167
|
+
CVPixelBufferGetHeight(imageBuffer))];
|
|
168
|
+
|
|
169
|
+
UIImage *image = [[UIImage alloc] initWithCGImage:videoImage];
|
|
170
|
+
CGImageRelease(videoImage);
|
|
171
|
+
|
|
172
|
+
//We're going to crop UIImage to the onscreen viewfinder's box size for faster processing.
|
|
173
|
+
UIImage *croppedImg = nil;
|
|
174
|
+
|
|
175
|
+
//Define the crop coordinates.
|
|
176
|
+
CGRect screenRect = [[UIScreen mainScreen] bounds];
|
|
177
|
+
CGFloat screenWidth = screenRect.size.width;
|
|
178
|
+
CGFloat screenHeight = screenRect.size.height;
|
|
179
|
+
|
|
180
|
+
CGFloat imageWidth = image.size.width;
|
|
181
|
+
CGFloat imageHeight = image.size.height;
|
|
182
|
+
|
|
183
|
+
CGFloat actualFrameWidth = 0;
|
|
184
|
+
CGFloat actualFrameHeight = 0;
|
|
185
|
+
|
|
186
|
+
//Figure out which ratio is bigger and then subtract a value off the frame width in case some of the camera preview is hanging off screen.
|
|
187
|
+
if(imageWidth/screenWidth < imageHeight/screenHeight){
|
|
188
|
+
actualFrameWidth = imageWidth * _detectorSize;
|
|
189
|
+
actualFrameHeight = actualFrameWidth;
|
|
190
|
+
} else {
|
|
191
|
+
actualFrameHeight = imageHeight * _detectorSize;
|
|
192
|
+
actualFrameWidth = actualFrameHeight;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
//Define crop rectangle.
|
|
196
|
+
CGRect cropRect = CGRectMake(imageWidth/2 - actualFrameWidth/2, imageHeight/2 - actualFrameHeight/2, actualFrameWidth, actualFrameHeight);
|
|
197
|
+
|
|
198
|
+
//Crop image
|
|
199
|
+
croppedImg = [self croppIngimageByImageName:image toRect:cropRect];
|
|
200
|
+
|
|
201
|
+
//Rotate the image.
|
|
202
|
+
MLKVisionImage *portraitImage = [[MLKVisionImage alloc] initWithImage:croppedImg];
|
|
203
|
+
portraitImage.orientation = UIImageOrientationRight;
|
|
204
|
+
|
|
205
|
+
//Send the image through the barcode reader.
|
|
206
|
+
[self.barcodeDetector processImage:portraitImage completion:^(NSArray<MLKBarcode *> *barcodes,
|
|
207
|
+
NSError *error) {
|
|
208
|
+
if (error != nil) {
|
|
209
|
+
return;
|
|
210
|
+
} else if (barcodes != nil) {
|
|
211
|
+
for (MLKBarcode *barcode in barcodes) {
|
|
212
|
+
NSLog(@"Barcode value: %@", barcode.rawValue);
|
|
213
|
+
[self cleanupCaptureSession];
|
|
214
|
+
[self->_session stopRunning];
|
|
215
|
+
[self->delegate sendResult:barcode];
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}];
|
|
220
|
+
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
#pragma mark - Camera setup
|
|
224
|
+
|
|
225
|
+
- (void)cleanupVideoProcessing {
|
|
226
|
+
if (self.videoDataOutput) {
|
|
227
|
+
[self.session removeOutput:self.videoDataOutput];
|
|
228
|
+
}
|
|
229
|
+
self.videoDataOutput = nil;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
- (void)cleanupCaptureSession {
|
|
233
|
+
[self.session stopRunning];
|
|
234
|
+
[self cleanupVideoProcessing];
|
|
235
|
+
self.session = nil;
|
|
236
|
+
[self.previewLayer removeFromSuperlayer];
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
- (void)setUpVideoProcessing {
|
|
240
|
+
self.videoDataOutput = [[AVCaptureVideoDataOutput alloc] init];
|
|
241
|
+
NSDictionary *rgbOutputSettings = @{
|
|
242
|
+
(__bridge NSString*)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_32BGRA)
|
|
243
|
+
};
|
|
244
|
+
[self.videoDataOutput setVideoSettings:rgbOutputSettings];
|
|
245
|
+
|
|
246
|
+
if (![self.session canAddOutput:self.videoDataOutput]) {
|
|
247
|
+
[self cleanupVideoProcessing];
|
|
248
|
+
NSLog(@"Failed to setup video output");
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
[self.videoDataOutput setAlwaysDiscardsLateVideoFrames:YES];
|
|
252
|
+
[self.videoDataOutput setSampleBufferDelegate:self queue:self.videoDataOutputQueue];
|
|
253
|
+
[self.session addOutput:self.videoDataOutput];
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
- (void)setUpCameraPreview {
|
|
257
|
+
self.previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.session];
|
|
258
|
+
[self.previewLayer setBackgroundColor:[UIColor blackColor].CGColor];
|
|
259
|
+
[self.previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
|
|
260
|
+
|
|
261
|
+
self.previewLayer.frame = self.view.superview.bounds;
|
|
262
|
+
[self.view.layer addSublayer:self.previewLayer];
|
|
263
|
+
|
|
264
|
+
CGRect screenRect = [[UIScreen mainScreen] bounds];
|
|
265
|
+
CGFloat screenWidth = screenRect.size.width;
|
|
266
|
+
CGFloat screenHeight = screenRect.size.height;
|
|
267
|
+
|
|
268
|
+
CGFloat frameWidth = screenWidth*_detectorSize;
|
|
269
|
+
CGFloat frameHeight = frameWidth;
|
|
270
|
+
|
|
271
|
+
UILabel* _label1 = [[UILabel alloc] init];
|
|
272
|
+
_label1.frame = CGRectMake(screenWidth/2 - frameWidth/2, screenHeight/2 - frameHeight/2, frameWidth, frameHeight);
|
|
273
|
+
_label1.layer.masksToBounds = NO;
|
|
274
|
+
_label1.layer.cornerRadius = 30;
|
|
275
|
+
_label1.userInteractionEnabled = YES;
|
|
276
|
+
_label1.layer.borderColor = [UIColor whiteColor].CGColor;
|
|
277
|
+
_label1.layer.borderWidth = 3.0;
|
|
278
|
+
UITapGestureRecognizer* tapScanner = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(focusAtPoint:)];
|
|
279
|
+
[_label1 addGestureRecognizer:tapScanner];
|
|
280
|
+
|
|
281
|
+
CGFloat buttonSize = 45.0;
|
|
282
|
+
|
|
283
|
+
UIButton *_cancelButton = [[UIButton alloc] init];
|
|
284
|
+
[_cancelButton addTarget:self
|
|
285
|
+
action:@selector(closeView:)
|
|
286
|
+
forControlEvents:UIControlEventTouchUpInside];
|
|
287
|
+
|
|
288
|
+
NSString * cancelBase64String = @"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAQAAABpN6lAAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QAAKqNIzIAAAAJcEhZcwAADdcAAA3XAUIom3gAAAAHdElNRQfhCxMVEyaNvw4TAAADNElEQVR42u2dv1LqQBSHv1DwBjY0FjyAA7wCtna2ttrwLr6GY4PWKfQBJGNtb2PDMFQ2ewvmDheBC0l295zjYVO6Cb/vC4b82c0p+Lf1GDNkwAVfzKh4oyRguxWMGTFgyBnvVMwo+dzd8Y4F4cfyQl+aoFXr87LFtOCW4mfHc8qtjqtlyWS7u4lWMGG5h6rkfBN/vqfjapnSlaap3bpM/8s0Xyso9u799fJkTEGXp4NM5d9v9t3BrtYUHIMfCNwC9HYc+mwrOBY/sKAHN0d2tqLgePxA4Abua3TXr6AefuAeXmutoFtBXfzAKwd+AC0pqI8fmMNH7ZV0KmiCH/iAhwar6VPQDD/w0KFq9IFXPCpS0OWRq0ZrVnDZyJymb0HTvR8IXEKx43rJkoI2+C+rk+H+3msm/Qra4C/Xl/qTxhuRVdAGPzBZb6g4cOmoU0E7/OnmXY52G5NQED2xLQVJ0tpRkCypDQVJU+pXkDyhbgVZ0ulVkC2ZTgVZU+lTkD2RLgUiafQoEEuiQ4FoCnkF4glkA4jjy4ZQgS8XRA2+TBhV+PkDqcPPG0olfr5gavHzhFONnz6gevy0IU3gpwtqBj9NWFP48QObw48b2iR+vOBm8eOEN40fQ4Fx/PYKzONLKVCEL6FAGX5uBQrxcypQip9LgWL8HAqU46dWYAA/pQIj+KkUGMJPocAYfmwFBvFjKjCKH0uBYfwYCpLjd6QN/e7m/F/A+UHQ+c+g8xMh56fCzi+GnF8OO78h4vyWmPObos5vizt/MOL80Zjzh6POH487HyDhfIiM80FSzofJOR8o6XyorPPB0s6HyzufMOF8yozzSVPOp805nzjpfOqs88nTzqfPiwfw/v4I0RQ68MWS6MEXSaMLP3siffhZU+nEz5ZML36WdLrxkyfUj580pQ38ZEnt4CdJaws/emL3r9Z2/nJ156/Xd19gwXmJjQ6jhh/7zDXf0uwAfHPNc8N1R+7L7JwKLZ1KbTkvtla30pSeQ9+uVv9wWJ0KLp5Kbrovunoqu4v7wssrBa5Lb6+6uyy+vrlve4wZMuCCL2ZUvFESpBlatoIxIwYMOeOdihkln+s//wFFdoCM42fEswAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNy0xMS0xOVQyMToxOTozOCswMTowMPNH2M8AAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTctMTEtMTlUMjE6MTk6MzgrMDE6MDCCGmBzAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAABJRU5ErkJggg==";
|
|
289
|
+
|
|
290
|
+
NSURL *cancelImageUrl = [NSURL URLWithString:cancelBase64String];
|
|
291
|
+
NSData *cancelImageData = [NSData dataWithContentsOfURL:cancelImageUrl];
|
|
292
|
+
UIImage *cancelIcon = [UIImage imageWithData:cancelImageData];
|
|
293
|
+
[_cancelButton setImage:cancelIcon
|
|
294
|
+
forState:UIControlStateNormal];
|
|
295
|
+
|
|
296
|
+
CGFloat screenOffset = (screenWidth/2 - frameWidth/2)/2 - buttonSize/2;
|
|
297
|
+
NSLog(@"screenOffset %f", screenOffset);
|
|
298
|
+
|
|
299
|
+
_cancelButton.frame = CGRectMake(screenOffset, screenHeight-screenOffset-buttonSize, buttonSize, buttonSize);
|
|
300
|
+
_cancelButton.backgroundColor = [UIColor colorWithWhite:1 alpha:0.4];
|
|
301
|
+
_cancelButton.transform=CGAffineTransformMakeRotation(M_PI / 2);
|
|
302
|
+
_cancelButton.layer.cornerRadius = buttonSize/2;
|
|
303
|
+
_cancelButton.contentEdgeInsets = UIEdgeInsetsMake(15, 15, 15, 15);
|
|
304
|
+
|
|
305
|
+
[self.view addSubview:_cancelButton];
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
self.torchButton = [[UIButton alloc] init];
|
|
311
|
+
[self.torchButton addTarget:self
|
|
312
|
+
action:@selector(toggleFlashlight:)
|
|
313
|
+
forControlEvents:UIControlEventTouchUpInside];
|
|
314
|
+
|
|
315
|
+
NSString * torchBase64String = @"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAQAAABpN6lAAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QAAKqNIzIAAAAJcEhZcwAADdcAAA3XAUIom3gAAAAHdElNRQfhCxMVAzOqoPipAAADM0lEQVR42u2dv2sTcRyG38RWzGYHhxYHp+B+Lk7iIlhFXZvdPeAouOuS1X/AVCiiCBU6OjgIOffG+gvEgCIqlsQi9JxEbC/XJt8fz136eTJecve+T+6Su8t9czX5oqmWEiVa9DbHfAZKlaqrfuDlTERNbQ2VRXwM1VaNrv2v/nrU8n8f62VR0EbqZ8rUpqtLUjPyyv//htB0jV93FrCiBia/oRYv4BxWX5IS1xm4f4x8Cv7FV8RAS7SADKzvoYH7JlBxTAAdgMYE0AFoTAAdwDAMwzAMo7q8ws4IZsr0wjW++57gFqrfeenuAt6YAJLXvADbBFABJVgDPmobrP+DF5BpAxPwyH0WPk6IPKmyAB8/MJ/UZ80D9T/ojPtMfKwB3/UcqO/l/fd1TvAxIuAhstRclrQT/ShgzU/0Y17m8lMLOh9V+UjX3L8CfbKgr1Hf/zt04f3EvFLorU7QdfdzXFuR6v/SRbpsPjci1b9MFx3P7eD1d3SFLlnM3cD1r9IFD+Z+wJW/AvWluh4EqT/UJbraYZnTmvf627pA12IV3KQrTa7gqcf6z+g603BKXzzV/+Z6NSjFiicB9+gi07PhRcBZusb0XPdQ3/nXP5J5D58Dt8JGDHuZ3G8Pp60C//AS+jrBl85zeBc24FxgAe/HTulrVT2lkhIlao0d/RNYQGhO527Xu+rsGWnUUEe7uc+tOPXc+su5z13OVVB59lfqjH1u5ygI2CwYZtfQZmwB8a8WX9Vo7LSRurHjxBfQK5yaRs8TnL2rdPEow8XZ3wRKRnwBicPUmRBQPNY4uoDwlPxrML6AI78jZLvC5ToYCv83JOMqHPZwOHBCTkBJEtqOEB2AxgTQAWhMAB2AxgTQAWhMAB2AxgTQAWhMAB2AxgTQAWhMAB2AxgTQAWhMAB2AxgTQAWhMAB2AxgTQAWhMAB2AxgTQAWhMAB2AxgTQAWhMAB2AxgTQAWhMAB2AxgTQAWhMAB2AxgQEX8IAfHUpBLgNhg0+lDa8gJ7Tq2dgLLHLbXk93Fa3DEz/d6ttOrofpr01d2lure1DwaQ3Z492c/V4jptqKVFy4F2KB0qVqqt+nFh/ADjJgLiaxweIAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE3LTExLTE5VDIxOjAzOjUxKzAxOjAwdhzbkgAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNy0xMS0xOVQyMTowMzo1MSswMTowMAdBYy4AAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAAAElFTkSuQmCCconv";
|
|
316
|
+
|
|
317
|
+
NSURL *torchImageUrl = [NSURL URLWithString:torchBase64String];
|
|
318
|
+
NSData *torchImageData = [NSData dataWithContentsOfURL:torchImageUrl];
|
|
319
|
+
UIImage *torchIcon = [UIImage imageWithData:torchImageData];
|
|
320
|
+
[self.torchButton setImage:torchIcon
|
|
321
|
+
forState:UIControlStateNormal];
|
|
322
|
+
|
|
323
|
+
self.torchButton.frame = CGRectMake(screenWidth-screenOffset-buttonSize, screenHeight-screenOffset-buttonSize, buttonSize, buttonSize);
|
|
324
|
+
self.torchButton.backgroundColor = [UIColor colorWithWhite:1 alpha:0.4];
|
|
325
|
+
self.torchButton.transform=CGAffineTransformMakeRotation(M_PI / 2);
|
|
326
|
+
self.torchButton.layer.cornerRadius = buttonSize/2;
|
|
327
|
+
self.torchButton.contentEdgeInsets = UIEdgeInsetsMake(10, 10, 10, 10);
|
|
328
|
+
|
|
329
|
+
[self.view addSubview:self.torchButton];
|
|
330
|
+
|
|
331
|
+
[self.view addSubview:_label1];
|
|
332
|
+
|
|
333
|
+
self.imageView = [[UIImageView alloc] initWithImage:nil];
|
|
334
|
+
|
|
335
|
+
UIView *catView = [[UIView alloc] initWithFrame:CGRectMake(0,0,frameWidth,frameHeight)];
|
|
336
|
+
self.imageView.frame = catView.bounds;
|
|
337
|
+
|
|
338
|
+
// add the imageview to the superview
|
|
339
|
+
[catView addSubview:self.imageView];
|
|
340
|
+
|
|
341
|
+
//add the view to the main view
|
|
342
|
+
|
|
343
|
+
[self.view addSubview:catView];
|
|
344
|
+
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
#pragma mark - Helper Functions
|
|
348
|
+
|
|
349
|
+
- (void)focusAtPoint:(id) sender {
|
|
350
|
+
NSLog(@"captured touch");
|
|
351
|
+
CGPoint touchPoint = [(UITapGestureRecognizer*)sender locationInView:self.view];
|
|
352
|
+
double focus_x = touchPoint.x/self.previewLayer.frame.size.width;
|
|
353
|
+
double focus_y = (touchPoint.y+66)/self.previewLayer.frame.size.height;
|
|
354
|
+
|
|
355
|
+
NSError *error;
|
|
356
|
+
NSArray *devices = [AVCaptureDevice devices];
|
|
357
|
+
for (AVCaptureDevice *device in devices){
|
|
358
|
+
NSLog(@"Device name: %@", [device localizedName]);
|
|
359
|
+
if ([device hasMediaType:AVMediaTypeVideo]) {
|
|
360
|
+
if ([device position] == AVCaptureDevicePositionBack) {
|
|
361
|
+
NSLog(@"Device position : back");
|
|
362
|
+
CGPoint point = CGPointMake(focus_y, 1-focus_x);
|
|
363
|
+
if ([device isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus] && [device lockForConfiguration:&error]){
|
|
364
|
+
[device setFocusPointOfInterest:point];
|
|
365
|
+
|
|
366
|
+
for (UIView *subView in self.view.subviews)
|
|
367
|
+
{
|
|
368
|
+
if (subView.tag == 99)
|
|
369
|
+
{
|
|
370
|
+
[subView removeFromSuperview];
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
CGRect rect = CGRectMake(touchPoint.x-30, touchPoint.y-30, 60, 60);
|
|
375
|
+
UIView *focusRect = [[UIView alloc] initWithFrame:rect];
|
|
376
|
+
focusRect.layer.borderColor = [UIColor colorWithRed:0.98 green:0.80 blue:0.18 alpha:.7].CGColor;
|
|
377
|
+
focusRect.layer.borderWidth = 1;
|
|
378
|
+
focusRect.tag = 99;
|
|
379
|
+
[self.view addSubview:focusRect];
|
|
380
|
+
|
|
381
|
+
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
|
|
382
|
+
[focusRect removeFromSuperview];
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
[device setFocusMode:AVCaptureFocusModeAutoFocus];
|
|
386
|
+
[device unlockForConfiguration];
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
static inline double radians (double degrees) {return degrees * M_PI/180;}
|
|
393
|
+
- (UIImage*) rotateImage:(UIImage*)src toOrientation:(UIImageOrientation) orientation
|
|
394
|
+
{
|
|
395
|
+
UIGraphicsBeginImageContext(src.size);
|
|
396
|
+
|
|
397
|
+
CGContextRef context = UIGraphicsGetCurrentContext();
|
|
398
|
+
|
|
399
|
+
if (orientation == UIImageOrientationRight) {
|
|
400
|
+
CGContextRotateCTM (context, radians(90));
|
|
401
|
+
} else if (orientation == UIImageOrientationLeft) {
|
|
402
|
+
CGContextRotateCTM (context, radians(-90));
|
|
403
|
+
} else if (orientation == UIImageOrientationDown) {
|
|
404
|
+
// NOTHING
|
|
405
|
+
} else if (orientation == UIImageOrientationUp) {
|
|
406
|
+
CGContextRotateCTM (context, radians(90));
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
[src drawAtPoint:CGPointMake(0, 0)];
|
|
410
|
+
|
|
411
|
+
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
|
|
412
|
+
UIGraphicsEndImageContext();
|
|
413
|
+
return image;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
- (UIImage *)croppIngimageByImageName:(UIImage *)imageToCrop toRect:(CGRect)rect
|
|
417
|
+
{
|
|
418
|
+
//CGRect CropRect = CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height+15);
|
|
419
|
+
|
|
420
|
+
CGImageRef imageRef = CGImageCreateWithImageInRect([imageToCrop CGImage], rect);
|
|
421
|
+
UIImage *cropped = [UIImage imageWithCGImage:imageRef];
|
|
422
|
+
CGImageRelease(imageRef);
|
|
423
|
+
|
|
424
|
+
return cropped;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
- (void) toggleFlashlight:(id)sender
|
|
428
|
+
{
|
|
429
|
+
// check if flashlight available
|
|
430
|
+
Class captureDeviceClass = NSClassFromString(@"AVCaptureDevice");
|
|
431
|
+
if (captureDeviceClass != nil) {
|
|
432
|
+
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
|
|
433
|
+
AVCapturePhotoSettings *photosettings = [AVCapturePhotoSettings photoSettings];
|
|
434
|
+
if ([device hasTorch] && [device hasFlash]){
|
|
435
|
+
|
|
436
|
+
[device lockForConfiguration:nil];
|
|
437
|
+
if (device.torchMode == AVCaptureTorchModeOff)
|
|
438
|
+
{
|
|
439
|
+
self.torchButton.backgroundColor = [UIColor colorWithWhite:1 alpha:1];
|
|
440
|
+
[device setTorchMode:AVCaptureTorchModeOn];
|
|
441
|
+
photosettings.flashMode = AVCaptureFlashModeOn;
|
|
442
|
+
//torchIsOn = YES;
|
|
443
|
+
}
|
|
444
|
+
else
|
|
445
|
+
{
|
|
446
|
+
self.torchButton.backgroundColor = [UIColor colorWithWhite:1 alpha:.4];
|
|
447
|
+
[device setTorchMode:AVCaptureTorchModeOff];
|
|
448
|
+
photosettings.flashMode = AVCaptureFlashModeOff;
|
|
449
|
+
// torchIsOn = NO;
|
|
450
|
+
}
|
|
451
|
+
[device unlockForConfiguration];
|
|
452
|
+
}
|
|
453
|
+
} }
|
|
454
|
+
|
|
455
|
+
- (void)closeView:(id)sender{
|
|
456
|
+
[ self cleanupCaptureSession];
|
|
457
|
+
[_session stopRunning];
|
|
458
|
+
[delegate closeScanner];
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
|
|
462
|
+
- (void)updateCameraSelection {
|
|
463
|
+
[self.session beginConfiguration];
|
|
464
|
+
|
|
465
|
+
// Remove old inputs
|
|
466
|
+
NSArray *oldInputs = [self.session inputs];
|
|
467
|
+
for (AVCaptureInput *oldInput in oldInputs) {
|
|
468
|
+
[self.session removeInput:oldInput];
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
AVCaptureDevicePosition desiredPosition = AVCaptureDevicePositionBack;
|
|
472
|
+
AVCaptureDeviceInput *input = [self captureDeviceInputForPosition:desiredPosition];
|
|
473
|
+
if (!input) {
|
|
474
|
+
// Failed, restore old inputs
|
|
475
|
+
for (AVCaptureInput *oldInput in oldInputs) {
|
|
476
|
+
[self.session addInput:oldInput];
|
|
477
|
+
}
|
|
478
|
+
} else {
|
|
479
|
+
// Succeeded, set input and update connection states
|
|
480
|
+
[self.session addInput:input];
|
|
481
|
+
}
|
|
482
|
+
[self.session commitConfiguration];
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
- (AVCaptureDeviceInput *)captureDeviceInputForPosition:(AVCaptureDevicePosition)desiredPosition {
|
|
486
|
+
for (AVCaptureDevice *device in [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]) {
|
|
487
|
+
if (device.position == desiredPosition) {
|
|
488
|
+
NSError *error = nil;
|
|
489
|
+
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device
|
|
490
|
+
error:&error];
|
|
491
|
+
if (error) {
|
|
492
|
+
NSLog(@"Could not initialize for AVMediaTypeVideo for device %@", device);
|
|
493
|
+
} else if ([self.session canAddInput:input]) {
|
|
494
|
+
return input;
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
return nil;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
@end
|
|
Binary file
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { MLKitBarcodeScanner } from './BarcodeScanner.plugin';
|
|
2
|
+
declare global {
|
|
3
|
+
interface CordovaPlugins {
|
|
4
|
+
mlkit: {
|
|
5
|
+
barcodeScanner: MLKitBarcodeScanner;
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export { MLKitBarcodeScanner } from './BarcodeScanner.plugin';
|
|
10
|
+
export { IBarcodeFormats, IError, IOptions, IResult } from './Interface';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var BarcodeScanner_plugin = require('./BarcodeScanner.plugin.js');
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
exports.MLKitBarcodeScanner = BarcodeScanner_plugin.MLKitBarcodeScanner;
|
|
10
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQmFyY29kZVNjYW5uZXIuY29udHJhY3QuanMiLCJzb3VyY2VzIjpbXSwic291cmNlc0NvbnRlbnQiOltdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7OzsifQ==
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { IError, IOptions, IResult } from './Interface';
|
|
2
|
+
export declare class MLKitBarcodeScanner {
|
|
3
|
+
private getBarcodeFormat;
|
|
4
|
+
private getBarcodeType;
|
|
5
|
+
private getBarcodeFormatFlags;
|
|
6
|
+
scan(userOptions: IOptions, success: (result: IResult | IResult[]) => unknown, failure: (error: IError) => unknown): void;
|
|
7
|
+
private sendScanRequest;
|
|
8
|
+
}
|