iOS 原生二維碼掃描和生成


代碼地址如下:
http://www.demodashi.com/demo/12551.html

一、效果預覽:


功能描述:WSLNativeScanTool是在利用原生API的條件下封裝的二維碼掃描工具,支持二維碼的掃描、識別圖中二維碼、生成自定義顏色和中心圖標的二維碼、監測環境亮度、打開閃光燈這些功能;WSLScanView是參照微信封裝的一個掃一掃界面,支持線條顏色、大小、動畫圖片、矩形掃描框樣式的自定義;這個示例本身就是仿照微信的掃一掃功能實現的。

二、實現

主要代碼如下:

  • 初始化掃描識別對象
- (AVCaptureSession *)session{
    
    if (_session == nil){
        //獲取攝像設備
        AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
        //創建輸入流
        AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
        if (!input){
            return nil;
        }
        
        //創建二維碼掃描輸出流
        AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc] init];
        //設置代理 在主線程里刷新
        [output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
        //設置采集掃描區域的比例 默認全屏是(0,0,1,1)
        //rectOfInterest 填寫的是一個比例,輸出流視圖preview.frame為 x , y, w, h, 要設置的矩形快的scanFrame 為 x1, y1, w1, h1. 那么rectOfInterest 應該設置為 CGRectMake(y1/y, x1/x, h1/h, w1/w)。
        CGFloat x = CGRectGetMinX(self.scanFrame)/ CGRectGetWidth(self.preview.frame);
        CGFloat y = CGRectGetMinY(self.scanFrame)/ CGRectGetHeight(self.preview.frame);
        CGFloat width = CGRectGetWidth(self.scanFrame)/ CGRectGetWidth(self.preview.frame);
        CGFloat height = CGRectGetHeight(self.scanFrame)/ CGRectGetHeight(self.preview.frame);
        output.rectOfInterest = CGRectMake(y, x, height, width);
        
        // 創建環境光感輸出流
        AVCaptureVideoDataOutput *lightOutput = [[AVCaptureVideoDataOutput alloc] init];
        [lightOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()];
        
        _session = [[AVCaptureSession alloc] init];
        //高質量采集率
        [_session setSessionPreset:AVCaptureSessionPresetHigh];
        [_session addInput:input];
        [_session addOutput:output];
        [_session addOutput:lightOutput];
        
        //設置掃碼支持的編碼格式(這里設置條形碼和二維碼兼容)
        output.metadataObjectTypes = @[AVMetadataObjectTypeQRCode,
                                       AVMetadataObjectTypeEAN13Code,
                                       AVMetadataObjectTypeEAN8Code,
                                       AVMetadataObjectTypeCode128Code];
    }
    
    return _session;
}
  • 掃描出結果的代理方法
#pragma mark -- AVCaptureMetadataOutputObjectsDelegate
//掃描完成后執行
-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{
    
    if (metadataObjects.count > 0){
        AVMetadataMachineReadableCodeObject *metadataObject = [metadataObjects firstObject];
        // 掃描完成后的字符
        //        NSLog(@"掃描出 %@",metadataObject.stringValue);
        if(self.scanFinishedBlock != nil){
            self.scanFinishedBlock(metadataObject.stringValue);
        }
    }
}
#pragma mark- AVCaptureVideoDataOutputSampleBufferDelegate的方法
//掃描過程中執行,主要用來判斷環境的黑暗程度
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection{
    
    if (self.monitorLightBlock == nil) {
        return;
    }
    
    CFDictionaryRef metadataDict = CMCopyDictionaryOfAttachments(NULL,sampleBuffer, kCMAttachmentMode_ShouldPropagate);
    NSDictionary *metadata = [[NSMutableDictionary alloc] initWithDictionary:(__bridge NSDictionary*)metadataDict];
    CFRelease(metadataDict);
    NSDictionary *exifMetadata = [[metadata objectForKey:(NSString *)kCGImagePropertyExifDictionary] mutableCopy];
    float brightnessValue = [[exifMetadata objectForKey:(NSString *)kCGImagePropertyExifBrightnessValue] floatValue];
    
    //    NSLog(@"環境光感 : %f",brightnessValue);
    
    // 根據brightnessValue的值來判斷是否需要打開和關閉閃光燈
    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    BOOL result = [device hasTorch];// 判斷設備是否有閃光燈
    if ((brightnessValue < 0) && result) {
        // 環境太暗,可以打開閃光燈了
    }else if((brightnessValue > 0) && result){
        // 環境亮度可以
    }
    if (self.monitorLightBlock != nil) {
        self.monitorLightBlock(brightnessValue);
    }
    
}

三、用法

  • 實例化WSLNativeScanTool工具類和WSLScanView界面類;用法很簡單,頭文件里注釋的也挺詳細的。
//輸出流視圖
    UIView *preview  = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height - 0)];
    [self.view addSubview:preview];
    __weak typeof(self) weakSelf = self;
    //構建掃描樣式視圖
    _scanView = [[WSLScanView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height - 0)];
    _scanView.scanRetangleRect = CGRectMake(60, 120, (self.view.frame.size.width - 2 * 60),  (self.view.frame.size.width - 2 * 60));
    _scanView.colorAngle = [UIColor greenColor];
    _scanView.photoframeAngleW = 20;
    _scanView.photoframeAngleH = 20;
    _scanView.photoframeLineW = 2;
    _scanView.isNeedShowRetangle = YES;
    _scanView.colorRetangleLine = [UIColor whiteColor];
    _scanView.notRecoginitonArea = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5];
    _scanView.animationImage = [UIImage imageNamed:@"scanLine"];
    _scanView.myQRCodeBlock = ^{
     [WSLNativeScanTool createQRCodeImageWithString:@"https://www.jianshu.com/u/e15d1f644bea" andSize:CGSizeMake(250, 250) andBackColor:[UIColor whiteColor] andFrontColor:[UIColor orangeColor] andCenterImage:[UIImage imageNamed:@"piao"]];
        createQRCodeController.qrString = @"https://www.jianshu.com/u/e15d1f644bea";
    };
    _scanView.flashSwitchBlock = ^(BOOL open) {
        [weakSelf.scanTool openFlashSwitch:open];
    };
    [self.view addSubview:_scanView];
    //初始化掃描工具
    _scanTool = [[WSLNativeScanTool alloc] initWithPreview:preview andScanFrame:_scanView.scanRetangleRect];
    _scanTool.scanFinishedBlock = ^(NSString *scanString) {
        NSLog(@"掃描結果 %@",scanString);
        [weakSelf.scanTool sessionStopRunning];
        [weakSelf.scanTool openFlashSwitch:NO];
    };
    _scanTool.monitorLightBlock = ^(float brightness) {
        NSLog(@"環境光感 : %f",brightness);
        if (brightness < 0) {
            // 環境太暗,顯示閃光燈開關按鈕
            [weakSelf.scanView showFlashSwitch:YES];
        }else if(brightness > 0){
            // 環境亮度可以,且閃光燈處於關閉狀態時,隱藏閃光燈開關
            if(!weakSelf.scanTool.flashOpen){
                [weakSelf.scanView showFlashSwitch:NO];
            }
        }
    };
    [_scanTool sessionStartRunning];
    [_scanView startScanAnimation];

四、項目結構

五、其他補充

暫沒
iOS 原生二維碼掃描和生成

代碼地址如下:
http://www.demodashi.com/demo/12551.html

注:本文著作權歸作者,由demo大師代發,拒絕轉載,轉載需要作者授權


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM