ios二维码条码扫描问题

来源:互联网 发布:孤独大脑 喻颖正 知乎 编辑:程序博客网 时间:2024/04/24 15:43

ios原生AVFoudation扫描在同时支持二维码和条码扫描时,二维码总是很快得到数据,条码则有时有有时无,在坑里待了一段时间后终于找到原因,VCaptureMetadataOutput 有一个属性 rectOfInterest



rectOfInterest

就是设置元数据识别搜索的区域。

这个属性有点问题,不是普通的CGRect,四个值都需要在0~1之间。

AVCaptureVideoPreviewLayer 有个方法 

- (CGRect)metadataOutputRectOfInterestForRect:(CGRect)rectInLayerCoordinates 

可以看看这个方法的说明:



方法说明

描述就是:把一个在previewlayer坐标系中的rect 转换成 一个在metadataoutputs坐标系中的rect。

这个方法需要的rect参数是我们系统坐标系中的rect.

SO 。这就得到了我们需要的rectOfInterest。


代码:

- (BOOL)startReading {

    NSError *error;

    

    //1.初始化捕捉设备(AVCaptureDevice),类型为AVMediaTypeVideo

    AVCaptureDevice *captureDevice = [AVCaptureDevicedefaultDeviceWithMediaType:AVMediaTypeVideo];

    

    //2.captureDevice创建输入流

    AVCaptureDeviceInput *input = [AVCaptureDeviceInputdeviceInputWithDevice:captureDeviceerror:&error];

    if (!input) {

        NSLog(@"%@", [errorlocalizedDescription]);

        returnNO;

    }

    

    //3.创建媒体数据输出流

    AVCaptureMetadataOutput *captureMetadataOutput = [[AVCaptureMetadataOutputalloc]init];

    

    //4.实例化捕捉会话

    _captureSession = [[AVCaptureSessionalloc]init];

    

    //4.1.将输入流添加到会话

    [_captureSessionaddInput:input];

    

    [_captureSessionsetSessionPreset:AVCaptureSessionPresetHigh];

    

    //4.2.将媒体输出流添加到会话中

    [_captureSessionaddOutput:captureMetadataOutput];

    

    //5.创建串行队列,并加媒体输出流添加到队列当中

    dispatch_queue_t dispatchQueue;

    //dispatchQueue = dispatch_queue_create("myQueue", NULL);

    dispatchQueue = dispatch_get_main_queue();

    //5.1.设置代理

    [captureMetadataOutput setMetadataObjectsDelegate:selfqueue:dispatchQueue];

    

    //5.2.设置输出媒体数据类型为QRCode

    [captureMetadataOutput setMetadataObjectTypes:@[AVMetadataObjectTypeQRCode,AVMetadataObjectTypeEAN13Code,AVMetadataObjectTypeEAN8Code,AVMetadataObjectTypeCode128Code]];

    

    //6.实例化预览图层

    _videoPreviewLayer = [[AVCaptureVideoPreviewLayeralloc]initWithSession:_captureSession];

    

    //7.设置预览图层填充方式

    [_videoPreviewLayersetVideoGravity:AVLayerVideoGravityResizeAspectFill];

    

    //8.设置图层的frame

    [_videoPreviewLayersetFrame:_vPreview.layer.bounds];

    

    //9.将图层添加到预览view的图层上

    [_vPreview.layeraddSublayer:_videoPreviewLayer];

    

    //10.设置扫描范围

    captureMetadataOutput.rectOfInterest =CGRectMake(0.2f,0.2f,0.8f,0.8f);

    

    //10.1.扫描框

    _boxView = [[UIViewalloc]initWithFrame:CGRectMake(60, [[UIScreenmainScreenbounds].size.height/2 -30 -([[UIScreenmainScreenbounds].size.width -60 * 2)/2, [[UIScreenmainScreenbounds].size.width -60 * 2, [[UIScreenmainScreenbounds].size.width -60 * 2)];

    _boxView.layer.borderColor =mainColor.CGColor;

    _boxView.layer.borderWidth =1.0f;

    [_vPreviewaddSubview:_boxView];

    

    //10.2.扫描线

    _scanLayer = [[CALayeralloc]init];

    _scanLayer.frame =CGRectMake(0,0,_boxView.bounds.size.width,1);

    _scanLayer.backgroundColor = [UIColorcolorWithRed:190.0/255green:190.0/255blue:190.0/255alpha:1.0].CGColor;

    [_boxView.layeraddSublayer:_scanLayer];

    

    NSTimer *timer = [NSTimerscheduledTimerWithTimeInterval:0.2ftarget:selfselector:@selector(moveScanLayer:)userInfo:nilrepeats:YES];

    [timer fire];

    

    //放大焦距

    [captureDevice lockForConfiguration:&error];

    

    if (captureDevice.activeFormat.videoMaxZoomFactor > 2) {

        captureDevice.videoZoomFactor =2;

    }else{

        captureDevice.videoZoomFactor = captureDevice.activeFormat.videoMaxZoomFactor;

    }

    [captureDevice unlockForConfiguration];

    

    //10.开始扫描

    [_captureSessionstartRunning];

    

    //11.必须在startRunning之后才会生效(坑哦)

    CGRect rect =CGRectMake(30,100,self.view.frame.size.width - 60, 300);

    CGRect intertRect = [_videoPreviewLayermetadataOutputRectOfInterestForRect:rect];

    CGRect layerRect = [_videoPreviewLayerrectForMetadataOutputRectOfInterest:intertRect];

    

    NSLog(@"%@,  %@",NSStringFromCGRect(intertRect),NSStringFromCGRect(layerRect));

    

    captureMetadataOutput.rectOfInterest = intertRect;

    

//    这种方法实际不可行

//    float width = self.view.frame.size.width;// AVCaptureVideoPreviewLayer的对象的宽度

//    float height = self.view.frame.size.height;// AVCaptureVideoPreviewLayer的对象的高度

//    

//    captureMetadataOutput.rectOfInterest=CGRectMake(100/height, (width/2 -110)/width +50, 220/height, 220/width);

    

    returnYES;

}


第11步就是解决方法,指定新的rectOfInterest给captureMetadataOutput,之后扫条码和二维码就都可以啦




阅读全文
0 0