cronapp-plugin-mlkit 1.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/package.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "cronapp-plugin-mlkit",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "cordova": {
6
+ "id": "cronapp-plugin-mlkit",
7
+ "platforms": [
8
+ "ios",
9
+ "android"
10
+ ]
11
+ },
12
+ "keywords": [
13
+ "cronapp",
14
+ "mlkit",
15
+ "ocr",
16
+ "ecosystem:cordova",
17
+ "cordova-ios",
18
+ "cordova-android"
19
+ ],
20
+ "author": "Cronapp Team",
21
+ "license": "MIT",
22
+ "repository": {
23
+ "type": "git"
24
+ }
25
+ }
package/plugin.xml ADDED
@@ -0,0 +1,65 @@
1
+ <?xml version='1.0' encoding='utf-8'?>
2
+ <plugin id="cronapp-plugin-mlkit" version="1.0.0" xmlns="http://apache.org/cordova/ns/plugins/1.0" xmlns:android="http://schemas.android.com/apk/res/android">
3
+ <name>CronappMLKitPlugin</name>
4
+
5
+ <js-module name="CronappMLKitPlugin" src="www/cronapp-mlkit.js">
6
+ <clobbers target="CronappMLKitPlugin" />
7
+ </js-module>
8
+ <platform name="ios">
9
+ <dependency id="cordova-plugin-add-swift-support" version="2.0.2"/>
10
+
11
+ <config-file target="config.xml" parent="/*">
12
+ <feature name="CronappMLKitPlugin">
13
+ <param name="ios-package" value="CronappMLKitPlugin" />
14
+ <param name="onload" value="true" />
15
+ </feature>
16
+ </config-file>
17
+
18
+ <source-file src="src/ios/CronappMLKitPlugin.swift" />
19
+ <source-file src="src/ios/CronappMLKitExtensions.swift" />
20
+
21
+ <podspec>
22
+ <config>
23
+ <source url="https://cdn.cocoapods.org/"/>
24
+ </config>
25
+ <pods use-frameworks="true">
26
+ <pod name="GoogleMLKit/TextRecognition"/>
27
+ <pod name="GoogleMLKit/BarcodeScanning"/>
28
+ <pod name="GoogleMLKit/ImageLabeling"/>
29
+ <pod name="GoogleMLKit/FaceDetection"/>
30
+ </pods>
31
+ </podspec>
32
+ </platform>
33
+
34
+ <platform name="android">
35
+ <dependency id="cordova-plugin-androidx" version="^2.0.0" />
36
+ <dependency id="cordova-plugin-androidx-adapter" version="^1.1.1" />
37
+
38
+ <config-file target="res/xml/config.xml" parent="/*">
39
+ <feature name="CronappMLKitPlugin">
40
+ <param name="android-package" value="io.cronapp.mlkit.CronappMLKitPlugin" />
41
+ <param name="onload" value="true" />
42
+ </feature>
43
+ </config-file>
44
+
45
+ <config-file target="AndroidManifest.xml" parent="/manifest/application">
46
+ <meta-data
47
+ android:name="com.google.mlkit.vision.DEPENDENCIES"
48
+ android:value="ocr" />
49
+ </config-file>
50
+
51
+ <source-file src="src/android/CronappMLKitPlugin.java" target-dir="io/cronapp/mlkit"/>
52
+ <source-file src="src/android/Utils.java" target-dir="io/cronapp/mlkit"/>
53
+
54
+ <preference name="MKLKIT_VERSION_TEXT_RECOGNITION" default="16.1.1"/>
55
+ <preference name="MKLKIT_VERSION_BARCODE" default="16.0.3"/>
56
+ <preference name="MKLKIT_VERSION_IMAGE_LABELLING" default="17.0.0"/>
57
+ <preference name="MKLKIT_VERSION_FACE" default="16.1.7"/>
58
+
59
+ <framework src="com.google.android.gms:play-services-mlkit-text-recognition:$MKLKIT_VERSION_TEXT_RECOGNITION"/>
60
+ <framework src="com.google.mlkit:barcode-scanning:$MKLKIT_VERSION_BARCODE"/>
61
+ <framework src="com.google.mlkit:image-labeling:$MKLKIT_VERSION_IMAGE_LABELLING"/>
62
+ <framework src="com.google.mlkit:face-detection:$MKLKIT_VERSION_FACE"/>
63
+
64
+ </platform>
65
+ </plugin>
@@ -0,0 +1,231 @@
1
+ package io.cronapp.mlkit;
2
+
3
+ import android.app.Activity;
4
+ import android.content.Context;
5
+ import android.graphics.Bitmap;
6
+ import android.graphics.BitmapFactory;
7
+ import android.util.Base64;
8
+
9
+ import com.google.android.gms.tasks.OnFailureListener;
10
+ import com.google.android.gms.tasks.OnSuccessListener;
11
+ import com.google.mlkit.vision.barcode.Barcode;
12
+ import com.google.mlkit.vision.barcode.BarcodeScanner;
13
+ import com.google.mlkit.vision.barcode.BarcodeScanning;
14
+ import com.google.mlkit.vision.common.InputImage;
15
+ import com.google.mlkit.vision.face.Face;
16
+ import com.google.mlkit.vision.face.FaceDetection;
17
+ import com.google.mlkit.vision.face.FaceDetector;
18
+ import com.google.mlkit.vision.face.FaceDetectorOptions;
19
+ import com.google.mlkit.vision.label.ImageLabel;
20
+ import com.google.mlkit.vision.label.ImageLabeler;
21
+ import com.google.mlkit.vision.label.ImageLabeling;
22
+ import com.google.mlkit.vision.label.defaults.ImageLabelerOptions;
23
+ import com.google.mlkit.vision.text.Text;
24
+ import com.google.mlkit.vision.text.TextRecognition;
25
+ import com.google.mlkit.vision.text.TextRecognizer;
26
+
27
+ import org.apache.cordova.CallbackContext;
28
+ import org.apache.cordova.CordovaPlugin;
29
+ import org.json.JSONArray;
30
+ import org.json.JSONException;
31
+ import org.json.JSONObject;
32
+
33
+ import java.io.ByteArrayOutputStream;
34
+ import java.io.IOException;
35
+ import java.io.InputStream;
36
+ import java.util.List;
37
+
38
+ import androidx.annotation.NonNull;
39
+
40
+ public class CronappMLKitPlugin extends CordovaPlugin {
41
+
42
+ protected static Context applicationContext = null;
43
+ private static Activity cordovaActivity = null;
44
+
45
+ @Override
46
+ protected void pluginInitialize() {
47
+ super.pluginInitialize();
48
+ cordovaActivity = this.cordova.getActivity();
49
+ applicationContext = cordovaActivity.getApplicationContext();
50
+ }
51
+
52
+ @Override
53
+ public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
54
+ if (action.equals("onDeviceTextRecognizer")) {
55
+ String message = args.getString(0);
56
+ this.onDeviceTextRecognizer(message, callbackContext);
57
+ return true;
58
+ } else if (action.equals("barcodeDetector")) {
59
+ String message = args.getString(0);
60
+ this.barcodeDetector(message, callbackContext);
61
+ return true;
62
+ } else if (action.equals("imageLabeler")) {
63
+ String message = args.getString(0);
64
+ this.imageLabeler(message, callbackContext);
65
+ return true;
66
+ } else if (action.equals("faceDetector")) {
67
+ String message = args.getString(0);
68
+ JSONObject options = args.getJSONObject(1);
69
+ this.faceDetector(message, options, callbackContext);
70
+ return true;
71
+ }
72
+ return false;
73
+ }
74
+
75
+ private void onDeviceTextRecognizer(String message, CallbackContext callbackContext) {
76
+ if (message != null && message.length() > 0) {
77
+ try {
78
+ InputImage image = getImage(message);
79
+ TextRecognizer recognizer = TextRecognition.getClient();
80
+ recognizer.process(image)
81
+ .addOnSuccessListener(new OnSuccessListener<Text>() {
82
+ @Override
83
+ public void onSuccess(Text firebaseVisionText) {
84
+ try {
85
+ JSONObject text = Utils.parseText(image, firebaseVisionText);
86
+ callbackContext.success(text);
87
+ } catch (Exception e) {
88
+ callbackContext.error(e.getLocalizedMessage());
89
+ }
90
+ }
91
+ })
92
+ .addOnFailureListener(new OnFailureListener() {
93
+ @Override
94
+ public void onFailure(@NonNull Exception e) {
95
+ callbackContext.error(e.getLocalizedMessage());
96
+ }
97
+ });
98
+ } catch (Exception e) {
99
+ callbackContext.error(e.getLocalizedMessage());
100
+ }
101
+ } else {
102
+ callbackContext.error("Expected one non-empty string argument.");
103
+ }
104
+ }
105
+
106
+ private void barcodeDetector(String message, CallbackContext callbackContext) {
107
+ if (message != null && message.length() > 0) {
108
+ try {
109
+ InputImage image = getImage(message);
110
+ BarcodeScanner detector = BarcodeScanning.getClient();
111
+ detector.process(image)
112
+ .addOnSuccessListener(new OnSuccessListener<List<Barcode>>() {
113
+ @Override
114
+ public void onSuccess(List<Barcode> firebaseVisionBarcodes) {
115
+ try {
116
+ JSONArray barcodes = Utils.parseBarcodes(image, firebaseVisionBarcodes);
117
+ callbackContext.success(barcodes);
118
+ } catch (Exception e) {
119
+ callbackContext.error(e.getLocalizedMessage());
120
+ }
121
+ }
122
+ })
123
+ .addOnFailureListener(new OnFailureListener() {
124
+ @Override
125
+ public void onFailure(@NonNull Exception e) {
126
+ callbackContext.error(e.getLocalizedMessage());
127
+ }
128
+ });
129
+ } catch (Exception e) {
130
+ callbackContext.error(e.getLocalizedMessage());
131
+ }
132
+ } else {
133
+ callbackContext.error("Expected one non-empty string argument.");
134
+ }
135
+ }
136
+
137
+ private void imageLabeler(String message, CallbackContext callbackContext) {
138
+ if (message != null && message.length() > 0) {
139
+ try {
140
+ InputImage image = getImage(message);
141
+ ImageLabeler detector = ImageLabeling.getClient(ImageLabelerOptions.DEFAULT_OPTIONS);
142
+ detector.process(image)
143
+ .addOnSuccessListener(new OnSuccessListener<List<ImageLabel>>() {
144
+ @Override
145
+ public void onSuccess(List<ImageLabel> imageLabels) {
146
+ try {
147
+ JSONArray imageLabels1 = Utils.parseImageLabels(imageLabels);
148
+ callbackContext.success(imageLabels1);
149
+ } catch (Exception e) {
150
+ callbackContext.error(e.getLocalizedMessage());
151
+ }
152
+ }
153
+ })
154
+ .addOnFailureListener(new OnFailureListener() {
155
+ @Override
156
+ public void onFailure(@NonNull Exception e) {
157
+ callbackContext.error(e.getLocalizedMessage());
158
+ }
159
+ });
160
+ } catch (Exception e) {
161
+ callbackContext.error(e.getLocalizedMessage());
162
+ }
163
+ } else {
164
+ callbackContext.error("Expected one non-empty string argument.");
165
+ }
166
+ }
167
+
168
+ private void faceDetector(String message, JSONObject options, CallbackContext callbackContext) {
169
+ if (message != null && message.length() > 0) {
170
+ try {
171
+ InputImage image = getImage(message);
172
+ FaceDetectorOptions faceDetectorOptions = new FaceDetectorOptions.Builder()
173
+ .setClassificationMode(FaceDetectorOptions.CLASSIFICATION_MODE_ALL)
174
+
175
+ .build();
176
+ FaceDetector detector = FaceDetection.getClient(faceDetectorOptions);
177
+ detector.process(image)
178
+ .addOnSuccessListener(new OnSuccessListener<List<Face>>() {
179
+ @Override
180
+ public void onSuccess(List<Face> faces) {
181
+ try {
182
+ JSONArray imageLabels1 = Utils.parseFaces(faces);
183
+ callbackContext.success(imageLabels1);
184
+ } catch (Exception e) {
185
+ callbackContext.error(e.getLocalizedMessage());
186
+ }
187
+ }
188
+ })
189
+ .addOnFailureListener(new OnFailureListener() {
190
+ @Override
191
+ public void onFailure(@NonNull Exception e) {
192
+ callbackContext.error(e.getLocalizedMessage());
193
+ }
194
+ });
195
+ } catch (Exception e) {
196
+ callbackContext.error(e.getLocalizedMessage());
197
+ }
198
+ } else {
199
+ callbackContext.error("Expected one non-empty string argument.");
200
+ }
201
+ }
202
+
203
+ private byte[] toBytes(InputStream stream) throws IOException {
204
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream();
205
+
206
+ int nRead;
207
+ byte[] data = new byte[16384];
208
+
209
+ while ((nRead = stream.read(data, 0, data.length)) != -1) {
210
+ buffer.write(data, 0, nRead);
211
+ }
212
+
213
+ return buffer.toByteArray();
214
+ }
215
+
216
+ private InputImage getImage(String message) throws IOException {
217
+ if (message.contains("data:")) {
218
+ message = message
219
+ .replace("data:image/png;base64,", "")
220
+ .replace("data:image/jpeg;base64,", "");
221
+ byte[] decodedString = Base64.decode(message, Base64.DEFAULT);
222
+ Bitmap bitMap = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
223
+ InputImage image = InputImage.fromBitmap(bitMap, 0);
224
+ return image;
225
+ } else {
226
+ Uri uri = Uri.parse("/sdcard/Download/face.jpg");
227
+ InputImage image = InputImage.fromFilePath(applicationContext, uri);
228
+ return image;
229
+ }
230
+ }
231
+ }
@@ -0,0 +1,299 @@
1
+ package io.cronapp.mlkit;
2
+
3
+ import android.graphics.Point;
4
+ import android.graphics.Rect;
5
+ import android.text.TextUtils;
6
+
7
+ import com.google.mlkit.vision.barcode.Barcode;
8
+ import com.google.mlkit.vision.common.InputImage;
9
+ import com.google.mlkit.vision.face.Face;
10
+ import com.google.mlkit.vision.label.ImageLabel;
11
+ import com.google.mlkit.vision.text.Text;
12
+
13
+ import org.json.JSONArray;
14
+ import org.json.JSONObject;
15
+
16
+ import java.util.List;
17
+ import java.util.Locale;
18
+
19
+
20
+ public class Utils {
21
+ public static JSONObject parseText(InputImage image, Text text) throws Exception {
22
+ JSONArray blocks = new JSONArray();
23
+ for (Text.TextBlock textBlock : text.getTextBlocks()) {
24
+ JSONArray lines = new JSONArray();
25
+ for (Text.Line line : textBlock.getLines()) {
26
+ JSONArray elements = new JSONArray();
27
+ for (Text.Element element : line.getElements()) {
28
+ JSONObject elementObject = new JSONObject();
29
+ elementObject.put("cornerPoints", parsePoints(element.getCornerPoints()));
30
+ elementObject.put("text", element.getText());
31
+ elementObject.put("frame", parseBoundingBox(element.getBoundingBox()));
32
+ elementObject.put("recognizedLanguages", element.getRecognizedLanguage());
33
+ elements.put(elementObject);
34
+ }
35
+ JSONObject lineObject = new JSONObject();
36
+ lineObject.put("cornerPoints", parsePoints(line.getCornerPoints()));
37
+ lineObject.put("text", line.getText());
38
+ lineObject.put("frame", parseBoundingBox(line.getBoundingBox()));
39
+ lineObject.put("recognizedLanguages", line.getRecognizedLanguage());
40
+ lineObject.put("elements", elements);
41
+ lines.put(lineObject);
42
+ }
43
+ JSONObject block = new JSONObject();
44
+ block.put("cornerPoints", parsePoints(textBlock.getCornerPoints()));
45
+ block.put("text", textBlock.getText());
46
+ block.put("frame", parseBoundingBox(textBlock.getBoundingBox()));
47
+ block.put("recognizedLanguages", textBlock.getRecognizedLanguage());
48
+ block.put("lines", lines);
49
+ blocks.put(block);
50
+ }
51
+
52
+ JSONObject result = new JSONObject();
53
+ result.put("text", text.getText());
54
+ result.put("blocks", blocks);
55
+ result.put("imageWidth", image.getWidth());
56
+ result.put("imageHeight", image.getHeight());
57
+
58
+ return result;
59
+ }
60
+
61
+ public static JSONArray parseBarcodes(InputImage image, List<Barcode> barcodes) throws Exception {
62
+ JSONArray array = new JSONArray();
63
+ for (Barcode barcode : barcodes) {
64
+
65
+ JSONObject barcodeMap = new JSONObject();
66
+ barcodeMap.put("valueType", barcode.getValueType());
67
+ barcodeMap.put("format", barcode.getFormat());
68
+ barcodeMap.put("rawValue", barcode.getRawValue());
69
+ barcodeMap.put("displayValue", barcode.getDisplayValue());
70
+ barcodeMap.put("cornerPoints", parsePoints(barcode.getCornerPoints()));
71
+ barcodeMap.put("boundingBox", barcode.getBoundingBox());
72
+ barcodeMap.put("imageWidth", image.getWidth());
73
+ barcodeMap.put("imageHeight", image.getHeight());
74
+
75
+
76
+ if (barcode.getEmail() != null) {
77
+ JSONObject email = new JSONObject();
78
+ email.put("address", barcode.getEmail().getAddress());
79
+ email.put("body", barcode.getEmail().getBody());
80
+ email.put("subject", barcode.getEmail().getSubject());
81
+ email.put("type", barcode.getEmail().getType());
82
+ barcodeMap.put("email", email);
83
+ }
84
+
85
+ if (barcode.getPhone() != null) {
86
+ JSONObject phone = new JSONObject();
87
+ phone.put("number", barcode.getPhone().getNumber());
88
+ phone.put("type", barcode.getPhone().getType());
89
+ barcodeMap.put("phone", phone);
90
+ }
91
+
92
+ if (barcode.getSms() != null) {
93
+ JSONObject sms = new JSONObject();
94
+ sms.put("phoneNumber", barcode.getSms().getPhoneNumber());
95
+ sms.put("message", barcode.getSms().getMessage());
96
+ barcodeMap.put("sms", sms);
97
+ }
98
+
99
+ if (barcode.getUrl() != null) {
100
+ JSONObject url = new JSONObject();
101
+ url.put("title", barcode.getUrl().getTitle());
102
+ url.put("url", barcode.getUrl().getUrl());
103
+ barcodeMap.put("url", url);
104
+ }
105
+
106
+ if (barcode.getWifi() != null) {
107
+ JSONObject wifi = new JSONObject();
108
+ wifi.put("ssid", barcode.getWifi().getSsid());
109
+ wifi.put("password", barcode.getWifi().getPassword());
110
+ wifi.put("type", barcode.getWifi().getEncryptionType());
111
+ barcodeMap.put("wifi", wifi);
112
+ }
113
+
114
+ if (barcode.getGeoPoint() != null) {
115
+ JSONObject geoPoint = new JSONObject();
116
+ geoPoint.put("latitude", barcode.getGeoPoint().getLat());
117
+ geoPoint.put("longitude", barcode.getGeoPoint().getLng());
118
+ barcodeMap.put("geoPoint", geoPoint);
119
+ }
120
+
121
+ if (barcode.getCalendarEvent() != null) {
122
+ JSONObject calendarEvent = new JSONObject();
123
+ calendarEvent.put("eventDescription", barcode.getCalendarEvent().getDescription());
124
+ calendarEvent.put("location", barcode.getCalendarEvent().getLocation());
125
+ calendarEvent.put("organizer", barcode.getCalendarEvent().getOrganizer());
126
+ calendarEvent.put("status", barcode.getCalendarEvent().getStatus());
127
+ calendarEvent.put("summary", barcode.getCalendarEvent().getSummary());
128
+ calendarEvent.put("start", toISOString(barcode.getCalendarEvent().getStart()));
129
+ calendarEvent.put("end", toISOString(barcode.getCalendarEvent().getEnd()));
130
+ barcodeMap.put("calendarEvent", calendarEvent);
131
+ }
132
+
133
+ if (barcode.getContactInfo() != null) {
134
+ JSONObject contactInfo = new JSONObject();
135
+ contactInfo.put("title", barcode.getContactInfo().getTitle());
136
+ contactInfo.put("name", barcode.getContactInfo().getName().getFormattedName());
137
+ contactInfo.put("addresses", parseAddresses(barcode.getContactInfo().getAddresses()));
138
+ contactInfo.put("phones", parsePhones(barcode.getContactInfo().getPhones()));
139
+ contactInfo.put("emails", parseEmails(barcode.getContactInfo().getEmails()));
140
+ contactInfo.put("organization", barcode.getContactInfo().getOrganization());
141
+ contactInfo.put("urls", TextUtils.join(",", barcode.getContactInfo().getUrls()));
142
+ barcodeMap.put("contactInfo", contactInfo);
143
+ }
144
+
145
+ if (barcode.getDriverLicense() != null) {
146
+ JSONObject driverLicense = new JSONObject();
147
+ driverLicense.put("firstName", barcode.getDriverLicense().getFirstName());
148
+ driverLicense.put("middleName", barcode.getDriverLicense().getMiddleName());
149
+ driverLicense.put("lastName", barcode.getDriverLicense().getLastName());
150
+ driverLicense.put("gender", barcode.getDriverLicense().getGender());
151
+ driverLicense.put("addressCity", barcode.getDriverLicense().getAddressCity());
152
+ driverLicense.put("addressState", barcode.getDriverLicense().getAddressState());
153
+ driverLicense.put("addressStreet", barcode.getDriverLicense().getAddressStreet());
154
+ driverLicense.put("addressZip", barcode.getDriverLicense().getAddressZip());
155
+ driverLicense.put("birthDate", barcode.getDriverLicense().getBirthDate());
156
+ driverLicense.put("documentType", barcode.getDriverLicense().getDocumentType());
157
+ driverLicense.put("licenseNumber", barcode.getDriverLicense().getLicenseNumber());
158
+ driverLicense.put("expiryDate", barcode.getDriverLicense().getExpiryDate());
159
+ driverLicense.put("issuingDate", barcode.getDriverLicense().getIssueDate());
160
+ driverLicense.put("issuingCountry", barcode.getDriverLicense().getIssuingCountry());
161
+ barcodeMap.put("driverLicense", driverLicense);
162
+ }
163
+
164
+ array.put(barcodeMap);
165
+ }
166
+ return array;
167
+ }
168
+
169
+ public static JSONArray parseImageLabels(List<ImageLabel> imageLabels) throws Exception {
170
+ JSONArray array = new JSONArray();
171
+ for (ImageLabel imageLabel : imageLabels) {
172
+
173
+ JSONObject imageLabelMap = new JSONObject();
174
+ imageLabelMap.put("text", imageLabel.getText());
175
+ imageLabelMap.put("confidence", imageLabel.getConfidence());
176
+ imageLabelMap.put("index", imageLabel.getIndex());
177
+
178
+ array.put(imageLabelMap);
179
+ }
180
+ return array;
181
+ }
182
+
183
+ public static JSONArray parseFaces(List<Face> faces) throws Exception {
184
+ JSONArray array = new JSONArray();
185
+ for (Face face : faces) {
186
+
187
+ array.put(FaceToJsonConverter.faceToJson(face));
188
+ }
189
+ return array;
190
+ }
191
+
192
+ private static JSONArray parsePhones(List<Barcode.Phone> phones) throws Exception {
193
+ JSONArray array = new JSONArray();
194
+ for (Barcode.Phone phone : phones) {
195
+
196
+ JSONObject phoneMap = new JSONObject();
197
+ phoneMap.put("number", phone.getNumber());
198
+ phoneMap.put("type", phone.getType());
199
+
200
+ array.put(phoneMap);
201
+ }
202
+ return array;
203
+ }
204
+
205
+ private static JSONArray parseAddresses(List<Barcode.Address> addresses) throws Exception {
206
+ JSONArray array = new JSONArray();
207
+ for (Barcode.Address address : addresses) {
208
+
209
+ JSONObject addressMap = new JSONObject();
210
+ addressMap.put("addressLine", TextUtils.join(",", address.getAddressLines()));
211
+ addressMap.put("type", address.getType());
212
+
213
+ array.put(addressMap);
214
+ }
215
+ return array;
216
+ }
217
+
218
+ private static JSONArray parseEmails(List<Barcode.Email> emails) throws Exception {
219
+ JSONArray array = new JSONArray();
220
+ for (Barcode.Email email : emails) {
221
+
222
+ JSONObject emailMap = new JSONObject();
223
+ emailMap.put("address", email.getAddress());
224
+ emailMap.put("body", email.getBody());
225
+ emailMap.put("subject", email.getSubject());
226
+ emailMap.put("type", email.getType());
227
+
228
+ array.put(emailMap);
229
+ }
230
+ return array;
231
+ }
232
+
233
+ private static JSONArray parsePoints(Point[] points) throws Exception {
234
+ JSONArray array = new JSONArray();
235
+ for (Point point : points) {
236
+
237
+ JSONObject pointMap = new JSONObject();
238
+ pointMap.put("x", point.x);
239
+ pointMap.put("y", point.y);
240
+ array.put(pointMap);
241
+ }
242
+ return array;
243
+ }
244
+
245
+ private static JSONObject parseBoundingBox(Rect rect) throws Exception {
246
+ JSONObject rectMap = new JSONObject();
247
+ rectMap.put("x", rect.left);
248
+ rectMap.put("y", rect.top);
249
+ rectMap.put("width", rect.width());
250
+ rectMap.put("height", rect.height());
251
+
252
+ return rectMap;
253
+ }
254
+
255
+ private static String toISOString(Barcode.CalendarDateTime date) {
256
+ return String.format(Locale.getDefault(), "%d-%02d-%02dT%02d:%02d:%02d",
257
+ date.getYear(), date.getMonth(), date.getDay(),
258
+ date.getHours(), date.getMinutes(), date.getSeconds());
259
+ }
260
+
261
+ public static JSONObject parseFaces(Face face) {
262
+
263
+ JSONObject faceData = new JSONObject();
264
+
265
+ try {
266
+ faceData.put("faceId", face.getTrackingId());
267
+ JSONObject boundingBox = new JSONObject();
268
+ boundingBox.put("left", face.getBoundingBox().left);
269
+ boundingBox.put("top", face.getBoundingBox().top);
270
+ boundingBox.put("right", face.getBoundingBox().right);
271
+ boundingBox.put("bottom", face.getBoundingBox().bottom);
272
+ faceData.put("boundingBox", boundingBox);
273
+ faceData.put("headEulerAngleX", face.getHeadEulerAngleX());
274
+ faceData.put("headEulerAngleY", face.getHeadEulerAngleY());
275
+ faceData.put("headEulerAngleZ", face.getHeadEulerAngleZ());
276
+
277
+ faceData.put("smilingProbability", face.getSmilingProbability());
278
+
279
+ faceData.put("rightEyeOpenProbability", face.getRightEyeOpenProbability());
280
+
281
+ faceData.put("leftEyeOpenProbability", face.getLeftEyeOpenProbability());
282
+
283
+ JSONArray landmarksArray = new JSONArray();
284
+ for (FaceLandmark landmark : face.getAllLandmarks()) {
285
+ JSONObject landmarkData = new JSONObject();
286
+ landmarkData.put("type", landmark.getLandmarkType());
287
+ landmarkData.put("x", landmark.getPosition().x);
288
+ landmarkData.put("y", landmark.getPosition().y);
289
+ landmarksArray.put(landmarkData);
290
+ }
291
+ faceData.put("landmarks", landmarksArray);
292
+ } catch (Exception e) {
293
+ e.printStackTrace();
294
+ }
295
+
296
+ return faceData;
297
+
298
+ }
299
+ }
@@ -0,0 +1,231 @@
1
+ import MLKitTextRecognition
2
+ import MLKitBarcodeScanning
3
+ import MLKitImageLabeling
4
+ import MLKitFaceDetection
5
+ import UIKit
6
+
7
+ extension Text {
8
+ func toJSON(with image: UIImage) -> [AnyHashable: Any] {
9
+ let blocksParsed = blocks.compactMap { (block) -> Any? in
10
+ let lines = block.lines.compactMap { (line) -> Any? in
11
+ let elements = line.elements.compactMap { (element) -> Any? in
12
+ return [
13
+ "cornerPoints": element.cornerPoints.toJSON() as Any,
14
+ "text": element.text,
15
+ "frame": element.frame.toJSON() as Any
16
+ ]
17
+ }
18
+ return [
19
+ "cornerPoints": line.cornerPoints.toJSON() as Any,
20
+ "text": line.text,
21
+ "frame": line.frame.toJSON() as Any,
22
+ "recognizedLanguages": line.recognizedLanguages.compactMap({$0.languageCode}),
23
+ "elements": elements
24
+ ]
25
+ }
26
+ return [
27
+ "cornerPoints": block.cornerPoints.toJSON() as Any,
28
+ "text": block.text,
29
+ "frame": block.frame.toJSON() as Any,
30
+ "recognizedLanguages": block.recognizedLanguages.compactMap({$0.languageCode}),
31
+ "lines": lines
32
+ ]
33
+ }
34
+
35
+ return [
36
+ "text": text,
37
+ "blocks": blocksParsed,
38
+ "imageWidth": image.size.width,
39
+ "imageHeight": image.size.height
40
+ ]
41
+ }
42
+ }
43
+
44
+ extension Face {
45
+ func toJSON(with image: UIImage) -> [AnyHashable: Any] {
46
+ var response: [AnyHashable: Any] = [:]
47
+
48
+ response["faceId"] = trackingID
49
+
50
+ let boundingBox = [
51
+ "x": frame.origin.x,
52
+ "y": frame.origin.y,
53
+ "width": frame.size.width,
54
+ "height": frame.size.height
55
+ ]
56
+ response["boundingBox"] = boundingBox
57
+
58
+ response["headEulerAngleX"] = headEulerAngleX
59
+ response["headEulerAngleY"] = headEulerAngleY
60
+ response["headEulerAngleZ"] = headEulerAngleZ
61
+
62
+ response["smilingProbability"] = smilingProbability ?? -1
63
+ response["leftEyeOpenProbability"] = leftEyeOpenProbability ?? -1
64
+ response["rightEyeOpenProbability"] = rightEyeOpenProbability ?? -1
65
+
66
+ var landmarksArray: [[AnyHashable: Any]] = []
67
+ for landmark in landmarks {
68
+ var landmarkData: [AnyHashable: Any] = [:]
69
+ landmarkData["type"] = landmark.type.rawValue
70
+ landmarkData["x"] = landmark.position.x
71
+ landmarkData["y"] = landmark.position.y
72
+
73
+ landmarksArray.append(landmarkData)
74
+ }
75
+ response["landmarks"] = landmarksArray
76
+
77
+ return response
78
+ }
79
+ }
80
+ extension Barcode {
81
+ func toJSON(with image: UIImage) -> [AnyHashable: Any] {
82
+ var response = [
83
+ "valueType": valueType.rawValue,
84
+ "format": format.rawValue,
85
+ "rawValue" : rawValue as Any,
86
+ "displayValue" : displayValue as Any,
87
+ "cornerPoints" : cornerPoints?.toJSON() as Any,
88
+ "imageWidth": image.size.width,
89
+ "imageHeight": image.size.height
90
+ ]
91
+ if let email = email {
92
+ response["email"] = [
93
+ "address" : email.address as Any,
94
+ "body" : email.body as Any,
95
+ "subject" : email.subject as Any,
96
+ "type" : email.type.rawValue as Any
97
+ ]
98
+ }
99
+ if let phone = phone {
100
+ response["phone"] = [
101
+ "number" : phone.number as Any,
102
+ "type" : phone.type.rawValue as Any
103
+ ]
104
+ }
105
+ if let sms = sms {
106
+ response["sms"] = [
107
+ "phoneNumber": sms.phoneNumber as Any,
108
+ "message": sms.message as Any
109
+ ]
110
+ }
111
+ if let url = url {
112
+ response["url"] = [
113
+ "title": url.title as Any,
114
+ "url": url.url as Any
115
+ ]
116
+ }
117
+ if let wifi = wifi {
118
+ response["wifi"] = [
119
+ "ssid" : wifi.ssid as Any,
120
+ "password" : wifi.password as Any,
121
+ "type" : wifi.type.rawValue as Any
122
+ ]
123
+ }
124
+ if let geoPoint = geoPoint {
125
+ response["geoPoint"] = [
126
+ "latitude" : geoPoint.latitude as Any,
127
+ "longitude" : geoPoint.longitude as Any
128
+ ]
129
+ }
130
+ if let calendarEvent = calendarEvent {
131
+ response["calendarEvent"] = [
132
+ "eventDescription": calendarEvent.eventDescription as Any,
133
+ "location": calendarEvent.location as Any,
134
+ "organizer": calendarEvent.organizer as Any,
135
+ "status": calendarEvent.status as Any,
136
+ "summary": calendarEvent.summary as Any,
137
+ "start": calendarEvent.start?.toISOString() as Any,
138
+ "end": calendarEvent.end?.toISOString() as Any
139
+ ]
140
+ }
141
+
142
+ if let contactInfo = contactInfo {
143
+ response["contactInfo"] = [
144
+ "title": contactInfo.jobTitle as Any,
145
+ "name": contactInfo.name?.formattedName as Any,
146
+ "addresses": contactInfo.addresses?.compactMap({ (address) -> [String: Any]? in
147
+ return [
148
+ "addressLine" : address.addressLines?.joined(separator: ",") as Any,
149
+ "type" : address.type.rawValue
150
+ ]
151
+ }) as Any,
152
+ "phones": contactInfo.phones?.compactMap({ (phone) -> [String: Any]? in
153
+ return [
154
+ "number": phone.number as Any,
155
+ "type": phone.type.rawValue
156
+ ]
157
+ }) as Any,
158
+ "emails": contactInfo.emails?.compactMap({ (email) -> [String: Any]? in
159
+ return [
160
+ "address": email.address as Any,
161
+ "body": email.body as Any,
162
+ "type": email.type.rawValue
163
+ ]
164
+ }) as Any,
165
+ "organization": contactInfo.organization as Any,
166
+ "urls": contactInfo.urls?.joined(separator: ",") as Any
167
+ ]
168
+ }
169
+
170
+
171
+ if let driverLicense = driverLicense {
172
+ response["driverLicense"] = [
173
+ "firstName": driverLicense.firstName as Any,
174
+ "middleName": driverLicense.middleName as Any,
175
+ "lastName": driverLicense.lastName as Any,
176
+ "gender": driverLicense.gender as Any,
177
+ "addressCity": driverLicense.addressCity as Any,
178
+ "addressState": driverLicense.addressState as Any,
179
+ "addressStreet": driverLicense.addressStreet as Any,
180
+ "addressZip": driverLicense.addressZip as Any,
181
+ "birthDate": driverLicense.birthDate as Any,
182
+ "documentType": driverLicense.documentType as Any,
183
+ "licenseNumber": driverLicense.licenseNumber as Any,
184
+ "expiryDate": driverLicense.expiryDate as Any,
185
+ "issuingDate": driverLicense.issuingDate as Any,
186
+ "issuingCountry": driverLicense.issuingCountry as Any
187
+ ]
188
+ }
189
+ return response
190
+ }
191
+ }
192
+
193
+ extension ImageLabel {
194
+ func toJSON() -> [String: Any] {
195
+ return [
196
+ "text": text,
197
+ "index": index,
198
+ "confidence": confidence
199
+ ]
200
+ }
201
+ }
202
+
203
+ extension Date {
204
+ func toISOString() -> String {
205
+ let formatter = DateFormatter()
206
+ formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
207
+ return formatter.string(from: self)
208
+ }
209
+ }
210
+
211
+ extension CGRect {
212
+ func toJSON() -> [AnyHashable: Any] {
213
+ return [
214
+ "x" : origin.x,
215
+ "y" : origin.y,
216
+ "width": size.width,
217
+ "height": size.height
218
+ ]
219
+ }
220
+ }
221
+
222
+ extension Array where Element: NSValue {
223
+ func toJSON() -> [[AnyHashable: Any]] {
224
+ return self.compactMap({
225
+ [
226
+ "x" : ($0 as! CGPoint).x,
227
+ "y" : ($0 as! CGPoint).y
228
+ ]
229
+ })
230
+ }
231
+ }
@@ -0,0 +1,163 @@
1
+ import MLKitTextRecognition
2
+ import MLKitBarcodeScanning
3
+ import MLKitImageLabeling
4
+ import MLKitFaceDetection
5
+ import MLKitVision
6
+ import UIKit
7
+
8
+ @objc(CronappMLKitPlugin)
9
+ class CronappMLKitPlugin: CDVPlugin {
10
+
11
+ @objc(onDeviceTextRecognizer:)
12
+ func onDeviceTextRecognizer(command: CDVInvokedUrlCommand) {
13
+ guard let imageURL = command.arguments.first as? String else {
14
+ let pluginResult = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: "Image URL required")
15
+ self.commandDelegate.send(pluginResult, callbackId: command.callbackId)
16
+ return
17
+ }
18
+ getImage(imageURL: imageURL) { (image, error) in
19
+ if let error = error {
20
+ let pluginResult = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: error.localizedDescription)
21
+ self.commandDelegate.send(pluginResult, callbackId: command.callbackId)
22
+ } else {
23
+ let textRecognizer = TextRecognizer.textRecognizer()
24
+ let visionImage = VisionImage(image: image!)
25
+ textRecognizer.process(visionImage) { (text, error) in
26
+ if let error = error {
27
+ let pluginResult = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: error.localizedDescription)
28
+ self.commandDelegate.send(pluginResult, callbackId: command.callbackId)
29
+ } else {
30
+ let pluginResult = CDVPluginResult(status: CDVCommandStatus_OK, messageAs: text?.toJSON(with: image!))
31
+ self.commandDelegate.send(pluginResult, callbackId: command.callbackId)
32
+ }
33
+ }
34
+ }
35
+ }
36
+ }
37
+
38
+
39
+ @objc(faceDetector:)
40
+ func faceDetector(command: CDVInvokedUrlCommand) {
41
+ guard let imageURL = command.arguments.first as? String else {
42
+ let pluginResult = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: "Image URL required")
43
+ self.commandDelegate.send(pluginResult, callbackId: command.callbackId)
44
+ return
45
+ }
46
+ getImage(imageURL: imageURL) { (image, error) in
47
+ if let error = error {
48
+ let pluginResult = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: error.localizedDescription)
49
+ self.commandDelegate.send(pluginResult, callbackId: command.callbackId)
50
+ } else {
51
+ let faceDetector = FaceDetector.faceDetector()
52
+ let visionImage = VisionImage(image: image!)
53
+ faceDetector.process(visionImage) { (faces, error) in
54
+ if let error = error {
55
+ let pluginResult = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: error.localizedDescription)
56
+ self.commandDelegate.send(pluginResult, callbackId: command.callbackId)
57
+ } else {
58
+ let barcodesDict = faces?.compactMap({ $0.toJSON(with: image!) })
59
+ let pluginResult = CDVPluginResult(status: CDVCommandStatus_OK, messageAs: barcodesDict)
60
+ self.commandDelegate.send(pluginResult, callbackId: command.callbackId)
61
+ }
62
+ }
63
+ }
64
+ }
65
+ }
66
+
67
+ @objc(barcodeDetector:)
68
+ func barcodeDetector(command: CDVInvokedUrlCommand) {
69
+ guard let imageURL = command.arguments.first as? String else {
70
+ let pluginResult = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: "Image URL required")
71
+ self.commandDelegate.send(pluginResult, callbackId: command.callbackId)
72
+ return
73
+ }
74
+ getImage(imageURL: imageURL) { (image, error) in
75
+ if let error = error {
76
+ let pluginResult = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: error.localizedDescription)
77
+ self.commandDelegate.send(pluginResult, callbackId: command.callbackId)
78
+ } else {
79
+ let barcodeDetector = BarcodeScanner.barcodeScanner()
80
+ let visionImage = VisionImage(image: image!)
81
+ barcodeDetector.process(visionImage) { (barcodes, error) in
82
+ if let error = error {
83
+ let pluginResult = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: error.localizedDescription)
84
+ self.commandDelegate.send(pluginResult, callbackId: command.callbackId)
85
+ } else {
86
+ let barcodesDict = barcodes?.compactMap({ $0.toJSON(with: image!) })
87
+ let pluginResult = CDVPluginResult(status: CDVCommandStatus_OK, messageAs: barcodesDict)
88
+ self.commandDelegate.send(pluginResult, callbackId: command.callbackId)
89
+ }
90
+ }
91
+ }
92
+ }
93
+ }
94
+
95
+ @objc(imageLabeler:)
96
+ func imageLabeler(command: CDVInvokedUrlCommand) {
97
+ guard let imageURL = command.arguments.first as? String else {
98
+ let pluginResult = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: "Image URL required")
99
+ self.commandDelegate.send(pluginResult, callbackId: command.callbackId)
100
+ return
101
+ }
102
+ getImage(imageURL: imageURL) { (image, error) in
103
+ if let error = error {
104
+ let pluginResult = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: error.localizedDescription)
105
+ self.commandDelegate.send(pluginResult, callbackId: command.callbackId)
106
+ } else {
107
+ let options = ImageLabelerOptions()
108
+ options.confidenceThreshold = 0.7
109
+ let imageLabeler = ImageLabeler.imageLabeler(options: options)
110
+ let visionImage = VisionImage(image: image!)
111
+ imageLabeler.process(visionImage) { (labels, error) in
112
+ if let error = error {
113
+ let pluginResult = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: error.localizedDescription)
114
+ self.commandDelegate.send(pluginResult, callbackId: command.callbackId)
115
+ } else {
116
+ let labelsDict = labels?.compactMap({$0.toJSON()})
117
+ let pluginResult = CDVPluginResult(status: CDVCommandStatus_OK, messageAs: labelsDict)
118
+ self.commandDelegate.send(pluginResult, callbackId: command.callbackId)
119
+ }
120
+ }
121
+ }
122
+ }
123
+ }
124
+
125
+ private func getImage(imageURL: String, _ completion: @escaping (_ image: UIImage?, _ error: Error?) -> Void) {
126
+ if imageURL.contains("data:") {
127
+ guard let data = Data(base64Encoded: imageURL
128
+ .replacingOccurrences(of: "data:image/jpeg;base64,", with: "")
129
+ .replacingOccurrences(of: "data:image/png;base64,", with: "")),
130
+ let image = UIImage(data: data) else {
131
+ let error = NSError(domain: "cronapp-plugin-mlkit",
132
+ code: -1,
133
+ userInfo: [NSLocalizedDescriptionKey : "Base64ImageError"])
134
+ completion(nil, error)
135
+ return
136
+ }
137
+ completion(image, nil)
138
+ } else {
139
+ guard let url = URL(string: imageURL) else {
140
+ let error = NSError(domain: "cronapp-plugin-mlkit",
141
+ code: -1,
142
+ userInfo: [NSLocalizedDescriptionKey : "URLImageError"])
143
+ completion(nil, error)
144
+ return
145
+ }
146
+ URLSession.shared.dataTask(with: url) { (data, response, error) in
147
+ if let error = error {
148
+ completion(nil, error)
149
+ } else {
150
+ guard let data = data, let image = UIImage(data: data) else {
151
+ let error = NSError(domain: "cronapp-plugin-mlkit",
152
+ code: -1,
153
+ userInfo: [NSLocalizedDescriptionKey : "DownloadImageError"])
154
+ completion(nil, error)
155
+ return
156
+ }
157
+ completion(image, nil)
158
+ }
159
+ }
160
+ .resume()
161
+ }
162
+ }
163
+ }
@@ -0,0 +1,17 @@
1
+ var exec = require('cordova/exec');
2
+
3
+ exports.onDeviceTextRecognizer = function (image, success, error) {
4
+ exec(success, error,'CronappMLKitPlugin', 'onDeviceTextRecognizer', [image])
5
+ }
6
+
7
+ exports.barcodeDetector = function (image, success, error) {
8
+ exec(success, error,'CronappMLKitPlugin', 'barcodeDetector', [image])
9
+ }
10
+
11
+ exports.imageLabeler = function (image, success, error) {
12
+ exec(success, error,'CronappMLKitPlugin', 'imageLabeler', [image])
13
+ }
14
+
15
+ exports.faceDetector = function (image, options, success, error) {
16
+ exec(success, error,'CronappMLKitPlugin', 'faceDetector', [image, options])
17
+ }