Skip to content

Commit c13fa3a

Browse files
update to v3.2.3000
1 parent 5a0499a commit c13fa3a

File tree

9 files changed

+172
-55
lines changed

9 files changed

+172
-55
lines changed

ScanDocument/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"dependencies": {
1313
"@react-navigation/native": "^7.1.9",
1414
"@react-navigation/native-stack": "^7.1.9",
15-
"dynamsoft-capture-vision-react-native": "^3.0.5200",
15+
"dynamsoft-capture-vision-react-native": "^3.2.3000",
1616
"react": "19.0.0",
1717
"react-native": "0.79.0",
1818
"react-native-fs": "^2.20.0",

ScanDocument/src/App.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,16 @@ import React, {useState} from 'react';
99
import {Button, StyleSheet, Text, View} from 'react-native';
1010
import {createNativeStackNavigator, NativeStackScreenProps} from '@react-navigation/native-stack';
1111
import {NavigationContainer} from '@react-navigation/native';
12-
import {ProcessedDocumentResult, ImageData, LicenseManager} from 'dynamsoft-capture-vision-react-native';
12+
import {Quadrilateral, ProcessedDocumentResult, ImageData, LicenseManager} from 'dynamsoft-capture-vision-react-native';
1313
import {Scanner} from './Scanner.tsx';
1414
import {Editor} from './Editor.tsx';
1515
import {NormalizedImage} from './NormalizedImage.tsx';
1616

1717
declare global {
1818
var originalImage: ImageData; //Used in Scanner.tsx and Editor.tsx
19-
var processedDocumentResult: ProcessedDocumentResult; //Used in Scanner.tsx and Editor.tsx
20-
var normalizedImage: ImageData; //Used in Editor.tsx and NormalizedImage.tsx
19+
var deskewedImage: ImageData; //Used in Editor.tsx and NormalizedImage.tsx
20+
var showingImage: ImageData; //Used in Editor.tsx and NormalizedImage.tsx
21+
var sourceDeskewQuad: Quadrilateral; //Used in Editor.tsx
2122
}
2223

2324
export type ScreenNames = ['Home', 'Scanner', 'Editor', 'NormalizedImage'];

ScanDocument/src/Editor.tsx

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {
44
EnumDrawingLayerId,
55
ImageData,
66
ImageEditorView,
7-
ImageManager,
7+
ImageProcessor,
88
} from 'dynamsoft-capture-vision-react-native';
99
import {StackNavigation} from './App.tsx';
1010

@@ -13,22 +13,14 @@ export function Editor({navigation}: StackNavigation) {
1313

1414
useEffect(() => {
1515
editorView.current!!.setOriginalImage(global.originalImage);
16-
editorView.current!!.setQuads(
17-
global.processedDocumentResult.detectedQuadResultItems?.map(item => item.location),
18-
EnumDrawingLayerId.DDN_LAYER_ID,
19-
);
20-
21-
return () => {
22-
if (global.originalImage && typeof global.originalImage.release === 'function') {
23-
global.originalImage.release();
24-
}
25-
};
16+
editorView.current!!.setQuads([global.sourceDeskewQuad], EnumDrawingLayerId.DDN_LAYER_ID);
2617
}, [editorView]);
2718

28-
const getSelectedQuadAndNormalize = async (): Promise<ImageData | null | undefined> => {
19+
const getSelectedQuadAndDeskew = async (): Promise<ImageData | null | undefined> => {
2920
const quad = await editorView.current!!.getSelectedQuad().catch(e => console.log(e));
3021
if (quad) {
31-
return new ImageManager().cropImage(global.originalImage, quad);
22+
global.sourceDeskewQuad = quad;
23+
return new ImageProcessor().cropAndDeskewImage(global.originalImage, quad);
3224
} else {
3325
console.log('Please select an item');
3426
return null;
@@ -39,12 +31,15 @@ export function Editor({navigation}: StackNavigation) {
3931
<ImageEditorView style={styles.fullScreen} ref={editorView}>
4032
<View style={styles.bottomView}>
4133
<Button
42-
title={'Normalize'}
34+
title={'Confirm'}
4335
onPress={async () => {
44-
const normalizedImage = await getSelectedQuadAndNormalize();
45-
if (normalizedImage) {
46-
global.normalizedImage = normalizedImage;
47-
navigation.navigate('NormalizedImage');
36+
const deskewedImage = await getSelectedQuadAndDeskew();
37+
if (deskewedImage) {
38+
if(global.deskewedImage) {
39+
global.deskewedImage.release();
40+
}
41+
global.deskewedImage = deskewedImage;
42+
navigation.pop(1);
4843
}
4944
}}
5045
/>
Lines changed: 138 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,148 @@
1-
import React, {useEffect} from 'react';
2-
import {Button, Image, Platform, StyleSheet, View} from 'react-native';
3-
import {ImageManager, imageDataToBase64} from 'dynamsoft-capture-vision-react-native';
4-
import {ExternalCachesDirectoryPath, TemporaryDirectoryPath} from 'react-native-fs';
1+
import React, {useCallback, useEffect, useState} from 'react';
2+
import {
3+
Alert,
4+
Image,
5+
Platform,
6+
StyleSheet,
7+
Text,
8+
TouchableOpacity,
9+
View,
10+
} from 'react-native';
11+
import {
12+
ImageIO,
13+
ImageProcessor,
14+
imageDataToBase64,
15+
} from 'dynamsoft-capture-vision-react-native';
16+
import {
17+
ExternalCachesDirectoryPath,
18+
TemporaryDirectoryPath,
19+
} from 'react-native-fs';
20+
import {StackNavigation} from './App.tsx';
21+
import {useFocusEffect} from '@react-navigation/native';
522

6-
export const NormalizedImage = () => {
7-
const base64Str = imageDataToBase64(global.normalizedImage);
23+
const ColourMode = {
24+
colour: 'colour',
25+
grayscale: 'grayscale',
26+
binary: 'binary',
27+
};
28+
29+
export const NormalizedImage = ({navigation}: StackNavigation) => {
30+
const [base64, setBase64] = useState('');
31+
32+
useFocusEffect(
33+
useCallback(() => {
34+
global.showingImage = global.deskewedImage;
35+
setBase64(imageDataToBase64(global.showingImage));
36+
}, []),
37+
);
838

939
useEffect(() => {
1040
return () => {
11-
if (global.normalizedImage && typeof global.normalizedImage.release === 'function') {
12-
global.normalizedImage.release();
13-
}
41+
global.originalImage?.release();
42+
global.deskewedImage?.release();
43+
global.showingImage?.release();
1444
};
1545
}, []);
16-
return <View style={{flex: 1}}>
17-
<Image source={{uri: 'data:image/png;base64,' + base64Str}} style={styles.fullScreen} resizeMode="contain"/>
18-
<Button title={'Save to file'} onPress={() => {
19-
const imageManager = new ImageManager();
20-
let savedPath = (Platform.OS === 'ios' ? TemporaryDirectoryPath : ExternalCachesDirectoryPath) + '/normalize.png';
21-
imageManager.saveToFile(global.normalizedImage, savedPath, true);
22-
// @ts-ignore
23-
window.alert('Has been saved to ' + savedPath);
24-
}}/>
25-
</View>;
46+
47+
const changeColourMode = (mode: string) => {
48+
if (global.showingImage && global.showingImage !== global.deskewedImage) {
49+
global.showingImage.release();
50+
}
51+
switch (mode) {
52+
case ColourMode.colour:
53+
global.showingImage = global.deskewedImage;
54+
break;
55+
case ColourMode.grayscale:
56+
global.showingImage = new ImageProcessor().convertToGray(
57+
global.deskewedImage,
58+
)!!;
59+
break;
60+
case ColourMode.binary:
61+
global.showingImage = new ImageProcessor().convertToBinaryLocal(
62+
global.deskewedImage,
63+
/*blockSize = */ 0,
64+
/*compensation = */ 10,
65+
/*invert = */ false,
66+
)!!;
67+
break;
68+
}
69+
setBase64(imageDataToBase64(global.showingImage));
70+
};
71+
72+
const onTabPress = (index: number) => {
73+
switch (index) {
74+
case 0: //'Back to Edit'
75+
navigation.navigate('Editor');
76+
break;
77+
case 1: //'Switch Colour'
78+
Alert.alert(
79+
'',
80+
'Select Colour Mode',
81+
[ColourMode.colour, ColourMode.grayscale, ColourMode.binary].map(
82+
mode => ({
83+
text: mode,
84+
onPress: () => changeColourMode(mode),
85+
}),
86+
),
87+
);
88+
break;
89+
case 2: //'Export'
90+
const imageIO = new ImageIO();
91+
let savedPath =
92+
(Platform.OS === 'ios'
93+
? TemporaryDirectoryPath
94+
: ExternalCachesDirectoryPath) + `/normalize_${Date.now()}.png`;
95+
imageIO.saveToFile(global.showingImage, savedPath, true);
96+
Alert.alert('Successfully saved', 'Has been saved to ' + savedPath);
97+
break;
98+
}
99+
};
100+
101+
return (
102+
<View style={styles.fullScreen}>
103+
<Image
104+
source={{uri: 'data:image/png;base64,' + base64}}
105+
style={styles.fullScreen}
106+
resizeMode="contain"
107+
/>
108+
<View style={styles.bottomBar}>
109+
{[
110+
{emoji: '✏️', label: 'Back to Edit'},
111+
{emoji: '🎨', label: 'Switch Colour'},
112+
{emoji: '💾', label: 'Export'},
113+
].map((item, index) => (
114+
<TouchableOpacity
115+
key={index}
116+
style={styles.tab}
117+
onPress={() => onTabPress(index)}>
118+
<Text style={styles.emoji}>{item.emoji}</Text>
119+
<Text style={styles.label}>{item.label}</Text>
120+
</TouchableOpacity>
121+
))}
122+
</View>
123+
</View>
124+
);
26125
};
27126

28127
const styles = StyleSheet.create({
29-
fullScreen: {flex: 0.9},
128+
fullScreen: {flex: 1},
129+
bottomBar: {
130+
flexDirection: 'row',
131+
justifyContent: 'space-around',
132+
alignItems: 'center',
133+
borderWidth: 1,
134+
paddingVertical: 10,
135+
},
136+
tab: {
137+
alignItems: 'center',
138+
flex: 1,
139+
},
140+
emoji: {
141+
fontSize: 24,
142+
},
143+
label: {
144+
fontSize: 12,
145+
marginTop: 4,
146+
color: '#333',
147+
},
30148
});

ScanDocument/src/Scanner.tsx

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ import {
66
CameraView,
77
CaptureVisionRouter,
88
EnumCapturedResultItemType,
9+
EnumCrossVerificationStatus,
910
EnumPresetTemplate,
1011
MultiFrameResultCrossFilter,
11-
EnumCrossVerificationStatus,
1212
} from 'dynamsoft-capture-vision-react-native';
1313
import {StackNavigation} from './App.tsx';
1414

@@ -37,35 +37,37 @@ export function Scanner({navigation}: StackNavigation): React.JSX.Element {
3737
camera.setCameraView(cameraView.current!!);
3838

3939
let filter = new MultiFrameResultCrossFilter();
40-
filter.enableResultCrossVerification(EnumCapturedResultItemType.CRIT_DETECTED_QUAD, true);
40+
filter.enableResultCrossVerification(EnumCapturedResultItemType.CRIT_DESKEWED_IMAGE, true);
4141
cvr.addFilter(filter);
4242

4343
let receiver = cvr.addResultReceiver({
4444
onProcessedDocumentResultReceived: result => {
4545
if (
46-
result.detectedQuadResultItems &&
47-
result.detectedQuadResultItems.length > 0 &&
46+
result.deskewedImageResultItems &&
47+
result.deskewedImageResultItems.length > 0 &&
4848
/*This means you can manually click the button to navigate to the next page,
4949
or navigate to the next page when the item's crossVerificationStatus is PASSED.*/
50-
(ifBtnClick.current || result.detectedQuadResultItems[0].crossVerificationStatus === EnumCrossVerificationStatus.CVS_PASSED)
50+
(ifBtnClick.current || result.deskewedImageResultItems[0].crossVerificationStatus === EnumCrossVerificationStatus.CVS_PASSED)
5151
) {
5252
ifBtnClick.current = false;
5353
/*Since the originalImage corresponding to originalImageHashId may be released after the callback ends,
5454
if you want to get the originalImage,
5555
you should call getOriginalImage(result.originalImageHashId) within the callback.*/
5656
global.originalImage = cvr.getIntermediateResultManager().getOriginalImage(result.originalImageHashId);
57-
global.processedDocumentResult = result;
57+
global.deskewedImage = result.deskewedImageResultItems[0].imageData;
58+
global.sourceDeskewQuad = result.deskewedImageResultItems[0].sourceDeskewQuad;
5859
if (global.originalImage.width > 0 && global.originalImage.height > 0) {
59-
navigation.navigate('Editor');
60+
navigation.navigate('NormalizedImage');
6061
}
6162
}
6263
},
6364
});
64-
cvr.startCapturing(EnumPresetTemplate.PT_DETECT_DOCUMENT_BOUNDARIES).catch(/*no-op*/);
65+
cvr.startCapturing(EnumPresetTemplate.PT_DETECT_AND_NORMALIZE_DOCUMENT).catch(/*no-op*/);
6566

6667
return () => {
6768
cvr.removeResultReceiver(receiver);
6869
cvr.stopCapturing().catch(/*no-op*/);
70+
camera.setCameraView(null);
6971
};
7072
}, [cvr, camera, cameraView, ifBtnClick, navigation]);
7173

ScanMRZ/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
"test": "jest"
1111
},
1212
"dependencies": {
13-
"dynamsoft-capture-vision-react-native": "^3.0.5200",
14-
"dynamsoft-mrz-scanner-bundle-react-native": "^3.0.5200",
13+
"dynamsoft-capture-vision-react-native": "^3.2.3000",
14+
"dynamsoft-mrz-scanner-bundle-react-native": "^3.2.3000",
1515
"react": "19.0.0",
1616
"react-native": "0.79.0"
1717
},

ScanVIN/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"test": "jest"
1111
},
1212
"dependencies": {
13-
"dynamsoft-capture-vision-react-native": "^3.0.5200",
13+
"dynamsoft-capture-vision-react-native": "^3.2.3000",
1414
"react": "19.0.0",
1515
"react-native": "0.79.0"
1616
},

ScanVIN/src/VINScanner.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export function ScannerView({onComplete}: ScannerViewProps) {
6262
} else if(result.items.length > 1) {
6363
for (let item of result.items) {
6464
//Information extracted from a barcode should have a higher priority
65-
if(item.targetROIDefName === 'roi-vin-barcode') {
65+
if(item.targetROIDefName?.includes('vin-barcode')) {
6666
parsedItem = item;
6767
}
6868
}
@@ -95,6 +95,7 @@ export function ScannerView({onComplete}: ScannerViewProps) {
9595
cvr.removeFilter(filter);
9696
cvr.stopCapturing();
9797
camera.close();
98+
camera.setCameraView(null);
9899
};
99100
}, [camera, cameraView, cvr, onComplete]);
100101

guide-scan-vin.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ export function Scanner() {
182182
} else if(result.items.length > 1) {
183183
for (let item of result.items) {
184184
//Information extracted from a barcode should have a higher priority
185-
if(item.targetROIDefName === 'roi-vin-barcode') {
185+
if(item.targetROIDefName?.includes('vin-barcode')) {
186186
parsedItem = item;
187187
}
188188
}

0 commit comments

Comments
 (0)