react-native-camera_edit/ios/RN/BarcodeDetectorManagerMlkit.m
2025-07-09 11:33:00 +09:00

440 lines
18 KiB
Objective-C

#import "BarcodeDetectorManagerMlkit.h"
#import <React/RCTConvert.h>
#if __has_include(<FirebaseMLVision/FirebaseMLVision.h>)
@interface BarcodeDetectorManagerMlkit ()
@property(nonatomic, strong) FIRVisionBarcodeDetector *barcodeRecognizer;
@property(nonatomic, strong) FIRVision *vision;
@property(nonatomic, assign) FIRVisionBarcodeFormat setOption;
@property(nonatomic, assign) float scaleX;
@property(nonatomic, assign) float scaleY;
@end
@implementation BarcodeDetectorManagerMlkit
- (instancetype)init
{
if (self = [super init]) {
self.vision = [FIRVision vision];
self.barcodeRecognizer = [_vision barcodeDetector];
}
return self;
}
- (BOOL)isRealDetector
{
return true;
}
+ (NSDictionary *)constants
{
return @{
@"CODE_128" : @(FIRVisionBarcodeFormatCode128),
@"CODE_39" : @(FIRVisionBarcodeFormatCode39),
@"CODE_93" : @(FIRVisionBarcodeFormatCode93),
@"CODABAR" : @(FIRVisionBarcodeFormatCodaBar),
@"EAN_13" : @(FIRVisionBarcodeFormatEAN13),
@"EAN_8" : @(FIRVisionBarcodeFormatEAN8),
@"ITF" : @(FIRVisionBarcodeFormatITF),
@"UPC_A" : @(FIRVisionBarcodeFormatUPCA),
@"UPC_E" : @(FIRVisionBarcodeFormatUPCE),
@"QR_CODE" : @(FIRVisionBarcodeFormatQRCode),
@"PDF417" : @(FIRVisionBarcodeFormatPDF417),
@"AZTEC" : @(FIRVisionBarcodeFormatAztec),
@"DATA_MATRIX" : @(FIRVisionBarcodeFormatDataMatrix),
@"ALL" : @(FIRVisionBarcodeFormatAll),
};
}
- (void)setType:(id)json queue:(dispatch_queue_t)sessionQueue
{
NSInteger requestedValue = [RCTConvert NSInteger:json];
if (self.setOption != requestedValue) {
if (sessionQueue) {
dispatch_async(sessionQueue, ^{
self.setOption = requestedValue;
FIRVisionBarcodeDetectorOptions *options =
[[FIRVisionBarcodeDetectorOptions alloc]
initWithFormats: requestedValue];
self.barcodeRecognizer =
[self.vision barcodeDetectorWithOptions:options];
});
}
}
}
- (void)findBarcodesInFrame:(UIImage *)uiImage
scaleX:(float)scaleX
scaleY:(float)scaleY
completed:(void (^)(NSArray *result))completed
{
self.scaleX = scaleX;
self.scaleY = scaleY;
FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];
NSMutableArray *emptyResult = [[NSMutableArray alloc] init];
[_barcodeRecognizer detectInImage:image
completion:^(NSArray<FIRVisionBarcode *> *barcodes, NSError *error) {
if (error != nil || barcodes == nil) {
completed(emptyResult);
} else {
completed([self processBarcodes:barcodes]);
}
}];
}
- (NSArray *)processBarcodes:(NSArray *)barcodes
{
NSMutableArray *result = [[NSMutableArray alloc] init];
for (FIRVisionBarcode *barcode in barcodes) {
NSMutableDictionary *resultDict =
[[NSMutableDictionary alloc] initWithCapacity:20];
// Boundaries of a barcode in image
NSDictionary *bounds = [self processBounds:barcode.frame];
[resultDict setObject:bounds forKey:@"bounds"];
// TODO send points to javascript - implement on android at the same time
// Point[] corners = barcode.getCornerPoints();
NSString *rawValue = barcode.rawValue;
NSString *displayValue = barcode.displayValue;
[resultDict setObject:rawValue forKey:@"dataRaw"];
[resultDict setObject:displayValue forKey:@"data"];
FIRVisionBarcodeValueType valueType = barcode.valueType;
[resultDict setObject:[self getType:barcode.valueType] forKey:@"type"];
switch (valueType) {
case FIRVisionBarcodeValueTypeWiFi:
if(barcode.wifi.ssid) {[resultDict setObject:barcode.wifi.ssid forKey:@"ssid"]; }
if(barcode.wifi.password) {[resultDict setObject:barcode.wifi.password forKey:@"password"]; }
if(barcode.wifi.type) {
NSString *encryptionTypeString = @"UNKNOWN";
int type = barcode.wifi.type;
switch (type) {
case FIRVisionBarcodeWiFiEncryptionTypeWEP:
encryptionTypeString = @"WEP";
break;
case FIRVisionBarcodeWiFiEncryptionTypeWPA:
encryptionTypeString = @"WPA";
break;
case FIRVisionBarcodeWiFiEncryptionTypeOpen:
encryptionTypeString = @"Open";
break;
default:
break;
}
[resultDict setObject:encryptionTypeString forKey:@"encryptionType"];
}
break;
case FIRVisionBarcodeValueTypeURL:
if(barcode.URL.url) { [resultDict setObject:barcode.URL.url forKey:@"url"]; }
if(barcode.URL.title) { [resultDict setObject:barcode.URL.title forKey:@"title"]; }
break;
case FIRVisionBarcodeValueTypeContactInfo:
if(barcode.contactInfo.addresses) {
NSMutableArray *addresses = [[NSMutableArray alloc] init];
for (FIRVisionBarcodeAddress *address in barcode.contactInfo.addresses) {
[addresses addObject:[self processAddress:address]];
}
[resultDict setObject:addresses forKey:@"addresses"];
}
if(barcode.contactInfo.emails) {
NSMutableArray *emails = [[NSMutableArray alloc] init];
for (FIRVisionBarcodeEmail *email in barcode.contactInfo.emails) {
[emails addObject:[self processEmail:email]];
}
[resultDict setObject:emails forKey:@"emails"];
}
if(barcode.contactInfo.name) {
FIRVisionBarcodePersonName *name = barcode.contactInfo.name;
NSObject *nameObject = @{
@"formattedName" : name.formattedName ? name.formattedName : @"",
@"firstName" : name.first ? name.first : @"",
@"middleName" : name.middle ? name.middle : @"",
@"lastName" : name.last ? name.last : @"",
@"prefix" : name.prefix ? name.prefix : @"",
@"pronounciation" : name.pronounciation ? name.pronounciation : @"",
@"suffix" : name.suffix ? name.suffix : @"",
};
[resultDict setObject:nameObject forKey:@"name"];
}
if(barcode.contactInfo.phones) {
NSMutableArray *phones = [[NSMutableArray alloc] init];
for (FIRVisionBarcodePhone *phone in barcode.contactInfo.phones) {
[phones addObject:[self processPhone:phone]];
}
[resultDict setObject:phones forKey:@"phones"];
}
if(barcode.contactInfo.urls) {[resultDict setObject:barcode.contactInfo.urls forKey:@"urls"]; }
if(barcode.contactInfo.organization) {[resultDict setObject:barcode.contactInfo.organization forKey:@"organization"]; }
break;
case FIRVisionBarcodeValueTypeSMS:
if(barcode.sms.message) {[resultDict setObject:barcode.sms.message forKey:@"message"]; }
if(barcode.sms.phoneNumber) {[resultDict setObject:barcode.sms.phoneNumber forKey:@"phoneNumber"]; }
break;
case FIRVisionBarcodeValueTypeGeographicCoordinates:
if(barcode.geoPoint.latitude) {[resultDict setObject:@(barcode.geoPoint.latitude) forKey:@"latitude"]; }
if(barcode.geoPoint.longitude) {[resultDict setObject:@(barcode.geoPoint.longitude) forKey:@"longitude"]; }
break;
case FIRVisionBarcodeValueTypeDriversLicense:
if(barcode.driverLicense.firstName) {[resultDict setObject:barcode.driverLicense.firstName forKey:@"firstName"]; }
if(barcode.driverLicense.middleName) {[resultDict setObject:barcode.driverLicense.middleName forKey:@"middleName"]; }
if(barcode.driverLicense.lastName) {[resultDict setObject:barcode.driverLicense.lastName forKey:@"lastName"]; }
if(barcode.driverLicense.gender) {[resultDict setObject:barcode.driverLicense.gender forKey:@"gender"]; }
if(barcode.driverLicense.addressCity) {[resultDict setObject:barcode.driverLicense.addressCity forKey:@"addressCity"]; }
if(barcode.driverLicense.addressState) {[resultDict setObject:barcode.driverLicense.addressState forKey:@"addressState"]; }
if(barcode.driverLicense.addressStreet) {[resultDict setObject:barcode.driverLicense.addressStreet forKey:@"addressStreet"]; }
if(barcode.driverLicense.addressZip) {[resultDict setObject:barcode.driverLicense.addressZip forKey:@"addressZip"]; }
if(barcode.driverLicense.birthDate) {[resultDict setObject:barcode.driverLicense.birthDate forKey:@"birthDate"]; }
if(barcode.driverLicense.documentType) {[resultDict setObject:barcode.driverLicense.documentType forKey:@"documentType"]; }
if(barcode.driverLicense.licenseNumber) {[resultDict setObject:barcode.driverLicense.licenseNumber forKey:@"licenseNumber"]; }
if(barcode.driverLicense.expiryDate) {[resultDict setObject:barcode.driverLicense.expiryDate forKey:@"expiryDate"]; }
if(barcode.driverLicense.issuingDate) {[resultDict setObject:barcode.driverLicense.issuingDate forKey:@"issuingDate"]; }
if(barcode.driverLicense.issuingCountry) {[resultDict setObject:barcode.driverLicense.issuingCountry forKey:@"issuingCountry"]; }
break;
case FIRVisionBarcodeValueTypeCalendarEvent:
if(barcode.calendarEvent.eventDescription) {[resultDict setObject:barcode.calendarEvent.eventDescription forKey:@"eventDescription"]; }
if(barcode.calendarEvent.location) {[resultDict setObject:barcode.calendarEvent.location forKey:@"location"]; }
if(barcode.calendarEvent.organizer) {[resultDict setObject:barcode.calendarEvent.organizer forKey:@"organizer"]; }
if(barcode.calendarEvent.status) {[resultDict setObject:barcode.calendarEvent.status forKey:@"status"]; }
if(barcode.calendarEvent.summary) {[resultDict setObject:barcode.calendarEvent.summary forKey:@"summary"]; }
if(barcode.calendarEvent.start) {
[resultDict setObject:[self processDate:barcode.calendarEvent.start] forKey:@"start"];
}
if(barcode.calendarEvent.end) {
[resultDict setObject:[self processDate:barcode.calendarEvent.end] forKey:@"end"];
}
break;
case FIRVisionBarcodeValueTypePhone:
if(barcode.phone.number) {[resultDict setObject:barcode.phone.number forKey:@"number"]; }
if(barcode.phone.type) {
[resultDict setObject:[self getPhoneType:barcode.phone.type] forKey:@"phoneType"];
}
break;
case FIRVisionBarcodeValueTypeEmail:
if(barcode.email.address) {[resultDict setObject:barcode.email.address forKey:@"address"]; }
if(barcode.email.body) {[resultDict setObject:barcode.email.body forKey:@"body"]; }
if(barcode.email.subject) {[resultDict setObject:barcode.email.subject forKey:@"subject"]; }
if(barcode.email.type) {[resultDict setObject:[self getEmailType:barcode.email.type] forKey:@"emailType"]; }
break;
default:
break;
}
[result addObject:resultDict];
}
return result;
}
- (NSString *)getType:(int)type
{
NSString *barcodeType = @"UNKNOWN";
switch (type) {
case FIRVisionBarcodeValueTypeEmail:
barcodeType = @"EMAIL";
break;
case FIRVisionBarcodeValueTypePhone:
barcodeType = @"PHONE";
break;
case FIRVisionBarcodeValueTypeCalendarEvent:
barcodeType = @"CALENDAR_EVENT";
break;
case FIRVisionBarcodeValueTypeDriversLicense:
barcodeType = @"DRIVER_LICENSE";
break;
case FIRVisionBarcodeValueTypeGeographicCoordinates:
barcodeType = @"GEO";
break;
case FIRVisionBarcodeValueTypeSMS:
barcodeType = @"SMS";
break;
case FIRVisionBarcodeValueTypeContactInfo:
barcodeType = @"CONTACT_INFO";
break;
case FIRVisionBarcodeValueTypeWiFi:
barcodeType = @"WIFI";
break;
case FIRVisionBarcodeValueTypeText:
barcodeType = @"TEXT";
break;
case FIRVisionBarcodeValueTypeISBN:
barcodeType = @"ISBN";
break;
case FIRVisionBarcodeValueTypeProduct:
barcodeType = @"PRODUCT";
break;
default:
break;
}
return barcodeType;
}
- (NSString *)getPhoneType:(int)type
{
NSString *typeString = @"UNKNOWN";
switch (type) {
case FIRVisionBarcodePhoneTypeFax:
typeString = @"Fax";
break;
case FIRVisionBarcodePhoneTypeHome:
typeString = @"Home";
case FIRVisionBarcodePhoneTypeWork:
typeString = @"Work";
case FIRVisionBarcodePhoneTypeMobile:
typeString = @"Mobile";
default:
break;
}
return typeString;
}
- (NSString *)getEmailType:(int)type
{
NSString *typeString = @"UNKNOWN";
switch (type) {
case FIRVisionBarcodeEmailTypeWork:
typeString = @"Work";
break;
case FIRVisionBarcodeEmailTypeHome:
typeString = @"Home";
default:
break;
}
return typeString;
}
- (NSDictionary *)processPhone:(FIRVisionBarcodePhone *)phone
{
NSString *number = @"";
NSString *typeString = @"UNKNOWN";
if (phone) {
typeString = [self getPhoneType:phone.type];
number = phone.number;
}
return @{@"number" : number, @"phoneType" : typeString};
}
- (NSDictionary *)processAddress:(FIRVisionBarcodeAddress *)address
{
NSArray *addressLines = [[NSArray alloc] init];
NSString *typeString = @"UNKNOWN";
if (address) {
int type = address.type;
NSString *typeString = @"UNKNOWN";
switch (type) {
case FIRVisionBarcodeAddressTypeWork:
typeString = @"Work";
break;
case FIRVisionBarcodeAddressTypeHome:
typeString = @"Home";
default:
break;
}
addressLines = address.addressLines;
}
return @{@"addressLines" : addressLines, @"addressType" : typeString};
}
- (NSDictionary *)processEmail:(FIRVisionBarcodeEmail *)email
{
NSString *subject = @"";
NSString *address =@"";
NSString *body =@"";
NSString *typeString = @"UNKNOWN";
if (email) {
if (email.subject) { subject = email.subject; }
if (email.address) { address = email.address; }
if (email.body) { body = email.body; }
typeString = [self getEmailType:email.type];
}
return @{@"subject" : subject, @"body" : body, @"address" : address, @"emailType" : typeString};
}
- (NSString *)processDate:(NSDate *)date
{
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"dd-MM-YYYY HH:mm:ss"];
return [dateFormatter stringFromDate:date];
}
- (NSDictionary *)processBounds:(CGRect)bounds
{
float width = bounds.size.width * _scaleX;
float height = bounds.size.height * _scaleY;
float originX = bounds.origin.x * _scaleX;
float originY = bounds.origin.y * _scaleY;
NSDictionary *boundsDict = @{
@"size" : @{@"width" : @(width), @"height" : @(height)},
@"origin" : @{@"x" : @(originX), @"y" : @(originY)}
};
return boundsDict;
}
- (NSDictionary *)processPoint:(FIRVisionPoint *)point
{
float originX = [point.x floatValue] * _scaleX;
float originY = [point.y floatValue] * _scaleY;
NSDictionary *pointDict = @{
@"x" : @(originX),
@"y" : @(originY)
};
return pointDict;
}
@end
#else
@interface BarcodeDetectorManagerMlkit ()
@end
@implementation BarcodeDetectorManagerMlkit
- (instancetype)init {
self = [super init];
return self;
}
- (BOOL)isRealDetector {
return false;
}
- (void)findBarcodesInFrame:(UIImage *)image
scaleX:(float)scaleX
scaleY:(float)scaleY
completed:(void (^)(NSArray *result))completed;
{
NSLog(@"BarcodeDetector not installed, stub used!");
NSArray *barcodes = @[ @"Error, Barcode Detector not installed" ];
completed(barcodes);
}
+ (NSDictionary *)constants
{
return @{
@"CODE_128" : @{},
@"CODE_39" : @{},
@"CODE_93" : @{},
@"CODABAR" : @{},
@"EAN_13" : @{},
@"EAN_8" : @{},
@"ITF" : @{},
@"UPC_A" : @{},
@"UPC_E" : @{},
@"QR_CODE" : @{},
@"PDF417" : @{},
@"AZTEC" : @{},
@"DATA_MATRIX" : @{},
};
}
- (void)setType:(id)json queue:(dispatch_queue_t)sessionQueue
{
return;
}
@end
#endif