1. 程式人生 > >IOS中生成二維碼、掃描二維碼

IOS中生成二維碼、掃描二維碼

轉載自:  http://www.jianshu.com/p/b8bf300e9a56

  • 從IOS7開始集成了二維碼的生成和讀取功能

生成二維碼

  • 1 匯入CoreImage框架
    #import <CoreImage/CoreImage.h>

  • 2 通過濾鏡CIFilter生成二維碼

/**
 *  生成二維碼
 */
- (void)creatCIQRCodeImage
{
    // 1.建立過濾器,這裡的@"CIQRCodeGenerator"是固定的
    CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];

    // 2.恢復預設設定
[filter setDefaults]; // 3. 給過濾器新增資料 NSString *dataString = @"二維碼測試資料"; NSData *data = [dataString dataUsingEncoding:NSUTF8StringEncoding]; // 注意,這裡的value必須是NSData型別 [filter setValue:data forKeyPath:@"inputMessage"]; // 4. 生成二維碼 CIImage *outputImage = [filter outputImage]; // 5. 顯示二維碼
self.imageView.image = [UIImage imageWithCIImage:outputImage]; }
  • 通過上述方法生成的二維碼圖片比較模糊,第5步顯示二維碼的時候可以呼叫以下方法生成比較清晰的二維碼
/**
 *  根據CIImage生成指定大小的UIImage
 *
 *  @param image CIImage
 *  @param size  圖片寬度
 *
 *  @return 生成高清的UIImage
 */
- (UIImage *)creatNonInterpolatedUIImageFormCIImage:(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]; }
  • 將上述生成高清二維碼的方法封裝成UIImage的Category如下

.h檔案

#import <UIKit/UIKit.h>

@interface UIImage (Category)

/**
 *  根據CIImage生成指定大小的UIImage
 *
 *  @param image CIImage
 *  @param size  圖片寬度
 *
 *  @return 生成的高清的UIImage
 */
+ (UIImage *)creatNonInterpolatedUIImageFormCIImage:(CIImage *)image withSize:(CGFloat)size;

@end

.m檔案

#import "UIImage+Category.h"

@implementation UIImage (Category)
/**
 *  根據CIImage生成指定大小的UIImage
 *
 *  @param image CIImage
 *  @param size  圖片寬度
 *
 *  @return 生成的高清的UIImage
 */
+ (UIImage *)creatNonInterpolatedUIImageFormCIImage:(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];
}
@end

掃描二維碼

  • 1 匯入<AVFoundation/AVFoundation.h>
  • 2 掃描二維碼實現
#import "ViewController.h"
// 匯入<AVFoundation/AVFoundation.h>框架
#import <AVFoundation/AVFoundation.h>

@interface ViewController ()<AVCaptureMetadataOutputObjectsDelegate>
/** 捕捉會話 */
@property (nonatomic, weak) AVCaptureSession *session;
/** 預覽圖層 */
@property (nonatomic, weak) AVCaptureVideoPreviewLayer *layer;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // 掃描二維碼
    [self scanCIQRCode];
}

/**
 *  掃描二維碼
 */
- (void)scanCIQRCode
{
    // 1. 建立捕捉會話
    AVCaptureSession *session = [[AVCaptureSession alloc] init];
    self.session = session;

    // 2. 新增輸入裝置(資料從攝像頭輸入)
    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
    [session addInput:input];

    // 3. 新增輸出資料介面
    AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc] init];
    // 設定輸出介面代理
    [output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
    [session addOutput:output];
    // 3.1 設定輸入元資料的型別(型別是二維碼資料)
    // 注意,這裡必須設定在addOutput後面,否則會報錯
    [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) {// 掃描到了資料
        AVMetadataMachineReadableCodeObject *object = [metadataObjects lastObject];

        // 停止掃描
        [self.session stopRunning];

        // 將預覽圖層移除
        [self.layer removeFromSuperlayer];
    }else{
        NSLog(@"沒有掃描到資料");
    }
}

@end


文/袁俊亮技術部落格(簡書作者)
原文連結:http://www.jianshu.com/p/b8bf300e9a56
著作權歸作者所有,轉載請聯絡作者獲得授權,並標註“簡書作者”。