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.
- package/LICENSE +0 -0
- package/README.md +361 -0
- package/android/.gradle/8.9/checksums/checksums.lock +0 -0
- package/android/.gradle/8.9/dependencies-accessors/gc.properties +0 -0
- package/android/.gradle/8.9/executionHistory/executionHistory.lock +0 -0
- package/android/.gradle/8.9/fileChanges/last-build.bin +0 -0
- package/android/.gradle/8.9/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/8.9/gc.properties +0 -0
- package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
- package/android/.gradle/buildOutputCleanup/cache.properties +2 -0
- package/android/.gradle/vcs-1/gc.properties +0 -0
- package/android/build.gradle +71 -0
- package/android/src/main/AndroidManifest.xml +10 -0
- package/android/src/main/java/com/mediversalrnimagintelligence/FaceDetectionModule.kt +147 -0
- package/android/src/main/java/com/mediversalrnimagintelligence/HandwritingRecognitionModule.kt +74 -0
- package/android/src/main/java/com/mediversalrnimagintelligence/ImageIntelligencePackage.kt +20 -0
- package/android/src/main/java/com/mediversalrnimagintelligence/TextRecognitionModule.kt +86 -0
- package/ios/FaceDetectionModule.m +16 -0
- package/ios/FaceDetectionModule.swift +164 -0
- package/ios/HandwritingRecognitionModule.m +14 -0
- package/ios/HandwritingRecognitionModule.swift +53 -0
- package/ios/TextRecognitionModule.m +14 -0
- package/ios/TextRecognitionModule.swift +102 -0
- package/lib/commonjs/NativeFaceDetectionModule.js +12 -0
- package/lib/commonjs/NativeFaceDetectionModule.js.map +1 -0
- package/lib/commonjs/NativeHandwritingRecognitionModule.js +12 -0
- package/lib/commonjs/NativeHandwritingRecognitionModule.js.map +1 -0
- package/lib/commonjs/NativeTextRecognitionModule.js +12 -0
- package/lib/commonjs/NativeTextRecognitionModule.js.map +1 -0
- package/lib/commonjs/index.js +194 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/types.js +2 -0
- package/lib/commonjs/types.js.map +1 -0
- package/lib/module/NativeFaceDetectionModule.js +8 -0
- package/lib/module/NativeFaceDetectionModule.js.map +1 -0
- package/lib/module/NativeHandwritingRecognitionModule.js +8 -0
- package/lib/module/NativeHandwritingRecognitionModule.js.map +1 -0
- package/lib/module/NativeTextRecognitionModule.js +8 -0
- package/lib/module/NativeTextRecognitionModule.js.map +1 -0
- package/lib/module/index.js +186 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/types.js +2 -0
- package/lib/module/types.js.map +1 -0
- package/lib/typescript/NativeFaceDetectionModule.d.ts +11 -0
- package/lib/typescript/NativeFaceDetectionModule.d.ts.map +1 -0
- package/lib/typescript/NativeHandwritingRecognitionModule.d.ts +11 -0
- package/lib/typescript/NativeHandwritingRecognitionModule.d.ts.map +1 -0
- package/lib/typescript/NativeTextRecognitionModule.d.ts +11 -0
- package/lib/typescript/NativeTextRecognitionModule.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +44 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/types.d.ts +91 -0
- package/lib/typescript/types.d.ts.map +1 -0
- package/mediversal-rn-image-intelligence.podspec +0 -0
- package/package.json +157 -0
- package/src/NativeFaceDetectionModule.ts +18 -0
- package/src/NativeHandwritingRecognitionModule.ts +16 -0
- package/src/NativeTextRecognitionModule.ts +14 -0
- package/src/index.tsx +243 -0
- package/src/types.ts +96 -0
package/package.json
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mediversal-rn-image-intelligence",
|
|
3
|
+
"version": "1.0.6",
|
|
4
|
+
"description": "Production-ready React Native library for intelligent image analysis using Google ML Kit (on-device)",
|
|
5
|
+
"main": "lib/commonjs/index.js",
|
|
6
|
+
"module": "lib/module/index.js",
|
|
7
|
+
"types": "lib/typescript/index.d.ts",
|
|
8
|
+
"react-native": "src/index.tsx",
|
|
9
|
+
"source": "src/index.tsx",
|
|
10
|
+
"files": [
|
|
11
|
+
"src",
|
|
12
|
+
"lib",
|
|
13
|
+
"android",
|
|
14
|
+
"ios",
|
|
15
|
+
"cpp",
|
|
16
|
+
"mediversal-rn-image-intelligence.podspec",
|
|
17
|
+
"!lib/typescript/example",
|
|
18
|
+
"!android/build",
|
|
19
|
+
"!ios/build",
|
|
20
|
+
"!**/__tests__",
|
|
21
|
+
"!**/__fixtures__",
|
|
22
|
+
"!**/__mocks__"
|
|
23
|
+
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"test": "jest",
|
|
26
|
+
"typescript": "tsc --noEmit",
|
|
27
|
+
"lint": "eslint \"**/*.{js,ts,tsx}\"",
|
|
28
|
+
"prepare": "bob build",
|
|
29
|
+
"release": "release-it",
|
|
30
|
+
"example": "yarn --cwd example",
|
|
31
|
+
"pods": "cd example && pod-install --quiet",
|
|
32
|
+
"bootstrap": "yarn example && yarn && yarn pods"
|
|
33
|
+
},
|
|
34
|
+
"keywords": [
|
|
35
|
+
"react-native",
|
|
36
|
+
"ios",
|
|
37
|
+
"android",
|
|
38
|
+
"ml-kit",
|
|
39
|
+
"google-ml-kit",
|
|
40
|
+
"face-detection",
|
|
41
|
+
"text-recognition",
|
|
42
|
+
"ocr",
|
|
43
|
+
"handwriting-recognition",
|
|
44
|
+
"image-analysis",
|
|
45
|
+
"computer-vision",
|
|
46
|
+
"turbomodule"
|
|
47
|
+
],
|
|
48
|
+
"repository": "https://github.com/mediversal/mediversal-rn-image-intelligence",
|
|
49
|
+
"author": "Mediversal <dev@mediversal.com> (https://mediversal.com)",
|
|
50
|
+
"license": "MIT",
|
|
51
|
+
"bugs": {
|
|
52
|
+
"url": "https://github.com/mediversal/mediversal-rn-image-intelligence/issues"
|
|
53
|
+
},
|
|
54
|
+
"homepage": "https://github.com/mediversal/mediversal-rn-image-intelligence#readme",
|
|
55
|
+
"publishConfig": {
|
|
56
|
+
"registry": "https://registry.npmjs.org/"
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"@babel/preset-typescript": "^7.28.5",
|
|
60
|
+
"@react-native-community/eslint-config": "^3.0.0",
|
|
61
|
+
"@types/jest": "^28.1.2",
|
|
62
|
+
"@types/react": "~17.0.21",
|
|
63
|
+
"@types/react-native": "0.70.0",
|
|
64
|
+
"eslint": "^8.4.1",
|
|
65
|
+
"eslint-config-prettier": "^8.5.0",
|
|
66
|
+
"eslint-plugin-prettier": "^4.0.0",
|
|
67
|
+
"jest": "^28.1.1",
|
|
68
|
+
"pod-install": "^0.1.0",
|
|
69
|
+
"prettier": "^2.0.5",
|
|
70
|
+
"react": "18.2.0",
|
|
71
|
+
"react-native": "0.72.0",
|
|
72
|
+
"react-native-builder-bob": "^0.20.0",
|
|
73
|
+
"release-it": "^15.0.0",
|
|
74
|
+
"typescript": "^4.5.2"
|
|
75
|
+
},
|
|
76
|
+
"peerDependencies": {
|
|
77
|
+
"react": "*",
|
|
78
|
+
"react-native": "*"
|
|
79
|
+
},
|
|
80
|
+
"jest": {
|
|
81
|
+
"preset": "react-native",
|
|
82
|
+
"moduleFileExtensions": [
|
|
83
|
+
"ts",
|
|
84
|
+
"tsx",
|
|
85
|
+
"js",
|
|
86
|
+
"jsx",
|
|
87
|
+
"json",
|
|
88
|
+
"node"
|
|
89
|
+
],
|
|
90
|
+
"transformIgnorePatterns": [
|
|
91
|
+
"node_modules/(?!((jest-)?react-native|@react-native|@react-native-community|@react-native-js-polyfills)/)"
|
|
92
|
+
],
|
|
93
|
+
"setupFiles": [
|
|
94
|
+
"<rootDir>/jest.setup.js"
|
|
95
|
+
]
|
|
96
|
+
},
|
|
97
|
+
"eslintConfig": {
|
|
98
|
+
"root": true,
|
|
99
|
+
"parser": "@typescript-eslint/parser",
|
|
100
|
+
"parserOptions": {
|
|
101
|
+
"ecmaVersion": 2020,
|
|
102
|
+
"sourceType": "module",
|
|
103
|
+
"ecmaFeatures": {
|
|
104
|
+
"jsx": true
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
"plugins": [
|
|
108
|
+
"@typescript-eslint"
|
|
109
|
+
],
|
|
110
|
+
"extends": [
|
|
111
|
+
"@react-native-community",
|
|
112
|
+
"prettier",
|
|
113
|
+
"plugin:@typescript-eslint/recommended"
|
|
114
|
+
],
|
|
115
|
+
"rules": {
|
|
116
|
+
"prettier/prettier": [
|
|
117
|
+
"error",
|
|
118
|
+
{
|
|
119
|
+
"quoteProps": "consistent",
|
|
120
|
+
"singleQuote": true,
|
|
121
|
+
"tabWidth": 2,
|
|
122
|
+
"trailingComma": "es5",
|
|
123
|
+
"useTabs": false
|
|
124
|
+
}
|
|
125
|
+
]
|
|
126
|
+
},
|
|
127
|
+
"ignorePatterns": [
|
|
128
|
+
"node_modules/",
|
|
129
|
+
"lib/"
|
|
130
|
+
]
|
|
131
|
+
},
|
|
132
|
+
"eslintIgnore": [
|
|
133
|
+
"node_modules/",
|
|
134
|
+
"lib/"
|
|
135
|
+
],
|
|
136
|
+
"prettier": {
|
|
137
|
+
"quoteProps": "consistent",
|
|
138
|
+
"singleQuote": true,
|
|
139
|
+
"tabWidth": 2,
|
|
140
|
+
"trailingComma": "es5",
|
|
141
|
+
"useTabs": false
|
|
142
|
+
},
|
|
143
|
+
"react-native-builder-bob": {
|
|
144
|
+
"source": "src",
|
|
145
|
+
"output": "lib",
|
|
146
|
+
"targets": [
|
|
147
|
+
"commonjs",
|
|
148
|
+
"module",
|
|
149
|
+
[
|
|
150
|
+
"typescript",
|
|
151
|
+
{
|
|
152
|
+
"project": "tsconfig.build.json"
|
|
153
|
+
}
|
|
154
|
+
]
|
|
155
|
+
]
|
|
156
|
+
}
|
|
157
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { TurboModule } from 'react-native';
|
|
2
|
+
import { TurboModuleRegistry } from 'react-native';
|
|
3
|
+
import type { NativeFaceDetectionResult } from './types';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Face Detection TurboModule Specification
|
|
7
|
+
*/
|
|
8
|
+
export interface Spec extends TurboModule {
|
|
9
|
+
detectFaces(
|
|
10
|
+
imageUri: string,
|
|
11
|
+
mode: string,
|
|
12
|
+
minFaceSize: number
|
|
13
|
+
): Promise<NativeFaceDetectionResult>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export default TurboModuleRegistry.getEnforcing<Spec>(
|
|
17
|
+
'FaceDetectionModule'
|
|
18
|
+
) as Spec;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { TurboModule } from 'react-native';
|
|
2
|
+
import { TurboModuleRegistry } from 'react-native';
|
|
3
|
+
import type { NativeHandwritingRecognitionResult } from './types';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Handwriting Recognition TurboModule Specification
|
|
7
|
+
*/
|
|
8
|
+
export interface Spec extends TurboModule {
|
|
9
|
+
recognizeHandwriting(
|
|
10
|
+
imageUri: string
|
|
11
|
+
): Promise<NativeHandwritingRecognitionResult>;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export default TurboModuleRegistry.getEnforcing<Spec>(
|
|
15
|
+
'HandwritingRecognitionModule'
|
|
16
|
+
) as Spec;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { TurboModule } from 'react-native';
|
|
2
|
+
import { TurboModuleRegistry } from 'react-native';
|
|
3
|
+
import type { NativeTextRecognitionResult } from './types';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Text Recognition TurboModule Specification
|
|
7
|
+
*/
|
|
8
|
+
export interface Spec extends TurboModule {
|
|
9
|
+
recognizeText(imageUri: string): Promise<NativeTextRecognitionResult>;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export default TurboModuleRegistry.getEnforcing<Spec>(
|
|
13
|
+
'TextRecognitionModule'
|
|
14
|
+
) as Spec;
|
package/src/index.tsx
ADDED
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import { Platform } from 'react-native';
|
|
2
|
+
import FaceDetectionModule from './NativeFaceDetectionModule';
|
|
3
|
+
import TextRecognitionModule from './NativeTextRecognitionModule';
|
|
4
|
+
import HandwritingRecognitionModule from './NativeHandwritingRecognitionModule';
|
|
5
|
+
import type { AnalysisResult, AnalysisOptions } from './types';
|
|
6
|
+
|
|
7
|
+
// Export types for consumers
|
|
8
|
+
export type {
|
|
9
|
+
AnalysisResult,
|
|
10
|
+
AnalysisOptions,
|
|
11
|
+
FaceData,
|
|
12
|
+
BoundingBox,
|
|
13
|
+
} from './types';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Default analysis options
|
|
17
|
+
*/
|
|
18
|
+
const DEFAULT_OPTIONS: Required<AnalysisOptions> = {
|
|
19
|
+
detectFaces: true,
|
|
20
|
+
detectPrintedText: true,
|
|
21
|
+
detectHandwrittenText: true,
|
|
22
|
+
faceDetectionMode: 'fast',
|
|
23
|
+
minFaceSize: 0.1,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Validates and normalizes the image URI
|
|
28
|
+
* @param imageUri - The image URI to validate
|
|
29
|
+
* @returns Normalized URI
|
|
30
|
+
* @throws Error if URI is invalid
|
|
31
|
+
*/
|
|
32
|
+
function validateImageUri(imageUri: string): string {
|
|
33
|
+
if (!imageUri || typeof imageUri !== 'string') {
|
|
34
|
+
throw new Error('Invalid image URI: must be a non-empty string');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const trimmedUri = imageUri.trim();
|
|
38
|
+
|
|
39
|
+
if (trimmedUri.length === 0) {
|
|
40
|
+
throw new Error('Invalid image URI: must be a non-empty string');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Validate URI format
|
|
44
|
+
if (Platform.OS === 'android') {
|
|
45
|
+
// Android accepts: file://, content://, or absolute paths
|
|
46
|
+
if (
|
|
47
|
+
!trimmedUri.startsWith('file://') &&
|
|
48
|
+
!trimmedUri.startsWith('content://') &&
|
|
49
|
+
!trimmedUri.startsWith('/')
|
|
50
|
+
) {
|
|
51
|
+
throw new Error(
|
|
52
|
+
'Invalid Android image URI: must start with file://, content://, or be an absolute path'
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
} else if (Platform.OS === 'ios') {
|
|
56
|
+
// iOS accepts: file://, ph://, assets-library://, or absolute paths
|
|
57
|
+
if (
|
|
58
|
+
!trimmedUri.startsWith('file://') &&
|
|
59
|
+
!trimmedUri.startsWith('ph://') &&
|
|
60
|
+
!trimmedUri.startsWith('assets-library://') &&
|
|
61
|
+
!trimmedUri.startsWith('/')
|
|
62
|
+
) {
|
|
63
|
+
throw new Error(
|
|
64
|
+
'Invalid iOS image URI: must start with file://, ph://, assets-library://, or be an absolute path'
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return trimmedUri;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Analyzes an image using Google ML Kit on-device APIs
|
|
74
|
+
*
|
|
75
|
+
* This function performs parallel analysis using three ML Kit models:
|
|
76
|
+
* - Face Detection: Detects human faces and facial attributes
|
|
77
|
+
* - Text Recognition: Extracts printed text (OCR)
|
|
78
|
+
* - Digital Ink Recognition: Extracts handwritten text
|
|
79
|
+
*
|
|
80
|
+
* @param imageUri - Local file URI (e.g., "file:///path/to/image.jpg", "content://...", or absolute path)
|
|
81
|
+
* @param options - Configuration options for the analysis
|
|
82
|
+
* @returns Promise resolving to the analysis result
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```typescript
|
|
86
|
+
* const result = await analyzeImage('file:///path/to/image.jpg');
|
|
87
|
+
*
|
|
88
|
+
* if (result.containsFace) {
|
|
89
|
+
* console.log(`Found ${result.faces?.length} face(s)`);
|
|
90
|
+
* result.faces?.forEach(face => {
|
|
91
|
+
* console.log('Smiling:', face.smilingProbability);
|
|
92
|
+
* });
|
|
93
|
+
* }
|
|
94
|
+
*
|
|
95
|
+
* if (result.containsPrintedText) {
|
|
96
|
+
* console.log('Text:', result.printedText);
|
|
97
|
+
* }
|
|
98
|
+
* ```
|
|
99
|
+
*
|
|
100
|
+
* @throws Error if imageUri is invalid or if all analyses fail
|
|
101
|
+
*/
|
|
102
|
+
export async function analyzeImage(
|
|
103
|
+
imageUri: string,
|
|
104
|
+
options: AnalysisOptions = {}
|
|
105
|
+
): Promise<AnalysisResult> {
|
|
106
|
+
// Validate input
|
|
107
|
+
const validatedUri = validateImageUri(imageUri);
|
|
108
|
+
|
|
109
|
+
// Merge with default options
|
|
110
|
+
const opts: Required<AnalysisOptions> = {
|
|
111
|
+
...DEFAULT_OPTIONS,
|
|
112
|
+
...options,
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
// Initialize result
|
|
116
|
+
const result: AnalysisResult = {
|
|
117
|
+
containsFace: false,
|
|
118
|
+
containsPrintedText: false,
|
|
119
|
+
containsHandwrittenText: false,
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
// Create promises array for parallel execution
|
|
123
|
+
const promises: Promise<void>[] = [];
|
|
124
|
+
|
|
125
|
+
// Face Detection
|
|
126
|
+
if (opts.detectFaces) {
|
|
127
|
+
promises.push(
|
|
128
|
+
(async () => {
|
|
129
|
+
try {
|
|
130
|
+
const faceResult = await FaceDetectionModule.detectFaces(
|
|
131
|
+
validatedUri,
|
|
132
|
+
opts.faceDetectionMode,
|
|
133
|
+
opts.minFaceSize
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
if (faceResult.error) {
|
|
137
|
+
result.errors = result.errors || {};
|
|
138
|
+
result.errors.faceDetection = faceResult.error;
|
|
139
|
+
} else if (faceResult.faces && faceResult.faces.length > 0) {
|
|
140
|
+
result.containsFace = true;
|
|
141
|
+
result.faces = faceResult.faces;
|
|
142
|
+
}
|
|
143
|
+
} catch (error) {
|
|
144
|
+
result.errors = result.errors || {};
|
|
145
|
+
result.errors.faceDetection =
|
|
146
|
+
error instanceof Error ? error.message : 'Unknown error';
|
|
147
|
+
}
|
|
148
|
+
})()
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Text Recognition (Printed)
|
|
153
|
+
if (opts.detectPrintedText) {
|
|
154
|
+
promises.push(
|
|
155
|
+
(async () => {
|
|
156
|
+
try {
|
|
157
|
+
const textResult = await TextRecognitionModule.recognizeText(
|
|
158
|
+
validatedUri
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
if (textResult.error) {
|
|
162
|
+
result.errors = result.errors || {};
|
|
163
|
+
result.errors.textRecognition = textResult.error;
|
|
164
|
+
} else if (textResult.text && textResult.text.trim().length > 0) {
|
|
165
|
+
result.containsPrintedText = true;
|
|
166
|
+
result.printedText = textResult.text;
|
|
167
|
+
}
|
|
168
|
+
} catch (error) {
|
|
169
|
+
result.errors = result.errors || {};
|
|
170
|
+
result.errors.textRecognition =
|
|
171
|
+
error instanceof Error ? error.message : 'Unknown error';
|
|
172
|
+
}
|
|
173
|
+
})()
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Handwriting Recognition
|
|
178
|
+
if (opts.detectHandwrittenText) {
|
|
179
|
+
promises.push(
|
|
180
|
+
(async () => {
|
|
181
|
+
try {
|
|
182
|
+
const handwritingResult =
|
|
183
|
+
await HandwritingRecognitionModule.recognizeHandwriting(
|
|
184
|
+
validatedUri
|
|
185
|
+
);
|
|
186
|
+
|
|
187
|
+
if (handwritingResult.error) {
|
|
188
|
+
result.errors = result.errors || {};
|
|
189
|
+
result.errors.handwritingRecognition = handwritingResult.error;
|
|
190
|
+
} else if (
|
|
191
|
+
handwritingResult.text &&
|
|
192
|
+
handwritingResult.text.trim().length > 0
|
|
193
|
+
) {
|
|
194
|
+
result.containsHandwrittenText = true;
|
|
195
|
+
result.handwrittenText = handwritingResult.text;
|
|
196
|
+
}
|
|
197
|
+
} catch (error) {
|
|
198
|
+
result.errors = result.errors || {};
|
|
199
|
+
result.errors.handwritingRecognition =
|
|
200
|
+
error instanceof Error ? error.message : 'Unknown error';
|
|
201
|
+
}
|
|
202
|
+
})()
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Wait for all analyses to complete
|
|
207
|
+
await Promise.all(promises);
|
|
208
|
+
|
|
209
|
+
// If all enabled analyses failed, throw an error
|
|
210
|
+
const enabledCount = promises.length;
|
|
211
|
+
const errorCount = result.errors ? Object.keys(result.errors).length : 0;
|
|
212
|
+
|
|
213
|
+
if (enabledCount > 0 && errorCount === enabledCount) {
|
|
214
|
+
throw new Error(
|
|
215
|
+
`All image analyses failed: ${JSON.stringify(result.errors)}`
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return result;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Check if the library is properly installed and native modules are available
|
|
224
|
+
* @returns Promise resolving to true if all modules are available
|
|
225
|
+
*/
|
|
226
|
+
export async function isAvailable(): Promise<boolean> {
|
|
227
|
+
try {
|
|
228
|
+
// Simple check - all modules should be available
|
|
229
|
+
return !!(
|
|
230
|
+
FaceDetectionModule &&
|
|
231
|
+
TextRecognitionModule &&
|
|
232
|
+
HandwritingRecognitionModule
|
|
233
|
+
);
|
|
234
|
+
} catch {
|
|
235
|
+
return false;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// Default export for convenience
|
|
240
|
+
export default {
|
|
241
|
+
analyzeImage,
|
|
242
|
+
isAvailable,
|
|
243
|
+
};
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bounding box coordinates and dimensions
|
|
3
|
+
*/
|
|
4
|
+
export interface BoundingBox {
|
|
5
|
+
x: number;
|
|
6
|
+
y: number;
|
|
7
|
+
width: number;
|
|
8
|
+
height: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Face detection result with metadata
|
|
13
|
+
*/
|
|
14
|
+
export interface FaceData {
|
|
15
|
+
/** Bounding box of the detected face */
|
|
16
|
+
boundingBox: BoundingBox;
|
|
17
|
+
/** Probability that the face is smiling (0.0 to 1.0) */
|
|
18
|
+
smilingProbability?: number;
|
|
19
|
+
/** Probability that the left eye is open (0.0 to 1.0) */
|
|
20
|
+
leftEyeOpenProbability?: number;
|
|
21
|
+
/** Probability that the right eye is open (0.0 to 1.0) */
|
|
22
|
+
rightEyeOpenProbability?: number;
|
|
23
|
+
/** Head rotation around Y-axis (yaw) in degrees */
|
|
24
|
+
headEulerAngleY?: number;
|
|
25
|
+
/** Head rotation around Z-axis (roll) in degrees */
|
|
26
|
+
headEulerAngleZ?: number;
|
|
27
|
+
/** Tracking ID for video sequences */
|
|
28
|
+
trackingId?: number;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Complete analysis result from image intelligence
|
|
33
|
+
*/
|
|
34
|
+
export interface AnalysisResult {
|
|
35
|
+
/** True if at least one human face was detected */
|
|
36
|
+
containsFace: boolean;
|
|
37
|
+
/** True if printed text was detected */
|
|
38
|
+
containsPrintedText: boolean;
|
|
39
|
+
/** True if handwritten text was detected */
|
|
40
|
+
containsHandwrittenText: boolean;
|
|
41
|
+
/** Array of detected faces with metadata */
|
|
42
|
+
faces?: FaceData[];
|
|
43
|
+
/** Extracted printed text content */
|
|
44
|
+
printedText?: string;
|
|
45
|
+
/** Extracted handwritten text content */
|
|
46
|
+
handwrittenText?: string;
|
|
47
|
+
/** Error messages if any module failed (won't throw, for graceful degradation) */
|
|
48
|
+
errors?: {
|
|
49
|
+
faceDetection?: string;
|
|
50
|
+
textRecognition?: string;
|
|
51
|
+
handwritingRecognition?: string;
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Configuration options for image analysis
|
|
57
|
+
*/
|
|
58
|
+
export interface AnalysisOptions {
|
|
59
|
+
/** Enable face detection (default: true) */
|
|
60
|
+
detectFaces?: boolean;
|
|
61
|
+
/** Enable printed text recognition (default: true) */
|
|
62
|
+
detectPrintedText?: boolean;
|
|
63
|
+
/** Enable handwritten text recognition (default: true) */
|
|
64
|
+
detectHandwrittenText?: boolean;
|
|
65
|
+
/** Face detection performance mode: 'fast' or 'accurate' (default: 'fast') */
|
|
66
|
+
faceDetectionMode?: 'fast' | 'accurate';
|
|
67
|
+
/** Minimum face size relative to image (0.0 to 1.0, default: 0.1) */
|
|
68
|
+
minFaceSize?: number;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Internal face detection result from native module
|
|
73
|
+
* @internal
|
|
74
|
+
*/
|
|
75
|
+
export interface NativeFaceDetectionResult {
|
|
76
|
+
faces: FaceData[];
|
|
77
|
+
error?: string;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Internal text recognition result from native module
|
|
82
|
+
* @internal
|
|
83
|
+
*/
|
|
84
|
+
export interface NativeTextRecognitionResult {
|
|
85
|
+
text: string;
|
|
86
|
+
error?: string;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Internal handwriting recognition result from native module
|
|
91
|
+
* @internal
|
|
92
|
+
*/
|
|
93
|
+
export interface NativeHandwritingRecognitionResult {
|
|
94
|
+
text: string;
|
|
95
|
+
error?: string;
|
|
96
|
+
}
|