65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Dynamsoft Mobile Barcode SDK 的 iOS 条形码扫描仪

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0投票)

2016年7月7日

CPOL

2分钟阅读

viewsIcon

22693

节省时间和金钱。使用 Dynamsoft 条码阅读器 SDK 加速 iOS 条码应用程序的开发。

引言

Dynamsoft 致力于为所有主流平台提供条码 SDK。目前,它已涵盖桌面平台的 WindowsLinuxmacOS。对于移动平台,Dynamsoft 已经发布了移动 iOS 条码 SDK。无论您更喜欢免费软件还是专有软件,这都是一个全新的选择。在下面的段落中,我们将向您展示如何使用 iOS 条码 SDK。

Dynamsoft iOS 条码阅读器的特性

兼容性

  • iOS 7.0 或更高版本
  • Xcode 6.0 或更高版本

输入数据

  • UIImage 或 NV21

支持的 1D/2D 条码类型

  • 1D:Code 39, Code 93, Code 128, Codabar, EAN-8, EAN-13, UPC-A, UPC-E, Interleaved 2 of 5 (ITF), Industrial 2 of 5 (Code 2 of 5 Industry, Standard 2 of 5, Code 2 of 5), ITF-14
  • 2D:QRCode, DataMatrix 和 PDF417

检测到的条码信息

  • 条码类型
  • 条码值(字符串形式)
  • 条码原始数据(字节形式)
  • 条码边界矩形
  • 四个角的坐标

iOS 条码扫描器示例

打开 Xcode 7 并按下 Shift+Command+N 创建一个使用 Single View Application 模板的新项目。

DynamsoftBarcodeReader.framework 拖到您的项目中。 选中“如果需要则复制项目”选项

该框架将被复制到您的项目文件夹中。您需要这样做吗? 打开项目属性并选择 Build Settings > Search Paths

如果您没有将框架复制到您的项目中,您需要更改 Framework Search Path。 否则,它将无法找到该框架。

添加依赖项。 选择 Build Phases > Link Binary With Libraries 以添加 DynamsoftBarcodeReader.frameworklibc++.tbd(Xcode 6 的 libc++.dylib)

ViewDidLoad 中创建一个 DbrManager 实例

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [[UIApplication sharedApplication] setIdleTimerDisabled: YES];
    
    //register notification for UIApplicationDidBecomeActiveNotification
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(didBecomeActive:)
                                                 name:UIApplicationDidBecomeActiveNotification
                                               object:nil];
    
    //init DbrManager with Dynamsoft Barcode Reader mobile license
    dbrManager = [[DbrManager alloc] initWithLicense:@"<license>"];
    [dbrManager setRecognitionCallback:self :@selector(onReadImageBufferComplete:)];
    [dbrManager beginVideoSession];
    
    [self configInterface];
}

使用有效的许可证初始化 Dynamsoft 条码阅读器

-(id)initWithLicense:(NSString *)license{
    self = [super init];
    
    if(self)
    {
        m_videoCaptureSession = nil;
        m_barcodeReader = [[BarcodeReader alloc] initWithLicense:license];
        
        isPauseFramesComing = NO;
        isCurrentFrameDecodeFinished = YES;
        
        barcodeFormat = [Barcode UNKNOWN];
        startRecognitionDate = nil;
        
        m_recognitionReceiver = nil;
    }
    
    return self;
}

使用后置摄像头作为捕获设备

-(AVCaptureDevice *)getAvailableCamera {
    NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
    AVCaptureDevice *captureDevice = nil;
    for (AVCaptureDevice *device in videoDevices) {
        if (device.position == AVCaptureDevicePositionBack) {
            captureDevice = device;
            break;
        }
    }
    
    if (!captureDevice)
        captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    
    return captureDevice;
}

创建一个视频捕获会话

-(void)beginVideoSession {
    AVCaptureDevice *inputDevice = [self getAvailableCamera];
    
    AVCaptureDeviceInput *captureInput = [AVCaptureDeviceInput
                                          deviceInputWithDevice:inputDevice
                                          error:nil];
    
    AVCaptureVideoDataOutput *captureOutput = [[AVCaptureVideoDataOutput alloc] init];
    
    captureOutput.alwaysDiscardsLateVideoFrames = YES;
    
    dispatch_queue_t queue;
    queue = dispatch_queue_create("dbrCameraQueue", NULL);
    [captureOutput setSampleBufferDelegate:self queue:queue];
    
    // Enable continuous autofocus
    if ([inputDevice isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus]) {
        NSError *error = nil;
        if ([inputDevice lockForConfiguration:&error]) {
            inputDevice.focusMode = AVCaptureFocusModeContinuousAutoFocus;
            [inputDevice unlockForConfiguration];
        }
    }
    
    // Enable AutoFocusRangeRestriction
     if([inputDevice respondsToSelector:@selector(isAutoFocusRangeRestrictionSupported)] &&
        inputDevice.autoFocusRangeRestrictionSupported) {
         if([inputDevice lockForConfiguration:nil]) {
             inputDevice.autoFocusRangeRestriction = AVCaptureAutoFocusRangeRestrictionNear;
             [inputDevice unlockForConfiguration];
         }
     }
    
    [captureOutput setVideoSettings:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_420YpCbCr8BiPlanarFullRange] forKey:(id)kCVPixelBufferPixelFormatTypeKey]];
    
    if(captureInput == nil || captureOutput == nil)
    {
        return;
    }
    
    m_videoCaptureSession = [[AVCaptureSession alloc] init];
    [m_videoCaptureSession addInput:captureInput];
    [m_videoCaptureSession addOutput:captureOutput];
    
    if ([m_videoCaptureSession canSetSessionPreset:AVCaptureSessionPreset1920x1080])
    {
        [m_videoCaptureSession setSessionPreset :AVCaptureSessionPreset1920x1080];
        cameraResolution.width = 1920;
        cameraResolution.height = 1080;
    }
    else if ([m_videoCaptureSession canSetSessionPreset:AVCaptureSessionPreset1280x720])
    {
        [m_videoCaptureSession setSessionPreset :AVCaptureSessionPreset1280x720];
        cameraResolution.width = 1280;
        cameraResolution.height = 720;
    }
    else if([m_videoCaptureSession canSetSessionPreset:AVCaptureSessionPreset640x480])
    {
        [m_videoCaptureSession setSessionPreset :AVCaptureSessionPreset640x480];
        cameraResolution.width = 640;
        cameraResolution.height = 480;
    }
    
    [m_videoCaptureSession startRunning];
}

在预览层上显示视频

AVCaptureSession* captureSession = [dbrManager getVideoSession];
    if(captureSession == nil)
        return;
    
    previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:captureSession];
    [previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
        previewLayer.frame = mainScreenLandscapeBoundary;
    cameraPreview = [[UIView alloc] init];
    [cameraPreview.layer addSublayer:previewLayer];
    [self.view insertSubview:cameraPreview atIndex:0];

根据环境亮度,切换闪光灯

- (void) turnFlashOn: (BOOL) on {
    // validate whether flashlight is available
    Class captureDeviceClass = NSClassFromString(@"AVCaptureDevice");
    if (captureDeviceClass != nil) {
        AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
        if (device != nil && [device hasTorch] && [device hasFlash]){
            [device lockForConfiguration:nil];
            
            if (on == YES) {
                [device setTorchMode:AVCaptureTorchModeOn];
                [device setFlashMode:AVCaptureFlashModeOn];
                [flashButton setImage:[UIImage imageNamed:@"flash_on"] forState:UIControlStateNormal];
                [flashButton setTitle:NSLocalizedString(@"flash-on", @"flash on string") forState:UIControlStateNormal];
                
            } else {
                [device setTorchMode:AVCaptureTorchModeOff];
                [device setFlashMode:AVCaptureFlashModeOff];
                [flashButton setImage:[UIImage imageNamed:@"flash_off"] forState:UIControlStateNormal];
                [flashButton setTitle:NSLocalizedString(@"flash-off", @"flash off string") forState:UIControlStateNormal];
            }
            
            [device unlockForConfiguration];
        }
    }
}

保持相机自动对焦

if ([inputDevice isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus]) {
        NSError *error = nil;
        if ([inputDevice lockForConfiguration:&error]) {
            inputDevice.focusMode = AVCaptureFocusModeContinuousAutoFocus;
            [inputDevice unlockForConfiguration];
        }
    }
    
     if([inputDevice respondsToSelector:@selector(isAutoFocusRangeRestrictionSupported)] &&
        inputDevice.autoFocusRangeRestrictionSupported) {
         if([inputDevice lockForConfiguration:nil]) {
             inputDevice.autoFocusRangeRestriction = AVCaptureAutoFocusRangeRestrictionNear;
             [inputDevice unlockForConfiguration];
         }
}

使用 AVCaptureVideoDataOutputSampleBufferDelegate 接收捕获的视频,并在 captureOutput 中读取条码

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection;
{
    @autoreleasepool {
        if(isPauseFramesComing == YES || isCurrentFrameDecodeFinished == NO) return;
        
        isCurrentFrameDecodeFinished = NO;
        
        void *imageData = NULL;
        uint8_t *copyToAddress;
        
        CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
        
        OSType pixelFormat = CVPixelBufferGetPixelFormatType(imageBuffer);
        
        if (!(pixelFormat == '420v' || pixelFormat == '420f'))
        {
            isCurrentFrameDecodeFinished = YES;
            return;
        }
        
        CVPixelBufferLockBaseAddress(imageBuffer, 0);
        int numPlanes = (int)CVPixelBufferGetPlaneCount(imageBuffer);
        int bufferSize = (int)CVPixelBufferGetDataSize(imageBuffer);
        int imgWidth = (int)CVPixelBufferGetWidthOfPlane(imageBuffer, 0);
        int imgHeight = (int)CVPixelBufferGetHeightOfPlane(imageBuffer, 0);
        
        if(numPlanes < 1)
        {
            isCurrentFrameDecodeFinished = YES;
            return;
        }
        
        uint8_t *baseAddress = (uint8_t *) CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0);
        size_t bytesToCopy = CVPixelBufferGetHeightOfPlane(imageBuffer, 0) * CVPixelBufferGetBytesPerRowOfPlane(imageBuffer, 0);
        imageData = malloc(bytesToCopy);
        copyToAddress = (uint8_t *) imageData;
        memcpy(copyToAddress, baseAddress, bytesToCopy);
        
        CVPixelBufferUnlockBaseAddress(imageBuffer, 0);
        
        NSData *buffer = [NSData dataWithBytesNoCopy:imageData length:bufferSize freeWhenDone:YES];
        
        startRecognitionDate = [NSDate date];
        
        // read frame using Dynamsoft Barcode Reader in async manner
        [m_barcodeReader readSingleAsync:buffer width:imgWidth height:imgHeight barcodeFormat: barcodeFormat sender:m_recognitionReceiver onComplete:m_recognitionCallback];
    }
}

应用下载

您可以从 iTunes App Store 安装该应用。

获取 iOS 条码 SDK

您想快速开发 iOS 条码应用程序吗? 现在就开始动手吧

Dynamsoft iOS 条码 SDK,30 天免费试用

支持

如果您对上述示例或 iOS 条码 SDK 有任何疑问,请随时联系 support@dynamsoft.com

© . All rights reserved.