ios 生成的二维码很密

2018-02-06 17:49:37 ZhongLv_HoneyMoon 阅读数 2919

系统二维码主要通过CIFilter的对象来完成, 当然首先我们需要先导入这个类所在的框架:

#import <CoreImage/CoreImage.h>

之后只需要实例化一个CIFilter的对象, 给该对象添加数据后生成二维码即可。

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    // 1. 创建一个二维码滤镜实例(CIFilter)
    CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
    // 滤镜恢复默认设置
    [filter setDefaults];
    
    // 2. 给滤镜添加数据
    NSString *string = @"are you ok?"
    NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
    // 使用KVC的方式给filter赋值
    [filter setValue:data forKeyPath:@"inputMessage"];
    
    // 3. 生成二维码
    CIImage *image = [filter outputImage];
    
    // 4. 显示二维码
    self.imageView.image = [UIImage imageWithCIImage:image];
}

二维码中的数据可以是字符串和URL两种类型, 如果我们想要生成URL的二维码, 只需要把字符串替换为一个URL字符串即可:

- (void)createCode:(NSString *)string

{

    // 1. 创建一个二维码滤镜实例(CIFilter)

    CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];

    // 滤镜恢复默认设置

    [filter setDefaults];

    

    // 2. 给滤镜添加数据

    

    NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];

    

    [filter setValue:data forKeyPath:@"inputMessage"];

    

    // 3. 生成二维码

    CIImage *ciimage = [filter outputImage];

    

    // 4. 显示二维码

    self.codeImg.image = [self createNonInterpolatedUIImageFormCIImage:ciimage withSize:180];

}

此外, 我们经常看到中间带有图片的二维码, 其实只需要在二维码的imageView上再添加一个imageView即可, 当然图片不能太大, 否则会导致扫描不到二维码中的信息

但这时候生成的二维码会比较模糊, 只需要使用下面的方法来获得一个清晰的image, 之后只要把image添加到二维码的imageView上即可:

/**

 *  根据CIImage生成指定大小的UIImage

 *

 *  @param image CIImage

 *  @param size  图片宽度以及高度

 */

- (UIImage *)createNonInterpolatedUIImageFormCIImage:(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];

}







2018-12-17 10:25:14 weixin_34319640 阅读数 429

级别:★★☆☆☆
标签:「iOS CIFilter」「CIQRCodeGenerator」「CICode128BarcodeGenerator」「二维码加logo」
作者: Xs·H
审校: QiShare团队


接上文iOS 扫描二维码/条形码iOS 扫描相册图片二维码,本文介绍iOS 生成二维码/条形码的相关技术点。先看看示例效果:

一、生成二维码

CoreImage框架中的CIFilter(常用来做滤镜)提供了生成二维码的方法,如下:

// 生成二维码
+ (UIImage *)generateQRCode:(NSString *)code size:(CGSize)size {
    
    NSData *codeData = [code dataUsingEncoding:NSUTF8StringEncoding];
    //  使用CIQRCodeGenerator创建filter
    CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator" withInputParameters:@{@"inputMessage": codeData, @"inputCorrectionLevel": QiInputCorrectionLevelH}];
    // 由filter.outputImage直接转成的UIImage不太清楚,需要做高清处理
    UIImage *codeImage = [QiCodeManager scaleImage:filter.outputImage toSize:size];
    
    return codeImage;
}
复制代码

借助CIFilter,生成二维码的步骤非常简单:
1、准备好二维码内容数据codeData;
2、使用CIQRCodeGenerator创建filter
3、为filter设置input参数:inputMessage: 要生成的二维码数据,inputCorrectionLevel: 二维码容错值;
4、通过filter.outputImage获取到CIImage类型的二维码图片,但图片不太清楚,需要做优化处理(见下文);

PS:
1、打印filter.inputKeys可查看不同name对应的input参数(比如CIQRCodeGenerator对应的inputCorrectionLevel参数);
2、inputCorrectionLevel对应四个容错率(如下),容错率越大,允许二维码污损的面积越大;
static NSString *QiInputCorrectionLevelL = @"L";//!< L: 7%
static NSString *QiInputCorrectionLevelM = @"M";//!< M: 15%
static NSString *QiInputCorrectionLevelQ = @"Q";//!< Q: 25%
static NSString *QiInputCorrectionLevelH = @"H";//!< H: 30%

二、生成条形码

生成条形码同样依赖CIFilter,且与生成二维码的方式相近,如下:

// 生成条形码
+ (UIImage *)generateCode128:(NSString *)code size:(CGSize)size {
    
    NSData *codeData = [code dataUsingEncoding:NSUTF8StringEncoding];
    //  使用CICode128BarcodeGenerator创建filter
    CIFilter *filter = [CIFilter filterWithName:@"CICode128BarcodeGenerator" withInputParameters:@{@"inputMessage": codeData, @"inputQuietSpace": @.0}];
    // 由filter.outputImage直接转成的UIImage不太清楚,需要做高清处理
    UIImage *codeImage = [QiCodeManager scaleImage:filter.outputImage toSize:size];
    
    return codeImage;
}
复制代码

生成条形码的步骤与生成二维码的步骤一样:
1、准备好条形码内容数据codeData;
2、使用CICode128BarcodeGenerator创建filter
3、为filter设置input参数:inputMessage:
要生成的条形码数据,inputQuietSpace: 条形码留白距离,inputBarcodeHeight: 条形码高度;
4、通过filter.outputImage获取到CIImage类型的二维码图片,但图片不太清楚,需要做优化处理(见下文);

三、优化二维码/条形码
1、图片变高清

由上文可知,在生成二维码/条形码得到filter.outputImage后都做了处理,目的是将生成的图片变高清。代码如下:

// 缩放图片(生成高质量图片)
+ (UIImage *)scaleImage:(CIImage *)image toSize:(CGSize)size {
    
    //! 将CIImage转成CGImageRef
    CGRect integralRect = image.extent;// CGRectIntegral(image.extent);// 将rect取整后返回,origin取舍,size取入
    CGImageRef imageRef = [[CIContext context] createCGImage:image fromRect:integralRect];
    
    //! 创建上下文
    CGFloat sideScale = fminf(size.width / integralRect.size.width, size.width / integralRect.size.height) * [UIScreen mainScreen].scale;// 计算需要缩放的比例
    size_t contextRefWidth = ceilf(integralRect.size.width * sideScale);
    size_t contextRefHeight = ceilf(integralRect.size.height * sideScale);
    CGContextRef contextRef = CGBitmapContextCreate(nil, contextRefWidth, contextRefHeight, 8, 0, CGColorSpaceCreateDeviceGray(), (CGBitmapInfo)kCGImageAlphaNone);// 灰度、不透明
    CGContextSetInterpolationQuality(contextRef, kCGInterpolationNone);// 设置上下文无插值
    CGContextScaleCTM(contextRef, sideScale, sideScale);// 设置上下文缩放
    CGContextDrawImage(contextRef, integralRect, imageRef);// 在上下文中的integralRect中绘制imageRef
    
    //! 从上下文中获取CGImageRef
    CGImageRef scaledImageRef = CGBitmapContextCreateImage(contextRef);
    
    CGContextRelease(contextRef);
    CGImageRelease(imageRef);
    
    //! 将CGImageRefc转成UIImage
    UIImage *scaledImage = [UIImage imageWithCGImage:scaledImageRef scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp];
    
    return scaledImage;
}
复制代码
2、图片加logo

对于二维码而言,经常会看到在中间加上logo的样式(微信公众号的二维码等),可使用绘制的方式实现,如下:

// 合成图片(code+logo)
+ (UIImage *)combinateCodeImage:(UIImage *)codeImage andLogo:(UIImage *)logo {
    
    UIGraphicsBeginImageContextWithOptions(codeImage.size, YES, [UIScreen mainScreen].scale);
    
    // 将codeImage画到上下文中
    [codeImage drawInRect:(CGRect){.0, .0, codeImage.size.width, codeImage.size.height}];
    
    // 定义logo的绘制参数
    CGFloat logoSide = fminf(codeImage.size.width, codeImage.size.height) / 4;
    CGFloat logoX = (codeImage.size.width - logoSide) / 2;
    CGFloat logoY = (codeImage.size.height - logoSide) / 2;
    CGRect logoRect = (CGRect){logoX, logoY, logoSide, logoSide};
    UIBezierPath *cornerPath = [UIBezierPath bezierPathWithRoundedRect:logoRect cornerRadius:logoSide / 5];
    [cornerPath setLineWidth:2.0];
    [[UIColor whiteColor] set];
    [cornerPath stroke];
    [cornerPath addClip];
    
    // 将logo画到上下文中
    [logo drawInRect:logoRect];
    
    // 从上下文中读取image
    codeImage = UIGraphicsGetImageFromCurrentImageContext();
    
    UIGraphicsEndImageContext();
    
    return codeImage;
}
复制代码

示例源码QiQRCode可从GitHub的QiShare开源库中获取。


作者微信:

关注我们的途径有:
QiShare(简书)
QiShare(掘金)
QiShare(知乎)
QiShare(GitHub)
QiShare(CocoaChina)
QiShare(StackOverflow)
QiShare(微信公众号)

推荐文章:
iOS 扫描二维码/条形码
iOS 了解Xcode Bitcode
iOS 重绘之drawRect
iOS 编写高质量Objective-C代码(八)
奇舞周刊

2017-06-02 17:10:46 shihuboke 阅读数 402

   联系人:石虎 QQ:1224614774  昵称: 嗡嘛呢叭咪哄

                        QQ群:807236138  群称: iOS 技术交流学习群

 

代码实现

#import "SHCodeTableViewCell.h"

#import "SHQRCodeView.h" //导入生成二维码封装类名

@interface XHCFCodeTableViewCell()

//全局的二维码类名
@property(nonatomic,strong)SHQRCodeView *qrCodeView;

@end

@implementation SHCodeTableViewCell

- (void)viewDidLoad {
    [superviewDidLoad];

    //调用自定义创建二维码方法\添加二维码URL
    [self setCreateTwoDimensionalCode:@"http://blog.csdn.net/shihuboke"];

}

#pragma mark - 创建二维码
- (void)setCreateTwoDimensionalCode:(NSString *)stringCode 
{

    //1.初始化SHQRCodeView方法封装
    self.qrCodeView = [[SHQRCodeViewalloc]init];

    //2.生成一个CIImage的二维码,并且控制图片的大小
    UIImage *qrcode = [self.qrCodeView createNonInterpolatedUIImageFormCIImage:[self.qrCodeView createQRForString:stringCode]withSize:250.0f];

    //3.把CIImage二维码 添加到自定义的customQrcode图片中,并且设置颜色
    UIImage *customQrcode = [self.qrCodeViewimageBlackToTransparent:qrcodewithRed:60.0fandGreen:74.0fandBlue:89.0f];

    //4.用自定义customQrcode显示在界面上
    self.imageCode.image = customQrcode;

    //5.如果还想加上阴影,就在ImageView的Layer上使用下面代码添加阴影:
    //5.1 设置阴影的偏移量
    self.imageCode.layer.shadowOffset = CGSizeMake(0,2);
    //5.2 设置阴影的半径
    self.imageCode.layer.shadowRadius = 2;
    //5.3 设置阴影的颜色为黑色
    self.imageCode.layer.shadowColor = [UIColorblackColor].CGColor;
    //5.4 设置阴影的不透明度
    self.imageCode.layer.shadowOpacity = 3;

}

注意:以下的代码是自己封装好的生成二维码,只要把下面的. h和. m 文件复制到项目的类中即可.

如图片:    http://img.blog.csdn.net/20170602174259983?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2hpaHVib2tl/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

 

     *************** 自封装的生成二维码类.h文件  *******************

//  Created by 石虎 on 16/5/10.
//  Copyright © 2016年 shih. All rights reserved.

#import <UIKit/UIKit.h>

@interface SHQRCodeView : UIView

/**
 因为生成的二维码是一个CIImage,我们直接转换成UIImage的话大小不好控制,所以使用下面方法返回需要大小的UIImage:

 */

- (UIImage *)createNonInterpolatedUIImageFormCIImage:(CIImage *)image withSize:(CGFloat) size ;

/**
 因为生成的二维码是黑白的,所以还要对二维码进行颜色填充,并转换为透明背景,使用遍历图片像素来更改图片颜色,

 */

- (UIImage*)imageBlackToTransparent:(UIImage*)image withRed:(CGFloat)red andGreen:(CGFloat)green andBlue:(CGFloat)blue;



/**

 首先是二维码的生成,使用CIFilter很简单,直接传入生成二维码的字符串即可:

 */

- (CIImage *)createQRForString:(NSString *)qrString;

@end


  *************** 自封装的生成二维码类.m文件  *******************


//  Created by 石虎 on 16/5/10.
//  Copyright © 2016年 shih. All rights reserved.
//


#import "SHQRCodeView.h"

@interface SHQRCodeView ()

@end

@implementation SHQRCodeView

- (UIImage *)createNonInterpolatedUIImageFormCIImage:(CIImage *)image withSize:(CGFloat) size {

    CGRect extent =CGRectIntegral(image.extent);

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

    

    // 创建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 = [CIContextcontextWithOptions:nil];

    CGImageRef bitmapImage = [contextcreateCGImage:imagefromRect:extent];

    CGContextSetInterpolationQuality(bitmapRef,kCGInterpolationNone);

    CGContextScaleCTM(bitmapRef, scale, scale);

    CGContextDrawImage(bitmapRef, extent, bitmapImage);

    

    //保存bitmap到图片

    CGImageRef scaledImage =CGBitmapContextCreateImage(bitmapRef);

    

    // Cleanup

    CGContextRelease(bitmapRef);

    CGImageRelease(bitmapImage);

    return [UIImageimageWithCGImage:scaledImage];

}



- (CIImage *)createQRForString:(NSString *)qrString {

    

    //需要将字符串转换为UTF-8编码的NSData对象

    NSData *stringData = [qrStringdataUsingEncoding:NSUTF8StringEncoding];

    // 创建filter

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

    // 设置内容和纠错级别

    [qrFilter setValue:stringDataforKey:@"inputMessage"];

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

    

    // Send the image back

    return qrFilter.outputImage;

}





void ProviderReleaseData (void *info,constvoid *data,size_t size){

    free((void*)data);

}

- (UIImage*)imageBlackToTransparent:(UIImage*)image withRed:(CGFloat)red andGreen:(CGFloat)green andBlue:(CGFloat)blue{

    

    constint imageWidth = image.size.width;

    constint imageHeight = image.size.height;

    size_t      bytesPerRow = imageWidth *4;

    uint32_t* rgbImageBuf = (uint32_t*)malloc(bytesPerRow * imageHeight);

    

    // create context

    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 < pixelNum; i++, pCurPtr++){

        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 = [UIImageimageWithCGImage:imageRef];

    // 清理空间

    CGImageRelease(imageRef);

    CGContextRelease(context);

    CGColorSpaceRelease(colorSpace);

    return resultUIImage;

}

谢谢!!!

 

2016-11-24 15:50:35 dkq972958298 阅读数 2324

生成二维码

  • 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/7a0a8c8703d3



文/袁俊亮技术博客(简书作者)
原文链接:http://www.jianshu.com/p/b8bf300e9a56

2016-06-07 14:31:57 qq_27633421 阅读数 692

生成二维码就不是AVFoundation架构了,使用的是CoreImage。之前在航歌上面看见一篇使用Swift生成二维码的文章。看了之后,我就想想,Swift可以使用原生的,那么OC可不可以呢?经过测试是可以的,而且可以生成带logo的。使用起来也很简单。

首先看看两种图片:


左右两张图,都是同一个二维码,可以扫扫,有惊喜的。

左边的一张看起来模糊,右边的看起来清晰多了,这又是为什么呢?下面就会有解答的。

怎么生成二维码:

[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. /** 
  2.  *  根据字符串生成二维码 CIImage 对象 
  3.  * 
  4.  *  @param urlString 需要生成二维码的字符串 
  5.  * 
  6.  *  @return 生成的二维码 
  7.  */  
  8. + (CIImage *)creatQRcodeWithUrlstring:(NSString *)urlString{  
  9.     // 1.实例化二维码滤镜  
  10.     CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];  
  11.     // 2.恢复滤镜的默认属性 (因为滤镜有可能保存上一次的属性)  
  12.     [filter setDefaults];  
  13.     // 3.将字符串转换成NSdata  
  14.     NSData *data  = [urlString dataUsingEncoding:NSUTF8StringEncoding];  
  15.     // 4.通过KVO设置滤镜, 传入data, 将来滤镜就知道要通过传入的数据生成二维码  
  16.     [filter setValue:data forKey:@"inputMessage"];  
  17.     // 5.生成二维码  
  18.     CIImage *outputImage = [filter outputImage];  
  19.     return outputImage;  
  20. }  
生成的时CIImage对象,在显示的时候还需要先转换为UIImage对象。

[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. CIImage *ciImage = [RadiusImage creatQRcodeWithUrlstring:@"http://blog.csdn.net/zhuming3834"];  
  2. UIImage *im = [UIImage imageWithCIImage:ciImage];  
  3. self.imageView.image = im;  
这样就生成了上面图片的左边那一张二维码。

为什么会模糊呢?

我们可以打印一下生成的图片的size:

[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. NSLog(@"im.size.height = %f,im.size.width = %f",im.size.height,im.size.width);  
  2. // im.size.height = 31.000000,im.size.width = 31.000000  
生成的二维码图片的大小是31x31,而我们的控件imageView的大小是180x180。原来是图片被拉伸了导致的模糊。

怎么解决这个问题呢?

写在这里的时候,想起了一个方法:

[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. im = [im stretchableImageWithLeftCapWidth:im.size.height/2 topCapHeight:im.size.width/2];  
  2. self.imageView2.image = im;  
这个是拉伸图片的,有没有作用呢?先测试一下看看。上图:


这是什么啊?上面的方法确实是拉伸图片,但是它使用图片的中心点开始拉伸,图片里面的元素也被拉伸了(向四周扩展了,而被挤到了一起)。很显然这个方法不能使用。那么有没有更好的方法呢?答案是有的。

[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. /** 
  2.  *  改变图片大小 (正方形图片) 
  3.  * 
  4.  *  @param ciImage 需要改变大小的CIImage 对象的图片 
  5.  *  @param size    图片大小 (正方形图片 只需要一个数) 
  6.  * 
  7.  *  @return 生成的目标图片 
  8.  */  
  9. + (UIImage *)changeImageSizeWithCIImage:(CIImage *)ciImage andSize:(CGFloat)size{  
  10.     CGRect extent = CGRectIntegral(ciImage.extent);  
  11.     CGFloat scale = MIN(size/CGRectGetWidth(extent), size/CGRectGetHeight(extent));  
  12.       
  13.     // 创建bitmap;  
  14.     size_t width = CGRectGetWidth(extent) * scale;  
  15.     size_t height = CGRectGetHeight(extent) * scale;  
  16.     CGColorSpaceRef cs = CGColorSpaceCreateDeviceGray();  
  17.     CGContextRef bitmapRef = CGBitmapContextCreate(nil, width, height, 80, cs, (CGBitmapInfo)kCGImageAlphaNone);  
  18.     CIContext *context = [CIContext contextWithOptions:nil];  
  19.     CGImageRef bitmapImage = [context createCGImage:ciImage fromRect:extent];  
  20.     CGContextSetInterpolationQuality(bitmapRef, kCGInterpolationNone);  
  21.     CGContextScaleCTM(bitmapRef, scale, scale);  
  22.     CGContextDrawImage(bitmapRef, extent, bitmapImage);  
  23.       
  24.     // 保存bitmap到图片  
  25.     CGImageRef scaledImage = CGBitmapContextCreateImage(bitmapRef);  
  26.     CGContextRelease(bitmapRef);  
  27.     CGImageRelease(bitmapImage);  
  28.       
  29.     return [UIImage imageWithCGImage:scaledImage];  
  30. }  
[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. self.imageView2.image = [RadiusImage changeImageSizeWithCIImage:ciImage andSize:180];  
这个imageView2显示的图片就是最清晰的那张二维码图片。


其实可以把上面两个方法合并在一起,我们只需要传递一个URL和二维码显示的控件就可以一行代码生成我们自己的二维码控件了。

iOS 生成二维码

阅读数 226