二维码的生成与识别

二维码的生成与识别

刚刚写了一篇扫描二维码的文章,就想着怎么样才能实现像微信那样的识别图片中的二维码呢?百度一下,发现基本上都是利用ZXing或ZBar来实现的,难道系统就没有方法吗?于是再继续找,终于发现了使用CoreImage类来实现二维码的识别。

CoreImage简介

iOS提供的CoreImage框架非常强大,简直可以用来完全实现自己的”PhotoShop”,当然我本人是只会点皮毛。现在就利用CoreImage中的CIFilter和CIDetector来实现二维码的生成和识别。

生成二维码

生成滤镜

生成二维码,主要是使用CIFilter类,该类代表了各种滤镜,利用该类的方法,可生成对应的滤镜:

+ (nullable CIFilter *) filterWithName:(NSString *) name;

查询滤镜信息

那怎么知道有哪些滤镜可以使用呢?该类还提供了另外一个方法,供我们查询可以使用哪些滤镜:

+ (CI_ARRAY(NSString*) *)filterNamesInCategory:(nullable NSString *)category;

该方法会返回一个包含指定分类的可用滤镜集合,那么问题又来了,我们又如何知道有哪些分类呢?滤镜名称只是一个字符串,在头文件中并没有任何相关的属性定义,但是分类是有的,对应请查看CIFilter.h

/* Categories */
CORE_IMAGE_EXPORT NSString * const kCICategoryDistortionEffect;
CORE_IMAGE_EXPORT NSString * const kCICategoryGeometryAdjustment;
CORE_IMAGE_EXPORT NSString * const kCICategoryCompositeOperation;
CORE_IMAGE_EXPORT NSString * const kCICategoryHalftoneEffect;
CORE_IMAGE_EXPORT NSString * const kCICategoryColorAdjustment;
CORE_IMAGE_EXPORT NSString * const kCICategoryColorEffect;
CORE_IMAGE_EXPORT NSString * const kCICategoryTransition;
CORE_IMAGE_EXPORT NSString * const kCICategoryTileEffect;
CORE_IMAGE_EXPORT NSString * const kCICategoryGenerator;
CORE_IMAGE_EXPORT NSString * const kCICategoryReduction NS_AVAILABLE(10_5, 5_0);
CORE_IMAGE_EXPORT NSString * const kCICategoryGradient;
CORE_IMAGE_EXPORT NSString * const kCICategoryStylize;
CORE_IMAGE_EXPORT NSString * const kCICategorySharpen;
CORE_IMAGE_EXPORT NSString * const kCICategoryBlur;
CORE_IMAGE_EXPORT NSString * const kCICategoryVideo;
CORE_IMAGE_EXPORT NSString * const kCICategoryStillImage;
CORE_IMAGE_EXPORT NSString * const kCICategoryInterlaced;
CORE_IMAGE_EXPORT NSString * const kCICategoryNonSquarePixels;
CORE_IMAGE_EXPORT NSString * const kCICategoryHighDynamicRange;
CORE_IMAGE_EXPORT NSString * const kCICategoryBuiltIn;
CORE_IMAGE_EXPORT NSString * const kCICategoryFilterGenerator NS_AVAILABLE(10_5, 9_0);

我们要生成二维码,可以使用kCICategoryGenerator,查看到该分类下面有一个CIQRCodeGenerator,别看这家伙的名字长的像一个类,其实就是一个字符串,所以在传入的时候只需以字符串的形式传入就行了。 个人感觉苹果这种做法有点操蛋,简单的找一个滤镜的名字,都这么麻烦。代码如下所示:

_QRCodeFilter = [CIFilter filterWithName:@"CIQRCodeGenerator"];

如果说这就觉得操蛋了,那接下来还有更加麻烦的事。要想使用CIFilter生成二维码,需要设置一些属性值,方法是通过KVC,setValue:forKey,我们需要设置两个属性,那么同名字一样,我哪知道要设置哪些属性?其实方法都是一样的,CIFilter还提供了inputKeys,outputKeys,attributes属性供我们查询,我们可以将attributes的内容输出来,如下所示:

{
    "CIAttributeFilterAvailable_Mac" = "10.9";
    "CIAttributeFilterAvailable_iOS" = 7;
    CIAttributeFilterCategories =     (
        CICategoryGenerator,
        CICategoryStillImage,
        CICategoryBuiltIn
    );
    CIAttributeFilterDisplayName = "QRCode Generator";
    CIAttributeFilterName = CIQRCodeGenerator;
    CIAttributeReferenceDocumentation = "http://developer.apple.com/library/ios/documentation/GraphicsImaging/Reference/CoreImageFilterReference/index.html#//apple_ref/doc/filter/ci/CIQRCodeGenerator";
    inputCorrectionLevel =     {
        CIAttributeClass = NSString;
        CIAttributeDefault = M;
        CIAttributeDescription = "QRCode correction level L, M, Q, or H.";
        CIAttributeDisplayName = CorrectionLevel;
    };
    inputMessage =     {
        CIAttributeClass = NSData;
        CIAttributeDisplayName = Message;
    };
}

在这些属性里面,我们可以看到,上面一些都是苹果设置的属性,我们需要设置的就是最后两个属性inputCorrectionLevel和inputMessage,
inputCorrectionLevel:该参数应该是代表生成二维码的精度(自己猜的)
inputMessage:该参数代表要生成的二维码中所包含的信息
从CIAttributeClass字段中,我们可以见到,inputCorrectionLevel的值是NSString类型,并且根据CIAttributeDescription知道可选的值有L,M,Q,H等。
而inputMessage的类型则是NSData。

获取二维码图像

设置这两个属性之后,我们就可以通过以下属性来获取处理后的图片:

@property (readonly, nonatomic, nullable) CIImage *outputImage NS_AVAILABLE(10_10, 5_0);

该方法返回一个CIImage,可以转换成UIImage并设置在UIImageView上。代码如下所示:

[_QRCodeFilter setValue:@"H" forKey:@"inputCorrectionLevel"];
    [_QRCodeFilter setValue:[_messageTextField.text dataUsingEncoding:NSUTF8StringEncoding] forKey:@"inputMessage"];
    [_QRCodeImageView setImage:[UIImage imageWithCIImage:_QRCodeFilter.outputImage]];

至此,就能成功生成一个二维码。接下来就是利用CIDetector来识别二维码。

识图二维码

相对起使用CIFilter生成二维码来说,识别二维码可要简单太多了,我们只需要实例化CIDetector类,并采用以下方法,便可以获取:

- (CI_ARRAY(CIFeature*) *)featuresInImage:(CIImage *)image
    NS_AVAILABLE(10_7, 5_0);

该方法返回包含CIFeature类的数组,对于二维码来说,该数组中的类型应该是CIQRCodeFeature类的实例,我们只需要通过其中的messageString属性即可以获取到二维码中的内容。

-(void)longPressed:(UILongPressGestureRecognizer*)recognizer {
    CIImage* image = _QRCodeFilter.outputImage;
    NSArray* array =[_QRCodeDector featuresInImage:image];

    for (CIFeature* feature in array) {
        if([feature isKindOfClass:[CIQRCodeFeature class]]) {
            CIQRCodeFeature* QRCodeFeature = (CIQRCodeFeature*)feature;
            [[[UIAlertView alloc] initWithTitle:@"二维码" message:QRCodeFeature.messageString delegate:nil cancelButtonTitle:@"确定" otherButtonTitles: nil] show];
            return;
        }
    }

    return ;
}

效果演示

最终的效果演示如下图所示:
效果演示

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值