mediversal-rn-image-intelligence 1.0.6

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.
Files changed (60) hide show
  1. package/LICENSE +0 -0
  2. package/README.md +361 -0
  3. package/android/.gradle/8.9/checksums/checksums.lock +0 -0
  4. package/android/.gradle/8.9/dependencies-accessors/gc.properties +0 -0
  5. package/android/.gradle/8.9/executionHistory/executionHistory.lock +0 -0
  6. package/android/.gradle/8.9/fileChanges/last-build.bin +0 -0
  7. package/android/.gradle/8.9/fileHashes/fileHashes.lock +0 -0
  8. package/android/.gradle/8.9/gc.properties +0 -0
  9. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  10. package/android/.gradle/buildOutputCleanup/cache.properties +2 -0
  11. package/android/.gradle/vcs-1/gc.properties +0 -0
  12. package/android/build.gradle +71 -0
  13. package/android/src/main/AndroidManifest.xml +10 -0
  14. package/android/src/main/java/com/mediversalrnimagintelligence/FaceDetectionModule.kt +147 -0
  15. package/android/src/main/java/com/mediversalrnimagintelligence/HandwritingRecognitionModule.kt +74 -0
  16. package/android/src/main/java/com/mediversalrnimagintelligence/ImageIntelligencePackage.kt +20 -0
  17. package/android/src/main/java/com/mediversalrnimagintelligence/TextRecognitionModule.kt +86 -0
  18. package/ios/FaceDetectionModule.m +16 -0
  19. package/ios/FaceDetectionModule.swift +164 -0
  20. package/ios/HandwritingRecognitionModule.m +14 -0
  21. package/ios/HandwritingRecognitionModule.swift +53 -0
  22. package/ios/TextRecognitionModule.m +14 -0
  23. package/ios/TextRecognitionModule.swift +102 -0
  24. package/lib/commonjs/NativeFaceDetectionModule.js +12 -0
  25. package/lib/commonjs/NativeFaceDetectionModule.js.map +1 -0
  26. package/lib/commonjs/NativeHandwritingRecognitionModule.js +12 -0
  27. package/lib/commonjs/NativeHandwritingRecognitionModule.js.map +1 -0
  28. package/lib/commonjs/NativeTextRecognitionModule.js +12 -0
  29. package/lib/commonjs/NativeTextRecognitionModule.js.map +1 -0
  30. package/lib/commonjs/index.js +194 -0
  31. package/lib/commonjs/index.js.map +1 -0
  32. package/lib/commonjs/types.js +2 -0
  33. package/lib/commonjs/types.js.map +1 -0
  34. package/lib/module/NativeFaceDetectionModule.js +8 -0
  35. package/lib/module/NativeFaceDetectionModule.js.map +1 -0
  36. package/lib/module/NativeHandwritingRecognitionModule.js +8 -0
  37. package/lib/module/NativeHandwritingRecognitionModule.js.map +1 -0
  38. package/lib/module/NativeTextRecognitionModule.js +8 -0
  39. package/lib/module/NativeTextRecognitionModule.js.map +1 -0
  40. package/lib/module/index.js +186 -0
  41. package/lib/module/index.js.map +1 -0
  42. package/lib/module/types.js +2 -0
  43. package/lib/module/types.js.map +1 -0
  44. package/lib/typescript/NativeFaceDetectionModule.d.ts +11 -0
  45. package/lib/typescript/NativeFaceDetectionModule.d.ts.map +1 -0
  46. package/lib/typescript/NativeHandwritingRecognitionModule.d.ts +11 -0
  47. package/lib/typescript/NativeHandwritingRecognitionModule.d.ts.map +1 -0
  48. package/lib/typescript/NativeTextRecognitionModule.d.ts +11 -0
  49. package/lib/typescript/NativeTextRecognitionModule.d.ts.map +1 -0
  50. package/lib/typescript/index.d.ts +44 -0
  51. package/lib/typescript/index.d.ts.map +1 -0
  52. package/lib/typescript/types.d.ts +91 -0
  53. package/lib/typescript/types.d.ts.map +1 -0
  54. package/mediversal-rn-image-intelligence.podspec +0 -0
  55. package/package.json +157 -0
  56. package/src/NativeFaceDetectionModule.ts +18 -0
  57. package/src/NativeHandwritingRecognitionModule.ts +16 -0
  58. package/src/NativeTextRecognitionModule.ts +14 -0
  59. package/src/index.tsx +243 -0
  60. package/src/types.ts +96 -0
package/LICENSE ADDED
File without changes
package/README.md ADDED
@@ -0,0 +1,361 @@
1
+ # mediversal-rn-image-intelligence
2
+
3
+ [![npm version](https://badge.fury.io/js/mediversal-rn-image-intelligence.svg)](https://badge.fury.io/js/mediversal-rn-image-intelligence)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+
6
+ 🎯 **Production-ready React Native library for intelligent image analysis using Google ML Kit (on-device)**
7
+
8
+ Analyze images to detect faces, extract printed text, and recognize handwritten contentβ€”all processed locally on the device for maximum privacy and performance.
9
+
10
+ ## 🌟 Features
11
+
12
+ - **Face Detection**: Detect human faces with detailed metadata (smiling probability, eye open probability, head rotation, etc.)
13
+ - **Text Recognition (OCR)**: Extract printed text from images with high accuracy
14
+ - **Handwriting Recognition**: Recognize handwritten text (requires stroke data)
15
+ - **πŸš€ On-Device Processing**: All analysis happens locally using Google ML Kit
16
+ - **πŸ”’ Privacy-First**: No data sent to external servers
17
+ - **⚑ Fast & Efficient**: Optimized for mobile performance
18
+ - **πŸ“± Cross-Platform**: Works seamlessly on iOS and Android
19
+ - **🎨 TurboModule Architecture**: Built with React Native New Architecture support
20
+ - **πŸ’ͺ TypeScript**: Fully typed API for excellent developer experience
21
+
22
+ ## πŸ“¦ Installation
23
+
24
+ ```bash
25
+ npm install mediversal-rn-image-intelligence
26
+ # or
27
+ yarn add mediversal-rn-image-intelligence
28
+ ```
29
+
30
+ ### iOS Setup
31
+
32
+ ```bash
33
+ cd ios && pod install
34
+ ```
35
+
36
+ **Required**: Add the following to your `Info.plist` if you need camera or photo library access:
37
+
38
+ ```xml
39
+ <key>NSCameraUsageDescription</key>
40
+ <string>We need access to your camera to capture images for analysis</string>
41
+ <key>NSPhotoLibraryUsageDescription</key>
42
+ <string>We need access to your photo library to analyze images</string>
43
+ ```
44
+
45
+ ### Android Setup
46
+
47
+ The library will automatically configure the required Google ML Kit dependencies. Ensure your `minSdkVersion` is at least 21:
48
+
49
+ ```gradle
50
+ // android/build.gradle
51
+ buildscript {
52
+ ext {
53
+ minSdkVersion = 21
54
+ }
55
+ }
56
+ ```
57
+
58
+ **Required**: Add permissions to your `AndroidManifest.xml` if needed:
59
+
60
+ ```xml
61
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
62
+ <uses-permission android:name="android.permission.CAMERA" />
63
+ ```
64
+
65
+ ## πŸš€ Usage
66
+
67
+ ### Basic Example
68
+
69
+ ```typescript
70
+ import { analyzeImage } from 'mediversal-rn-image-intelligence';
71
+
72
+ async function analyzeMyImage() {
73
+ try {
74
+ const result = await analyzeImage('file:///path/to/image.jpg');
75
+
76
+ console.log('Contains face:', result.containsFace);
77
+ console.log('Contains printed text:', result.containsPrintedText);
78
+ console.log('Contains handwritten text:', result.containsHandwrittenText);
79
+
80
+ // Access detected faces
81
+ if (result.faces) {
82
+ result.faces.forEach((face, index) => {
83
+ console.log(`Face ${index + 1}:`);
84
+ console.log(' Bounding box:', face.boundingBox);
85
+ console.log(' Smiling:', face.smilingProbability);
86
+ console.log(' Left eye open:', face.leftEyeOpenProbability);
87
+ console.log(' Right eye open:', face.rightEyeOpenProbability);
88
+ });
89
+ }
90
+
91
+ // Access extracted text
92
+ if (result.printedText) {
93
+ console.log('Extracted text:', result.printedText);
94
+ }
95
+ } catch (error) {
96
+ console.error('Analysis failed:', error);
97
+ }
98
+ }
99
+ ```
100
+
101
+ ### Advanced Example with Options
102
+
103
+ ```typescript
104
+ import {
105
+ analyzeImage,
106
+ type AnalysisOptions,
107
+ } from 'mediversal-rn-image-intelligence';
108
+
109
+ const options: AnalysisOptions = {
110
+ detectFaces: true,
111
+ detectPrintedText: true,
112
+ detectHandwrittenText: false, // Skip handwriting for performance
113
+ faceDetectionMode: 'accurate', // 'fast' or 'accurate'
114
+ minFaceSize: 0.15, // Minimum face size (0.0 to 1.0)
115
+ };
116
+
117
+ const result = await analyzeImage('file:///path/to/image.jpg', options);
118
+ ```
119
+
120
+ ### With Image Picker
121
+
122
+ ```typescript
123
+ import { launchImageLibrary } from 'react-native-image-picker';
124
+ import { analyzeImage } from 'mediversal-rn-image-intelligence';
125
+
126
+ async function pickAndAnalyze() {
127
+ const response = await launchImageLibrary({
128
+ mediaType: 'photo',
129
+ quality: 1,
130
+ });
131
+
132
+ if (response.assets && response.assets[0].uri) {
133
+ const result = await analyzeImage(response.assets[0].uri);
134
+ console.log(result);
135
+ }
136
+ }
137
+ ```
138
+
139
+ ### React Component Example
140
+
141
+ ```typescript
142
+ import React, { useState } from 'react';
143
+ import { View, Button, Text, Image } from 'react-native';
144
+ import { launchImageLibrary } from 'react-native-image-picker';
145
+ import {
146
+ analyzeImage,
147
+ type AnalysisResult,
148
+ } from 'mediversal-rn-image-intelligence';
149
+
150
+ export default function ImageAnalyzer() {
151
+ const [imageUri, setImageUri] = useState<string | null>(null);
152
+ const [result, setResult] = useState<AnalysisResult | null>(null);
153
+ const [loading, setLoading] = useState(false);
154
+
155
+ const selectAndAnalyze = async () => {
156
+ const response = await launchImageLibrary({ mediaType: 'photo' });
157
+
158
+ if (response.assets && response.assets[0].uri) {
159
+ const uri = response.assets[0].uri;
160
+ setImageUri(uri);
161
+ setLoading(true);
162
+
163
+ try {
164
+ const analysis = await analyzeImage(uri);
165
+ setResult(analysis);
166
+ } catch (error) {
167
+ console.error(error);
168
+ } finally {
169
+ setLoading(false);
170
+ }
171
+ }
172
+ };
173
+
174
+ return (
175
+ <View style={{ padding: 20 }}>
176
+ <Button title="Select Image" onPress={selectAndAnalyze} />
177
+
178
+ {imageUri && (
179
+ <Image source={{ uri: imageUri }} style={{ width: 300, height: 300 }} />
180
+ )}
181
+
182
+ {loading && <Text>Analyzing...</Text>}
183
+
184
+ {result && (
185
+ <View style={{ marginTop: 20 }}>
186
+ <Text>Faces detected: {result.containsFace ? 'Yes' : 'No'}</Text>
187
+ <Text>
188
+ Text detected: {result.containsPrintedText ? 'Yes' : 'No'}
189
+ </Text>
190
+ {result.faces && <Text>Number of faces: {result.faces.length}</Text>}
191
+ {result.printedText && (
192
+ <Text>Extracted text: {result.printedText}</Text>
193
+ )}
194
+ </View>
195
+ )}
196
+ </View>
197
+ );
198
+ }
199
+ ```
200
+
201
+ ## πŸ“š API Reference
202
+
203
+ ### `analyzeImage(imageUri: string, options?: AnalysisOptions): Promise<AnalysisResult>`
204
+
205
+ Main function to analyze an image.
206
+
207
+ **Parameters:**
208
+
209
+ - `imageUri` (string): Local file URI. Supported formats:
210
+ - Android: `file:///path/to/image.jpg`, `content://...`, or absolute path
211
+ - iOS: `file:///path/to/image.jpg`, `ph://...`, `assets-library://...`, or absolute path
212
+ - `options` (AnalysisOptions, optional): Configuration options
213
+
214
+ **Returns:** Promise<AnalysisResult>
215
+
216
+ ### `isAvailable(): Promise<boolean>`
217
+
218
+ Check if the library is properly installed and native modules are available.
219
+
220
+ ## πŸ“‹ Types
221
+
222
+ ### `AnalysisResult`
223
+
224
+ ```typescript
225
+ interface AnalysisResult {
226
+ containsFace: boolean;
227
+ containsPrintedText: boolean;
228
+ containsHandwrittenText: boolean;
229
+ faces?: FaceData[];
230
+ printedText?: string;
231
+ handwrittenText?: string;
232
+ errors?: {
233
+ faceDetection?: string;
234
+ textRecognition?: string;
235
+ handwritingRecognition?: string;
236
+ };
237
+ }
238
+ ```
239
+
240
+ ### `FaceData`
241
+
242
+ ```typescript
243
+ interface FaceData {
244
+ boundingBox: BoundingBox;
245
+ smilingProbability?: number; // 0.0 to 1.0
246
+ leftEyeOpenProbability?: number; // 0.0 to 1.0
247
+ rightEyeOpenProbability?: number; // 0.0 to 1.0
248
+ headEulerAngleY?: number; // Yaw in degrees
249
+ headEulerAngleZ?: number; // Roll in degrees
250
+ trackingId?: number;
251
+ }
252
+ ```
253
+
254
+ ### `BoundingBox`
255
+
256
+ ```typescript
257
+ interface BoundingBox {
258
+ x: number;
259
+ y: number;
260
+ width: number;
261
+ height: number;
262
+ }
263
+ ```
264
+
265
+ ### `AnalysisOptions`
266
+
267
+ ```typescript
268
+ interface AnalysisOptions {
269
+ detectFaces?: boolean; // default: true
270
+ detectPrintedText?: boolean; // default: true
271
+ detectHandwrittenText?: boolean; // default: true
272
+ faceDetectionMode?: 'fast' | 'accurate'; // default: 'fast'
273
+ minFaceSize?: number; // 0.0 to 1.0, default: 0.1
274
+ }
275
+ ```
276
+
277
+ ## ⚑ Performance Tips
278
+
279
+ 1. **Use 'fast' mode for real-time applications**: The `faceDetectionMode: 'fast'` option provides better performance for live camera feeds.
280
+
281
+ 2. **Disable unused features**: If you only need face detection, disable text recognition:
282
+
283
+ ```typescript
284
+ analyzeImage(uri, {
285
+ detectPrintedText: false,
286
+ detectHandwrittenText: false,
287
+ });
288
+ ```
289
+
290
+ 3. **Optimize image size**: Resize large images before analysis to improve processing time.
291
+
292
+ 4. **Parallel processing**: The library automatically runs all enabled analyses in parallel for maximum efficiency.
293
+
294
+ ## πŸ”’ Privacy & Security
295
+
296
+ All image processing happens **locally on the device** using Google ML Kit's on-device APIs. No image data is ever sent to external servers, ensuring:
297
+
298
+ - βœ… Complete user privacy
299
+ - βœ… Offline functionality
300
+ - βœ… Faster processing
301
+ - βœ… No data usage costs
302
+ - βœ… GDPR & CCPA compliance
303
+
304
+ ## πŸ› Troubleshooting
305
+
306
+ ### iOS: "Module not found"
307
+
308
+ Make sure you've run `pod install`:
309
+
310
+ ```bash
311
+ cd ios && pod install
312
+ ```
313
+
314
+ ### Android: Gradle build errors
315
+
316
+ Ensure your `minSdkVersion` is at least 21 and you're using Java 11:
317
+
318
+ ```gradle
319
+ android {
320
+ compileOptions {
321
+ sourceCompatibility JavaVersion.VERSION_11
322
+ targetCompatibility JavaVersion.VERSION_11
323
+ }
324
+ }
325
+ ```
326
+
327
+ ### Image URI format errors
328
+
329
+ - **Android**: Use `file://`, `content://`, or absolute paths
330
+ - **iOS**: Use `file://`, `ph://`, `assets-library://`, or absolute paths
331
+
332
+ ### Digital Ink Recognition limitation
333
+
334
+ The Digital Ink Recognition API is designed for real-time stroke data (from drawing apps), not static images. For handwriting recognition in static images, consider:
335
+
336
+ - Using Google Cloud Vision API (cloud-based)
337
+ - Pre-processing images to extract stroke information
338
+ - Using alternative OCR solutions specifically designed for handwriting
339
+
340
+ ## 🀝 Contributing
341
+
342
+ Contributions are welcome! Please feel free to submit a Pull Request.
343
+
344
+ ## πŸ“„ License
345
+
346
+ MIT Β© Mediversal
347
+
348
+ ## πŸ™ Acknowledgments
349
+
350
+ Built with:
351
+
352
+ - [Google ML Kit](https://developers.google.com/ml-kit)
353
+ - [React Native](https://reactnative.dev/)
354
+
355
+ ## πŸ“ž Support
356
+
357
+ - πŸ“§ Email: sushantbibhu@gmail.com
358
+ - πŸ› Issues: [GitHub Issues](https://github.com/thisissushant/mediversal-rn-image-intelligence)
359
+ - πŸ“– Documentation: [GitHub Wiki](https://github.com/thisissushant/mediversal-rn-image-intelligence)
360
+
361
+ ---
File without changes
@@ -0,0 +1,2 @@
1
+ #Tue Jan 27 14:16:03 IST 2026
2
+ gradle.version=8.9
File without changes
@@ -0,0 +1,71 @@
1
+ buildscript {
2
+ repositories {
3
+ google()
4
+ mavenCentral()
5
+ }
6
+
7
+ dependencies {
8
+ classpath 'com.android.tools.build:gradle:7.4.2'
9
+ }
10
+ }
11
+
12
+ apply plugin: 'com.android.library'
13
+ apply plugin: 'kotlin-android'
14
+
15
+ def safeExtGet(prop, fallback) {
16
+ rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
17
+ }
18
+
19
+ android {
20
+ compileSdkVersion safeExtGet('compileSdkVersion', 33)
21
+
22
+ namespace "com.mediversalrnimagintelligence"
23
+
24
+ defaultConfig {
25
+ minSdkVersion safeExtGet('minSdkVersion', 21)
26
+ targetSdkVersion safeExtGet('targetSdkVersion', 33)
27
+ versionCode 1
28
+ versionName "1.0.0"
29
+ }
30
+
31
+ buildTypes {
32
+ release {
33
+ minifyEnabled false
34
+ }
35
+ }
36
+
37
+ compileOptions {
38
+ sourceCompatibility JavaVersion.VERSION_11
39
+ targetCompatibility JavaVersion.VERSION_11
40
+ }
41
+
42
+ kotlinOptions {
43
+ jvmTarget = '11'
44
+ }
45
+ }
46
+
47
+ repositories {
48
+ google()
49
+ mavenCentral()
50
+ }
51
+
52
+ dependencies {
53
+ // React Native
54
+ implementation 'com.facebook.react:react-native:+'
55
+
56
+ // Kotlin
57
+ implementation "org.jetbrains.kotlin:kotlin-stdlib:1.8.0"
58
+
59
+ // Google ML Kit - Face Detection
60
+ implementation 'com.google.mlkit:face-detection:16.1.5'
61
+
62
+ // Google ML Kit - Text Recognition v2 (newer API)
63
+ implementation 'com.google.android.gms:play-services-mlkit-text-recognition:19.0.0'
64
+
65
+ // Google ML Kit - Digital Ink Recognition
66
+ implementation 'com.google.mlkit:digital-ink-recognition:18.1.0'
67
+
68
+ // Coroutines for async operations
69
+ implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4'
70
+ implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4'
71
+ }
@@ -0,0 +1,10 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
2
+ package="com.mediversalrnimagintelligence">
3
+
4
+ <!-- Permissions for reading images -->
5
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
6
+
7
+ <!-- Optional: for camera access if needed -->
8
+ <uses-permission android:name="android.permission.CAMERA" />
9
+
10
+ </manifest>
@@ -0,0 +1,147 @@
1
+ package com.mediversalrnimagintelligence
2
+
3
+ import android.graphics.Rect
4
+ import android.net.Uri
5
+ import com.facebook.react.bridge.Arguments
6
+ import com.facebook.react.bridge.Promise
7
+ import com.facebook.react.bridge.ReactApplicationContext
8
+ import com.facebook.react.bridge.ReactContextBaseJavaModule
9
+ import com.facebook.react.bridge.ReactMethod
10
+ import com.facebook.react.bridge.WritableMap
11
+ import com.facebook.react.bridge.WritableArray
12
+ import com.google.mlkit.vision.common.InputImage
13
+ import com.google.mlkit.vision.face.Face
14
+ import com.google.mlkit.vision.face.FaceDetection
15
+ import com.google.mlkit.vision.face.FaceDetectorOptions
16
+ import java.io.IOException
17
+
18
+ class FaceDetectionModule(reactContext: ReactApplicationContext) :
19
+ ReactContextBaseJavaModule(reactContext) {
20
+
21
+ override fun getName(): String {
22
+ return "FaceDetectionModule"
23
+ }
24
+
25
+ @ReactMethod
26
+ fun detectFaces(imageUri: String, mode: String, minFaceSize: Double, promise: Promise) {
27
+ try {
28
+ // Parse the image from URI
29
+ val image = parseImageFromUri(imageUri)
30
+
31
+ // Configure face detector
32
+ val detectorOptions = when (mode) {
33
+ "accurate" -> FaceDetectorOptions.Builder()
34
+ .setPerformanceMode(FaceDetectorOptions.PERFORMANCE_MODE_ACCURATE)
35
+ .setLandmarkMode(FaceDetectorOptions.LANDMARK_MODE_ALL)
36
+ .setClassificationMode(FaceDetectorOptions.CLASSIFICATION_MODE_ALL)
37
+ .setMinFaceSize(minFaceSize.toFloat())
38
+ .enableTracking()
39
+ .build()
40
+ else -> FaceDetectorOptions.Builder()
41
+ .setPerformanceMode(FaceDetectorOptions.PERFORMANCE_MODE_FAST)
42
+ .setClassificationMode(FaceDetectorOptions.CLASSIFICATION_MODE_ALL)
43
+ .setMinFaceSize(minFaceSize.toFloat())
44
+ .build()
45
+ }
46
+
47
+ val detector = FaceDetection.getClient(detectorOptions)
48
+
49
+ // Process the image
50
+ detector.process(image)
51
+ .addOnSuccessListener { faces ->
52
+ val result = Arguments.createMap()
53
+ val facesArray = Arguments.createArray()
54
+
55
+ for (face in faces) {
56
+ facesArray.pushMap(convertFaceToMap(face))
57
+ }
58
+
59
+ result.putArray("faces", facesArray)
60
+ promise.resolve(result)
61
+ }
62
+ .addOnFailureListener { e ->
63
+ val result = Arguments.createMap()
64
+ result.putArray("faces", Arguments.createArray())
65
+ result.putString("error", e.message ?: "Face detection failed")
66
+ promise.resolve(result)
67
+ }
68
+
69
+ } catch (e: Exception) {
70
+ val result = Arguments.createMap()
71
+ result.putArray("faces", Arguments.createArray())
72
+ result.putString("error", e.message ?: "Failed to process image")
73
+ promise.resolve(result)
74
+ }
75
+ }
76
+
77
+ private fun parseImageFromUri(uriString: String): InputImage {
78
+ val context = reactApplicationContext
79
+
80
+ return try {
81
+ when {
82
+ uriString.startsWith("file://") -> {
83
+ val uri = Uri.parse(uriString)
84
+ InputImage.fromFilePath(context, uri)
85
+ }
86
+ uriString.startsWith("content://") -> {
87
+ val uri = Uri.parse(uriString)
88
+ InputImage.fromFilePath(context, uri)
89
+ }
90
+ uriString.startsWith("/") -> {
91
+ // Absolute file path
92
+ val uri = Uri.parse("file://$uriString")
93
+ InputImage.fromFilePath(context, uri)
94
+ }
95
+ else -> {
96
+ throw IOException("Unsupported URI format: $uriString")
97
+ }
98
+ }
99
+ } catch (e: IOException) {
100
+ throw IOException("Failed to load image from URI: ${e.message}")
101
+ }
102
+ }
103
+
104
+ private fun convertFaceToMap(face: Face): WritableMap {
105
+ val faceMap = Arguments.createMap()
106
+
107
+ // Bounding box
108
+ val boundingBox = Arguments.createMap()
109
+ val bounds: Rect = face.boundingBox
110
+ boundingBox.putInt("x", bounds.left)
111
+ boundingBox.putInt("y", bounds.top)
112
+ boundingBox.putInt("width", bounds.width())
113
+ boundingBox.putInt("height", bounds.height())
114
+ faceMap.putMap("boundingBox", boundingBox)
115
+
116
+ // Smiling probability
117
+ if (face.smilingProbability != null) {
118
+ faceMap.putDouble("smilingProbability", face.smilingProbability!!.toDouble())
119
+ }
120
+
121
+ // Left eye open probability
122
+ if (face.leftEyeOpenProbability != null) {
123
+ faceMap.putDouble("leftEyeOpenProbability", face.leftEyeOpenProbability!!.toDouble())
124
+ }
125
+
126
+ // Right eye open probability
127
+ if (face.rightEyeOpenProbability != null) {
128
+ faceMap.putDouble("rightEyeOpenProbability", face.rightEyeOpenProbability!!.toDouble())
129
+ }
130
+
131
+ // Head Euler angles
132
+ if (face.headEulerAngleY != null) {
133
+ faceMap.putDouble("headEulerAngleY", face.headEulerAngleY!!.toDouble())
134
+ }
135
+
136
+ if (face.headEulerAngleZ != null) {
137
+ faceMap.putDouble("headEulerAngleZ", face.headEulerAngleZ!!.toDouble())
138
+ }
139
+
140
+ // Tracking ID
141
+ if (face.trackingId != null) {
142
+ faceMap.putInt("trackingId", face.trackingId!!)
143
+ }
144
+
145
+ return faceMap
146
+ }
147
+ }
@@ -0,0 +1,74 @@
1
+ package com.mediversalrnimagintelligence
2
+
3
+ import android.graphics.Bitmap
4
+ import android.graphics.BitmapFactory
5
+ import android.net.Uri
6
+ import com.facebook.react.bridge.Arguments
7
+ import com.facebook.react.bridge.Promise
8
+ import com.facebook.react.bridge.ReactApplicationContext
9
+ import com.facebook.react.bridge.ReactContextBaseJavaModule
10
+ import com.facebook.react.bridge.ReactMethod
11
+ import com.facebook.react.bridge.WritableMap
12
+ import com.google.mlkit.vision.digitalink.DigitalInkRecognition
13
+ import com.google.mlkit.vision.digitalink.DigitalInkRecognitionModel
14
+ import com.google.mlkit.vision.digitalink.DigitalInkRecognitionModelIdentifier
15
+ import com.google.mlkit.vision.digitalink.DigitalInkRecognizer
16
+ import com.google.mlkit.vision.digitalink.DigitalInkRecognizerOptions
17
+ import com.google.mlkit.vision.digitalink.Ink
18
+ import java.io.IOException
19
+ import java.io.InputStream
20
+
21
+ class HandwritingRecognitionModule(reactContext: ReactApplicationContext) :
22
+ ReactContextBaseJavaModule(reactContext) {
23
+
24
+ override fun getName(): String {
25
+ return "HandwritingRecognitionModule"
26
+ }
27
+
28
+ @ReactMethod
29
+ fun recognizeHandwriting(imageUri: String, promise: Promise) {
30
+ try {
31
+ // Note: Digital Ink Recognition in ML Kit is designed for real-time stroke data,
32
+ // not static images. For production use with static images, you would need to:
33
+ // 1. Use a different API (like Cloud Vision API's handwriting detection)
34
+ // 2. Or pre-process the image to extract strokes
35
+ //
36
+ // For this implementation, we'll provide a graceful fallback indicating
37
+ // that handwriting recognition from static images is not fully supported
38
+ // by the on-device Digital Ink API.
39
+
40
+ val result = Arguments.createMap()
41
+ result.putString("text", "")
42
+ result.putString(
43
+ "error",
44
+ "Digital Ink Recognition requires stroke data, not static images. " +
45
+ "For handwriting in static images, consider using Cloud Vision API or " +
46
+ "preprocessing to extract stroke information."
47
+ )
48
+ promise.resolve(result)
49
+
50
+ // Alternative implementation note:
51
+ // If you have stroke data (from a drawing canvas), the proper implementation would be:
52
+ // 1. Create an Ink object from strokes
53
+ // 2. Get recognizer with appropriate model
54
+ // 3. Call recognizer.recognize(ink)
55
+ //
56
+ // Example (commented out as it requires stroke data):
57
+ // val modelIdentifier = DigitalInkRecognitionModelIdentifier.fromLanguageTag("en-US")
58
+ // val model = DigitalInkRecognitionModel.builder(modelIdentifier!!).build()
59
+ // val recognizer = DigitalInkRecognition.getClient(
60
+ // DigitalInkRecognizerOptions.builder(model).build()
61
+ // )
62
+ // recognizer.recognize(ink)
63
+ // .addOnSuccessListener { result ->
64
+ // // Process candidates
65
+ // }
66
+
67
+ } catch (e: Exception) {
68
+ val result = Arguments.createMap()
69
+ result.putString("text", "")
70
+ result.putString("error", e.message ?: "Handwriting recognition failed")
71
+ promise.resolve(result)
72
+ }
73
+ }
74
+ }