react-native-rectangle-doc-scanner 3.63.0 → 3.65.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/package.json
CHANGED
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
[self setEnableBorderDetection:YES];
|
|
13
13
|
[self setDelegate: self];
|
|
14
14
|
_hasSetupCamera = NO;
|
|
15
|
-
self.manualOnly = YES
|
|
16
|
-
self.detectionCountBeforeCapture =
|
|
15
|
+
self.manualOnly = NO; // Changed from YES to NO - allow manual capture to work
|
|
16
|
+
self.detectionCountBeforeCapture = 99999; // High threshold to prevent auto-capture
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
return self;
|
|
@@ -15,17 +15,20 @@
|
|
|
15
15
|
#import <ImageIO/ImageIO.h>
|
|
16
16
|
#import <GLKit/GLKit.h>
|
|
17
17
|
|
|
18
|
-
@interface IPDFCameraViewController () <AVCaptureVideoDataOutputSampleBufferDelegate>
|
|
18
|
+
@interface IPDFCameraViewController () <AVCaptureVideoDataOutputSampleBufferDelegate, AVCapturePhotoCaptureDelegate>
|
|
19
19
|
|
|
20
20
|
@property (nonatomic,strong) AVCaptureSession *captureSession;
|
|
21
21
|
@property (nonatomic,strong) AVCaptureDevice *captureDevice;
|
|
22
22
|
@property (nonatomic,strong) EAGLContext *context;
|
|
23
23
|
|
|
24
|
-
@property (nonatomic, strong)
|
|
24
|
+
@property (nonatomic, strong) AVCapturePhotoOutput* photoOutput;
|
|
25
|
+
@property (nonatomic, strong) AVCaptureStillImageOutput* stillImageOutput; // Kept for backward compatibility
|
|
25
26
|
|
|
26
27
|
@property (nonatomic, assign) BOOL forceStop;
|
|
27
28
|
@property (nonatomic, assign) float lastDetectionRate;
|
|
28
29
|
|
|
30
|
+
@property (nonatomic, copy) void (^captureCompletionHandler)(UIImage *, UIImage *, CIRectangleFeature *);
|
|
31
|
+
|
|
29
32
|
@end
|
|
30
33
|
|
|
31
34
|
@implementation IPDFCameraViewController
|
|
@@ -143,8 +146,21 @@
|
|
|
143
146
|
[dataOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()];
|
|
144
147
|
[session addOutput:dataOutput];
|
|
145
148
|
|
|
146
|
-
|
|
147
|
-
|
|
149
|
+
// Use modern AVCapturePhotoOutput for iOS 10+
|
|
150
|
+
if (@available(iOS 10.0, *)) {
|
|
151
|
+
self.photoOutput = [[AVCapturePhotoOutput alloc] init];
|
|
152
|
+
if ([session canAddOutput:self.photoOutput]) {
|
|
153
|
+
[session addOutput:self.photoOutput];
|
|
154
|
+
NSLog(@"[IPDFCamera] Using AVCapturePhotoOutput (modern API)");
|
|
155
|
+
} else {
|
|
156
|
+
NSLog(@"[IPDFCamera] ERROR: Cannot add AVCapturePhotoOutput");
|
|
157
|
+
}
|
|
158
|
+
} else {
|
|
159
|
+
// Fallback for older iOS versions (< iOS 10)
|
|
160
|
+
self.stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
|
|
161
|
+
[session addOutput:self.stillImageOutput];
|
|
162
|
+
NSLog(@"[IPDFCamera] Using AVCaptureStillImageOutput (legacy API)");
|
|
163
|
+
}
|
|
148
164
|
|
|
149
165
|
AVCaptureConnection *connection = [dataOutput.connections firstObject];
|
|
150
166
|
[connection setVideoOrientation:AVCaptureVideoOrientationPortrait];
|
|
@@ -413,7 +429,23 @@
|
|
|
413
429
|
|
|
414
430
|
- (void)captureImageWithCompletionHander:(void(^)(id data, id initialData, CIRectangleFeature *rectangleFeature))completionHandler
|
|
415
431
|
{
|
|
416
|
-
|
|
432
|
+
NSLog(@"[IPDFCameraViewController] captureImageWithCompletionHander called, _isCapturing=%@", _isCapturing ? @"YES" : @"NO");
|
|
433
|
+
|
|
434
|
+
if (_isCapturing) {
|
|
435
|
+
NSLog(@"[IPDFCameraViewController] Already capturing, ignoring request");
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
if (!completionHandler) {
|
|
440
|
+
NSLog(@"[IPDFCameraViewController] ERROR: No completion handler provided");
|
|
441
|
+
return;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
if (!self.captureSession || !self.captureSession.isRunning) {
|
|
445
|
+
NSLog(@"[IPDFCameraViewController] ERROR: captureSession is not running");
|
|
446
|
+
_isCapturing = NO;
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
417
449
|
|
|
418
450
|
__weak typeof(self) weakSelf = self;
|
|
419
451
|
|
|
@@ -427,76 +459,188 @@
|
|
|
427
459
|
|
|
428
460
|
_isCapturing = YES;
|
|
429
461
|
|
|
430
|
-
|
|
431
|
-
|
|
462
|
+
// Store completion handler for delegate callback
|
|
463
|
+
self.captureCompletionHandler = completionHandler;
|
|
464
|
+
|
|
465
|
+
// Use modern AVCapturePhotoOutput API (iOS 10+)
|
|
466
|
+
if (@available(iOS 10.0, *)) {
|
|
467
|
+
if (!self.photoOutput) {
|
|
468
|
+
NSLog(@"[IPDFCameraViewController] ERROR: photoOutput is nil");
|
|
469
|
+
_isCapturing = NO;
|
|
470
|
+
self.captureCompletionHandler = nil;
|
|
471
|
+
[weakSelf hideGLKView:NO completion:nil];
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
NSLog(@"[IPDFCameraViewController] Using AVCapturePhotoOutput to capture");
|
|
476
|
+
AVCapturePhotoSettings *settings = [AVCapturePhotoSettings photoSettings];
|
|
477
|
+
[self.photoOutput capturePhotoWithSettings:settings delegate:self];
|
|
478
|
+
} else {
|
|
479
|
+
// Fallback to deprecated API for iOS < 10
|
|
480
|
+
if (!self.stillImageOutput) {
|
|
481
|
+
NSLog(@"[IPDFCameraViewController] ERROR: stillImageOutput is nil");
|
|
482
|
+
_isCapturing = NO;
|
|
483
|
+
self.captureCompletionHandler = nil;
|
|
484
|
+
[weakSelf hideGLKView:NO completion:nil];
|
|
485
|
+
return;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
AVCaptureConnection *videoConnection = nil;
|
|
489
|
+
for (AVCaptureConnection *connection in self.stillImageOutput.connections)
|
|
490
|
+
{
|
|
491
|
+
for (AVCaptureInputPort *port in [connection inputPorts])
|
|
492
|
+
{
|
|
493
|
+
if ([[port mediaType] isEqual:AVMediaTypeVideo] )
|
|
494
|
+
{
|
|
495
|
+
videoConnection = connection;
|
|
496
|
+
break;
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
if (videoConnection) break;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
if (!videoConnection) {
|
|
503
|
+
NSLog(@"[IPDFCameraViewController] ERROR: No video connection found");
|
|
504
|
+
_isCapturing = NO;
|
|
505
|
+
self.captureCompletionHandler = nil;
|
|
506
|
+
[weakSelf hideGLKView:NO completion:nil];
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
NSLog(@"[IPDFCameraViewController] Using AVCaptureStillImageOutput (legacy)");
|
|
511
|
+
[self.stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error)
|
|
512
|
+
{
|
|
513
|
+
[weakSelf handleCapturedImageData:imageSampleBuffer error:error];
|
|
514
|
+
}];
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
// AVCapturePhotoCaptureDelegate method for iOS 11+
|
|
519
|
+
- (void)captureOutput:(AVCapturePhotoOutput *)output didFinishProcessingPhoto:(AVCapturePhoto *)photo error:(NSError *)error API_AVAILABLE(ios(11.0)) {
|
|
520
|
+
NSLog(@"[IPDFCameraViewController] didFinishProcessingPhoto called, error=%@", error);
|
|
521
|
+
|
|
522
|
+
if (error) {
|
|
523
|
+
NSLog(@"[IPDFCameraViewController] ERROR in didFinishProcessingPhoto: %@", error);
|
|
524
|
+
_isCapturing = NO;
|
|
525
|
+
self.captureCompletionHandler = nil;
|
|
526
|
+
[self hideGLKView:NO completion:nil];
|
|
527
|
+
return;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
NSData *imageData = [photo fileDataRepresentation];
|
|
531
|
+
if (!imageData) {
|
|
532
|
+
NSLog(@"[IPDFCameraViewController] ERROR: Failed to get image data from photo");
|
|
533
|
+
_isCapturing = NO;
|
|
534
|
+
self.captureCompletionHandler = nil;
|
|
535
|
+
[self hideGLKView:NO completion:nil];
|
|
536
|
+
return;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
[self processImageData:imageData];
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
// AVCapturePhotoCaptureDelegate method for iOS 10
|
|
543
|
+
- (void)captureOutput:(AVCapturePhotoOutput *)output didFinishProcessingPhotoSampleBuffer:(CMSampleBufferRef)photoSampleBuffer previewPhotoSampleBuffer:(CMSampleBufferRef)previewPhotoSampleBuffer resolvedSettings:(AVCaptureResolvedPhotoSettings *)resolvedSettings bracketSettings:(AVCaptureBracketedStillImageSettings *)bracketSettings error:(NSError *)error API_DEPRECATED("Use -captureOutput:didFinishProcessingPhoto:error: instead.", ios(10.0, 11.0)) {
|
|
544
|
+
NSLog(@"[IPDFCameraViewController] didFinishProcessingPhotoSampleBuffer called (iOS 10)");
|
|
545
|
+
[self handleCapturedImageData:photoSampleBuffer error:error];
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
- (void)handleCapturedImageData:(CMSampleBufferRef)sampleBuffer error:(NSError *)error {
|
|
549
|
+
NSLog(@"[IPDFCameraViewController] handleCapturedImageData called, error=%@, buffer=%@", error, sampleBuffer ? @"YES" : @"NO");
|
|
550
|
+
|
|
551
|
+
if (error) {
|
|
552
|
+
NSLog(@"[IPDFCameraViewController] ERROR capturing image: %@", error);
|
|
553
|
+
_isCapturing = NO;
|
|
554
|
+
self.captureCompletionHandler = nil;
|
|
555
|
+
[self hideGLKView:NO completion:nil];
|
|
556
|
+
return;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
if (!sampleBuffer) {
|
|
560
|
+
NSLog(@"[IPDFCameraViewController] ERROR: sampleBuffer is nil");
|
|
561
|
+
_isCapturing = NO;
|
|
562
|
+
self.captureCompletionHandler = nil;
|
|
563
|
+
[self hideGLKView:NO completion:nil];
|
|
564
|
+
return;
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:sampleBuffer];
|
|
568
|
+
|
|
569
|
+
if (!imageData) {
|
|
570
|
+
NSLog(@"[IPDFCameraViewController] ERROR: Failed to create image data from sample buffer");
|
|
571
|
+
_isCapturing = NO;
|
|
572
|
+
self.captureCompletionHandler = nil;
|
|
573
|
+
[self hideGLKView:NO completion:nil];
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
[self processImageData:imageData];
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
- (void)processImageData:(NSData *)imageData {
|
|
581
|
+
NSLog(@"[IPDFCameraViewController] processImageData called, imageData size: %lu bytes", (unsigned long)imageData.length);
|
|
582
|
+
|
|
583
|
+
__weak typeof(self) weakSelf = self;
|
|
584
|
+
void (^completionHandler)(UIImage *, UIImage *, CIRectangleFeature *) = self.captureCompletionHandler;
|
|
585
|
+
|
|
586
|
+
if (!completionHandler) {
|
|
587
|
+
NSLog(@"[IPDFCameraViewController] ERROR: completionHandler is nil");
|
|
588
|
+
_isCapturing = NO;
|
|
589
|
+
[self hideGLKView:NO completion:nil];
|
|
590
|
+
return;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
if (self.cameraViewType == IPDFCameraViewTypeBlackAndWhite || self.isBorderDetectionEnabled)
|
|
432
594
|
{
|
|
433
|
-
|
|
595
|
+
CIImage *enhancedImage = [CIImage imageWithData:imageData];
|
|
596
|
+
|
|
597
|
+
if (self.cameraViewType == IPDFCameraViewTypeBlackAndWhite)
|
|
598
|
+
{
|
|
599
|
+
enhancedImage = [self filteredImageUsingEnhanceFilterOnImage:enhancedImage];
|
|
600
|
+
}
|
|
601
|
+
else
|
|
602
|
+
{
|
|
603
|
+
enhancedImage = [self filteredImageUsingContrastFilterOnImage:enhancedImage];
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
if (self.isBorderDetectionEnabled && rectangleDetectionConfidenceHighEnough(_imageDedectionConfidence))
|
|
434
607
|
{
|
|
435
|
-
|
|
608
|
+
CIRectangleFeature *rectangleFeature = [self biggestRectangleInRectangles:[[self highAccuracyRectangleDetector] featuresInImage:enhancedImage]];
|
|
609
|
+
|
|
610
|
+
if (rectangleFeature)
|
|
436
611
|
{
|
|
437
|
-
|
|
438
|
-
|
|
612
|
+
enhancedImage = [self correctPerspectiveForImage:enhancedImage withFeatures:rectangleFeature];
|
|
613
|
+
|
|
614
|
+
UIGraphicsBeginImageContext(CGSizeMake(enhancedImage.extent.size.height, enhancedImage.extent.size.width));
|
|
615
|
+
[[UIImage imageWithCIImage:enhancedImage scale:1.0 orientation:UIImageOrientationRight] drawInRect:CGRectMake(0,0, enhancedImage.extent.size.height, enhancedImage.extent.size.width)];
|
|
616
|
+
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
|
|
617
|
+
UIImage *initialImage = [UIImage imageWithData:imageData];
|
|
618
|
+
UIGraphicsEndImageContext();
|
|
619
|
+
|
|
620
|
+
[weakSelf hideGLKView:NO completion:nil];
|
|
621
|
+
completionHandler(image, initialImage, rectangleFeature);
|
|
622
|
+
} else {
|
|
623
|
+
// No rectangle detected, return original image
|
|
624
|
+
NSLog(@"[IPDFCameraViewController] No rectangle detected during manual capture, returning original image");
|
|
625
|
+
[weakSelf hideGLKView:NO completion:nil];
|
|
626
|
+
UIImage *initialImage = [UIImage imageWithData:imageData];
|
|
627
|
+
completionHandler(initialImage, initialImage, nil);
|
|
439
628
|
}
|
|
629
|
+
} else {
|
|
630
|
+
[weakSelf hideGLKView:NO completion:nil];
|
|
631
|
+
UIImage *initialImage = [UIImage imageWithData:imageData];
|
|
632
|
+
completionHandler(initialImage, initialImage, nil);
|
|
440
633
|
}
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
if (weakSelf.cameraViewType == IPDFCameraViewTypeBlackAndWhite)
|
|
453
|
-
{
|
|
454
|
-
enhancedImage = [self filteredImageUsingEnhanceFilterOnImage:enhancedImage];
|
|
455
|
-
}
|
|
456
|
-
else
|
|
457
|
-
{
|
|
458
|
-
enhancedImage = [self filteredImageUsingContrastFilterOnImage:enhancedImage];
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
if (weakSelf.isBorderDetectionEnabled && rectangleDetectionConfidenceHighEnough(_imageDedectionConfidence))
|
|
462
|
-
{
|
|
463
|
-
CIRectangleFeature *rectangleFeature = [self biggestRectangleInRectangles:[[self highAccuracyRectangleDetector] featuresInImage:enhancedImage]];
|
|
464
|
-
|
|
465
|
-
if (rectangleFeature)
|
|
466
|
-
{
|
|
467
|
-
enhancedImage = [self correctPerspectiveForImage:enhancedImage withFeatures:rectangleFeature];
|
|
468
|
-
|
|
469
|
-
UIGraphicsBeginImageContext(CGSizeMake(enhancedImage.extent.size.height, enhancedImage.extent.size.width));
|
|
470
|
-
[[UIImage imageWithCIImage:enhancedImage scale:1.0 orientation:UIImageOrientationRight] drawInRect:CGRectMake(0,0, enhancedImage.extent.size.height, enhancedImage.extent.size.width)];
|
|
471
|
-
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
|
|
472
|
-
UIImage *initialImage = [UIImage imageWithData:imageData];
|
|
473
|
-
UIGraphicsEndImageContext();
|
|
474
|
-
|
|
475
|
-
[weakSelf hideGLKView:NO completion:nil];
|
|
476
|
-
completionHandler(image, initialImage, rectangleFeature);
|
|
477
|
-
} else {
|
|
478
|
-
// No rectangle detected, return original image
|
|
479
|
-
NSLog(@"[IPDFCameraViewController] No rectangle detected during manual capture, returning original image");
|
|
480
|
-
[weakSelf hideGLKView:NO completion:nil];
|
|
481
|
-
UIImage *initialImage = [UIImage imageWithData:imageData];
|
|
482
|
-
completionHandler(initialImage, initialImage, nil);
|
|
483
|
-
}
|
|
484
|
-
} else {
|
|
485
|
-
[weakSelf hideGLKView:NO completion:nil];
|
|
486
|
-
UIImage *initialImage = [UIImage imageWithData:imageData];
|
|
487
|
-
completionHandler(initialImage, initialImage, nil);
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
}
|
|
491
|
-
else
|
|
492
|
-
{
|
|
493
|
-
[weakSelf hideGLKView:NO completion:nil];
|
|
494
|
-
UIImage *initialImage = [UIImage imageWithData:imageData];
|
|
495
|
-
completionHandler(initialImage, initialImage, nil);
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
_isCapturing = NO;
|
|
499
|
-
}];
|
|
634
|
+
}
|
|
635
|
+
else
|
|
636
|
+
{
|
|
637
|
+
[weakSelf hideGLKView:NO completion:nil];
|
|
638
|
+
UIImage *initialImage = [UIImage imageWithData:imageData];
|
|
639
|
+
completionHandler(initialImage, initialImage, nil);
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
_isCapturing = NO;
|
|
643
|
+
self.captureCompletionHandler = nil;
|
|
500
644
|
}
|
|
501
645
|
|
|
502
646
|
- (void)hideGLKView:(BOOL)hidden completion:(void(^)())completion
|