@trustchex/react-native-sdk 1.362.6 → 1.374.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/TrustchexSDK.podspec +3 -3
- package/android/build.gradle +3 -3
- package/android/src/main/java/com/trustchex/reactnativesdk/camera/TrustchexCameraView.kt +71 -17
- package/ios/Camera/TrustchexCameraView.swift +166 -119
- package/lib/module/Shared/Components/FaceCamera.js +1 -0
- package/lib/module/Shared/Components/IdentityDocumentCamera.js +344 -207
- package/lib/module/Shared/Components/QrCodeScannerCamera.js +1 -8
- package/lib/module/Shared/Libs/mrz.utils.js +202 -9
- package/lib/module/Translation/Resources/en.js +0 -4
- package/lib/module/Translation/Resources/tr.js +0 -4
- package/lib/module/version.js +1 -1
- package/lib/typescript/src/Shared/Components/FaceCamera.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/QrCodeScannerCamera.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Components/TrustchexCamera.d.ts +1 -0
- package/lib/typescript/src/Shared/Components/TrustchexCamera.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Libs/mrz.utils.d.ts +8 -0
- package/lib/typescript/src/Shared/Libs/mrz.utils.d.ts.map +1 -1
- package/lib/typescript/src/Translation/Resources/en.d.ts +0 -4
- package/lib/typescript/src/Translation/Resources/en.d.ts.map +1 -1
- package/lib/typescript/src/Translation/Resources/tr.d.ts +0 -4
- package/lib/typescript/src/Translation/Resources/tr.d.ts.map +1 -1
- package/lib/typescript/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/Shared/Components/FaceCamera.tsx +1 -0
- package/src/Shared/Components/IdentityDocumentCamera.tsx +443 -265
- package/src/Shared/Components/QrCodeScannerCamera.tsx +1 -9
- package/src/Shared/Components/TrustchexCamera.tsx +1 -0
- package/src/Shared/Libs/mrz.utils.ts +238 -26
- package/src/Translation/Resources/en.ts +0 -4
- package/src/Translation/Resources/tr.ts +0 -4
- package/src/version.ts +1 -1
|
@@ -20,7 +20,6 @@ import { useKeepAwake } from '../Libs/native-keep-awake.utils';
|
|
|
20
20
|
import { useIsFocused } from '@react-navigation/native';
|
|
21
21
|
import { useTranslation } from 'react-i18next';
|
|
22
22
|
import { debugLog, logError } from '../Libs/debug.utils';
|
|
23
|
-
import LottieView from 'lottie-react-native';
|
|
24
23
|
import StyledButton from './StyledButton';
|
|
25
24
|
import { useTheme } from '../Contexts/ThemeContext';
|
|
26
25
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
@@ -193,14 +192,7 @@ const QrCodeScannerCamera = ({
|
|
|
193
192
|
<View style={styles.leftZone} />
|
|
194
193
|
<View style={styles.rightZone} />
|
|
195
194
|
<View style={styles.bottomZone} />
|
|
196
|
-
<View style={styles.scanArea}
|
|
197
|
-
<LottieView
|
|
198
|
-
source={require('../../Shared/Animations/scanning.json')}
|
|
199
|
-
style={styles.animation}
|
|
200
|
-
loop={true}
|
|
201
|
-
autoPlay
|
|
202
|
-
/>
|
|
203
|
-
</View>
|
|
195
|
+
<View style={styles.scanArea} />
|
|
204
196
|
{onClose && (
|
|
205
197
|
<TouchableOpacity
|
|
206
198
|
onPress={onClose}
|
|
@@ -102,6 +102,7 @@ interface TrustchexCameraProps {
|
|
|
102
102
|
torchEnabled?: boolean;
|
|
103
103
|
enableFrameProcessing?: boolean;
|
|
104
104
|
targetFps?: number;
|
|
105
|
+
resolution?: string;
|
|
105
106
|
// ML Kit detection modes — processing runs natively, results arrive in Frame
|
|
106
107
|
enableFaceDetection?: boolean;
|
|
107
108
|
enableTextRecognition?: boolean;
|
|
@@ -29,6 +29,9 @@ const fixMRZ = (rawText: string): string => {
|
|
|
29
29
|
// Ensure uppercase immediately
|
|
30
30
|
rawText = rawText.toUpperCase();
|
|
31
31
|
|
|
32
|
+
// Apply OCR-B specific corrections early
|
|
33
|
+
rawText = applyOCRBCorrections(rawText);
|
|
34
|
+
|
|
32
35
|
const fillerChar = '<';
|
|
33
36
|
const mrzFormats = [
|
|
34
37
|
{ lines: 3, length: 30 }, // TD1
|
|
@@ -44,9 +47,21 @@ const fixMRZ = (rawText: string): string => {
|
|
|
44
47
|
cleanedText = cleanedText.replace(/^1</gm, 'I<');
|
|
45
48
|
cleanedText = cleanedText.replace(/\n1</g, '\nI<');
|
|
46
49
|
|
|
50
|
+
// Fix lowercase letters that should be uppercase (common OCR error)
|
|
51
|
+
cleanedText = cleanedText
|
|
52
|
+
.split('\n')
|
|
53
|
+
.map((line) => {
|
|
54
|
+
// Only uppercase if line contains fillers (indicates MRZ line)
|
|
55
|
+
if (line.includes('<')) {
|
|
56
|
+
return line.toUpperCase();
|
|
57
|
+
}
|
|
58
|
+
return line;
|
|
59
|
+
})
|
|
60
|
+
.join('\n');
|
|
61
|
+
|
|
47
62
|
// Conservative OCR error corrections - only fix clear filler character errors
|
|
48
63
|
// Don't touch valid digit sequences!
|
|
49
|
-
|
|
64
|
+
|
|
50
65
|
// Pattern 1: TD1 Line 2 filler area - After TUR, convert all K to < before check digit
|
|
51
66
|
// Structure: ...TUR<<<<<<<<<<<<8 (11 fillers + 1 check digit)
|
|
52
67
|
// OCR often reads: TUR<<<KKKK<<8 or TURK<<KK<<<8
|
|
@@ -54,40 +69,62 @@ const fixMRZ = (rawText: string): string => {
|
|
|
54
69
|
const fillerPart = match.substring(3, match.length - 1).replace(/K/g, '<');
|
|
55
70
|
return 'TUR' + fillerPart + checkDigit;
|
|
56
71
|
});
|
|
57
|
-
|
|
72
|
+
|
|
58
73
|
// Pattern 2: Convert K at the very end of a line before check digit
|
|
59
74
|
// e.g., "<<<K8" → "<<<8" (K is misread <, 8 is check digit)
|
|
60
75
|
cleanedText = cleanedText.replace(/K(\d)$/gm, '<$1');
|
|
61
|
-
|
|
76
|
+
|
|
62
77
|
// Pattern 3: Convert K when surrounded by fillers only
|
|
63
78
|
// e.g., "<<K<<" → "<<<<<" (clearly a filler position)
|
|
64
79
|
cleanedText = cleanedText.replace(/(<+)K(<+)/g, '$1<$2');
|
|
65
|
-
|
|
80
|
+
|
|
66
81
|
// Pattern 4: Fix trailing filler area corruption at line end
|
|
67
82
|
// e.g., "TUR<<<<<KK" → "TUR<<<<<<<" (only at end after clear filler sequence)
|
|
68
83
|
cleanedText = cleanedText.replace(/(<{5,})[KGB]+$/gm, (match, fillers) => {
|
|
69
84
|
return fillers.padEnd(match.length, '<');
|
|
70
85
|
});
|
|
71
86
|
|
|
87
|
+
// Pattern 5: Fix common OCR misreadings in filler areas
|
|
88
|
+
// Convert non-alphanumeric chars in filler areas to '<' (but not digits/letters in content areas)
|
|
89
|
+
cleanedText = cleanedText
|
|
90
|
+
.split('\n')
|
|
91
|
+
.map((line) => {
|
|
92
|
+
// If line has fillers, likely MRZ - safe to convert uncommon chars near fillers
|
|
93
|
+
if (!line.includes('<')) return line;
|
|
94
|
+
|
|
95
|
+
// Replace '.' ',' '-' with fillers in MRZ lines (OCR noise)
|
|
96
|
+
line = line.replace(/[.,\-~`^]/g, '<');
|
|
97
|
+
|
|
98
|
+
// Replace lowercase o/i/l with uppercase or filler depending on context
|
|
99
|
+
line = line.replace(/o(?=[A-Z<]|[A-Z<]o)/g, 'O'); // lowercase o surrounded by uppercase
|
|
100
|
+
line = line.replace(/i(?=[A-Z<]|[A-Z<]i)/g, 'I'); // lowercase i surrounded by uppercase
|
|
101
|
+
line = line.replace(/l(?=[A-Z<0-9])/g, 'L'); // lowercase l before uppercase or digit
|
|
102
|
+
line = line.replace(/l$/g, '<'); // lowercase l at line end is filler
|
|
103
|
+
|
|
104
|
+
return line;
|
|
105
|
+
})
|
|
106
|
+
.join('\n');
|
|
107
|
+
|
|
72
108
|
// Split into lines and filter for MRZ-like content
|
|
73
109
|
// MRZ lines must start with I< or contain long sequences of < and alphanumeric chars
|
|
74
110
|
const lines = cleanedText
|
|
75
111
|
.split('\n')
|
|
76
|
-
.map(line => line.trim())
|
|
77
|
-
.filter(line => {
|
|
112
|
+
.map((line) => line.trim())
|
|
113
|
+
.filter((line) => {
|
|
78
114
|
// Must contain filler characters
|
|
79
115
|
if (!/<+/.test(line)) return false;
|
|
80
|
-
|
|
116
|
+
|
|
81
117
|
// Prioritize lines starting with I< (document code)
|
|
82
118
|
if (line.startsWith('I<')) return true;
|
|
83
|
-
|
|
119
|
+
|
|
84
120
|
// Or lines with numbers and fillers (second line of TD1: birth date, expiry, etc.)
|
|
85
121
|
if (/\d{5,}/.test(line) && /<{3,}/.test(line)) return true;
|
|
86
|
-
|
|
122
|
+
|
|
87
123
|
// Or lines that look like name fields (third line of TD1: surname, given names)
|
|
88
124
|
// Accept shorter lines (min 10 chars) since OCR often truncates the third line
|
|
89
|
-
if (line.length >= 10 && /^[A-Z<]+$/.test(line) && /<{2,}/.test(line))
|
|
90
|
-
|
|
125
|
+
if (line.length >= 10 && /^[A-Z<]+$/.test(line) && /<{2,}/.test(line))
|
|
126
|
+
return true;
|
|
127
|
+
|
|
91
128
|
return false;
|
|
92
129
|
});
|
|
93
130
|
|
|
@@ -100,7 +137,7 @@ const fixMRZ = (rawText: string): string => {
|
|
|
100
137
|
for (const format of mrzFormats) {
|
|
101
138
|
const expectedLen = format.length;
|
|
102
139
|
// Check if all lines are within acceptable length
|
|
103
|
-
if (lines.every(line => line.length <= expectedLen + 5)) {
|
|
140
|
+
if (lines.every((line) => line.length <= expectedLen + 5)) {
|
|
104
141
|
detectedFormat = format;
|
|
105
142
|
break;
|
|
106
143
|
}
|
|
@@ -141,20 +178,127 @@ const fixMRZ = (rawText: string): string => {
|
|
|
141
178
|
|
|
142
179
|
const AMBIGUOUS_CHAR_MAP: Record<string, string[]> = {
|
|
143
180
|
'0': ['O', 'Q', 'D'],
|
|
144
|
-
O: ['0', 'Q', 'D'],
|
|
145
|
-
Q: ['0', 'O', 'D'],
|
|
146
|
-
D: ['0', 'O', 'Q'],
|
|
181
|
+
'O': ['0', 'Q', 'D'],
|
|
182
|
+
'Q': ['0', 'O', 'D'],
|
|
183
|
+
'D': ['0', 'O', 'Q'],
|
|
147
184
|
'1': ['I', 'L'],
|
|
148
|
-
I: ['1', 'L'],
|
|
149
|
-
L: ['1', 'I'],
|
|
185
|
+
'I': ['1', 'L'],
|
|
186
|
+
'L': ['1', 'I'],
|
|
150
187
|
'2': ['Z'],
|
|
151
|
-
Z: ['2'],
|
|
188
|
+
'Z': ['2'],
|
|
152
189
|
'5': ['S'],
|
|
153
|
-
S: ['5'],
|
|
190
|
+
'S': ['5'],
|
|
154
191
|
'6': ['G'],
|
|
155
|
-
G: ['6'],
|
|
192
|
+
'G': ['6'],
|
|
156
193
|
'8': ['B'],
|
|
157
|
-
B: ['8'],
|
|
194
|
+
'B': ['8'],
|
|
195
|
+
'9': ['g'],
|
|
196
|
+
'g': ['9'],
|
|
197
|
+
'4': ['A'],
|
|
198
|
+
'A': ['4'],
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* OCR-B specific character corrections (used for MRZ on passports/IDs)
|
|
203
|
+
* OCR-B is monospaced and has specific glyph patterns that differ from other fonts
|
|
204
|
+
* Common OCR-B misreadings in document scanning context
|
|
205
|
+
*/
|
|
206
|
+
const OCRB_SPECIFIC_MAP: Record<string, string> = {
|
|
207
|
+
// Glyph confusion in OCR-B (low contrast scanning)
|
|
208
|
+
Ø: '0', // Slashed zero sometimes appears as capital O with slash
|
|
209
|
+
ø: '0', // Lowercase variant
|
|
210
|
+
œ: 'O', // Ligature
|
|
211
|
+
|
|
212
|
+
// Common in monospace OCR
|
|
213
|
+
Ι: 'I', // Greek capital iota confused with I
|
|
214
|
+
ι: 'i', // Greek lowercase iota
|
|
215
|
+
l: 'I', // Lowercase L as I (common with serif OCR-B variants)
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Validates OCR-B specific character patterns
|
|
220
|
+
* @param text Text to validate
|
|
221
|
+
* @returns True if text matches OCR-B patterns reasonably well
|
|
222
|
+
*/
|
|
223
|
+
const isValidOCRBPattern = (text: string): boolean => {
|
|
224
|
+
const lines = text.split('\n').filter((l) => l.trim());
|
|
225
|
+
|
|
226
|
+
// OCR-B MRZ validation
|
|
227
|
+
for (const line of lines) {
|
|
228
|
+
if (!/<+/.test(line)) continue; // Skip non-MRZ lines
|
|
229
|
+
|
|
230
|
+
// OCR-B characteristics check:
|
|
231
|
+
// 1. Monospaced - all lines should have similar length (±2 chars)
|
|
232
|
+
// 2. Specific filler pattern - at least 3 consecutive fillers
|
|
233
|
+
// 3. Mixed digits and letters - checkdigits, names, dates
|
|
234
|
+
|
|
235
|
+
const fillerGroups = (line.match(/<+/g) || []).length;
|
|
236
|
+
const letterDigitSegments = (line.match(/[A-Z0-9]+/g) || []).length;
|
|
237
|
+
|
|
238
|
+
// Valid OCR-B should have 2-4 filler groups and 2-4 alphanumeric segments
|
|
239
|
+
if (fillerGroups < 1 || letterDigitSegments < 1) return false;
|
|
240
|
+
if (fillerGroups > 6 || letterDigitSegments > 6) return false; // Too fragmented
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return true;
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Applies OCR-B specific corrections to raw OCR text
|
|
248
|
+
* @param text Raw OCR text
|
|
249
|
+
* @returns Text with OCR-B corrections applied
|
|
250
|
+
*/
|
|
251
|
+
const applyOCRBCorrections = (text: string): string => {
|
|
252
|
+
let corrected = text;
|
|
253
|
+
|
|
254
|
+
// Replace OCR-B specific misreadings
|
|
255
|
+
for (const [wrong, correct] of Object.entries(OCRB_SPECIFIC_MAP)) {
|
|
256
|
+
corrected = corrected.replace(new RegExp(wrong, 'g'), correct);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Apply line-by-line OCR-B specific logic
|
|
260
|
+
corrected = corrected
|
|
261
|
+
.split('\n')
|
|
262
|
+
.map((line) => {
|
|
263
|
+
if (!line.includes('<')) return line; // Not an MRZ line
|
|
264
|
+
|
|
265
|
+
// In OCR-B MRZ, digit positions are strictly defined
|
|
266
|
+
// If we see obvious letter/digit confusion in digit areas, correct it
|
|
267
|
+
|
|
268
|
+
// Document number area: should be digits or fillers
|
|
269
|
+
// Pattern: after 2nd filler block, expect <8-9 digit chars> before next filler block
|
|
270
|
+
line = line.replace(
|
|
271
|
+
/([<]+)([A-Z])([0-9]{1,2})([<]+)/g,
|
|
272
|
+
(match, filler1, letter, digits, filler2) => {
|
|
273
|
+
// If single letter between fillers and digits, likely OCR error
|
|
274
|
+
if (letter === 'O') return `${filler1}0${digits}${filler2}`; // O -> 0
|
|
275
|
+
if (letter === 'I' || letter === 'L')
|
|
276
|
+
return `${filler1}1${digits}${filler2}`; // I/L -> 1
|
|
277
|
+
return match;
|
|
278
|
+
}
|
|
279
|
+
);
|
|
280
|
+
|
|
281
|
+
// Check digit areas (end of lines): should be single digit, not letter
|
|
282
|
+
line = line.replace(
|
|
283
|
+
/([<]+)([A-Z])(\d)?$/gm,
|
|
284
|
+
(match, fillers, letter, maybeDigit) => {
|
|
285
|
+
// If a letter appears before line end in check digit area, convert
|
|
286
|
+
if (letter === 'O') return `${fillers}0${maybeDigit || ''}`;
|
|
287
|
+
if (letter === 'I' || letter === 'L')
|
|
288
|
+
return `${fillers}1${maybeDigit || ''}`;
|
|
289
|
+
if (letter === 'S') return `${fillers}5${maybeDigit || ''}`;
|
|
290
|
+
if (letter === 'Z') return `${fillers}2${maybeDigit || ''}`;
|
|
291
|
+
if (letter === 'B') return `${fillers}8${maybeDigit || ''}`;
|
|
292
|
+
if (letter === 'G') return `${fillers}6${maybeDigit || ''}`;
|
|
293
|
+
return match;
|
|
294
|
+
}
|
|
295
|
+
);
|
|
296
|
+
|
|
297
|
+
return line;
|
|
298
|
+
})
|
|
299
|
+
.join('\n');
|
|
300
|
+
|
|
301
|
+
return corrected;
|
|
158
302
|
};
|
|
159
303
|
|
|
160
304
|
const generateAmbiguousVariants = (
|
|
@@ -182,7 +326,7 @@ const generateAmbiguousVariants = (
|
|
|
182
326
|
|
|
183
327
|
for (const replacement of replacements) {
|
|
184
328
|
if (replacement === entryChar) continue;
|
|
185
|
-
if (entries.length >= maxVariants) return entries.map(e => e.text);
|
|
329
|
+
if (entries.length >= maxVariants) return entries.map((e) => e.text);
|
|
186
330
|
|
|
187
331
|
const newText =
|
|
188
332
|
entry.text.slice(0, i) + replacement + entry.text.slice(i + 1);
|
|
@@ -194,7 +338,7 @@ const generateAmbiguousVariants = (
|
|
|
194
338
|
}
|
|
195
339
|
}
|
|
196
340
|
|
|
197
|
-
return entries.map(e => e.text);
|
|
341
|
+
return entries.map((e) => e.text);
|
|
198
342
|
};
|
|
199
343
|
|
|
200
344
|
/**
|
|
@@ -277,12 +421,76 @@ const validateMRZ = (
|
|
|
277
421
|
* @param mrzText Raw OCR text
|
|
278
422
|
* @returns Validation result with parsed fields
|
|
279
423
|
*/
|
|
280
|
-
const validateMRZWithCorrections = (
|
|
281
|
-
mrzText: string
|
|
282
|
-
): MRZValidationResult => {
|
|
424
|
+
const validateMRZWithCorrections = (mrzText: string): MRZValidationResult => {
|
|
283
425
|
return validateMRZ(mrzText, true);
|
|
284
426
|
};
|
|
285
427
|
|
|
428
|
+
/**
|
|
429
|
+
* Calculates quality score for recognized MRZ text (0-100)
|
|
430
|
+
* Higher score = higher confidence in the OCR result
|
|
431
|
+
* @param mrzText Recognized MRZ text
|
|
432
|
+
* @returns Quality score 0-100
|
|
433
|
+
*/
|
|
434
|
+
const calculateMRZQualityScore = (mrzText: string): number => {
|
|
435
|
+
if (!mrzText) return 0;
|
|
436
|
+
|
|
437
|
+
let score = 100;
|
|
438
|
+
const lines = mrzText.split('\n').filter((l) => l.trim());
|
|
439
|
+
|
|
440
|
+
// Penalty for incomplete lines
|
|
441
|
+
if (lines.length < 2) score -= 40;
|
|
442
|
+
if (lines.some((l) => l.length < 30)) score -= 20;
|
|
443
|
+
|
|
444
|
+
for (const line of lines) {
|
|
445
|
+
// Count suspicious patterns that indicate OCR errors
|
|
446
|
+
const fillerCount = (line.match(/</g) || []).length;
|
|
447
|
+
const digitCount = (line.match(/\d/g) || []).length;
|
|
448
|
+
const letterCount = (line.match(/[A-Z]/g) || []).length;
|
|
449
|
+
const suspiciousCount = (line.match(/[KGB]{2,}|[0O]{2,}/g) || []).length;
|
|
450
|
+
|
|
451
|
+
// Penalize if too many suspicious patterns
|
|
452
|
+
if (suspiciousCount > 0) score -= suspiciousCount * 5;
|
|
453
|
+
|
|
454
|
+
// Penalize if ratio of fillers seems wrong (should be 40-60% for most lines)
|
|
455
|
+
const fillerRatio = fillerCount / line.length;
|
|
456
|
+
if (fillerRatio < 0.3 || fillerRatio > 0.7) score -= 10;
|
|
457
|
+
|
|
458
|
+
// Penalize if no digits where expected (birth date, expiry date, check digits)
|
|
459
|
+
if (letterCount > digitCount) {
|
|
460
|
+
// Some lines should have mostly digits (date lines)
|
|
461
|
+
if (line.match(/\d{5,6}/)) {
|
|
462
|
+
// Has valid date pattern, ok
|
|
463
|
+
} else if (line.length > 30 && digitCount === 0) {
|
|
464
|
+
score -= 15;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
// Apply consistency bonus if lines have similar length
|
|
470
|
+
const lengths = lines.map((l) => l.length);
|
|
471
|
+
const avgLength = lengths.reduce((a, b) => a + b, 0) / lines.length;
|
|
472
|
+
const variance =
|
|
473
|
+
lengths.reduce((sum, len) => sum + Math.abs(len - avgLength), 0) /
|
|
474
|
+
lines.length;
|
|
475
|
+
if (variance < 5) score += 10;
|
|
476
|
+
|
|
477
|
+
return Math.max(0, Math.min(100, score));
|
|
478
|
+
};
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* Validates MRZ quality and returns confidence level
|
|
482
|
+
* @param mrzText Raw or fixed MRZ text
|
|
483
|
+
* @returns Object with quality score and confidence level
|
|
484
|
+
*/
|
|
485
|
+
const assessMRZQuality = (mrzText: string) => {
|
|
486
|
+
const score = calculateMRZQualityScore(mrzText);
|
|
487
|
+
return {
|
|
488
|
+
score,
|
|
489
|
+
confidence: score >= 80 ? 'high' : score >= 60 ? 'medium' : 'low',
|
|
490
|
+
reliable: score >= 70,
|
|
491
|
+
};
|
|
492
|
+
};
|
|
493
|
+
|
|
286
494
|
/**
|
|
287
495
|
* Converts an MRZ date string to an ISO date string.
|
|
288
496
|
* @param mrzDate The MRZ date string to convert (YYMMDD format)
|
|
@@ -308,5 +516,9 @@ export default {
|
|
|
308
516
|
fixMRZ,
|
|
309
517
|
validateMRZ,
|
|
310
518
|
validateMRZWithCorrections,
|
|
519
|
+
calculateMRZQualityScore,
|
|
520
|
+
assessMRZQuality,
|
|
521
|
+
isValidOCRBPattern,
|
|
522
|
+
applyOCRBCorrections,
|
|
311
523
|
convertMRZDateToISODate,
|
|
312
524
|
};
|
|
@@ -131,10 +131,6 @@ export default {
|
|
|
131
131
|
'identityDocumentCamera.alignIDBackSide':
|
|
132
132
|
'Align the back side of your ID card',
|
|
133
133
|
'identityDocumentCamera.scanCompleted': 'Scan completed!',
|
|
134
|
-
'identityDocumentCamera.frontSideScanned': 'Front side scanned!',
|
|
135
|
-
'identityDocumentCamera.passportScanned': 'Passport scanned!',
|
|
136
|
-
'identityDocumentCamera.backSideScanned': 'Back side scanned!',
|
|
137
|
-
'identityDocumentCamera.hologramVerified': 'Hologram verified!',
|
|
138
134
|
'identityDocumentCamera.searchingDocument':
|
|
139
135
|
'Position document within the frame',
|
|
140
136
|
'identityDocumentCamera.faceDetected': 'Keep device steady...',
|
|
@@ -132,10 +132,6 @@ export default {
|
|
|
132
132
|
'identityDocumentCamera.alignIDBackSide':
|
|
133
133
|
'Kimlik kartınızın arka yüzünü hizalayın',
|
|
134
134
|
'identityDocumentCamera.scanCompleted': 'Tarama tamamlandı!',
|
|
135
|
-
'identityDocumentCamera.frontSideScanned': 'Ön yüz tarandı!',
|
|
136
|
-
'identityDocumentCamera.passportScanned': 'Pasaport tarandı!',
|
|
137
|
-
'identityDocumentCamera.backSideScanned': 'Arka yüz tarandı!',
|
|
138
|
-
'identityDocumentCamera.hologramVerified': 'Hologram doğrulandı!',
|
|
139
135
|
'identityDocumentCamera.searchingDocument':
|
|
140
136
|
'Belgeyi çerçeve içine yerleştirin',
|
|
141
137
|
'identityDocumentCamera.faceDetected': 'Cihazı sabit tutun...',
|
package/src/version.ts
CHANGED