使用 Dynamsoft Mobile Barcode SDK 的 iOS 条形码扫描仪
节省时间和金钱。使用 Dynamsoft 条码阅读器 SDK 加速 iOS 条码应用程序的开发。
引言
Dynamsoft 致力于为所有主流平台提供条码 SDK。目前,它已涵盖桌面平台的 Windows、Linux 和 macOS。对于移动平台,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.framework
和 libc++.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 条码应用程序吗? 现在就开始动手吧
支持
如果您对上述示例或 iOS 条码 SDK 有任何疑问,请随时联系 support@dynamsoft.com。