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#ifdef __IPHONE_15_4
27    if (@available(iOS 15.4, *)) {
28      validTypes[@"codabar"] = AVMetadataObjectTypeCodabarCode;
29    }
30#endif
31    return validTypes;
32}
33
34+ (AVCaptureVideoOrientation)videoOrientationForInterfaceOrientation:(UIInterfaceOrientation)orientation
35{
36  switch (orientation) {
37    case UIInterfaceOrientationPortrait:
38      return AVCaptureVideoOrientationPortrait;
39    case UIInterfaceOrientationPortraitUpsideDown:
40      return AVCaptureVideoOrientationPortraitUpsideDown;
41    case UIInterfaceOrientationLandscapeRight:
42      return AVCaptureVideoOrientationLandscapeRight;
43    case UIInterfaceOrientationLandscapeLeft:
44      return AVCaptureVideoOrientationLandscapeLeft;
45    default:
46      return 0;
47  }
48}
49
50+ (AVCaptureDevice *)deviceWithMediaType:(AVMediaType)mediaType
51                      preferringPosition:(AVCaptureDevicePosition)position
52{
53  return [AVCaptureDevice defaultDeviceWithDeviceType:AVCaptureDeviceTypeBuiltInWideAngleCamera mediaType:mediaType position:position];
54}
55
56+ (NSDictionary *)ciQRCodeFeatureToDicitionary:(CIQRCodeFeature *)barCodeScannerResult barCodeType:(NSString *)type
57{
58  NSMutableDictionary *result = [NSMutableDictionary new];
59  result[@"type"] = type;
60  result[@"data"] = barCodeScannerResult.messageString;
61
62  if (!CGRectIsEmpty(barCodeScannerResult.bounds)) {
63    NSMutableArray<NSDictionary *> *cornerPointsResult = [NSMutableArray new];
64    for (NSValue *nsPoint in @[
65      [NSValue valueWithCGPoint:barCodeScannerResult.topLeft],
66      [NSValue valueWithCGPoint:barCodeScannerResult.topRight],
67      [NSValue valueWithCGPoint:barCodeScannerResult.bottomRight],
68      [NSValue valueWithCGPoint:barCodeScannerResult.bottomLeft]
69    ]) {
70      CGPoint point = [nsPoint CGPointValue];
71      [cornerPointsResult addObject:@{
72        @"x": @(point.x),
73        @"y": @(point.y)
74      }];
75    }
76
77    result[@"cornerPoints"] = cornerPointsResult;
78    result[@"bounds"] = @{
79      @"origin": @{
80          @"x": @(barCodeScannerResult.bounds.origin.x),
81          @"y": @(barCodeScannerResult.bounds.origin.y),
82      },
83      @"size": @{
84          @"width": @(barCodeScannerResult.bounds.size.width),
85          @"height": @(barCodeScannerResult.bounds.size.height),
86      }
87    };
88  }
89
90  return result;
91}
92
93+ (NSDictionary *)avMetadataCodeObjectToDicitionary:(AVMetadataMachineReadableCodeObject *)barCodeScannerResult
94{
95  NSMutableDictionary *result = [NSMutableDictionary new];
96  result[@"type"] = barCodeScannerResult.type;
97  result[@"data"] = barCodeScannerResult.stringValue;
98
99  if (barCodeScannerResult.corners.count) {
100    NSMutableArray<NSDictionary *> *cornerPointsResult = [NSMutableArray new];
101    for (NSDictionary *point in barCodeScannerResult.corners) {
102      [cornerPointsResult addObject:@{
103        @"x": point[@"X"],
104        @"y": point[@"Y"]
105      }];
106    }
107    result[@"cornerPoints"] = cornerPointsResult;
108    result[@"bounds"] = @{
109      @"origin": @{
110          @"x": @(barCodeScannerResult.bounds.origin.x),
111          @"y": @(barCodeScannerResult.bounds.origin.y),
112      },
113      @"size": @{
114          @"width": @(barCodeScannerResult.bounds.size.width),
115          @"height": @(barCodeScannerResult.bounds.size.height),
116      }
117    };
118  }
119  return result;
120}
121
122+ (NSDictionary *)zxResultToDicitionary:(ZXResult *)barCodeScannerResult
123{
124  NSMutableDictionary *result = [NSMutableDictionary new];
125  result[@"type"] = [EXBarCodeScannerUtils zxingFormatToString:barCodeScannerResult.barcodeFormat];
126
127  // text contains characteres u'\0' (null character) that malforme resulting string, so we get rid of them
128  NSMutableString* data = [NSMutableString new];
129  for (int i = 0; i < [barCodeScannerResult.text length]; i++) {
130    if ([barCodeScannerResult.text characterAtIndex:i] != u'\0') {
131      [data appendFormat:@"%c", [barCodeScannerResult.text characterAtIndex:i]];
132    }
133  }
134  result[@"data"] = data;
135
136  return result;
137}
138
139+ (NSString *)zxingFormatToString:(ZXBarcodeFormat)format
140{
141  switch (format) {
142    case kBarcodeFormatPDF417:
143      return AVMetadataObjectTypePDF417Code;
144    case kBarcodeFormatCode39:
145      return AVMetadataObjectTypeCode39Code;
146    case kBarcodeFormatCodabar:
147#ifdef __IPHONE_15_4
148      if (@available(iOS 15.4, *)) {
149        return AVMetadataObjectTypeCodabarCode;
150      }
151#endif
152      return @"unknown";
153    default:
154      return @"unknown";
155  }
156}
157
158@end
159