Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

add tap to focus functionality to ZBarReaderViewController

I am using the zbarsdk to read the barcodes . It is working fine , but my problem is I have added the overlay view to the ZBarReaderViewController (reader in my code ). So now I tried to add the tap to focus functionality . But it is crashing . Below is my code . Thanks in advance . Any ideas would be grateful .

-(IBAction)scanBarCode:(id)sender
{
    barcodeClicked = 1;

    NSLog(@"TBD: scan barcode here...");
    // ADD: present a barcode reader that scans from the camera feed
    reader = [ZBarReaderViewController new];
    reader.readerDelegate = self;
    reader.supportedOrientationsMask = ZBarOrientationMaskAll;

    ZBarImageScanner *scanner = reader.scanner;
    // TODO: (optional) additional reader configuration here

    // EXAMPLE: disable rarely used I2/5 to improve performance
    [scanner setSymbology: ZBAR_I25
                   config: ZBAR_CFG_ENABLE
                       to: 0];
    reader.showsZBarControls = NO;

    UIView *ovlView = [[UIView alloc] init];
    [ovlView setFrame:CGRectMake(0, 0, 320, 480)];
    [ovlView setBackgroundColor:[UIColor clearColor]];

    UIImageView *leftBracket = [[UIImageView alloc] init];
    [leftBracket setFrame:CGRectMake(21, 100, 278, 15)];
    [leftBracket setImage:[UIImage imageNamed:@"TopBracket.png"]];

    UIImageView *rightBracket = [[UIImageView alloc] init];
    [rightBracket setFrame:CGRectMake(21, 240, 278, 15)];
    [rightBracket setImage:[UIImage imageNamed:@"BottomBracket.png"]];

    UIToolbar *bottomBar = [[UIToolbar alloc] init];
    [bottomBar setBarStyle:UIBarStyleBlackOpaque];

    if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone && [UIScreen mainScreen].bounds.size.height * [UIScreen mainScreen].scale >= 1136)
    {
        [bottomBar setFrame:CGRectMake(0, 524, 320, 44)];
    }
    else
        [bottomBar setFrame:CGRectMake(0, 436, 320, 44)];

    UIBarButtonItem *cancel = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancelCamera)];
    /*UIBarButtonItem *flexItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
                                                                              target:nil
                                                                              action:nil];*/
    //UIBarButtonItem *infoButton = [[UIBarButtonItem alloc] initWithTitle:@" Info " style:UIBarButtonItemStyleBordered target:self action:@selector(infoButton)];
    /*UIButton *info = [UIButton buttonWithType:UIButtonTypeInfoLight];
    [info addTarget:self action:@selector(infoButton) forControlEvents:UIControlEventTouchUpInside];
    UIBarButtonItem *infoButton = [[UIBarButtonItem alloc] initWithCustomView:info];

    [bottomBar setItems:[NSArray arrayWithObjects:cancel,flexItem,infoButton, nil]];*/

    [bottomBar setItems:[NSArray arrayWithObjects:cancel, nil]];

    [ovlView addSubview:leftBracket];
    [ovlView addSubview:rightBracket];
    [ovlView addSubview:bottomBar];

    reader.cameraOverlayView = ovlView;

    // present and release the controller
    [self presentModalViewController:reader
                            animated: YES];
    [reader release];
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    UIView * previewView = [[[[[[[[[[
                                     reader.view // UILayoutContainerView
                                     subviews] objectAtIndex:0] // UINavigationTransitionView
                                   subviews] objectAtIndex:0] // UIViewControllerWrapperView
                                 subviews] objectAtIndex:0] // UIView
                               subviews] objectAtIndex:0] // PLCameraView
                             subviews] objectAtIndex:0]; // PLPreviewView
    [previewView touchesBegan:touches withEvent:event];
}
like image 840
sri Avatar asked Dec 21 '22 11:12

sri


1 Answers

Thanks for MacN00b's answer! That points out the right direction to go for me. I have implemented tap-focus for zbarViewController. Here is the idea:

You can add a custom view to zbarViewController by assigning a custom view to its cameraOverlayView. Then add a TapGestureRecagonizer to the custom view to catch the tap. Then, get the touch point and make the camera focus to the touch point. You would like possibly add a little rectangle around the touch point(that is what I did).

Here goes the code(assigning the custom view to cameraOverlayView:

UIView *view = [[UIView alloc] init];
UITapGestureRecognizer* tapScanner = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(focusAtPoint:)];
[view addGestureRecognizer:tapScanner];    
reader.cameraOverlayView = view;

Then in selector focusAtPoint:

- (void)focusAtPoint:(id) sender{
    CGPoint touchPoint = [(UITapGestureRecognizer*)sender locationInView:_reader.cameraOverlayView];
    double focus_x = touchPoint.x/_reader.cameraOverlayView.frame.size.width;
    double focus_y = (touchPoint.y+66)/_reader.cameraOverlayView.frame.size.height;
    NSError *error;
    NSArray *devices = [AVCaptureDevice devices];
    for (AVCaptureDevice *device in devices){
        NSLog(@"Device name: %@", [device localizedName]);
        if ([device hasMediaType:AVMediaTypeVideo]) {
            if ([device position] == AVCaptureDevicePositionBack) {
                NSLog(@"Device position : back");
                CGPoint point = CGPointMake(focus_y, 1-focus_x);
                if ([device isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus] && [device lockForConfiguration:&error]){
                    [device setFocusPointOfInterest:point];
                    CGRect rect = CGRectMake(touchPoint.x-30, touchPoint.y-30, 60, 60);
                    UIView *focusRect = [[UIView alloc] initWithFrame:rect];
                    focusRect.layer.borderColor = [UIColor whiteColor].CGColor;
                    focusRect.layer.borderWidth = 2;
                    focusRect.tag = 99;
                    [_reader.cameraOverlayView addSubview:focusRect];
                    [NSTimer scheduledTimerWithTimeInterval: 1
                                target: self
                                selector: @selector(dismissFocusRect)
                                userInfo: nil
                                repeats: NO];
                    [device setFocusMode:AVCaptureFocusModeAutoFocus];
                    [device unlockForConfiguration];
                }
            }
        }
    }
}

I have added a white rectangle around the touch point, and then use selector dismissFocusRect to dismiss this rectangle. Here is the code:

- (void) dismissFocusRect{
    for (UIView *subView in _reader.cameraOverlayView.subviews)
    {
        if (subView.tag == 99)
        {
            [subView removeFromSuperview];
        }
    }
}

I hope this could help!

like image 129
Mathieu Avatar answered May 10 '23 12:05

Mathieu