iOS Barcode Scanner with Dynamsoft Mobile Barcode SDK
Save time and money. Expedite development of iOS barcode apps using Dynamsoft Barcode Reader SDK.
Introduction
Dynamsoft aims to make barcode SDK available for all mainstream platforms. So far, it has covered Windows, Linux, and macOS for desktop platforms. As for mobile platforms, Dynamsoft has released the mobile barcode SDK for iOS. No matter whether you prefer free or proprietary software, this is a new option. In the following paragraph, we will show you how to use the iOS barcode SDK.
Features of Dynamsoft Barcode Reader for iOS
Compatibility:
- iOS 7.0 or later
- Xcode 6.0 or later
Input Data:
- UIImage or NV21
Supported 1D/2D Barcode Types:
- 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, and PDF417
Detected Barcode Information:
- Barcode type
- Barcode value as string
- Barcode raw data as bytes
- Barcode bounding rectangle
- Coordinate of four corners
iOS Barcode Scanner Example
Open Xcode 7 and press Shift+Command+N to create a new project with the Single View Application template.
Drag DynamsoftBarcodeReader.framework
to your project. Check the option "Copy items if needed":
The framework will be copied to your project folder. Why do you need to do this? Open project properties and select Build Settings > Search Paths:
If you do not copy the Framework into your project, you have to change the Framework Search Path. Otherwise, it will fail to find the framework.
Add dependencies. Select Build Phases > Link Binary With Libraries to add DynamsoftBarcodeReader.framework
and libc++.tbd(libc++.dylib for Xcode 6):
Create an instance of DbrManager
in ViewDidLoad
:
- (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]; }
Initialize Dynamsoft Barcode Reader with a valid license:
-(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; }
Use back-facing camera as the capture device:
-(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; }
Create a video capture session:
-(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]; }
Display video on preview layer:
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];
According to the environment brightness, toggle flash:
- (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]; } } }
Keep camera automatically focused:
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]; } }
Receive captured video with AVCaptureVideoDataOutputSampleBufferDelegate
and read barcode in 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]; } }
App Download
You can install the app from iTunes App Store.
Get iOS Barcode SDK
Do you want to quickly develop iOS barcode apps? Get your hands dirty now:
Dynamsoft iOS Barcode SDK, 30-day Free Trial
Support
If you have any questions about the above sample or the iOS barcode SDK, please feel free to contact support@dynamsoft.com.