react-native-rectangle-doc-scanner 3.110.0 → 3.111.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/dist/FullDocScanner.js +20 -68
- package/package.json +1 -1
- package/src/FullDocScanner.tsx +25 -94
package/dist/FullDocScanner.js
CHANGED
|
@@ -44,24 +44,15 @@ const react_native_image_crop_picker_1 = __importDefault(require("react-native-i
|
|
|
44
44
|
const react_native_fs_1 = __importDefault(require("react-native-fs"));
|
|
45
45
|
const DocScanner_1 = require("./DocScanner");
|
|
46
46
|
let ImageManipulator = null;
|
|
47
|
-
let ImageRotate = null;
|
|
48
47
|
try {
|
|
49
48
|
ImageManipulator = require('expo-image-manipulator');
|
|
50
49
|
}
|
|
51
50
|
catch (error) {
|
|
52
|
-
console.warn('[FullDocScanner] expo-image-manipulator module unavailable.
|
|
53
|
-
}
|
|
54
|
-
try {
|
|
55
|
-
const rotateModule = require('react-native-image-rotate');
|
|
56
|
-
ImageRotate = (rotateModule?.default ?? rotateModule);
|
|
57
|
-
}
|
|
58
|
-
catch (error) {
|
|
59
|
-
console.warn('[FullDocScanner] react-native-image-rotate module unavailable. Image rotation fallback disabled.', error);
|
|
51
|
+
console.warn('[FullDocScanner] expo-image-manipulator module unavailable.', error);
|
|
60
52
|
}
|
|
61
53
|
let expoManipulatorUnavailable = false;
|
|
62
54
|
const isExpoImageManipulatorAvailable = () => !!ImageManipulator?.manipulateAsync && !expoManipulatorUnavailable;
|
|
63
|
-
const
|
|
64
|
-
const isImageRotationSupported = () => isExpoImageManipulatorAvailable() || isImageRotateAvailable;
|
|
55
|
+
const isImageRotationSupported = () => isExpoImageManipulatorAvailable();
|
|
65
56
|
const stripFileUri = (value) => value.replace(/^file:\/\//, '');
|
|
66
57
|
const ensureFileUri = (value) => (value.startsWith('file://') ? value : `file://${value}`);
|
|
67
58
|
const CROPPER_TIMEOUT_MS = 8000;
|
|
@@ -363,22 +354,6 @@ const FullDocScanner = ({ onResult, onClose, detectionConfig, overlayColor = '#3
|
|
|
363
354
|
const handleFlashToggle = (0, react_1.useCallback)(() => {
|
|
364
355
|
setFlashEnabled(prev => !prev);
|
|
365
356
|
}, []);
|
|
366
|
-
const rotateImageWithFallback = (0, react_1.useCallback)((uri, angle) => {
|
|
367
|
-
return new Promise((resolve, reject) => {
|
|
368
|
-
if (!ImageRotate?.rotateImage) {
|
|
369
|
-
reject(new Error('react-native-image-rotate unavailable'));
|
|
370
|
-
return;
|
|
371
|
-
}
|
|
372
|
-
ImageRotate.rotateImage(uri, angle, (rotatedUri) => resolve(rotatedUri), (error) => {
|
|
373
|
-
const message = typeof error === 'string'
|
|
374
|
-
? error
|
|
375
|
-
: error && typeof error === 'object' && 'message' in error
|
|
376
|
-
? String(error.message)
|
|
377
|
-
: 'Unknown rotation error';
|
|
378
|
-
reject(new Error(message));
|
|
379
|
-
});
|
|
380
|
-
});
|
|
381
|
-
}, []);
|
|
382
357
|
const handleRotateImage = (0, react_1.useCallback)((degrees) => {
|
|
383
358
|
if (!isImageRotationSupported()) {
|
|
384
359
|
console.warn('[FullDocScanner] Image rotation requested but no rotation module is available.');
|
|
@@ -457,47 +432,24 @@ const FullDocScanner = ({ onResult, onClose, detectionConfig, overlayColor = '#3
|
|
|
457
432
|
}
|
|
458
433
|
}
|
|
459
434
|
}
|
|
460
|
-
//
|
|
461
|
-
|
|
462
|
-
console.log('[FullDocScanner] Using react-native-image-rotate for rotation');
|
|
463
|
-
const sourceUri = ensureFileUri(croppedImageData.path);
|
|
464
|
-
try {
|
|
465
|
-
const rotatedUri = await rotateImageWithFallback(sourceUri, rotationNormalized);
|
|
466
|
-
console.log('[FullDocScanner] Image rotated via react-native-image-rotate:', rotatedUri);
|
|
467
|
-
// rotatedUri를 파일로 저장하고 base64 생성
|
|
468
|
-
const destinationPath = `${react_native_fs_1.default.CachesDirectoryPath}/rotated_img_${Date.now()}.jpeg`;
|
|
469
|
-
// rotatedUri는 이미 file://로 시작하므로 stripFileUri로 정리
|
|
470
|
-
const cleanRotatedUri = stripFileUri(rotatedUri);
|
|
471
|
-
// 파일 복사
|
|
472
|
-
await react_native_fs_1.default.copyFile(cleanRotatedUri, destinationPath);
|
|
473
|
-
console.log('[FullDocScanner] Copied rotated file to:', destinationPath);
|
|
474
|
-
// Base64 생성
|
|
475
|
-
const base64Data = await react_native_fs_1.default.readFile(destinationPath, 'base64');
|
|
476
|
-
console.log('[FullDocScanner] Got result:', {
|
|
477
|
-
path: destinationPath,
|
|
478
|
-
hasBase64: true,
|
|
479
|
-
base64Length: base64Data.length,
|
|
480
|
-
});
|
|
481
|
-
onResult({
|
|
482
|
-
path: destinationPath,
|
|
483
|
-
base64: base64Data,
|
|
484
|
-
});
|
|
485
|
-
setProcessing(false);
|
|
486
|
-
return;
|
|
487
|
-
}
|
|
488
|
-
catch (rotateError) {
|
|
489
|
-
console.error('[FullDocScanner] react-native-image-rotate error:', rotateError);
|
|
490
|
-
throw rotateError;
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
// 회전 불가능한 경우 경고 후 원본 반환
|
|
494
|
-
console.warn('[FullDocScanner] Rotation requested but no supported rotation module is available. Returning original image.');
|
|
495
|
-
react_native_1.Alert.alert('알림', '이미지 회전 기능을 사용할 수 없습니다. 원본 이미지를 사용합니다.');
|
|
496
|
-
onResult({
|
|
497
|
-
path: croppedImageData.path,
|
|
498
|
-
base64: croppedImageData.base64,
|
|
499
|
-
});
|
|
435
|
+
// expo-image-manipulator를 사용할 수 없는 경우 에러 처리
|
|
436
|
+
console.error('[FullDocScanner] Rotation requested but expo-image-manipulator is not available.');
|
|
500
437
|
setProcessing(false);
|
|
438
|
+
react_native_1.Alert.alert('회전 불가', 'expo-image-manipulator가 설치되지 않아 이미지 회전을 수행할 수 없습니다.\n\n패키지를 설치해주세요:\nnpm install expo-image-manipulator', [
|
|
439
|
+
{
|
|
440
|
+
text: '원본 사용',
|
|
441
|
+
onPress: () => {
|
|
442
|
+
onResult({
|
|
443
|
+
path: croppedImageData.path,
|
|
444
|
+
base64: croppedImageData.base64,
|
|
445
|
+
});
|
|
446
|
+
},
|
|
447
|
+
},
|
|
448
|
+
{
|
|
449
|
+
text: '취소',
|
|
450
|
+
style: 'cancel',
|
|
451
|
+
},
|
|
452
|
+
]);
|
|
501
453
|
}
|
|
502
454
|
catch (error) {
|
|
503
455
|
console.error('[FullDocScanner] Image rotation error on confirm:', error);
|
|
@@ -510,7 +462,7 @@ const FullDocScanner = ({ onResult, onClose, detectionConfig, overlayColor = '#3
|
|
|
510
462
|
base64: croppedImageData.base64,
|
|
511
463
|
});
|
|
512
464
|
}
|
|
513
|
-
}, [croppedImageData, rotationDegrees, onResult
|
|
465
|
+
}, [croppedImageData, rotationDegrees, onResult]);
|
|
514
466
|
const handleRetake = (0, react_1.useCallback)(() => {
|
|
515
467
|
console.log('[FullDocScanner] Retake - clearing cropped image and resetting scanner');
|
|
516
468
|
setCroppedImageData(null);
|
package/package.json
CHANGED
package/src/FullDocScanner.tsx
CHANGED
|
@@ -22,33 +22,14 @@ import type {
|
|
|
22
22
|
} from './DocScanner';
|
|
23
23
|
|
|
24
24
|
type ImageManipulatorModule = typeof import('expo-image-manipulator');
|
|
25
|
-
type ImageRotateModule = {
|
|
26
|
-
rotateImage: (
|
|
27
|
-
uri: string,
|
|
28
|
-
angle: number,
|
|
29
|
-
onSuccess: (uri: string) => void,
|
|
30
|
-
onError: (error: unknown) => void,
|
|
31
|
-
) => void;
|
|
32
|
-
} | null;
|
|
33
25
|
|
|
34
26
|
let ImageManipulator: ImageManipulatorModule | null = null;
|
|
35
|
-
let ImageRotate: ImageRotateModule = null;
|
|
36
27
|
|
|
37
28
|
try {
|
|
38
29
|
ImageManipulator = require('expo-image-manipulator') as ImageManipulatorModule;
|
|
39
30
|
} catch (error) {
|
|
40
31
|
console.warn(
|
|
41
|
-
'[FullDocScanner] expo-image-manipulator module unavailable.
|
|
42
|
-
error,
|
|
43
|
-
);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
try {
|
|
47
|
-
const rotateModule = require('react-native-image-rotate');
|
|
48
|
-
ImageRotate = (rotateModule?.default ?? rotateModule) as ImageRotateModule;
|
|
49
|
-
} catch (error) {
|
|
50
|
-
console.warn(
|
|
51
|
-
'[FullDocScanner] react-native-image-rotate module unavailable. Image rotation fallback disabled.',
|
|
32
|
+
'[FullDocScanner] expo-image-manipulator module unavailable.',
|
|
52
33
|
error,
|
|
53
34
|
);
|
|
54
35
|
}
|
|
@@ -56,8 +37,7 @@ try {
|
|
|
56
37
|
let expoManipulatorUnavailable = false;
|
|
57
38
|
const isExpoImageManipulatorAvailable = () =>
|
|
58
39
|
!!ImageManipulator?.manipulateAsync && !expoManipulatorUnavailable;
|
|
59
|
-
const
|
|
60
|
-
const isImageRotationSupported = () => isExpoImageManipulatorAvailable() || isImageRotateAvailable;
|
|
40
|
+
const isImageRotationSupported = () => isExpoImageManipulatorAvailable();
|
|
61
41
|
|
|
62
42
|
const stripFileUri = (value: string) => value.replace(/^file:\/\//, '');
|
|
63
43
|
const ensureFileUri = (value: string) => (value.startsWith('file://') ? value : `file://${value}`);
|
|
@@ -494,30 +474,6 @@ export const FullDocScanner: React.FC<FullDocScannerProps> = ({
|
|
|
494
474
|
setFlashEnabled(prev => !prev);
|
|
495
475
|
}, []);
|
|
496
476
|
|
|
497
|
-
const rotateImageWithFallback = useCallback((uri: string, angle: number) => {
|
|
498
|
-
return new Promise<string>((resolve, reject) => {
|
|
499
|
-
if (!ImageRotate?.rotateImage) {
|
|
500
|
-
reject(new Error('react-native-image-rotate unavailable'));
|
|
501
|
-
return;
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
ImageRotate.rotateImage(
|
|
505
|
-
uri,
|
|
506
|
-
angle,
|
|
507
|
-
(rotatedUri) => resolve(rotatedUri),
|
|
508
|
-
(error) => {
|
|
509
|
-
const message =
|
|
510
|
-
typeof error === 'string'
|
|
511
|
-
? error
|
|
512
|
-
: error && typeof error === 'object' && 'message' in error
|
|
513
|
-
? String((error as any).message)
|
|
514
|
-
: 'Unknown rotation error';
|
|
515
|
-
reject(new Error(message));
|
|
516
|
-
},
|
|
517
|
-
);
|
|
518
|
-
});
|
|
519
|
-
}, []);
|
|
520
|
-
|
|
521
477
|
const handleRotateImage = useCallback(
|
|
522
478
|
(degrees: -90 | 90) => {
|
|
523
479
|
if (!isImageRotationSupported()) {
|
|
@@ -617,55 +573,30 @@ export const FullDocScanner: React.FC<FullDocScannerProps> = ({
|
|
|
617
573
|
}
|
|
618
574
|
}
|
|
619
575
|
|
|
620
|
-
//
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
const sourceUri = ensureFileUri(croppedImageData.path);
|
|
624
|
-
|
|
625
|
-
try {
|
|
626
|
-
const rotatedUri = await rotateImageWithFallback(sourceUri, rotationNormalized);
|
|
627
|
-
console.log('[FullDocScanner] Image rotated via react-native-image-rotate:', rotatedUri);
|
|
628
|
-
|
|
629
|
-
// rotatedUri를 파일로 저장하고 base64 생성
|
|
630
|
-
const destinationPath = `${RNFS.CachesDirectoryPath}/rotated_img_${Date.now()}.jpeg`;
|
|
631
|
-
|
|
632
|
-
// rotatedUri는 이미 file://로 시작하므로 stripFileUri로 정리
|
|
633
|
-
const cleanRotatedUri = stripFileUri(rotatedUri);
|
|
634
|
-
|
|
635
|
-
// 파일 복사
|
|
636
|
-
await RNFS.copyFile(cleanRotatedUri, destinationPath);
|
|
637
|
-
console.log('[FullDocScanner] Copied rotated file to:', destinationPath);
|
|
638
|
-
|
|
639
|
-
// Base64 생성
|
|
640
|
-
const base64Data = await RNFS.readFile(destinationPath, 'base64');
|
|
641
|
-
console.log('[FullDocScanner] Got result:', {
|
|
642
|
-
path: destinationPath,
|
|
643
|
-
hasBase64: true,
|
|
644
|
-
base64Length: base64Data.length,
|
|
645
|
-
});
|
|
646
|
-
|
|
647
|
-
onResult({
|
|
648
|
-
path: destinationPath,
|
|
649
|
-
base64: base64Data,
|
|
650
|
-
});
|
|
651
|
-
setProcessing(false);
|
|
652
|
-
return;
|
|
653
|
-
} catch (rotateError) {
|
|
654
|
-
console.error('[FullDocScanner] react-native-image-rotate error:', rotateError);
|
|
655
|
-
throw rotateError;
|
|
656
|
-
}
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
// 회전 불가능한 경우 경고 후 원본 반환
|
|
660
|
-
console.warn(
|
|
661
|
-
'[FullDocScanner] Rotation requested but no supported rotation module is available. Returning original image.',
|
|
576
|
+
// expo-image-manipulator를 사용할 수 없는 경우 에러 처리
|
|
577
|
+
console.error(
|
|
578
|
+
'[FullDocScanner] Rotation requested but expo-image-manipulator is not available.',
|
|
662
579
|
);
|
|
663
|
-
Alert.alert('알림', '이미지 회전 기능을 사용할 수 없습니다. 원본 이미지를 사용합니다.');
|
|
664
|
-
onResult({
|
|
665
|
-
path: croppedImageData.path,
|
|
666
|
-
base64: croppedImageData.base64,
|
|
667
|
-
});
|
|
668
580
|
setProcessing(false);
|
|
581
|
+
Alert.alert(
|
|
582
|
+
'회전 불가',
|
|
583
|
+
'expo-image-manipulator가 설치되지 않아 이미지 회전을 수행할 수 없습니다.\n\n패키지를 설치해주세요:\nnpm install expo-image-manipulator',
|
|
584
|
+
[
|
|
585
|
+
{
|
|
586
|
+
text: '원본 사용',
|
|
587
|
+
onPress: () => {
|
|
588
|
+
onResult({
|
|
589
|
+
path: croppedImageData.path,
|
|
590
|
+
base64: croppedImageData.base64,
|
|
591
|
+
});
|
|
592
|
+
},
|
|
593
|
+
},
|
|
594
|
+
{
|
|
595
|
+
text: '취소',
|
|
596
|
+
style: 'cancel',
|
|
597
|
+
},
|
|
598
|
+
],
|
|
599
|
+
);
|
|
669
600
|
} catch (error) {
|
|
670
601
|
console.error('[FullDocScanner] Image rotation error on confirm:', error);
|
|
671
602
|
setProcessing(false);
|
|
@@ -680,7 +611,7 @@ export const FullDocScanner: React.FC<FullDocScannerProps> = ({
|
|
|
680
611
|
base64: croppedImageData.base64,
|
|
681
612
|
});
|
|
682
613
|
}
|
|
683
|
-
}, [croppedImageData, rotationDegrees, onResult
|
|
614
|
+
}, [croppedImageData, rotationDegrees, onResult]);
|
|
684
615
|
|
|
685
616
|
const handleRetake = useCallback(() => {
|
|
686
617
|
console.log('[FullDocScanner] Retake - clearing cropped image and resetting scanner');
|