我如何扫描iOS上的条形码?
我如何简单地扫描iPhone和/或iPad上的条形码?
我们为iPhone制作了“条形码”应用程序。 它可以解码QR码。 源代码可以从zxing项目中获得 ; 具体来说,你想看看iPhone客户端和核心库的部分C ++端口 。 从Java代码的0.9版本开始,这个端口有点旧了,但仍然能够很好地工作。
如果您需要扫描其他格式(如1D格式),则可以将此项目中的Java代码的端口继续保存为C ++。
编辑:项目中的条码和iphone
代码在2014年年初开始退休。
查阅ZBar读取QR码和ECN / ISBN代码,并可在LGPL v2许可下使用。
与iOS7
的发布一样,您不再需要使用外部框架或库。 具有AVFoundation的iOS生态系统现在完全支持从EAN到UPC的几乎所有的QR码扫描 。
只要看看技术说明和AVFoundation编程指南。 AVMetadataObjectTypeQRCode
是你的朋友。
这是一个很好的教程 ,它一步一步显示: iPhone QR码扫描库iOS7
只是一个例子,如何设置它:
#pragma mark - #pragma mark AVFoundationScanSetup - (void) setupScanner; { self.device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; self.input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:nil]; self.session = [[AVCaptureSession alloc] init]; self.output = [[AVCaptureMetadataOutput alloc] init]; [self.session addOutput:self.output]; [self.session addInput:self.input]; [self.output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()]; self.output.metadataObjectTypes = @[AVMetadataObjectTypeQRCode]; self.preview = [AVCaptureVideoPreviewLayer layerWithSession:self.session]; self.preview.videoGravity = AVLayerVideoGravityResizeAspectFill; self.preview.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height); AVCaptureConnection *con = self.preview.connection; con.videoOrientation = AVCaptureVideoOrientationLandscapeLeft; [self.view.layer insertSublayer:self.preview atIndex:0]; }
iPhone 4相机不仅仅是条码的function。 斑马线条码库在github zxing-iphone上有一个叉子。 它是开源的。
liteqr是github上的“从zxing移植到Objective C中的精简QR阅读器”,并且支持Xcode 4。
有两个主要的图书馆:
-
ZXing用Java编写的库,然后移植到Objective C / C ++(仅QR码)。 另一个端口ObjC已经完成了,由TheLevelUp: ZXingObjC
-
ZBar是一款用于阅读条码的开源软件,基于C语言。
根据我的实验,至less在iPhone上, ZBar比ZXing 更精确,更快速 。
HOWTO:添加一个条形码阅读器到iPhone应用程序 ,指向ZBar iPhone SDK ,看起来很有帮助( 从另一个线程 )。
不知道这是否会有所帮助,但是这里是一个开源QR码库的链接。 正如你可以看到一些人已经使用这个来创buildiphone的应用程序。
维基百科有一篇文章解释什么是QR码 。 在我看来,QR码比iPhone中的标准条码更适合用途,因为它是为这种types的实现而devise的。
如果支持iPad 2或iPod Touch对于您的应用程序非常重要,我会select一个条形码扫描器SDK,可以解码模糊图像中的条形码,比如我们的iOS和Android版的Scandit条形码扫描仪SDK 。 对具有自动对焦相机的手机解码模糊条形码图像也很有帮助,因为用户无需等待自动对焦。
Scandit提供免费的社区价格计划,还有一个产品API,可以很容易地将条形码数字转换为产品名称。
(声明:我是Scandit的联合创始人)
你可以看看Stefan Hafeneger的iPhone DataMatrix Reader源代码 ( Google Code项目 ; 存档的博客文章 ),如果它仍然可用的话。
现在还有另外一个select,如果你愿意授权SDK。 查看适用于UPCA / EAN13的RedLaser SDK ,使用或不使用自动对焦。 最近更新。
我是计算机视觉创业公司的创始人,只是供参考。
iPhone相机的问题是,第一个型号(其中有吨使用)有一个固定焦距的相机,不能在2英尺的距离上的图像对焦。 图像模糊和扭曲,如果距离较远,条形码中没有足够的细节/信息。
一些公司已经开发出iPhone应用程序,可以使用先进的去模糊技术。 这些应用程序,你可以find苹果应用程序商店:pic2shop,RedLaser和ShopSavvy。 所有的公司都宣布,他们也有SDKs – 一些免费或非常优惠的条款,检查一个。
对于本机iOS 7条形码扫描器,请查看我在GitHub上的项目:
这里是简单的代码:
func scanbarcode() { view.backgroundColor = UIColor.blackColor() captureSession = AVCaptureSession() let videoCaptureDevice = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo) let videoInput: AVCaptureDeviceInput do { videoInput = try AVCaptureDeviceInput(device: videoCaptureDevice) } catch { return } if (captureSession.canAddInput(videoInput)) { captureSession.addInput(videoInput) } else { failed(); return; } let metadataOutput = AVCaptureMetadataOutput() if (captureSession.canAddOutput(metadataOutput)) { captureSession.addOutput(metadataOutput) metadataOutput.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue()) metadataOutput.metadataObjectTypes = [AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypePDF417Code] } else { failed() return } previewLayer = AVCaptureVideoPreviewLayer(session: captureSession); previewLayer.frame = view.layer.bounds; previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; view.layer.addSublayer(previewLayer); view.addSubview(closeBtn) view.addSubview(backimg) captureSession.startRunning(); } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } func failed() { let ac = UIAlertController(title: "Scanning not supported", message: "Your device does not support scanning a code from an item. Please use a device with a camera.", preferredStyle: .Alert) ac.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil)) presentViewController(ac, animated: true, completion: nil) captureSession = nil } override func viewWillAppear(animated: Bool) { super.viewWillAppear(animated) if (captureSession?.running == false) { captureSession.startRunning(); } } override func viewWillDisappear(animated: Bool) { super.viewWillDisappear(animated) if (captureSession?.running == true) { captureSession.stopRunning(); } } func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) { captureSession.stopRunning() if let metadataObject = metadataObjects.first { let readableObject = metadataObject as! AVMetadataMachineReadableCodeObject; AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate)) foundCode(readableObject.stringValue); } // dismissViewControllerAnimated(true, completion: nil) } func foundCode(code: String) { var createAccountErrorAlert: UIAlertView = UIAlertView() createAccountErrorAlert.delegate = self createAccountErrorAlert.title = "Alert" createAccountErrorAlert.message = code createAccountErrorAlert.addButtonWithTitle("ok") createAccountErrorAlert.addButtonWithTitle("Retry") createAccountErrorAlert.show() NSUserDefaults.standardUserDefaults().setObject(code, forKey: "barcode") NSUserDefaults.standardUserDefaults().synchronize() ItemBarcode = code print(code) } override func prefersStatusBarHidden() -> Bool { return true } override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask { return .Portrait }
有时生成QR码也是有用的。 这里有一个非常好的C库,它就像一个魅力一样。 它被称为libqrencode 。 编写显示QR码的自定义视图并不困难,可以通过对QuartzCore的基本了解来完成。
你可以检查ZBarSDK读取QR码和ECN / ISBN码很容易集成尝试下面的代码。
- (void)scanBarcodeWithZBarScanner { // ADD: present a barcode reader that scans from the camera feed ZBarReaderViewController *reader = [ZBarReaderViewController new]; reader.readerDelegate = self; reader.supportedOrientationsMask = ZBarOrientationMaskAll; ZBarImageScanner *scanner = reader.scanner; // TODO: (optional) additional reader configuration here // EXAMPLE: disable rarely used I2/5 to improve performance [scanner setSymbology: ZBAR_I25 config: ZBAR_CFG_ENABLE to: 0]; //Get the return value from controller [reader setReturnBlock:^(BOOL value) { }
而在didFinishPickingMediaWithInfo中,我们获得条形码值。
- (void) imagePickerController: (UIImagePickerController*) reader didFinishPickingMediaWithInfo: (NSDictionary*) info { // ADD: get the decode results id<NSFastEnumeration> results = [info objectForKey: ZBarReaderControllerResults]; ZBarSymbol *symbol = nil; for(symbol in results) // EXAMPLE: just grab the first barcode break; // EXAMPLE: do something useful with the barcode data barcodeValue = symbol.data; // EXAMPLE: do something useful with the barcode image barcodeImage = [info objectForKey:UIImagePickerControllerOriginalImage]; [_barcodeIV setImage:barcodeImage]; //set the values for to TextFields [self setBarcodeValue:YES]; // ADD: dismiss the controller (NB dismiss from the *reader*!) [reader dismissViewControllerAnimated:YES completion:nil]; }
我相信这可以使用AVFramework完成,这里是示例代码来做到这一点
import UIKit import AVFoundation class ViewController: UIViewController, AVCaptureMetadataOutputObjectsDelegate { @IBOutlet weak var lblQRCodeResult: UILabel! @IBOutlet weak var lblQRCodeLabel: UILabel! var objCaptureSession:AVCaptureSession? var objCaptureVideoPreviewLayer:AVCaptureVideoPreviewLayer? var vwQRCode:UIView? override func viewDidLoad() { super.viewDidLoad() self.configureVideoCapture() self.addVideoPreviewLayer() self.initializeQRView() } func configureVideoCapture() { let objCaptureDevice = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo) var error:NSError? let objCaptureDeviceInput: AnyObject! do { objCaptureDeviceInput = try AVCaptureDeviceInput(device: objCaptureDevice) as AVCaptureDeviceInput } catch let error1 as NSError { error = error1 objCaptureDeviceInput = nil } objCaptureSession = AVCaptureSession() objCaptureSession?.addInput(objCaptureDeviceInput as! AVCaptureInput) let objCaptureMetadataOutput = AVCaptureMetadataOutput() objCaptureSession?.addOutput(objCaptureMetadataOutput) objCaptureMetadataOutput.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue()) objCaptureMetadataOutput.metadataObjectTypes = [AVMetadataObjectTypeQRCode] } func addVideoPreviewLayer() { objCaptureVideoPreviewLayer = AVCaptureVideoPreviewLayer(session: objCaptureSession) objCaptureVideoPreviewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill objCaptureVideoPreviewLayer?.frame = view.layer.bounds self.view.layer.addSublayer(objCaptureVideoPreviewLayer!) objCaptureSession?.startRunning() self.view.bringSubviewToFront(lblQRCodeResult) self.view.bringSubviewToFront(lblQRCodeLabel) } func initializeQRView() { vwQRCode = UIView() vwQRCode?.layer.borderColor = UIColor.redColor().CGColor vwQRCode?.layer.borderWidth = 5 self.view.addSubview(vwQRCode!) self.view.bringSubviewToFront(vwQRCode!) } func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) { if metadataObjects == nil || metadataObjects.count == 0 { vwQRCode?.frame = CGRectZero lblQRCodeResult.text = "QR Code wans't found" return } let objMetadataMachineReadableCodeObject = metadataObjects[0] as! AVMetadataMachineReadableCodeObject if objMetadataMachineReadableCodeObject.type == AVMetadataObjectTypeQRCode { let objBarCode = objCaptureVideoPreviewLayer?.transformedMetadataObjectForMetadataObject(objMetadataMachineReadableCodeObject as AVMetadataMachineReadableCodeObject) as! AVMetadataMachineReadableCodeObject vwQRCode?.frame = objBarCode.bounds; if objMetadataMachineReadableCodeObject.stringValue != nil { lblQRCodeResult.text = objMetadataMachineReadableCodeObject.stringValue } } } }