1// Copyright 2016-present 650 Industries. All rights reserved.
2
3#import <UIKit/UIKit.h>
4#import <AVFoundation/AVFoundation.h>
5#import <EXBarCodeScanner/EXBarCodeScannerUtils.h>
6
7@implementation EXBarCodeScannerUtils
8
9+ (NSDictionary *)validBarCodeTypes
10{
11    NSMutableDictionary *validTypes = [@{
12      @"upc_e" : AVMetadataObjectTypeUPCECode,
13      @"code39" : AVMetadataObjectTypeCode39Code,
14      @"code39mod43" : AVMetadataObjectTypeCode39Mod43Code,
15      @"ean13" : AVMetadataObjectTypeEAN13Code,
16      @"ean8" : AVMetadataObjectTypeEAN8Code,
17      @"code93" : AVMetadataObjectTypeCode93Code,
18      @"code128" : AVMetadataObjectTypeCode128Code,
19      @"pdf417" : AVMetadataObjectTypePDF417Code,
20      @"qr" : AVMetadataObjectTypeQRCode,
21      @"aztec" : AVMetadataObjectTypeAztecCode,
22      @"interleaved2of5" : AVMetadataObjectTypeInterleaved2of5Code,
23      @"itf14" : AVMetadataObjectTypeITF14Code,
24      @"datamatrix" : AVMetadataObjectTypeDataMatrixCode,
25    } mutableCopy];
26    if (@available(iOS 15.4, *)) {
27      validTypes[@"codabar"] = AVMetadataObjectTypeCodabarCode;
28    }
29    return validTypes;
30}
31
32+ (AVCaptureVideoOrientation)videoOrientationForInterfaceOrientation:(UIInterfaceOrientation)orientation
33{
34  switch (orientation) {
35    case UIInterfaceOrientationPortrait:
36      return AVCaptureVideoOrientationPortrait;
37    case UIInterfaceOrientationPortraitUpsideDown:
38      return AVCaptureVideoOrientationPortraitUpsideDown;
39    case UIInterfaceOrientationLandscapeRight:
40      return AVCaptureVideoOrientationLandscapeRight;
41    case UIInterfaceOrientationLandscapeLeft:
42      return AVCaptureVideoOrientationLandscapeLeft;
43    default:
44      return 0;
45  }
46}
47
48+ (AVCaptureDevice *)deviceWithMediaType:(AVMediaType)mediaType
49                      preferringPosition:(AVCaptureDevicePosition)position
50{
51  return [AVCaptureDevice defaultDeviceWithDeviceType:AVCaptureDeviceTypeBuiltInWideAngleCamera mediaType:mediaType position:position];
52}
53
54+ (NSDictionary *)ciQRCodeFeatureToDicitionary:(CIQRCodeFeature *)barCodeScannerResult barCodeType:(NSString *)type
55{
56  NSMutableDictionary *result = [NSMutableDictionary new];
57  result[@"type"] = type;
58  result[@"data"] = barCodeScannerResult.messageString;
59
60  if (!CGRectIsEmpty(barCodeScannerResult.bounds)) {
61    NSMutableArray<NSDictionary *> *cornerPointsResult = [NSMutableArray new];
62    for (NSValue *nsPoint in @[
63      [NSValue valueWithCGPoint:barCodeScannerResult.topLeft],
64      [NSValue valueWithCGPoint:barCodeScannerResult.topRight],
65      [NSValue valueWithCGPoint:barCodeScannerResult.bottomRight],
66      [NSValue valueWithCGPoint:barCodeScannerResult.bottomLeft]
67    ]) {
68      CGPoint point = [nsPoint CGPointValue];
69      [cornerPointsResult addObject:@{
70        @"x": @(point.x),
71        @"y": @(point.y)
72      }];
73    }
74
75    result[@"cornerPoints"] = cornerPointsResult;
76    result[@"bounds"] = @{
77      @"origin": @{
78          @"x": @(barCodeScannerResult.bounds.origin.x),
79          @"y": @(barCodeScannerResult.bounds.origin.y),
80      },
81      @"size": @{
82          @"width": @(barCodeScannerResult.bounds.size.width),
83          @"height": @(barCodeScannerResult.bounds.size.height),
84      }
85    };
86  }
87
88  return result;
89}
90
91+ (NSDictionary *)avMetadataCodeObjectToDicitionary:(AVMetadataMachineReadableCodeObject *)barCodeScannerResult
92{
93  NSMutableDictionary *result = [NSMutableDictionary new];
94  result[@"type"] = barCodeScannerResult.type;
95  result[@"data"] = barCodeScannerResult.stringValue;
96
97  if (barCodeScannerResult.corners.count) {
98    NSMutableArray<NSDictionary *> *cornerPointsResult = [NSMutableArray new];
99    for (NSDictionary *point in barCodeScannerResult.corners) {
100      [cornerPointsResult addObject:@{
101        @"x": point[@"X"],
102        @"y": point[@"Y"]
103      }];
104    }
105    result[@"cornerPoints"] = cornerPointsResult;
106    result[@"bounds"] = @{
107      @"origin": @{
108          @"x": @(barCodeScannerResult.bounds.origin.x),
109          @"y": @(barCodeScannerResult.bounds.origin.y),
110      },
111      @"size": @{
112          @"width": @(barCodeScannerResult.bounds.size.width),
113          @"height": @(barCodeScannerResult.bounds.size.height),
114      }
115    };
116  }
117  return result;
118}
119
120+ (NSDictionary *)zxResultToDicitionary:(ZXResult *)barCodeScannerResult
121{
122  NSMutableDictionary *result = [NSMutableDictionary new];
123  result[@"type"] = [EXBarCodeScannerUtils zxingFormatToString:barCodeScannerResult.barcodeFormat];
124
125  // text contains characteres u'\0' (null character) that malforme resulting string, so we get rid of them
126  NSMutableString* data = [NSMutableString new];
127  for (int i = 0; i < [barCodeScannerResult.text length]; i++) {
128    if ([barCodeScannerResult.text characterAtIndex:i] != u'\0') {
129      [data appendFormat:@"%c", [barCodeScannerResult.text characterAtIndex:i]];
130    }
131  }
132  result[@"data"] = data;
133
134  return result;
135}
136
137+ (NSString *)zxingFormatToString:(ZXBarcodeFormat)format
138{
139  switch (format) {
140    case kBarcodeFormatPDF417:
141      return AVMetadataObjectTypePDF417Code;
142    case kBarcodeFormatCode39:
143      return AVMetadataObjectTypeCode39Code;
144    case kBarcodeFormatCodabar:
145      // available in iOS 15.4+
146      if (@available(iOS 15.4, *)) {
147        return AVMetadataObjectTypeCodabarCode;
148      } else {
149        return @"unknown";
150      }
151    default:
152      return @"unknown";
153  }
154}
155
156@end
157