原生二维码扫描实现, 二维码、中间带小图标、条形码生成
来源:互联网 发布:施工横道图绘制软件 编辑:程序博客网 时间:2024/05/18 01:04
今天在review代码的时候重新整理了一下项目中的原生的二维码扫描及生成的代码,和大家分享一下。
跟大家分享的主要有两个类:
QRCodeScanView 扫描视图, 识别出信息后回有震动提示,可以打开手电筒
QRCodeCreateTools 二维码、条形码生成工具,你还可以生成中间带小图标的二维码
先看看怎么使用吧
- (void)viewDidLoad {[super viewDidLoad];//创建扫面视图你只需要self.scanView = [[QRCodeScanView alloc] initWithFrame:[UIScreen mainScreen].bounds minX:0.2 minY:0.2];[self.view insertSubview:self.scanView atIndex:0];}
效果图:
生成一个二维码
UIImage *qrcode = [QRCodeCreateTools creatQRCodeWithUrlstring:@"这是一个二维码" imageWidth:200];
生成一个中间带小图标的二维码
UIImage *iconQrcode = [QRCodeCreateTools creatQRCodeWithUrlstring:@"这是一个带头像的二维码" imageWidth:200 withIcon:icon withScale:0.2];
效果图:
生成一个条形码
UIImage *qrcode = [QRCodeCreateTools creatBarCode:@"11234598765" width:300 height:100];
有没有 很简单! 源码来了
#import <UIKit/UIKit.h>#import <AVFoundation/AVFoundation.h>@interface QRCodeScanView : UIView@property (nonatomic, strong)UILabel *detailLabel;@property (nonatomic, strong)UILabel *descriptionLabel;@property (nonatomic, copy)void (^scanFinishBlock)(AVCaptureOutput *captureOutput, NSArray *metadataObjects, AVCaptureConnection *connection);/** * 初始化扫描视图 * * @param frame 扫描视图的frame * @param minX 扫描区域距视图左边界的比例 * @param minY 扫描区域距视图上边界的比例 */- (instancetype)initWithFrame:(CGRect)frame minX:(CGFloat)minX minY:(CGFloat)minY;/** * 开始扫描 */- (void)startScan;/** * 暂停扫描 */- (void)stopScan;@end
#import "QRCodeScanView.h"#import <AudioToolbox/AudioToolbox.h>//扫描框四个角的颜色#define BordColor [UIColor redColor]//扫描线的颜色#define ScanLineColor [UIColor redColor]@interface QRCodeScanView ()<AVCaptureMetadataOutputObjectsDelegate, UIAlertViewDelegate>{ NSTimer *_timer; CGFloat _minX; CGFloat _minY;}@property (nonatomic, strong)AVCaptureSession *session;@property (nonatomic, strong)AVCaptureDeviceInput *input;@property (nonatomic, strong)AVCaptureMetadataOutput *output;@property (nonatomic, strong)AVCaptureVideoPreviewLayer *scanView;@property (nonatomic, strong)UIImageView *scanLine;@property (nonatomic, strong)UIView *boxView;@end@implementation QRCodeScanView- (void)awakeFromNib{ [super awakeFromNib]; _minX = 0.2; _minY = 0.2; [self setupUIWithMinX:0.2 minY:0.2];}- (instancetype)initWithFrame:(CGRect)frame{ self = [super initWithFrame:frame]; if (self != nil) { _minX = 0.2; _minY = 0.2; [self setupUIWithMinX:0.2 minY:0.2]; } return self;}- (instancetype)initWithFrame:(CGRect)frame minX:(CGFloat)minX minY:(CGFloat)minY{ self = [super initWithFrame:frame]; if (self != nil) { _minX = minX; _minY = minY; [self setupUIWithMinX:minX minY:minY]; } return self;}- (void)setupUIWithMinX:(CGFloat)minX minY:(CGFloat)minY{ _session = [AVCaptureSession new]; if (self.input != nil) { [_session addInput:self.input]; } else { AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]; NSString *message = nil; switch (status) { case AVAuthorizationStatusNotDetermined: message = @"用户尚未作出关于应用是否可以访问相机的选择"; break; case AVAuthorizationStatusRestricted: message = @"应用没有被授权访问媒体类型的硬件"; break; case AVAuthorizationStatusDenied: message = @"应用未被授权访问相机,可在设置中打开权限"; break; case AVAuthorizationStatusAuthorized: break; default: message = @""; break; } if (message != nil) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:message delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil, nil]; [alert show]; return; } } [_session addOutput:self.output]; _output.metadataObjectTypes = @[AVMetadataObjectTypeQRCode, AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeCode39Code, AVMetadataObjectTypeCode39Mod43Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode93Code,AVMetadataObjectTypeCode128Code, AVMetadataObjectTypeUPCECode]; [self.layer addSublayer:self.scanView]; CGFloat boxWidth = self.bounds.size.width * (1 - 2*minX); //设置扫描范围 _output.rectOfInterest = CGRectMake(minY, minX, boxWidth/self.bounds.size.height, boxWidth/self.bounds.size.width); UIView *maskView = [[UIView alloc] initWithFrame:self.bounds]; maskView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5]; [self addSubview:maskView]; UIBezierPath *maskPath = [UIBezierPath bezierPathWithRect:self.bounds]; [maskPath appendPath:[[UIBezierPath bezierPathWithRoundedRect:CGRectMake(self.bounds.size.width * minX, self.bounds.size.height * minY, boxWidth, boxWidth) cornerRadius:1] bezierPathByReversingPath]]; CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init]; maskLayer.path = maskPath.CGPath; maskView.layer.mask = maskLayer; CGFloat cornerW = boxWidth/10; UIView *topLeftView = [self cornImageWithWidth:cornerW position:CGPointMake(1, 1)]; topLeftView.frame = CGRectMake(self.bounds.size.width * minX, self.bounds.size.height * minY, cornerW, cornerW); [self insertSubview:topLeftView belowSubview:maskView]; UIView *topRightView = [self cornImageWithWidth:cornerW position:CGPointMake(-1, 1)]; topRightView.frame = CGRectMake(self.bounds.size.width * minX + boxWidth - cornerW, self.bounds.size.height * minY, cornerW, cornerW); [self insertSubview:topRightView belowSubview:maskView]; UIView *bottomLeftView = [self cornImageWithWidth:cornerW position:CGPointMake(1, -1)]; bottomLeftView.frame = CGRectMake(self.bounds.size.width * minX, self.bounds.size.height *minY + boxWidth - cornerW, cornerW, cornerW); [self insertSubview:bottomLeftView belowSubview:maskView]; UIView *bottomRightView = [self cornImageWithWidth:cornerW position:CGPointMake(-1, -1)]; bottomRightView.frame = CGRectMake(self.bounds.size.width * minX + boxWidth - cornerW, self.bounds.size.height *minY + boxWidth - cornerW, cornerW, cornerW); [self insertSubview:bottomRightView belowSubview:maskView]; //扫描线 _scanLine = [[UIImageView alloc] init]; _scanLine.frame = CGRectMake(self.bounds.size.width * minX, self.bounds.size.height * minY, boxWidth, 1.5); _scanLine.backgroundColor = ScanLineColor; [self insertSubview:_scanLine belowSubview:maskView]; _timer = [NSTimer scheduledTimerWithTimeInterval:0.1f target:self selector:@selector(moveScanLayer:) userInfo:nil repeats:YES]; [_timer fire]; _detailLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, self.bounds.size.height * minY + boxWidth + 15, self.bounds.size.width, 20)]; _detailLabel.textColor = [UIColor whiteColor]; _detailLabel.font = [UIFont systemFontOfSize:15]; _detailLabel.textAlignment = NSTextAlignmentCenter; _detailLabel.text = @"将二维码放入扫描框内,即可自动扫描"; [self addSubview:_detailLabel]; UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake((self.bounds.size.width - 100)/2.0, CGRectGetMaxY(_detailLabel.frame) + 30, 100, 40)]; [button addTarget:self action:@selector(openLight:) forControlEvents:UIControlEventTouchUpInside]; [button setTitle:@"打开手电筒" forState:UIControlStateNormal]; [button setTitle:@"关闭手电筒" forState:UIControlStateSelected]; [self addSubview:button]; [self startScan];}- (UIView *)cornImageWithWidth:(CGFloat)width position:(CGPoint)point{ UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, width)]; view.backgroundColor = BordColor; UIBezierPath *maskPath = [UIBezierPath bezierPathWithRect:self.bounds]; [maskPath appendPath:[[UIBezierPath bezierPathWithRoundedRect:CGRectMake(point.x * width/5.0, point.y * width/5.0, width, width) cornerRadius:1] bezierPathByReversingPath]]; CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init]; maskLayer.path = maskPath.CGPath; view.layer.mask = maskLayer; return view;}- (void)moveScanLayer:(NSTimer *)timer{ CGRect frame = _scanLine.frame; CGFloat boxWidth = self.bounds.size.width * (1 - 2*_minX); if (self.frame.size.height * _minY + boxWidth - 3 < _scanLine.frame.origin.y) { frame.origin.y = self.bounds.size.height * _minY; _scanLine.frame = frame; }else{ frame.origin.y += 3; [UIView animateWithDuration:0.1 animations:^{ _scanLine.frame = frame; }]; }}#pragma mark - AVCaptureMetadataOutputObjectsDelegate- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{ if (metadataObjects != nil && [metadataObjects count] > 0) { [self stopScan]; if (self.scanFinishBlock != nil) { [self playBeep]; self.scanFinishBlock(captureOutput,metadataObjects,connection); } }}#pragma mark - 开始/暂停扫描- (void)startScan{ if (![_timer isValid]) { return ; } [_timer setFireDate:[NSDate date]]; [self.session startRunning];}- (void)stopScan{ if (![_timer isValid]) { return ; } [_timer setFireDate:[NSDate distantFuture]]; [self.session stopRunning];}//扫描震动- (void)playBeep{ AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);}- (void)openLight:(UIButton *)sender{ sender.selected = !sender.selected; BOOL isopen = sender.selected; AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType: AVMediaTypeVideo]; if (![device hasTorch]) { } else { if (isopen) { // 开启闪光灯 if(device.torchMode != AVCaptureTorchModeOn || device.flashMode != AVCaptureFlashModeOn){ [device lockForConfiguration:nil]; [device setTorchMode:AVCaptureTorchModeOn]; [device setFlashMode:AVCaptureFlashModeOn]; [device unlockForConfiguration]; } } else { // 关闭闪光灯 if(device.torchMode != AVCaptureTorchModeOff || device.flashMode != AVCaptureFlashModeOff){ [device lockForConfiguration:nil]; [device setTorchMode:AVCaptureTorchModeOff]; [device setFlashMode:AVCaptureFlashModeOff]; [device unlockForConfiguration]; } } }}#pragma mark - 懒加载- (AVCaptureMetadataOutput *)output{ if (_output == nil) { _output = [AVCaptureMetadataOutput new]; [_output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()]; } return _output;}- (AVCaptureDeviceInput *)input{ if (_input == nil) { AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; NSError *error = nil; _input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error]; NSLog(@"二维码扫描 error------%@",error); } return _input;}- (AVCaptureVideoPreviewLayer *)scanView{ if (_scanView == nil) { _scanView = [AVCaptureVideoPreviewLayer layerWithSession: self.session]; _scanView.videoGravity = AVLayerVideoGravityResizeAspectFill; _scanView.frame = self.bounds; } return _scanView;}@end
#import <Foundation/Foundation.h>#import <UIKit/UIKit.h>@interface QRCodeCreateTools : NSObject/** * 生成二维码 * * @param urlString 二维码链接 * @param width 二维码图片宽度 * * @return 二维码图片 */+ (UIImage *)creatQRCodeWithUrlstring:(NSString *)urlString imageWidth:(CGFloat)width;/** * 生成二维码中间加 icon * * @param urlString 二维码链接 * @param width 二维码图片宽度 * @param icon 中间图片icon * @param scale 中间图片占二维码的比例 * * @return 二维码图片 */+ (UIImage *)creatQRCodeWithUrlstring:(NSString *)urlString imageWidth:(CGFloat)width withIcon:(UIImage *)icon withScale:(CGFloat)scale;/** * 生成条形码 * * @param codeString 条形码信息 * @param width 条形码宽度 * @param height 条形码长度 * * @return 条形码图片 */+ (UIImage *)creatBarCode:(NSString *)codeString width:(CGFloat)width height:(CGFloat)height;@end
#import "QRCodeCreateTools.h"@implementation QRCodeCreateTools+ (UIImage *)creatQRCodeWithUrlstring:(NSString *)urlString imageWidth:(CGFloat)width withIcon:(UIImage *)icon withScale:(CGFloat)scale{ UIImage *QRImage = [self creatQRCodeWithUrlstring:urlString imageWidth:width]; return [self addIconToQRCodeImage:QRImage withIcon:icon withScale:scale];}+ (UIImage *)creatQRCodeWithUrlstring:(NSString *)urlString imageWidth:(CGFloat)width{ CIFilter *filter=[CIFilter filterWithName:@"CIQRCodeGenerator"]; [filter setDefaults]; NSData *data=[urlString dataUsingEncoding:NSUTF8StringEncoding]; [filter setValue:data forKey:@"inputMessage"]; [filter setValue:@"Q" forKey:@"inputCorrectionLevel"];//纠错等级越高,识别越易识别,L | M | Q | H CIImage *outputImage=[filter outputImage]; CGFloat scaleX = width / outputImage.extent.size.width; CGFloat scaleY = width / outputImage.extent.size.height; CIImage *transformedImage = [outputImage imageByApplyingTransform:CGAffineTransformScale(CGAffineTransformIdentity, scaleX, scaleY)]; return [UIImage imageWithCIImage:transformedImage];}+(UIImage *)addIconToQRCodeImage:(UIImage *)image withIcon:(UIImage *)icon withScale:(CGFloat)scale { UIGraphicsBeginImageContext(image.size); //通过两张图片进行位置和大小的绘制,实现两张图片的合并 CGFloat widthOfImage = image.size.width; CGFloat heightOfImage = image.size.height; CGFloat widthOfIcon = widthOfImage * scale; CGFloat heightOfIcon = heightOfImage * scale; [image drawInRect:CGRectMake(0, 0, widthOfImage, heightOfImage)]; icon = [self circleImage:icon withParam:0]; [icon drawInRect:CGRectMake((widthOfImage-widthOfIcon)/2, (heightOfImage-heightOfIcon)/2,widthOfIcon, heightOfIcon)]; UIImage *img = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return img; }+ (UIImage *)creatBarCode:(NSString *)codeString width:(CGFloat)width height:(CGFloat)height{ CIImage *barcodeImage; NSData *data = [codeString dataUsingEncoding:NSISOLatin1StringEncoding allowLossyConversion:false]; CIFilter *filter = [CIFilter filterWithName:@"CICode128BarcodeGenerator"]; [filter setValue:data forKey:@"inputMessage"]; barcodeImage = [filter outputImage]; CGFloat scaleX = width / barcodeImage.extent.size.width; CGFloat scaleY = height / barcodeImage.extent.size.height; CIImage *transformedImage = [barcodeImage imageByApplyingTransform:CGAffineTransformScale(CGAffineTransformIdentity, scaleX, scaleY)]; return [UIImage imageWithCIImage:transformedImage];}+ (UIImage*) circleImage:(UIImage*) image withParam:(CGFloat) inset { UIGraphicsBeginImageContext(image.size); CGContextRef context =UIGraphicsGetCurrentContext(); CGContextSetLineWidth(context,1); CGContextSetStrokeColorWithColor(context, [UIColor clearColor].CGColor); CGRect rect = CGRectMake(inset, inset, image.size.width - inset *2.0f, image.size.height - inset *2.0f); CGContextAddEllipseInRect(context, rect); CGContextClip(context); //在圆区域内画出image原图 [image drawInRect:rect]; CGContextAddEllipseInRect(context, rect); CGContextStrokePath(context); //生成新的image UIImage *newimg = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return newimg;}@end
好了,目前要分享的就这些,后续会添加识别相册中的二维码信息功能,完整 demo下载 喜欢就给个star吧
如有问题,欢迎评论交流!
1 0
- 原生二维码扫描实现, 二维码、中间带小图标、条形码生成
- iOS原生二维码生成与扫描以及条形码的扫描
- Android基于Zxing实现二维码,条形码扫描和生成二维码
- Zxing二维码、条形码扫描/生成
- [iOS 原生代码实现扫描二维码/条形码] AVCaptureDevice
- ZXing生成条形码、二维码、带logo二维码
- QRCode 扫描二维码、扫描条形码、相册获取图片后识别、生成带 Logo 二维码、支持微博微信 QQ 二维码扫描样式
- 扫描二维码、扫描条形码、相册获取图片后识别、生成带 Logo 二维码、支持微博微信 QQ 二维码扫描样式
- 原生二维码和条形码扫描代码
- iOS系统原生二维码条形码扫描
- iOS系统原生二维码条形码扫描
- iOS 原生的二维码/条形码扫描
- OC - 原生扫码(扫描二维码,条形码)
- iOS7自带扫描二维码、条形码功能实现
- iOS7自带扫描二维码、条形码功能实现
- iOS原生二维码扫描&libqrencode生成二维码
- Android基于Google Zxing实现二维码/条形码扫描、生成二维码/条形码
- 实现扫描二维码和生成带logo的二维码
- 数据库水平切分的实现原理解析(分库,分表,主从,集群,负载均衡器)
- bower入门
- 做外贸要收款,哪些是没有拒付、效果比较好的?
- 网络爬虫--数据处理,jsoup工具解析html,dom4j解析xml
- 你值得拥有:25个Linux性能监控工具
- 原生二维码扫描实现, 二维码、中间带小图标、条形码生成
- 常用的几个开源 API网关管理系统
- Java中字符串indexof() 的使用方法
- Vue.js的组件(六)分发 之 具名Slot
- IOS真机上使用XMPP 调试时遇到的问题
- go的并发机制goroutine
- 麦克风阵列处理之TF-GSC 广义旁瓣相消器
- Java提高篇(三四)-----fail-fast机制
- 使用git时遇到的坑 non-fast-forward