iOS 系统原生二维码

本文中使用的是系统原生coreimage,实现功能​二维码扫描和解析和生成

======================二维码扫描和解析=============================

@interfaceScanViewController () 

@property (weak, nonatomic) IBOutletNSLayoutConstraint *topLayoutConstraint;

@property (nonatomic,strong) AVCaptureSession *codeCaptureSession;

@property (nonatomic,strong) AVCaptureVideoPreviewLayer *codeCaptureVideoPreviewLayer;@end

@implementation ScanViewController

#pragma mark - 进入相册- (IBAction)QRCodeFromPickeC:(id)sender {        

UIImagePickerController *imagePC = [[UIImagePickerControlleralloc] init];       

 imagePC.delegate = self;       

 [selfpresentViewController:imagePC animated:YEScompletion:nil];    }

#pragma mark - 点击图片进行解析- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info

{

[picker dismissViewControllerAnimated:YEScompletion:nil];

NSData *data =  UIImageJPEGRepresentation(info[UIImagePickerControllerOriginalImage], 1);

NSLog(@"%@",[selfstringFromCiImage:[CIImageimageWithData:data]]);

[selfaddAlertViewControllerWithMessage:[selfstringFromCiImage:[CIImageimageWithData:data]]];

}

#pragma mark -  解析图片

- (NSString *)stringFromCiImage:(CIImage *)ciimage {

NSString *content = @"" ;

if (!ciimage) {

return content;

}

CIDetector *detector = [CIDetectordetectorOfType:CIDetectorTypeQRCode

context:[CIContext contextWithOptions:nil]

options:@{CIDetectorAccuracy:CIDetectorAccuracyHigh}];

NSArray *features = [detector featuresInImage:ciimage];

if (features.count) {

for (CIFeature *feature in features) {

if ([feature isKindOfClass:[CIQRCodeFeatureclass]]) {

content = ((CIQRCodeFeature *)feature).messageString;

break;

}

}

} else {

[selfaddAlertViewControllerWithMessage:@"未正常解析二维码图片, 请确保iphone5/5c以上的设备"];

NSLog(@"未正常解析二维码图片, 请确保iphone5/5c以上的设备");

}

return content;

}

#pragma mark - 提示框

- (void)addAlertViewControllerWithMessage:(NSString *)message

{

UIAlertController *alert = [UIAlertControlleralertControllerWithTitle:@"解析内容"  message:[message stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding] preferredStyle:UIAlertControllerStyleAlert];

[alert addAction:[UIAlertActionactionWithTitle:@"朕知道了!"style:UIAlertActionStyleDefaulthandler:^(UIAlertAction * _Nonnull action) {

[self.codeCaptureSessionstartRunning];

[selfaddAnimationForLine]; // 上下进行扫描的线动画

}]];

[selfpresentViewController:alert animated:YEScompletion:nil];

}

#pragma mark - 二维码采集对象

- (AVCaptureSession *)codeCaptureSession

{

if (!_codeCaptureSession) {

// 二维码采集对象

_codeCaptureSession = [[AVCaptureSessionalloc] init];

}

return_codeCaptureSession;

}

#pragma mark - 显示采集图像的对象

- (AVCaptureVideoPreviewLayer *)codeCaptureVideoPreviewLayer

{

if (!_codeCaptureVideoPreviewLayer) {

_codeCaptureVideoPreviewLayer  = [AVCaptureVideoPreviewLayerlayerWithSession:self.codeCaptureSession];

_codeCaptureVideoPreviewLayer.bounds = self.view.bounds;

_codeCaptureVideoPreviewLayer.position = self.view.center;

[self.view.layerinsertSublayer:_codeCaptureVideoPreviewLayeratIndex:0];

}

return_codeCaptureVideoPreviewLayer;

}

- (void)viewWillAppear:(BOOL)animated

{

[super viewWillAppear:animated];

#if TARGET_IPHONE_SIMULATOR//模拟器

UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"小提示" message:@"模拟器不能进行扫码" delegate:nil cancelButtonTitle:@"朕知道了!" otherButtonTitles:nil,nil];

[alert show];

#elif TARGET_OS_IPHONE//真机

NSLog(@"真机运行时");

#endif

}

#pragma mark - viewDidLoad

- (void)viewDidLoad {

[superviewDidLoad];

// Do any additional setup after loading the view.

// 隐藏返回按钮的文字

[[UIBarButtonItemappearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(0, -60)

forBarMetrics:UIBarMetricsDefault];

//------------------------------------------------------ 创建输入流--------------------------------------------------------

// 信息采集设备

AVCaptureDevice *codeCaptureDevice = [AVCaptureDevicedefaultDeviceWithMediaType:AVMediaTypeVideo];

NSError *error;

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

if (error) {

NSLog(@"创建输入流error:%@",error);

return;

}

// 设置输入流

[self.codeCaptureSessionaddInput:input];

//------------------------------------------------------ 创建输入流--------------------------------------------------

//------------------------------------------------------ 创建输出流--------------------------------------------------

AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutputalloc] init];

// 设置输出流

[self.codeCaptureSessionaddOutput:output];

//设置输出流代理,在代理中获取二维码的结果

[output setMetadataObjectsDelegate:selfqueue:dispatch_get_main_queue()];

// 设置输出类型

output.metadataObjectTypes = @[AVMetadataObjectTypeUPCECode,

AVMetadataObjectTypeCode39Code,

AVMetadataObjectTypeCode39Mod43Code,

AVMetadataObjectTypeEAN13Code,

AVMetadataObjectTypeEAN8Code,

AVMetadataObjectTypeCode93Code,

AVMetadataObjectTypeCode128Code,

AVMetadataObjectTypePDF417Code,

AVMetadataObjectTypeQRCode,

AVMetadataObjectTypeAztecCode,

AVMetadataObjectTypeInterleaved2of5Code,

AVMetadataObjectTypeITF14Code,

AVMetadataObjectTypeDataMatrixCode];

//    [output availableMetadataObjectTypes]; 获取输出支持类型

//设置采样率,越高识别越精准,速度越慢

[self.codeCaptureSessionsetSessionPreset:AVCaptureSessionPreset1920x1080];

//------------------------------------------------------ 创建输出流--------------------------------------------------

// 采集图像显示

[selfcodeCaptureVideoPreviewLayer];

// 开始采集

[self.codeCaptureSessionstartRunning];

}

#pragma mark - 输出流代理方法----采集到数据就会调用该方法

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection

{

// 获得二维码数据

AVMetadataMachineReadableCodeObject *codeObject = [metadataObjects lastObject];

//转化为字符串

NSString *resultString = codeObject.stringValue;

if (resultString) {

[self.codeCaptureSessionstopRunning]; // 停止采集二维码

self.topLayoutConstraint.constant = 10;

[self.codeCaptureVideoPreviewLayerremoveFromSuperlayer];// 删除预览图层

}

[selfaddAlertViewControllerWithMessage:resultString];

}

- (void)viewDidAppear:(BOOL)animated

{

[super viewDidAppear:animated];

[selfaddAnimationForLine]; // 上下进行扫描的线动画

}

#pragma mark - 上下进行扫描的线动画

- (void)addAnimationForLine

{

self.topLayoutConstraint.constant = 10;

[self.viewlayoutIfNeeded];

[UIViewbeginAnimations:@"LineAnimation"context:nil];

[UIViewsetAnimationDuration:1.0f];

[UIViewsetAnimationRepeatAutoreverses:YES];

[UIViewsetAnimationRepeatCount:INFINITY];

[UIViewsetAnimationCurve:UIViewAnimationCurveEaseInOut];

self.topLayoutConstraint.constant = [UIScreenmainScreen].bounds.size.width-40-40;

[self.viewlayoutIfNeeded];

[UIViewcommitAnimations];

}

======================二维码扫描和解析=============================

======================二维码生成=============================

​#pragma mark -  viewDidLoad

- (void)viewDidLoad {

[superviewDidLoad];

// Do any additional setup after loading the view.

[[UIBarButtonItemappearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(0, -60)

forBarMetrics:UIBarMetricsDefault];

self.codeImageView.image = [selfimageBlackToTransparent: [selfcreateNoninterpolatedUIImageFormCIImage:[selfcreateQRForString:@"请输入要生成二维码的内容"] withSize:CGRectGetWidth(self.codeImageView.frame)] withRed:0.fandGreen:0.fandBlue:0.f];

self.codeImageView.layer.shadowOffset = CGSizeMake(0, 0.5);  // 设置阴影的偏移量

self.codeImageView.layer.shadowRadius = 1;  // 设置阴影的半径

self.codeImageView.layer.shadowColor = [UIColorblackColor].CGColor; // 设置阴影的颜色为黑色

self.codeImageView.layer.shadowOpacity = 0.3; // 设置阴影的不透明度

}

#pragma mark - 根据指定的字符串来生成二维码的CIImage对象

- (CIImage *)createQRForString:(NSString *)QRString

{

// 获取支持的二维码和条码生成器

NSLog(@"%@",[CIFilterfilterNamesInCategory:kCICategoryGenerator]);

// 实例化二维码滤镜

CIFilter *QRFilter = [CIFilterfilterWithName:@"CIQRCodeGenerator"];

// 恢复滤镜的默认属性

[QRFilter setDefaults]; // 可以省略

// 设置二维码的内容

[QRFilter setValue:[QRString dataUsingEncoding:NSUTF8StringEncoding] forKey:@"inputMessage"];

// 设置二维码的纠错级别

[QRFilter setValue:@"M"forKey:@"inputCorrectionLevel"];

return QRFilter.outputImage;

}

#pragma mark - 根据指定的CIImage对象来转换成指定大小的UIImage对象

- (UIImage *)createNoninterpolatedUIImageFormCIImage:(CIImage *)image

withSize:(CGFloat)size

{

CGRect extent = CGRectIntegral(image.extent);

CGFloat scale = MIN(size/CGRectGetWidth(extent), size/CGRectGetHeight(extent));

// 创建bitmap

size_t with = CGRectGetWidth(extent)*scale;

size_t height = CGRectGetHeight(extent)*scale;

CGColorSpaceRef cs = CGColorSpaceCreateDeviceGray();

CGContextRef bitmap = CGBitmapContextCreate(nil, with, height, 8, 0, cs, (CGBitmapInfo)kCGImageAlphaNone);

CIContext *context = [CIContextcontextWithOptions:nil];

CGImageRef bitmapImage = [context createCGImage:image fromRect:extent];

CGContextSetInterpolationQuality(bitmap, kCGInterpolationNone);

CGContextScaleCTM(bitmap, scale, scale);

CGContextDrawImage(bitmap, extent, bitmapImage);

// 保存bitmap到图片

CGImageRef scaledImage = CGBitmapContextCreateImage(bitmap);

CGContextRelease(bitmap);

CGImageRelease(bitmapImage);

return [UIImageimageWithCGImage:scaledImage];

}

#pragma mark - 二维码颜色填充

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);

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

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, ProviderReleaseData);

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 - Navigation

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {

if ([segue.identifierisEqualToString:@"GenerateVCToQRCodeSetVC"]) {

QRCodeSetViewController *QRCodeSetVC = segue.destinationViewController;

[QRCodeSetVC setQRCodeSetBlock:^(CGFloat R, CGFloat G , CGFloat B, NSString *QRCodeContent) {

self.codeImageView.image = [selfimageBlackToTransparent: [selfcreateNoninterpolatedUIImageFormCIImage:[selfcreateQRForString:QRCodeContent] withSize:CGRectGetWidth(self.codeImageView.frame)] withRed:R andGreen:G andBlue:B];

}];

}

}

你可能感兴趣的:(iOS 系统原生二维码)