原生二维码扫描实现, 二维码、中间带小图标、条形码生成

来源:互联网 发布:施工横道图绘制软件 编辑:程序博客网 时间: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
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 红米4a进水了怎么办 魅族耳机声音小怎么办 魅蓝note6声音小怎么办 魅蓝3s锁定怎么办 红米1密码忘了怎么办 小米手环升级失败怎么办 红米4忘记密码怎么办 红米1代忘记密码怎么办 红米3s忘记密码怎么办 小米3卡槽卡住了怎么办 红米4手机信号不好怎么办 红米note3信号差怎么办 红米note3没信号怎么办 红米3运行慢怎么办 红米手机运行慢怎么办 红米手机忘记解锁图案怎么办 小米手机解锁图案忘了怎么办 红米2内屏坏了怎么办 红米密码忘记了怎么办 红米pro玩王者卡怎么办 红米note4不支持计步怎么办 红米pro玩游戏卡怎么办 红米手机费电快怎么办 荣耀5c忘记密码怎么办 小米之家不退货怎么办 手机号绑定过多小米账户怎么办 耐克黑色鞋褪色怎么办 买广汽传祺7s新车有问题怎么办 华为荣耀10边框掉色了怎么办 网购商家打来无货怎么办 客户拍了不发货怎么办 天猫商家欺骗买家怎么办 阿里买家投诉我发空包怎么办 苹果6s电池坏了怎么办 hm买的单鞋脏了怎么办 微店违规屏蔽搜索怎么办 ios微信支付失效怎么办 京东第三方店铺关闭怎么办 京东店铺关门了怎么办 国美退款不到账怎么办 小米小店通过了怎么办