iOS

AVFoundation(iOS標準)の機能を使ってバーコードリーダを作ってみる

昨年、ZBarライブラリを使ったリーダのデモを作ったままでしたが、いつのまにかバーコードリーディングの機能がiOS標準になってしまっていたみたいです。必要なライブラリはAVFoundationのみというシンプルさ。

AVFoundation.framework

細かく分けても結局分かり難そうなので、ビューのコードを全部載せちゃいましょう。見慣れないのはAVCaptureMetadataOutputとAVCaptureMetadataOutputObjectsDelegateあたりでしょうか。メタデータとはいうもののバーコード以外に何を読んでくれるのかは分かりませんが…。

#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>

@interface ViewController () <AVCaptureMetadataOutputObjectsDelegate>
{
    AVCaptureSession *session;
    AVCaptureDevice *device;
    AVCaptureDeviceInput *input;
    AVCaptureMetadataOutput *output;
    AVCaptureVideoPreviewLayer *layer;

    UIView *hView;
    UILabel *hLabel;
}

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    hView = [[UIView alloc] init];
    hView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibleBottomMargin;
    hView.layer.borderColor = [UIColor greenColor].CGColor;
    hView.layer.borderWidth = 3;
    [self.view addSubview:hView];

    hLabel = [[UILabel alloc] init];
    hLabel.frame = CGRectMake(0, self.view.bounds.size.height - 40,self.view.bounds.size.width,40);
    hLabel.backgroundColor = [UIColor colorWithWhite:0.15 alpha:0.65];
    hLabel.textColor = [UIColor whiteColor];
    hLabel.textAlignment = NSTextAlignmentCenter;
    hLabel.text = @"(none)";
    [self.view addSubview:hLabel];

    session = [[AVCaptureSession alloc]init];
    device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    NSError *error = nil;

    input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
    if (input) {
        [session addInput:input];
    }else{
        NSLog(@"Error: %@",error);
    }

    output = [[AVCaptureMetadataOutput alloc]init];
    [output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
    [session addOutput:output];
    output.metadataObjectTypes = [output availableMetadataObjectTypes];

    layer = [AVCaptureVideoPreviewLayer layerWithSession:session];
    layer.frame = self.view.bounds;
    layer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    [self.view.layer addSublayer:layer];

    [session startRunning];

    [self.view bringSubviewToFront:hView];
    [self.view bringSubviewToFront:hLabel];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
}

- (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 *)[layer transformedMetadataObjectForMetadataObject:(AVMetadataMachineReadableCodeObject *)metadata];
                highlightViewRect = barCodeObject.bounds;
                detectionString = [(AVMetadataMachineReadableCodeObject *)metadata stringValue];
                break;
            }
        }

        if (detectionString != nil)
        {
            hLabel.text = detectionString;
            break;
        }
        else
            hLabel.text = @"(none)";
    }

    hView.frame = highlightViewRect;
}
@end

参考URL