二維碼掃描:ZBar,ZXing的使用

原文鏈接:http://blog.csdn.net/whjblog/article/details/15809859

iOS二維碼掃描開源庫主要有Zbar和ZXing,在完成項目的過程中都用過,開始時用了Zbar,但其相對於ZXing掃描識別效率太低,無法達到項目要求,所以改用ZXing。兩個開源庫都可以識別二維碼,但ZBar還支持條形碼,ZXing識別條形碼還需要改一些地方。


一、ZBar的使用

1.下載ZBar SDK,將ZBarSDK拖動到Xcode項目

下載地址:https://github.com/bmorton/ZBarSDK

2.添加framework框架

      * AVFoundation.framework (weak)
      * CoreMedia.framework (weak)
      * CoreVideo.framework (weak)
      * QuartzCore.framework

3.掃描代碼

引入頭文件 #import  "ZBarSDK.h" ,實現ZBarReaderDelegate協議

  1. ZBarReaderViewController *reader = [ZBarReaderViewController new];  
  2.    reader.readerDelegate = self;  
  3.    reader.supportedOrientationsMask = ZBarOrientationMaskAll;  
  4.      
  5.    ZBarImageScanner *scanner = reader.scanner;  
  6.      
  7.    [scanner setSymbology: ZBAR_I25  
  8.                   config: ZBAR_CFG_ENABLE  
  9.                       to: 0];  
  10.      
  11.    [self presentModalViewController:reader animated:YES];  
  12.    [reader release];  

掃描結果回調

  1. - (void) imagePickerController: (UIImagePickerController*) reader didFinishPickingMediaWithInfo: (NSDictionary*) info  
  2. {  
  3.     id<NSFastEnumeration> results = [info objectForKey: ZBarReaderControllerResults];  
  4.     ZBarSymbol *symbol = nil;  
  5.     for(symbol in results)  
  6.         break;  
  7.       
  8.     text =  symbol.data ;  
  9. }  

還可以在ZBarReaderViewController自定義掃描界面和掃描區域(scanCrop)。


二、ZXing的使用

1.下載ZXIng,下載地址: https://github.com/zxing/zxing   .由於支持各種語言,整個工程比較大,IOS 只需保留cpp和iphone這2個文件夾,整個目錄結構不變,cpp文件夾只保留cpp/core/src/zxing下面的內容,其餘都可以全部刪除。然後把刪減好的zxing目錄移動到我們的iOS項目的目錄下(也可以右擊選擇Add files to ‘project’),並在 zxing/iphone/ZXingWidget/目錄下把ZXingWidget.xcodeproj拖動到我們的項目工程中。

2.選擇 target ——>Build Phases   在 Link Binary with Libraries裏 添加libZXingWidget.a,在Target Dependencies添加ZXingWidget在target ——>Build Settings ——>Headers Search Path 添加兩個路徑: 

./zxing/iphone/ZXingWidget/Classes

./zxing/cpp/core/src

第一個設成recursive ,第二個設成non-recursive

添加一下frameworks 支持

  • AVFoundation
  • AudioToolbox
  • CoreVideo
  • CoreMedia
  • libiconv
  • AddressBook
  • AddressBookUI

3.掃描代碼

(1)直接引用

頭文件:
#import <ZXingWidgetController.h>

#import <QRCodeReader.h>

掃描調用代碼:

  1. ZXingWidgetController *widController = [[ZXingWidgetController alloc] initWithDelegate:self showCancel:YES OneDMode:NO];  
  2.    NSMutableSet *readers = [[NSMutableSet alloc] init];  
  3.    QRCodeReader *qrcodeReader = [[QRCodeReader alloc] init];  
  4.    [readers addObject:qrcodeReader];  
  5.    widController.readers = readers;  
  6.    [self presentViewController:widController animated:YES completion:^{}];  

掃描結果回調:

  1. @protocol ZXingDelegate  
  2. - (void)zxingController:(ZXingWidgetController*)controller didScanResult:(NSString *)result;  
  3. - (void)zxingControllerDidCancel:(ZXingWidgetController*)controller;  
  4. @end  

還需要把引入的.m文件改爲.mm。

(2)自定義掃描

我的項目要求中需要自定義掃描界面和掃描區域,還要加入C語言混編,所以就用了這種方法。

頭文件:

  1. #import <AssetsLibrary/AssetsLibrary.h>  
  2. #import <QRCodeReader.h>  
  3. #import <TwoDDecoderResult.h>  
  4. #import <Decoder.h>  

初始化AVCapture

  1. - (void)initCapture  
  2. {  
  3.   AVCaptureDevice* inputDevice =  
  4.     [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];  
  5.   AVCaptureDeviceInput *captureInput =  
  6.     [AVCaptureDeviceInput deviceInputWithDevice:inputDevice error:nil];  
  7.   AVCaptureVideoDataOutput *captureOutput = [[AVCaptureVideoDataOutput alloc] init];   
  8.   captureOutput.alwaysDiscardsLateVideoFrames = YES;   
  9.   [captureOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()];  
  10.   NSString* key = (NSString*)kCVPixelBufferPixelFormatTypeKey;  
  11.   NSNumber* value = [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA];   
  12.   NSDictionary* videoSettings = [NSDictionary dictionaryWithObject:value forKey:key];   
  13.   [captureOutput setVideoSettings:videoSettings];   
  14.   self.captureSession = [[[AVCaptureSession alloc] init] autorelease];  
  15.   
  16.   NSString* preset = 0;  
  17.   if (NSClassFromString(@"NSOrderedSet") && // Proxy for "is this iOS 5" ...  
  18.       [UIScreen mainScreen].scale > 1 &&  
  19.       isIPad() &&   
  20.       [inputDevice  
  21.         supportsAVCaptureSessionPreset:AVCaptureSessionPresetiFrame960x540]) {  
  22.     preset = AVCaptureSessionPresetiFrame960x540;  
  23.   }  
  24.   if (!preset) {  
  25.     preset = AVCaptureSessionPresetMedium;  
  26.   }  
  27.   self.captureSession.sessionPreset = preset;  
  28.   
  29.   [self.captureSession addInput:captureInput];  
  30.   [self.captureSession addOutput:captureOutput];  
  31.   
  32.   [captureOutput release];  
  33.   
  34.   if (!self.prevLayer) {  
  35.     self.prevLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.captureSession];  
  36.   }  
  37.   self.prevLayer.frame = self.view.bounds;  
  38.   self.prevLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;  
  39.   [self.view.layer addSublayerself.prevLayer];  
  40.   [self.captureSession startRunning];  
  41. }  

 得到AVCapture回調函數

  1. - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection  
  2. {  
  3.     if (!isScanning||delegate==nil) {  
  4.         return;  
  5.     }  
  6.     if (sampleBuffer)  
  7.     {  
  8.         //將sampleBuffer轉化爲UIImage  
  9.         UIImage *image = [self imageFromSampleBuffer:sampleBuffer];  
  10.         //用Decoder來解析識別圖像  
  11.         [self decodeImage:image];  
  12.     }  
  13. }  
  1. - (void)decodeImage:(UIImage *)image  
  2. {  
  3.     NSMutableSet *qrReader = [[NSMutableSet alloc] init];  
  4.     QRCodeReader *qrcoderReader = [[QRCodeReader alloc] init];  
  5.     [qrReader addObject:qrcoderReader];  
  6.     [qrcoderReader release];  
  7.       
  8.     Decoder *decoder = [[Decoder alloc] init];  
  9.     decoder.delegate = self;  
  10.     decoder.readers = qrReader;  
  11.     [decoder decodeImage:image];  
  12.     [decoder release];  
  13.     [qrReader release];  
  14. }  
Decoder回調獲得識別結果

  1. @optional  
  2. - (void)decoder:(Decoder *)decoder willDecodeImage:(UIImage *)image usingSubset:(UIImage *)subset;  
  3. - (void)decoder:(Decoder *)decoder didDecodeImage:(UIImage *)image usingSubset:(UIImage *)subset withResult:(TwoDDecoderResult *)result;  
  4. - (void)decoder:(Decoder *)decoder failedToDecodeImage:(UIImage *)image usingSubset:(UIImage *)subset reason:(NSString *)reason;  
  5. - (void)decoder:(Decoder *)decoder foundPossibleResultPoint:(CGPoint)point;  

注意掃描的畫面不會跟着設備旋轉,當橫豎轉換是需要改變畫面

  1. CGFloat angle = 0.0f;  
  2.     switch (barOrientation)  
  3.     {  
  4.         case UIInterfaceOrientationPortrait:  
  5.             angle = 0.0f;  
  6.             break;  
  7.         case UIInterfaceOrientationPortraitUpsideDown:  
  8.             angle = M_PI;  
  9.             break;  
  10.         case UIInterfaceOrientationLandscapeLeft:  
  11.             angle = M_PI / 2;  
  12.             break;  
  13.         case UIInterfaceOrientationLandscapeRight:  
  14.             angle = -M_PI / 2;  
  15.             break;  
  16.         default:  
  17.             break;  
  18.     }  
  19.     CATransform3D transform =  CATransform3DMakeRotation(angle, 001.0);  
  20.     self.captureVideoPreviewLayer.transform =transform;  
  21.     self.captureVideoPreviewLayer.frame = layerframe;  

發佈了34 篇原創文章 · 獲贊 4 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章