蘋果原生二維碼生成與掃描及生成的二維碼不清楚的解決方案


使用蘋果原生的框架實現二維碼的生成與掃描

 

#pragma mark -- 生成二維碼(普通/帶LOGO)

 

給NSString添加一個分類(分類下載地址: https://github.com/lieryang/Category/tree/master/Category)

 

NSString+EYQRCode.h

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@interface NSString (EYQRCode)

/**
 根據字符串創建二維碼圖片

 @param size 二維碼的大小
 @return 生成的二維碼圖片
 */
- (UIImage *)ey_createQRCodeImageWithSize:(CGFloat)size;

/**
 根據字符串創建帶logo的二維碼圖片

 @param size 二維碼圖片總大小
 @param logoImage logo圖片
 @param logoSize 二維碼中的logo圖片大小
 @return 生成的帶logo的二維碼圖片
 */
- (UIImage *)ey_createQRCodeImageWithSize:(CGFloat)size withLogoImage:(UIImage *)logoImage withLogoSize:(CGFloat)logoSize;

 

 NSString+EYQRCode.m

#import "NSString+EYQRCode.h"

@implementation NSString (EYQRCode)

#pragma mark - 外界調用接口
/**
 根據字符串創建二維碼圖片

 @param size 二維碼的大小
 @return 生成的二維碼圖片
 */
- (UIImage *)ey_createQRCodeImageWithSize:(CGFloat)size
{
    //生成二維碼圖片
    CIImage * ciImage = [self creatQRcodeWithUrlString:self];

    //提高清晰度,修改二維碼大小
    return [self createNonInterpolatedUIImageFormCIImage:ciImage withSize:size];
}

/**
 根據字符串創建帶logo的二維碼圖片

 @param size 二維碼圖片總大小
 @param logoImage logo圖片
 @param logoSize 二維碼中的logo圖片大小
 @return 生成的帶logo的二維碼圖片
 */
- (UIImage *)ey_createQRCodeImageWithSize:(CGFloat)size withLogoImage:(UIImage *)logoImage withLogoSize:(CGFloat)logoSize
{
    UIImage *superImage = [self ey_createQRCodeImageWithSize:size];
    if (logoSize < 0) {
        return superImage;
    } else {
        return [self mergeImage:superImage withSubImage:logoImage withSubImageSize:logoSize];
    }
}

#pragma mark - 內部使用的方法
/**
 根據字符串生成二維碼 CIImage 對象

 @param urlString 需要生成二維碼的字符串
 @return 生成的二維碼
 */
- (CIImage *)creatQRcodeWithUrlString:(NSString *)urlString
{
    // 1.創建過濾器 CIQRCodeGenerator這個字符串是固定的不能修改為其他的字符串
    CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
    // 2.恢復濾鏡的默認屬性 (因為濾鏡有可能保存上一次的屬性)
    [filter setDefaults];
    // 3.將字符串轉換成NSdata
    NSData *data = [urlString dataUsingEncoding:NSUTF8StringEncoding];
    // 4.獲取輸出的二維碼
    [filter setValue:data forKey:@"inputMessage"];
    // 5.生成二維碼
    CIImage *outputImage = [filter outputImage];
    return outputImage;
}

/* 根據CIImage生成指定大小的UIImage 更加清晰
 *
 * @param image CIImage
 * @param size 圖片寬度
 */
- (UIImage *)createNonInterpolatedUIImageFormCIImage:(CIImage *)image withSize:(CGFloat)size
{
    CGRect extent = CGRectIntegral(image.extent);
    CGFloat extentWidth = CGRectGetWidth(extent);
    CGFloat extentHeight = CGRectGetHeight(extent);
    if (size < extentWidth || size < extentHeight) {
       size = MIN(CGRectGetWidth(extent), CGRectGetHeight(extent));
    }

    CGFloat scale = MIN(size/extentWidth, size/extentHeight);

    // 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];
}

/**
 合並兩張圖片

 @param superImage 底層圖片
 @param subImage 上層圖片
 @return 合並后的圖片
 */
- (UIImage *)mergeImage:(UIImage *)superImage withSubImage:(UIImage *)subImage withSubImageSize:(CGFloat)subSize
{
    UIGraphicsBeginImageContext(superImage.size);
    CGFloat superW = superImage.size.width;
    CGFloat superH = superImage.size.height;
    CGFloat subW = subSize;
    CGFloat subH = subSize;

    [superImage drawInRect:CGRectMake(0, 0, superW, superH)];

    [subImage drawInRect:CGRectMake((superW - subW) / 2,(superH - subH) / 2, subW, subH)];

    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return image;
}

@end 

 

使用如下: 不要忘記導入分類的頭文件呦 NSString+EYQRCode.h

//測試普通二維碼生成
self.QRCodeImageView.image = [@"www.baidu.com" ey_createQRCodeImageWithSize:200];

//測試logo二維碼生成
self.QRCodeImageView.image = [@"www.baidu.com" ey_createQRCodeImageWithSize:375 withLogoImage:[UIImage imageNamed:@"logo"] withLogoSize:50];


#pragma mark -- 掃描二維碼  

 

 

#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>

@interface ViewController ()<AVCaptureMetadataOutputObjectsDelegate>

@property (nonatomic, strong) AVCaptureSession *session;

@property (nonatomic, strong) AVCaptureVideoPreviewLayer *layer;

@end

@implementation ViewController
- (void)viewDidLoad
{
    [super viewDidLoad];
    
    // 1.創建捕捉會話
    AVCaptureSession *session = [[AVCaptureSession alloc] init];
    self.session = session;
    
    // 2.添加輸入設備(數據從攝像頭輸入)
    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    
    AVAuthorizationStatus authStatus =  [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
    if (authStatus == AVAuthorizationStatusRestricted || authStatus ==AVAuthorizationStatusDenied)
    {
        NSLog(@"沒有開啟攝像頭權限");//可以提示用戶開啟權限
        return;
    }
    NSError * error = nil;
    AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
    if (error) {
        NSLog(@"沒有攝像頭或者攝像頭損壞或者沒有開啟攝像頭權限");//可以提示用戶
        return;
    }
    
    [session addInput:input];
    
    // 3.添加輸出數據(示例對象-->類對象-->元類對象-->根元類對象)
    AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc] init];
    [output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
    [session addOutput:output];
    
    // 3.1.設置輸入元數據的類型(類型是二維碼數據)
    [output setMetadataObjectTypes:@[AVMetadataObjectTypeQRCode]];
    
    // 4.添加掃描圖層
    AVCaptureVideoPreviewLayer *layer = [AVCaptureVideoPreviewLayer layerWithSession:session];
    layer.frame = self.view.bounds;
    [self.view.layer addSublayer:layer];
    self.layer = layer;
    
    // 5.開始掃描
    [session startRunning];
}

#pragma mark - AVCaptureMetadataOutputObjectsDelegate
// 當掃描到數據時就會執行該方法
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
    if (metadataObjects.count > 0) {
        AVMetadataMachineReadableCodeObject *object = [metadataObjects lastObject];
        
        // 可以跳轉界面
        NSLog(@"掃描出來的字符串%@", object.stringValue);
        
        // 停止掃描
        [self.session stopRunning];
        
        // 將預覽圖層移除
        [self.layer removeFromSuperlayer];
        
    } else {
        NSLog(@"沒有掃描到數據");
    }
}

@end

  


 更多內容--> 博客導航 每周一篇喲!!!

 

 

有任何關於iOS開發的問題!歡迎下方留言!!!或者郵件lieryangios@126.com 雖然我不一定能夠解答出來,但是我會請教iOS開發高手!!!解答您的問題!!!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM