iOS - QRCode(二维码)的生成和识别

时间:2022-02-11 08:50:26

I. 二维码的生成模块

#import "CreatQRViewController.h"
//必须调用
#import <CoreImage/CoreImage.h>

@interface CreatQRViewController ()

@property (weak, nonatomic) IBOutlet UIImageView *QRCodeImgV; //生成二维码的UIImageView

@property (weak, nonatomic) IBOutlet UITextField *inputWordTF; //字符串输入框

/**生成二维码的方法*/
- (IBAction)createQRCode:(UIButton *)sender;

@end

@implementation CreatQRViewController

- (void)viewDidLoad {
[super viewDidLoad];
}

/**
* 根据CIImage生成指定大小的UIImage
*
* @param image CIImage
* @param size 图片宽度
*/

- (UIImage *)createNonInterpolatedUIImageFormCIImage:(CIImage *)image withSize:(CGFloat) size
{
CGRect extent = CGRectIntegral(image.extent);
CGFloat scale = MIN(size/CGRectGetWidth(extent), size/CGRectGetHeight(extent));

// 1.创建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);

// 2.保存bitmap到图片
CGImageRef scaledImage = CGBitmapContextCreateImage(bitmapRef);
CGContextRelease(bitmapRef);
CGImageRelease(bitmapImage);
return [UIImage imageWithCGImage:scaledImage];
}

- (IBAction)createQRCode:(UIButton *)sender {

//1.实例化二维码滤镜
CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];

//2.恢复滤镜的默认属性
[filter setDefaults];

//3.将字符串转化为NSData
NSString *string = self.inputWordTF.text;
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];

//4.通过KVO设置滤镜inputMessage数据
[filter setValue:data forKeyPath:@"inputMessage"];

//5.获得滤镜输出的图像
CIImage *outputImg = [filter outputImage];

//6.将CIImage转换为UIImage 并放大显示
self.QRCodeImgV.image = [self createNonInterpolatedUIImageFormCIImage:outputImg withSize:200];
}

@end

II. 二维码的扫描和识别模块

#import "ScanQRViewController.h"
//必须调用
#import <AVFoundation/AVFoundation.h>

@interface ScanQRViewController ()<AVCaptureMetadataOutputObjectsDelegate>

@property (nonatomic, strong) AVCaptureSession *session;
@property (nonatomic, strong) AVCaptureVideoPreviewLayer *layer;
@property (weak, nonatomic) IBOutlet UILabel *scanResults; //扫描结果

/**扫描及显示识别结果*/
- (IBAction)scanQRCode:(UIButton *)sender;

@end

@implementation ScanQRViewController

- (void)viewDidLoad {
[super viewDidLoad];
}

#pragma mark - 实现output的回调方法
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
if (metadataObjects.count > 0) {
AVMetadataMachineReadableCodeObject *obj = [metadataObjects lastObject];

//有数据的时候
self.scanResults.text = obj.stringValue;

[self.session stopRunning];
[self.layer removeFromSuperlayer];

}else {

//没数据的时候
self.scanResults.text = @"没有任何数据";

}
}

- (IBAction)scanQRCode:(UIButton *)sender {

AVCaptureSession *session = [[AVCaptureSession alloc] init];
self.session = session;

AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
[session addInput:input];

AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc] init];
[output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
[session addOutput:output];

[output setMetadataObjectTypes:@[AVMetadataObjectTypeQRCode]];

AVCaptureVideoPreviewLayer *layer = [AVCaptureVideoPreviewLayer layerWithSession:session];
layer.frame = self.view.bounds;
[self.view.layer addSublayer:layer];
self.layer = layer;

[session startRunning];
}

@end