zoukankan      html  css  js  c++  java
  • 二维码扫描

    原生二维码扫描

    个人是比较支持用原生二维码扫描的,这里也就仅仅以原生二维码扫面为范例。另也有二维码扫描库ZBarSDK(点这里)

    1.原生扫描用到的几个类

    1 @property (strong,nonatomic)AVCaptureDevice * device;
    2 @property (strong,nonatomic)AVCaptureDeviceInput * input;
    3 @property (strong,nonatomic)AVCaptureMetadataOutput * output;
    4 @property (strong,nonatomic)AVCaptureSession * session;
    5 @property (strong,nonatomic)AVCaptureVideoPreviewLayer * preview;

    2.在viewDidLoad里创建它们

     1 // Device
     2 _device = [AVCaptureDevicedefaultDeviceWithMediaType:AVMediaTypeVideo];
     3 
     4 // Input
     5 _input = [AVCaptureDeviceInputdeviceInputWithDevice:self.deviceerror:nil];
     6 
     7 // Output
     8 _output = [[AVCaptureMetadataOutputalloc]init];
     9 [_outputsetMetadataObjectsDelegate:selfqueue:dispatch_get_main_queue()];
    10 
    11 // Session
    12 _session = [[AVCaptureSessionalloc]init];
    13 [_sessionsetSessionPreset:AVCaptureSessionPresetHigh];

    连接输入和输出

    if ([_sessioncanAddInput:self.input])
    {
        [_sessionaddInput:self.input];
    }
    
    if ([_sessioncanAddOutput:self.output])
    {
        [_sessionaddOutput:self.output];
    }

    设置条码类型

     _output.metadataObjectTypes =@[AVMetadataObjectTypeQRCode]; 

    添加扫描画面

    1 _preview =[AVCaptureVideoPreviewLayerlayerWithSession:_session];
    2 _preview.videoGravity =AVLayerVideoGravityResizeAspectFill;
    3 _preview.frame =self.view.layer.bounds;
    4 [self.view.layerinsertSublayer:_previewatIndex:0];

    开始扫描

    [_sessionstartRunning];

    最后实现协议AVCaptureMetadataOutputObjectsDelegate

    - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
    {
       NSString *stringValue;
       if ([metadataObjectscount] >0){
       //停止扫描
       [_sessionstopRunning];        
       AVMetadataMachineReadableCodeObject * metadataObject = [metadataObjectsobjectAtIndex:0];
       stringValue = metadataObject.stringValue;        
      }
    }

    到了这一步就可以成功扫描二维码了

    还有一个小问题需要说明一下,之前写过一篇限制二维码扫描区域的,在这里稍微提一下。如下图微信扫描,把扫描范围限制在中间的方框内


    微信二维码扫描

    要想限制二维码扫描区域,需要设置一个参数rectOfInterest 这个参数有点特别 根据页面位置的 (0.X) 来确定。

    设置的方法

      [_output setRectOfInterest:CGRectMake()];

    生成二维码图片

    首先.h中
    /**
     *  生成二维码图片
     *
     *  @param QRString  二维码内容
     *  @param sizeWidth 图片size(正方形)
     *  @param color     填充色
     *
     *  @return  二维码图片
     */
    +(UIImage *)createQRimageString:(NSString *)QRString sizeWidth:(CGFloat)sizeWidth fillColor:(UIColor *)color;
    .m中
    #pragma mark 生成二维码
    /**
     *  生成二维码图片
     *
     *  @param QRString  二维码内容
     *  @param sizeWidth 图片size(正方形)
     *  @param color     填充色
     *
     *  @return  二维码图片
     */
    +(UIImage *)createQRimageString:(NSString *)QRString sizeWidth:(CGFloat)sizeWidth fillColor:(UIColor *)color{
    CIImage *ciimage = [self createQRForString:QRString];
    UIImage *qrcode = [self createNonInterpolatedUIImageFormCIImage:ciimage withSize:sizeWidth];
    if (color) {
        CGFloat R, G, B;
    
        CGColorRef colorRef = [color CGColor];
        long numComponents = CGColorGetNumberOfComponents(colorRef);
    
        if (numComponents == 4)
        {
            const CGFloat *components = CGColorGetComponents(colorRef);
            R = components[0];
            G = components[1];
            B = components[2];
        }
    
        UIImage *customQrcode = [self imageBlackToTransparent:qrcode withRed:R andGreen:G andBlue:B];
        return customQrcode;
    }
    
    return qrcode;
    
    }
    pragma mark
    
       #pragma mark - QRCodeGenerator
    + (CIImage *)createQRForString:(NSString *)qrString {
    // Need to convert the string to a UTF-8 encoded NSData object
    NSData *stringData = [qrString dataUsingEncoding:NSUTF8StringEncoding];
    // Create the filter
    CIFilter *qrFilter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
    // Set the message content and error-correction level
    [qrFilter setValue:stringData forKey:@"inputMessage"];
    [qrFilter setValue:@"M" forKey:@"inputCorrectionLevel"];
    // Send the image back
    return qrFilter.outputImage;
    }
    pragma mark
    
    #pragma mark - InterpolatedUIImage
    + (UIImage *)createNonInterpolatedUIImageFormCIImage:(CIImage *)image withSize:(CGFloat) size {
    CGRect extent = CGRectIntegral(image.extent);
    CGFloat scale = MIN(size/CGRectGetWidth(extent), size/CGRectGetHeight(extent));
    // create a bitmap image that we'll draw into a bitmap context at the desired size;
    size_t width = CGRectGetWidth(extent) * scale;
    size_t height = CGRectGetHeight(extent) * scale;
    CGColorSpaceRef cs = CGColorSpaceCreateDeviceGray();
    CGContextRef bitmapRef = CGBitmapContextCreate(nil, width, height, 8, 0, cs, (CGBitmapInfo)kCGImageAlphaNone);
    CIContext *context = [CIContext contextWithOptions:nil];
    CGImageRef bitmapImage = [context createCGImage:image fromRect:extent];
    CGContextSetInterpolationQuality(bitmapRef, kCGInterpolationNone);
    CGContextScaleCTM(bitmapRef, scale, scale);
    CGContextDrawImage(bitmapRef, extent, bitmapImage);
    // Create an image with the contents of our bitmap
    CGImageRef scaledImage = CGBitmapContextCreateImage(bitmapRef);
    // Cleanup
    CGContextRelease(bitmapRef);
    CGImageRelease(bitmapImage);
    return [UIImage imageWithCGImage:scaledImage];
    }
    pragma mark
    
    #pragma mark - imageToTransparent
    void ProviderReleaseData (void *info, const void *data, size_t size){
    free((void*)data);
    }
    + (UIImage*)imageBlackToTransparent:(UIImage*)image withRed:(CGFloat)red andGreen:(CGFloat)green andBlue:(CGFloat)blue{
    const int imageWidth = image.size.width;
    const int imageHeight = image.size.height;
    size_t      bytesPerRow = imageWidth * 4;
    uint32_t* rgbImageBuf = (uint32_t*)malloc(bytesPerRow * imageHeight);
    // create context
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(rgbImageBuf, imageWidth, imageHeight, 8, bytesPerRow, colorSpace,
                                                 kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipLast);
    CGContextDrawImage(context, CGRectMake(0, 0, imageWidth, imageHeight), image.CGImage);
    // traverse pixe
    int pixelNum = imageWidth * imageHeight;
    uint32_t* pCurPtr = rgbImageBuf;
    for (int i = 0; i < pixelNum; i++, pCurPtr++){
        if ((*pCurPtr & 0xFFFFFF00) < 0x99999900){
            // change color
            uint8_t* ptr = (uint8_t*)pCurPtr;
            ptr[3] = red; //0~255
            ptr[2] = green;
            ptr[1] = blue;
        }else{
            uint8_t* ptr = (uint8_t*)pCurPtr;
            ptr[0] = 0;
        }
    }
    // context to image
    CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, rgbImageBuf, bytesPerRow * imageHeight, ProviderReleaseData);
    CGImageRef imageRef = CGImageCreate(imageWidth, imageHeight, 8, 32, bytesPerRow, colorSpace,
                                        kCGImageAlphaLast | kCGBitmapByteOrder32Little, dataProvider,
                                        NULL, true, kCGRenderingIntentDefault);
    CGDataProviderRelease(dataProvider);
    UIImage* resultUIImage = [UIImage imageWithCGImage:imageRef];
    // release
    CGImageRelease(imageRef);
    CGContextRelease(context);
    CGColorSpaceRelease(colorSpace);
    return resultUIImage;
    }

    解析二维码图片

    .h中

    /**
     *  读取图片中二维码信息
     *
     *  @param image 图片
     *
     *  @return 二维码内容
     */
    +(NSString *)readQRCodeFromImage:(UIImage *)image;
    .m中
    #pragma mark 读取图片二维码
    /**
     *  读取图片中二维码信息
     *
     *  @param image 图片
     *
     *  @return 二维码内容
     */
    +(NSString *)readQRCodeFromImage:(UIImage *)image{
    NSData *data = UIImagePNGRepresentation(image);
    CIImage *ciimage = [CIImage imageWithData:data];
    if (ciimage) {
        CIDetector *qrDetector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:[CIContext contextWithOptions:@{kCIContextUseSoftwareRenderer:@(YES)}] options:@{CIDetectorAccuracy : CIDetectorAccuracyHigh}];
        NSArray *resultArr = [qrDetector featuresInImage:ciimage];
        if (resultArr.count >0) {
            CIFeature *feature = resultArr[0];
            CIQRCodeFeature *qrFeature = (CIQRCodeFeature *)feature;
            NSString *result = qrFeature.messageString;
    
            return result;
        }else{
            return nil;
        }
    }else{
        return nil;
    }
    }
    
     
  • 相关阅读:
    (转)关于IBM小机P520的面板使用
    (转)mysql的sql_mode合理设置
    (转)Mysql技术内幕InnoDB存储引擎-事务&备份&性能调优
    杨辉三角
    异或的陷阱(转)
    通过数组看栈堆
    数组的一些知识点和插入选择冒泡排序
    运算符
    Java的变量相关
    有符号的数据表示法(原、反、补)
  • 原文地址:https://www.cnblogs.com/-yun/p/5846384.html
Copyright © 2011-2022 走看看