1
votes

I am using iOS 7 AVFoundation framework for Barcode scanning. It works fine for me but on some Barcodes it gives me wrong result.

I am adding code file and Barcode also to generate the issue. Please take a look and help me to find out the problem.

Code Sample:

ViewController.h Class-

#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>

@interface ViewController : UIViewController <AVCaptureMetadataOutputObjectsDelegate>
{
    AVCaptureSession                *_session;
    AVCaptureDevice                 *_device;
    AVCaptureDeviceInput            *_input;
    AVCaptureMetadataOutput         *_output;
    AVCaptureVideoPreviewLayer      *_prevLayer;

    UIView                          *_highlightView;

    IBOutlet    UIView              *_viewBg;
    IBOutlet    UIButton            *_btnScanning;
}

@end

ViewController.m Class Methods -

- (void)setScanningVideoOrientation
{
    if ([UIDevice currentDevice].orientation == UIInterfaceOrientationPortrait)
    {
        _prevLayer.connection.videoOrientation = AVCaptureVideoOrientationPortrait;
    }
    else if ([UIDevice currentDevice].orientation == UIInterfaceOrientationPortraitUpsideDown)
    {
        _prevLayer.connection.videoOrientation = AVCaptureVideoOrientationPortraitUpsideDown;
    }
    else if ([UIDevice currentDevice].orientation == UIInterfaceOrientationLandscapeLeft)
    {
        _prevLayer.connection.videoOrientation = AVCaptureVideoOrientationLandscapeLeft;
    }
    else if ([UIDevice currentDevice].orientation == UIInterfaceOrientationLandscapeRight)
    {
        _prevLayer.connection.videoOrientation = AVCaptureVideoOrientationLandscapeRight;
    }
}


- (void)startScanning
{
    // Create Session.------------------------------------------------------
    _session = nil;
    _session = [[AVCaptureSession alloc] init];
    _device = nil;
    _device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    NSError *error = nil;

    _input = nil;
    _input = [AVCaptureDeviceInput deviceInputWithDevice:_device error:&error];
    if (_input)
    {
        [_session addInput:_input];

        _output = nil;
        _output = [[AVCaptureMetadataOutput alloc] init];
        [_output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
        [_session addOutput:_output];

        _output.metadataObjectTypes = [_output availableMetadataObjectTypes];

        _prevLayer = nil;
        _prevLayer = [AVCaptureVideoPreviewLayer layerWithSession:_session];
        _prevLayer.frame = _viewBg.frame;
        _prevLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
        [self setScanningVideoOrientation];
        [self.view.layer addSublayer:_prevLayer];

        [_session startRunning];
    } else
    {
        NSLog(@"Error: %@", error);
    }
    //----------------------------------------------------------------------
}

In this delegate method. I am getting wrong barcode string. Please take a look on 'detectionString'.

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray     *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
    CGRect highlightViewRect = CGRectZero;
    AVMetadataMachineReadableCodeObject *barCodeObject;
    NSString *detectionString = nil;
    NSArray *barCodeTypes = @[AVMetadataObjectTypeUPCECode, AVMetadataObjectTypeCode39Code,     AVMetadataObjectTypeCode39Mod43Code,
                          AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode93Code, AVMetadataObjectTypeCode128Code,
                          AVMetadataObjectTypePDF417Code, AVMetadataObjectTypeQRCode, AVMetadataObjectTypeAztecCode];

    for (AVMetadataObject *metadata in metadataObjects) {
        for (NSString *type in barCodeTypes) {
            if ([metadata.type isEqualToString:type])
            {
                barCodeObject = (AVMetadataMachineReadableCodeObject *)[_prevLayer     transformedMetadataObjectForMetadataObject:(AVMetadataMachineReadableCodeObject *)metadata];
                highlightViewRect = barCodeObject.bounds;
                detectionString = [(AVMetadataMachineReadableCodeObject *)metadata stringValue];
                break;
            }
        }

        if (detectionString != nil)
        {
            NSLog(@"ViewController-->captureOutput-->detectionString = %@",detectionString);
            [self stopScanning];
            break;
        }
    }

    barCodeObject   = nil;
    detectionString = nil;
    barCodeTypes    = nil;
}

Barcode Image -

enter image description here

I am getting result - 0649954006029

But it should be - 649954006029.

As for some other barcodes, i am seeing 'l' before actual barcode scanning string.

Hope it will help you to identify the problem.

Thanks.

1
Do not add code to your question as images. Please copy and paste the relevant code as text and properly format it. It makes it much easier to read and it makes it easier to reference in answers. - rmaddy
Hope it will help you to identify the problem. If attached image is not proper for scanning, then please use Barcode form your nearby belongings. You will definitely get the issue. Thanks! - Mohd Haider
Can you just strip off the leading zero? - Shane Wealti
@Shane.. Thanks for your comment but it is not the actual solution. I need to know the reason behind this but I am still getting this issue. AVFoundation gives proper result for some barcodes, so striping off the leading character will not be a right solution. - Mohd Haider
AFAIK that's because of code being 12 symbols instead of 13, so it has leading zero. - Timur Kuchkarov

1 Answers

3
votes

The reason you're getting a 13 digit code is because you're trying to scan a UPC-A code (649954..) and iOS doesn't have a separate category for UPC-A codes.

UPC-A codes come scanned in as EAN13 codes, and those are 13 digits long, so they get a prefix of 0.

From AVFoundation/AVMetadata.h

/*! @constant AVMetadataObjectTypeEAN13Code

@abstract An identifier for an instance of AVMetadataMachineReadableCodeObject having a type AVMetadataObjectTypeEAN13Code.

@discussion AVMetadataMachineReadableCodeObject objects generated from EAN-13 (including UPC-A) codes return this constant as their type. */

AVF_EXPORT NSString *const AVMetadataObjectTypeEAN13Code NS_AVAILABLE(NA, 7_0);