iOS原生二维码/条形码相关

来源:互联网 发布:qq邮箱smtp设置 端口 编辑:程序博客网 时间:2024/05/20 18:46

一. 二维码/条形码扫描
iOS7以后AVFoundation框架可以实现二维码的扫描,首先介绍一下AVFoundation框架是如何实现此功能的:

AVFoundation是一个很大的基础库,用来创建基于时间的视听媒体,可以用它来创建,检查,编辑媒体文件也可以输入流从设备和操作视频实时捕捉和回放,详细框架可以到官网去查看About AVFoundation。下面主要介绍如何运用AVFoundation来扫描二维码;

首先获取流媒体信息我们需要用AVCaptureSession这样的一个对象来管理输入流和输出流,AVCaptureVideoPreviewsLayer对象来显示信息。基本流程:

这里写图片描述

AVCaptureSession 管理输入(AVCaptureInput)和输出(AVCaptureOutput)流,包含开启和停止会话方法。

AVCaptureDeviceInput 是AVCaptureInput的子类,可以作为输入捕获会话,用AVCaptureDevice实例初始化。

AVCaptureDevice 代表了物理捕获设备如:摄像机。用于配置等底层硬件设置相机的自动对焦模式。

AVCaptureMetadataOutput 是AVCaptureOutput的子类,处理输出捕获会话。捕获的对象传递给一个委托实现AVCaptureMetadataOutputObjectsDelegate协议。协议方法在指定的派发队列(dispatch queue)上执行。

AVCaptureVideoPreviewLayer CALayer的一个子类,显示捕获到的相机输出流

二维码扫描
二维码自定义扫描界面

代码实现:

- (void)createScanQRCode {    // 1. 创建捕捉会话    self.captureSession = [[AVCaptureSession alloc] init];    // 2. 添加输入设备    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];    AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];    [self.captureSession addInput:input];    // 3. 添加输出数据    AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc] init];    // 设置代理    [output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];    [self.captureSession addOutput:output];    // 设置输入元数据的类型    // AVMetadataObjectTypeQRCode    二维码    [output setMetadataObjectTypes:@[AVMetadataObjectTypeQRCode, AVMetadataObjectTypeEAN13Code]];    // 这句代码又放在添加输出数据(addOutPut: )之后,否则会报错    // 设置扫描区域    // 此属性坐标系平常设置的坐标系是完全相反的,即X与Y互换、W与H互换。    [output setRectOfInterest:CGRectMake(80 / kScreenHeight, 50 / kScreenWidth, (kScreenWidth - 100) / kScreenHeight, (kScreenWidth - 100) / kScreenWidth)];    // 4. 添加扫描图层    self.previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.captureSession];    self.previewLayer.frame = self.view.bounds;    [self.view.layer insertSublayer:self.previewLayer atIndex:0];    // 5. 开始扫描    [self.captureSession startRunning];    // 设置扫描区域的动画效果    [self scanWindowAnimation];}
// 设置扫描区域的动画效果()- (void)scanWindowAnimation {    if (self.isScan) {        [UIView animateWithDuration:10 animations:^{            self.lineView.frame = CGRectMake(50, 80 + kScreenWidth - 100, kScreenWidth - 100, 1);        } completion:^(BOOL finished) {            self.lineView.frame = CGRectMake(50, 80, kScreenWidth - 100, 1);            [self scanWindowAnimation];        }];    }}
#pragma mark - AVCaptureMetadataOutputObjectsDelegate 实现output的回调方法// 当扫描到数据时就会执行该方法- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection {    self.isScan = NO;    NSLog(@"%@", [NSThread currentThread]);    if (metadataObjects.count > 0) {        AVMetadataMachineReadableCodeObject *object = [metadataObjects lastObject];        NSLog(@"%@", object.stringValue);        // 停止扫描        [self.captureSession stopRunning];        // 将预览图层移除        [self.previewLayer removeFromSuperlayer];    } else {        NSLog(@"没有扫描到数据");    }}

二. 生成二维码图片

/**    生成二维码图片    @param QRString     二维码内容    @param sizeWidth    图片宽度(正方形)    @param color        填充色    @return             二维码图片 */+ (UIImage *)createQRImageString:(NSString *)QRString sizeWidth:(CGFloat)sizeWidth fillColor:(UIColor *)color;
#pragma mark - 生成二维码图片+ (UIImage *)createQRImageString:(NSString *)QRString sizeWidth:(CGFloat)sizeWidth fillColor:(UIColor *)color {    CIImage *ciImage = [self createQRForString:QRString];    UIImage *qrCode = [self createNonInterpolatedUIImageFromCIImage: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] * 255.0f;            G = components[1] * 255.0f;            B = components[2] * 255.0f;        }        UIImage *customQrcode = [self imageBlackToTransparent:qrCode withRed:R green:G blue:B];        return customQrcode;    }    return qrCode;}
#pragma mark - QRCodeGenerator+ (CIImage *)createQRForString:(NSString *)qrString {    // 将字符串转换为data数据    NSData *strData = [qrString dataUsingEncoding:NSUTF8StringEncoding];    // 创建filter    CIFilter *qrFilter = [CIFilter filterWithName:@"CIQRCodeGenerator"];    // 设置内容和纠错类别    [qrFilter setValue:strData forKey:@"inputMessage"];    [qrFilter setValue:@"H" forKey:@"inputCorrectionLevel"];    // 返回CIImage    return qrFilter.outputImage;}
#pragma mark - InterpolatedUIImage// 将CIImage转换为UIImage+ (UIImage *)createNonInterpolatedUIImageFromCIImage:(CIImage *)image withSize:(CGFloat)size {    CGRect extent = CGRectIntegral(image.extent);    CGFloat scale = MIN(size / CGRectGetWidth(extent), size / CGRectGetHeight(extent));    // 创建bitmap    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);    // 保存bitmap到图片    CGImageRef scaledImage = CGBitmapContextCreateImage(bitmapRef);    // 释放    CGContextRelease(bitmapRef);    CGImageRelease(bitmapImage);    return [UIImage imageWithCGImage:scaledImage];}
#pragma mark - imageToTransparent// 对二维码颜色进行填充void ProvideReleaseData (void *info, const void *data, size_t size) {    free((void *)data);}+ (UIImage *)imageBlackToTransparent:(UIImage *)image withRed:(CGFloat)red green:(CGFloat)green blue:(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);    // 创建上下文    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();    CGContextRef context = CGBitmapContextCreate(rgbImageBuf, imageWidth, imageHeight, 8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipLast);    CGContextDrawImage(context, CGRectMake(0, 0, imageWidth, imageHeight), image.CGImage);    // 遍历像素    int pixelNum = imageWidth * imageHeight;    uint32_t *pCurPtr = rgbImageBuf;    for (int i = 0; i < pixelNum; i++, pCurPtr++) {        if ((*pCurPtr & 0xFFFFFF00) < 0x99999900) {            // 改变颜色            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;        }    }    // 输出图片    CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, rgbImageBuf, bytesPerRow * imageHeight, ProvideReleaseData);    CGImageRef imageRef = CGImageCreate(imageWidth, imageHeight, 8, 32, bytesPerRow, colorSpace, kCGImageAlphaLast | kCGBitmapByteOrder32Little, dataProvider, NULL, true, kCGRenderingIntentDefault);    CGDataProviderRelease(dataProvider);    UIImage *resultUIImage = [UIImage imageWithCGImage:imageRef];    // 清理空间    CGImageRelease(imageRef);    CGContextRelease(context);    CGColorSpaceRelease(colorSpace);    return resultUIImage;}

三. 解析二维码图片

#pragma mark - 读取图片二维码+ (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 *resultArray = [qrDetector featuresInImage:ciImage];        if (resultArray.count > 0) {            CIFeature *feature = resultArray[0];            CIQRCodeFeature *qrFeature = (CIQRCodeFeature *)feature;            NSString *result = qrFeature.messageString;            return result;        } else {            return nil;        }    } else {        return nil;    }}
0 0
原创粉丝点击