2016-09-10 20:04:54 HK_5788 阅读数 2910

                                                   ~~~写在前面的话~~~

 我之前打算做一个APP,然后把电话号码生成二维码 或者条形码, 用手机扫描,这样,就不用担心会输入错误电话号码了。

 在下面是实现的扫描二维码的功能中,扫描完成,将会把扫描到的号码 拨打出去。~~~

关于应用之间的切换,参考链接:

http://blog.sina.com.cn/s/blog_7ea0400d0102uy01.html

 


~~CSDN不知道怎么了,贴代码的地方不能有横向的滚动条了,不过,可以用下面的方法查看到具体代码呢~~



------------我是分割线--------------

基于AVFoundation实现的。

1、效果图

     生成界面


  

     扫描界面:



2、环境

     ios9.3.2 

     Xcode7.3(swift 3)


3、生成二维码

     ~~新建项目~~

     A、新建文件:QRCode View.swift  , 该文件主要用来生成二维码

     B、该文件源码内容如下:

import UIKit

/// 生成二维码
class QRCodeView: UIView
{
    /**
     - logo
     - parameter surperImage: 二维码
     - parameter subImage:    logo
     - parameter postRext:    logo位置
     - returns: 返回加上logo的图片
     */
    private func imageViewAddImage(surperImage: UIImage, subImage: UIImage, postRect:CGRect) -> UIImage
    {
        //// 创建图像
        UIGraphicsBeginImageContext(surperImage.size);
        
        //// 设置坐标
        surperImage.drawInRect(CGRect(x:0, y:0, width: surperImage.size.width, height: surperImage.size.height));
        
        surperImage.drawInRect(postRect);
        
        //// 返回一个图像基于当前位图图形
        let newImage = UIGraphicsGetImageFromCurrentImageContext();
        
        //// 移除当前位图图形
        UIGraphicsEndImageContext();
        
        return newImage;
    }
    
    /**
     调整大小
     - parameter ciImage: 待改变的image
     - parameter width:   设置比例系数
     - returns: 设置比例后的图片
     */
    private func SetSize(ciImage: CIImage, _width:CGFloat) -> UIImage
    {
        let extent = CGRectIntegral(ciImage.extent);
        let scale = min(_width / CGRectGetWidth(extent), _width / CGRectGetHeight(extent));
        
        let width = CGRectGetWidth(extent) * scale;
        let height = CGRectGetHeight(extent) * scale;
        
        let cs = CGColorSpaceCreateDeviceGray();
        let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.None.rawValue);
        
        let bitmapRef = CGBitmapContextCreate(nil, Int(width), Int(height), 8, 0, cs, bitmapInfo.rawValue);
        
        let context = CIContext(options: [kCIContextUseSoftwareRenderer:(true)]);
        let bitmapImage = context.createCGImage(ciImage, fromRect: extent);
        
        CGContextSetInterpolationQuality(bitmapRef, CGInterpolationQuality.None)
        CGContextScaleCTM(bitmapRef, scale, scale)
        CGContextDrawImage(bitmapRef, extent, bitmapImage);
        
        let scaledImage = CGBitmapContextCreateImage(bitmapRef);
        
        return UIImage(CGImage: scaledImage!);
    }
    
    
    /**
     截取logo边角
     - parameter cornerRadius: 截取度
     - parameter image:        需要截取边角的图片
     - returns: 截取边角后的图片
     */
    private func ImageAfterCutOutCorner(cornerRadius:CGFloat, image:UIImage) -> UIImage
    {
        let frame = CGRectMake(0, 0, image.size.width, image.size.height);
        UIGraphicsBeginImageContextWithOptions(image.size, false, 1.0);
        UIBezierPath.init(roundedRect:frame, cornerRadius: cornerRadius).addClip();
        image.drawInRect(frame);
        let im = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        
        return im;
    }
    
    /**
     生成二维码
     - parameter urlString:    电话号码
     - parameter surperView:   image View
     - parameter logo:         logo的位置
     - parameter logoSize:     logo的大小
     - parameter cornerRadius: 边角裁剪度 
     - returns: 二维码
     */
    class func GenerateQRCode(urlString:String, surperView:UIView, logo:UIImage, logoSize:CGSize, cornerRadius: CGFloat) -> QRCodeView
    {
        let qrCodeView = QRCodeView();
        
        qrCodeView.frame = CGRect(x: 0, y: 0, width: surperView.frame.size.width, height: surperView.frame.size.height);
        //// 该参数代表二维码不可改变
        let filter = CIFilter.init(name: "CIQRCodeGenerator");
        filter?.setDefaults();
        filter?.setValue(urlString.dataUsingEncoding(NSUTF8StringEncoding), forKey: "inputMessage"); //inputMessage 固定写法,代表输入信息 的意思
        let ciImage = filter?.outputImage;
        
        let QRImage = qrCodeView.SetSize(ciImage!, _width: surperView.frame.width);
        
        var cornerRadius_1 = cornerRadius;
        if (!logo.isEqual(nil))
        {
            if (cornerRadius_1 < 0)
            {
                cornerRadius_1 = 0;
            }
        }
        qrCodeView.layer.contents = QRImage.CGImage;
        surperView.addSubview(qrCodeView);
        
        return qrCodeView;
    }
}


     二维码创建好了,接下来就是调用了
     C、在ViewController.swift 文件中调用。

      D、在main.storyboard中添加控件:


     E、在viewcontroller.swift 做关联:


     F、同理,在 viewcontroller.swift  关联按钮的事件


     G、关联完成,接着就在viewcontroller.swift中调用创建二维码了

         生成二维码,当然是写在这个按钮下啦。 在 F 的函数中写上如下代码:

    /**
     生成按钮
     - parameter sender: nothing
     */
    @IBAction func BtnGenerateQRCode(sender: UIButton)
    {
        label.text = "";
        if (textField.text == "")
        {
            label.font = UIFont.systemFontOfSize(20);
            label.text = "电话号码不能为空";
            return;
        }
    
        textField.resignFirstResponder();/// 取消焦点
        // 生成二维码
        QRCodeView.GenerateQRCode(textField.text!, surperView: imageView, logo: UIImage(named: "logo")!, logoSize: CGSizeMake(100, 100), cornerRadius: CGFloat(1000));
        
    }
    同时,在ViewDidLoad方法中写上代码,设置控件属性

    /**
     窗口加载
     */
    override func viewDidLoad()
    {
        super.viewDidLoad();
        
    
        label.adjustsFontSizeToFitWidth = true;// 设置自适应
        label.text = "";       /// 清空
        
        
        // Do any additional setup after loading the view, typically from a nib.
    }

    OK,二维码生成完成~~~

下面是  viewcontroller.swift 的详细源码:

//
//  ViewController.swift
//  GenerateQRCode
//
//  Created by driver on 16/9/7.
//  Copyright © 2016年 driver. All rights reserved.
//

import UIKit

class ViewController: UIViewController {
    /// 提示label
    @IBOutlet weak var label: UILabel!
    /// 二维码显示框
    @IBOutlet weak var imageView: UIImageView!
    /// 电话号码输入框
    @IBOutlet weak var textField: UITextField!

    /**
     窗口加载
     */
    override func viewDidLoad()
    {
        super.viewDidLoad();
        
    
        label.adjustsFontSizeToFitWidth = true;// 设置自适应
        label.text = "";       /// 清空
        
        
        // Do any additional setup after loading the view, typically from a nib.
    }
    
    /**
     生成按钮
     - parameter sender: nothing
     */
    @IBAction func BtnGenerateQRCode(sender: UIButton)
    {
        label.text = "";
        if (textField.text == "")
        {
            label.font = UIFont.systemFontOfSize(20);
            label.text = "电话号码不能为空";
            return;
        }
    
        textField.resignFirstResponder();/// 取消焦点
        // 生成二维码
        QRCodeView.GenerateQRCode(textField.text!, surperView: imageView, logo: UIImage(named: "logo")!, logoSize: CGSizeMake(100, 100), cornerRadius: CGFloat(1000));
        
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}



///-----我是分割线--------------------

4、扫描二维码

   ~~~~ 新建项目~~~

    A、扫描,就是在main.storyboard 中添加一个控件:按钮, 然后关联其touch事件。

    B、在 Viewcontroller.swift  中,导入的库:

import UIKit
import AVFoundation
    C、

ViewController类继承的有:

UIViewController, AVCaptureMetadataOutputObjectsDelegate
代码:

class ViewController: UIViewController, AVCaptureMetadataOutputObjectsDelegate
  D、viewcontroller类 定义的属性有:

    ////定义属性
    var session: AVCaptureSession?;
    var layer: AVCaptureVideoPreviewLayer?;

E、viewDidLoad方法中添加代码:

        super.viewDidLoad();
        ///self.view.backgroundColor = UIColor.lightGrayColor();
        self.modalPresentationStyle = .Custom;
F、在自己关联的按钮事件函数,源码如下:

    ////扫描
    @IBAction func scanQRcode(sender: AnyObject)
    {
        self.session = AVCaptureSession();
        
        //// 
        let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo);
        do
        {
            let input = try AVCaptureDeviceInput(device: device);
            
            if (self.session!.canAddInput(input))
            {
                self.session!.addInput(input);
            }
            
            ////输出
            let output = AVCaptureMetadataOutput();
            output.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue());
            
            if (self.session!.canAddOutput(output))
            {
                self.session!.addOutput(output)
                output.metadataObjectTypes = [AVMetadataObjectTypeQRCode];
            }
            
            ////添加图层
            self.layer = AVCaptureVideoPreviewLayer(session:self.session!);
            self.layer!.frame = self.view.frame;
            self.view.layer.addSublayer(self.layer!);
            
            //// 开始扫描
            self.session?.startRunning();
        }
        catch let error as NSError
        {
            print(error);
        }
    }

F、实现  AVCaptureMetadataOutputObjectsDelegate   委托中的方法:

    ////委托
    @objc func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!)
    {
        let stringValue:String?;
        
        if (metadataObjects.count > 0)
        {
            let metadataObject = metadataObjects[0] as! AVMetadataMachineReadableCodeObject;
            
            ////
            stringValue = metadataObject.stringValue;
            if (nil != stringValue) ////这里捕捉到二维码
            {
                self.session!.stopRunning();
                //// 移除图层
                self.layer!.removeFromSuperlayer();
                
                ////启动拨号~~
                UIApplication.sharedApplication().openURL(NSURL(string: "tel://\(stringValue)")!);
                
                
//                let alertView = UIAlertController(title: "二维码", message: stringValue, preferredStyle: .Alert);
//                let action = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil);
//                alertView.addAction(action);
                
                ////显示提示框
//                self.presentViewController(alertView, animated: true, completion:nil);
            }
            else
            {
                let alertView = UIAlertController(title: "二维码", message: "没有扫描到二维码", preferredStyle: .Alert);
                let action = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil);
                alertView.addAction(action);
                
                ////显示提示框
                self.presentViewController(alertView, animated: true, completion:nil);
            }
        }
    }


G、详细源码:


import UIKit
import AVFoundation

class ViewController: UIViewController, AVCaptureMetadataOutputObjectsDelegate
{
    ////定义属性
    var session: AVCaptureSession?;
    var layer: AVCaptureVideoPreviewLayer?;
    
    
    ////方法
    override func viewDidLoad()
    {
        super.viewDidLoad();
        ///self.view.backgroundColor = UIColor.lightGrayColor();
        self.modalPresentationStyle = .Custom;
        
    }

    
    ////扫描
    @IBAction func scanQRcode(sender: AnyObject)
    {
        self.session = AVCaptureSession();
        
        //// 
        let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo);
        do
        {
            let input = try AVCaptureDeviceInput(device: device);
            
            if (self.session!.canAddInput(input))
            {
                self.session!.addInput(input);
            }
            
            ////输出
            let output = AVCaptureMetadataOutput();
            output.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue());
            
            if (self.session!.canAddOutput(output))
            {
                self.session!.addOutput(output)
                output.metadataObjectTypes = [AVMetadataObjectTypeQRCode];
            }
            
            ////添加图层
            self.layer = AVCaptureVideoPreviewLayer(session:self.session!);
            self.layer!.frame = self.view.frame;
            self.view.layer.addSublayer(self.layer!);
            
            //// 开始扫描
            self.session?.startRunning();
        }
        catch let error as NSError
        {
            print(error);
        }
    }
    
    ////委托
    @objc func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!)
    {
        let stringValue:String?;
        
        if (metadataObjects.count > 0)
        {
            let metadataObject = metadataObjects[0] as! AVMetadataMachineReadableCodeObject;
            
            ////
            stringValue = metadataObject.stringValue;
            if (nil != stringValue) ////这里捕捉到二维码
            {
                self.session!.stopRunning();
                //// 移除图层
                self.layer!.removeFromSuperlayer();
                
                ////启动拨号~~
                UIApplication.sharedApplication().openURL(NSURL(string: "tel://\(stringValue)")!);
                
                
//                let alertView = UIAlertController(title: "二维码", message: stringValue, preferredStyle: .Alert);
//                let action = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil);
//                alertView.addAction(action);
                
                ////显示提示框
//                self.presentViewController(alertView, animated: true, completion:nil);
            }
            else
            {
                let alertView = UIAlertController(title: "二维码", message: "没有扫描到二维码", preferredStyle: .Alert);
                let action = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil);
                alertView.addAction(action);
                
                ////显示提示框
                self.presentViewController(alertView, animated: true, completion:nil);
            }
        }
    }
    
    override func didReceiveMemoryWarning()
    {
        super.didReceiveMemoryWarning()
      
    }


}

2016-03-31 23:23:33 feng2qing 阅读数 2038

首先需要:   import AVFoundation


// MARK: - 1. 懒加载: 会,输入设备,输出设备,预览图层

//会

private lazy var session: AVCaptureSession = AVCaptureSession()


//拿到输入设备

private lazy var deviceInput: AVCaptureDeviceInput? = {

    

    //获取摄像头

    let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)

    

    do {

        //创建输入对象

        let input = try AVCaptureDeviceInput(device: device)

        return input

    } catch {

        //打印错误信息

        print(error)

        return nil

    }

}()


//拿到输出设备

private lazy var output: AVCaptureMetadataOutput = AVCaptureMetadataOutput()


//创建预览图层

private lazy var previewLayer: AVCaptureVideoPreviewLayer = {

    

    let layer = AVCaptureVideoPreviewLayer(session: self.session)

    layer.frame = UIScreen.mainScreen().bounds

    return layer

}()


//MARK: - 2. 扫描二维码

func starScan() {

    

   //先判断是否能将设备添加到回话中

    if !session.canAddInput(deviceInput) {

        return

    }

    

   //判断是否能够将输出添加到回话中

    if !session .canAddOutput(output) {

        return

    }

    

   //将输入和输出添加到回话中

    session.addInput(deviceInput)

    session.addOutput(output)

    

   //设置输入能够解析的数据类型

   //设置能解析的数据类型,一定要在输出对象添加到会员之后设置

    output.metadataObjectTypes = output.availableMetadataObjectTypes

    

   //设置输出对象的代理,只要解析成功,就会通知代理

    output.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())

    

    //添加预览图层

    view.layer.insertSublayer(previewLayer, atIndex: 0)

    

    //告诉session开始扫描

    session.startRunning()

}


//MARK: - 3. 实现代理 AVCaptureMetadataOutputObjectsDelegate

extension QRCodeViewController: AVCaptureMetadataOutputObjectsDelegate {

    

   //只要解析到数据就会调用

    func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) {

        

//获取扫描结果

        //注意是: stringValue

        print(metadataObjects.last?.stringValue)

    }

}


2016-09-06 16:54:53 lulu_ldy 阅读数 1276

根据项目的需求,所以这里主要介绍一下由链接生成的二维码,长按二维码,截取二维码部分保存到本地相册中。
最初我想用UIImageWriteToSavedPhotosAlbum方法直接把生成的二维码存入相册中,但是发现保存失败,感觉应该是类型问题出的错,所以我用了截屏的方法。

override func viewWillAppear(animated: Bool) {

        qrCodeImageView.image = createQRForString(url,qrImageName: "QRCoreImage")

    }

    //创建二维码图片
    func createQRForString(qrString: String?, qrImageName: String?) -> UIImage?{

            let stringData = sureQRString.dataUsingEncoding(NSUTF8StringEncoding,
                allowLossyConversion: false)

            // 创建一个二维码的滤镜
            let qrFilter = CIFilter(name: "CIQRCodeGenerator")!
            qrFilter.setValue(stringData, forKey: "inputMessage")
            qrFilter.setValue("H", forKey: "inputCorrectionLevel")
            let qrCIImage = qrFilter.outputImage
            // 创建一个颜色滤镜,黑白色
            let colorFilter = CIFilter(name: "CIFalseColor")!
            colorFilter.setDefaults()
            colorFilter.setValue(qrCIImage, forKey: "inputImage")
            colorFilter.setValue(CIColor(red: 0, green: 0, blue: 0), forKey: "inputColor0")
            colorFilter.setValue(CIColor(red: 1, green: 1, blue: 1), forKey: "inputColor1")
            // 返回二维码image
            let codeImage = UIImage(CIImage: colorFilter.outputImage!

            // 下面是将头像之类的图片放到二维码中
            //            if let iconImage = UIImage(named: qrImageName!) {
            //                let rect = CGRectMake(0, 0, codeImage.size.width, codeImage.size.height)
            //                UIGraphicsBeginImageContext(rect.size)
            //
            //                codeImage.drawInRect(rect)
            //                let avatarSize = CGSizeMake(rect.size.width * 0.25, rect.size.height * 0.25)
            //                let x = (rect.width - avatarSize.width) * 0.5
            //                let y = (rect.height - avatarSize.height) * 0.5
            //                iconImage.drawInRect(CGRectMake(x, y, avatarSize.width, avatarSize.height))
            //                let resultImage = UIGraphicsGetImageFromCurrentImageContext()
            //
            //                UIGraphicsEndImageContext()
            //                return resultImage
            //            }

            return codeImage
        }
        return nil
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        //添加长按事件
        let upKeyGesture = UILongPressGestureRecognizer()
        upKeyGesture.addTarget(self, action: "qrCodeButtonClicked:")
        qrCodeButton.addGestureRecognizer(upKeyGesture)
    }


    //长按事件
    func qrCodeButtonClicked(sender: UILongPressGestureRecognizer) {

        if sender.state == UIGestureRecognizerState.Began{

            // 开始截取二维码部分(设置截取大小)
            UIGraphicsBeginImageContext(qrCodeImageView.bounds.size) 

            // 获得截取到的图像
            let img : UIImage = UIGraphicsGetImageFromCurrentImageContext() 

            // 结束截取
            UIGraphicsEndImageContext() 

            //将图片保存到本地
            UIImageWriteToSavedPhotosAlbum(img, self, "image:didFinishSavingWithError:contextInfo:", nil) 

        }else if sender.state == UIGestureRecognizerState.Ended{

            return
        }

    }

    func image(image:UIImage,didFinishSavingWithError error:NSError?,contextInfo:AnyObject) {

        if error != nil {
            UIhelper.showToast("保存失败", view: self.view)

        } else {
            UIhelper.showToast("保存成功", view: self.view)
        }
    }

最后要注意的是,我在开始的时候,保存二维码,在本地相册中会同时保存两张,后来发现是长按方法执行了两次,所以进行了UIGestureRecognizerState的判断。

2016-04-03 00:32:50 feng2qing 阅读数 2066

//MARK: -传进去字符串,生成二维码图片

private func creatQRCodeImage(text: String) -> UIImage{

    

    //创建滤镜

    let filter = CIFilter(name: "CIQRCodeGenerator")

   //还原滤镜的默认属性

    filter?.setDefaults()

   //设置需要生成二维码的数据

    filter?.setValue(text.dataUsingEncoding(NSUTF8StringEncoding), forKey: "inputMessage")

   //从滤镜中取出生成的图片

    let ciImage = filter?.outputImage

   //这个清晰度不好

    //let bgImage = UIImage(CIImage: ciImage!)

    //这个清晰度好

    let bgImage = createNonInterpolatedUIImageFormCIImage(ciImage!, size: 300)

    //创建一个头像

    let icon = UIImage(named: "navigationbar_pop_highlighted")

   //合成图片(把二维码和头像合并)

    let newImage = creatImage(bgImage, iconImage: icon!)

   //返回生成好的二维码

    return newImage

    }

    

   //MARK: - 根据背景图片和头像合成头像二维码

    private func creatImage(bgImage: UIImage, iconImage:UIImage) -> UIImage{

        

        //开启图片上下文

        UIGraphicsBeginImageContext(bgImage.size)

        //绘制背景图片

        bgImage.drawInRect(CGRect(origin: CGPointZero, size: bgImage.size))

        //绘制头像

        let width: CGFloat = 50

        let height: CGFloat = width

        let x = (bgImage.size.width - width) * 0.5

        let y = (bgImage.size.height - height) * 0.5

        iconImage.drawInRect(CGRect(x: x, y: y, width: width, height: height))

        //取出绘制好的图片

        let newImage = UIGraphicsGetImageFromCurrentImageContext()

        //关闭上下文

        UIGraphicsEndImageContext()

        //返回合成好的图片

        return newImage

    }

    

    //MARK: - 根据CIImage生成指定大小的高清UIImage

   private func createNonInterpolatedUIImageFormCIImage(image: CIImage, size: CGFloat) -> UIImage {

        

        let extent: CGRect = CGRectIntegral(image.extent)

        let scale: CGFloat = min(size/CGRectGetWidth(extent), size/CGRectGetHeight(extent))

        

        let width = CGRectGetWidth(extent) * scale

        let height = CGRectGetHeight(extent) * scale

        let cs: CGColorSpaceRef = CGColorSpaceCreateDeviceGray()!

        let bitmapRef = CGBitmapContextCreate(nil, Int(width), Int(height), 8, 0, cs, 0)!

        

        let context = CIContext(options: nil)

        let bitmapImage: CGImageRef = context.createCGImage(image, fromRect: extent)

        

        CGContextSetInterpolationQuality(bitmapRef,  CGInterpolationQuality.None)

        CGContextScaleCTM(bitmapRef, scale, scale);

        CGContextDrawImage(bitmapRef, extent, bitmapImage);

        let scaledImage: CGImageRef = CGBitmapContextCreateImage(bitmapRef)!

        return UIImage(CGImage: scaledImage)

    }

2016-08-17 18:01:00 qq_30970529 阅读数 2137

在iOS中有个类CIFilter,通过这个类可以创建各种特定的过滤器,今天我们主要介绍一种二维码发生器(CIQRCodeGenerator)滤镜,通过这个滤镜可以自动生成我们需要的二维码。
首先我们要创建一个二维码滤镜:

            //创建二维码滤镜
            let qrCIFilter = CIFilter(name: "CIQRCodeGenerator")

注意,这个初始化方法中的传入参数是只有固定的几种字符串的,使用不同的字符串可以创建不同用处的滤镜的。所以在官方的参考文档中特别说明在创建以后要检查qrCIFilter是否为空,以防拼写错误无法创建滤镜。如果我们想知道到底有哪几种固定的字符串可以在Xcode中command+右键点击CIQRCodeGenerator字符串,跳到的参考文献上下文中有其他固定值的介绍的。
滤镜创建出来了,我们还要给这滤镜添加各种属性,滤镜的属性是一对一对的键值对的,同样的这个属性字典的key值也是固定的,二维码滤镜有两种属性inputMessage和inputCorrectionLevel,在iOS中,滤镜的属性如果你不特别设置那么系统会给一个默认值,所以你无需再统一设置默认值。inputMessage指输入信息,具体来说就是你要加密的的字符串,但是value值是NSData类型的,inputCorrectionLevel指输入的纠错级别,有四种不同的级别:A single letter specifying the error correction format. An NSString object whose display name is CorrectionLevel不多说了,看代码:

            //二维码包含的信息
            qrCIFilter!.setValue(messageData, forKey: "inputMessage")
            //L7% M15% Q25% H%30% 纠错级别. 默认值是M
            qrCIFilter!.setValue("H", forKey: "inputCorrectionLevel")

到这一步其实你已经创建了一个最简单的二维码了,你可以输出过滤后的图片了:

        let qrImage = qrCIFilter?.outputImage

这里qrImage是CIImage类型的,你可以通过这个qrImage创建一个UIImage类型的图片,然后放到UIImageView视图显示出来,但是你会发现这个二维码会非常模糊,我们要对它进一步处理。
在这里先感谢一下航哥的无私奉献,下面的处理我也是看到他的分享后才知道可以这么做的。我们在上面的基础上再创建一个滤镜CIFalseColor,我查了下官方文档度这种滤镜的说明简单:False color is often used to process astronomical and other scientific data, such as ultraviolet and x-ray images,其实它的用处是用来伪造颜色的。CIFalseColor只有三个固定的属性inputImage,inputColor0,inputColor1。这三属性很好理解,直接看代码:

            let colorFilter = CIFilter(name: "CIFalseColor")
            //输入图片
            colorFilter!.setValue(qrImage, forKey: "inputImage")
            //输入颜色
             colorFilter!.setValue(CIColor(red: 0,green: 0,blue: 0), forKey: "inputColor0")
            colorFilter!.setValue(CIColor(red: 1,green: 1,blue: 1), forKey: "inputColor1")

然后我们再对图片进行缩放(缩放后图片会很清晰),并且转换成UIImage类型:

var image = UIImage(CIImage: colorFilter!.outputImage!
                .imageByApplyingTransform(CGAffineTransformMakeScale(5, 5)))

到这里我们的二维码图片已经生成完毕了,但是我们常常会在二维码中间放置图片来做个性化处理。这个就相当于在图片中再添加一个图片,处理起来就比较简单了,其实就四个步骤:第一开启上下文;第二图片重绘这里我们要重绘两张图片一张是二维码图片一张是个性化图片;第三是通过上下文获取图片;第三是关闭上下文。

              //开启上下文
            UIGraphicsBeginImageContext(frame.size)
            //二维码图片重绘(二维码图片如果不绘制,获取的图片无法反过来创建CIImage)
            image.drawInRect(frame)
            if let myImage = UIImage(named:andImageName) {
                //个性图片尺寸
                let mySize = CGSizeMake(frame.size.width/4, frame.size.height/4)
                //重绘自定义图片
                myImage.drawInRect(CGRectMake(frame.size.width/2-mySize.width/2, frame.size.height/2-mySize.height/2, mySize.width, mySize.height))
            }
            //从上下文获取图片
            image = UIGraphicsGetImageFromCurrentImageContext()
            //关闭上下文
            UIGraphicsEndImageContext()

下面我们再看看二维码的识别,先创建一个长按手势:

         let longTap = UILongPressGestureRecognizer(target: self, action: #selector(longPress))
        self.view .addGestureRecognizer(longTap)

然后当长按时我们解析我们的二维码。解析二维码要创建探测器,探测器有不同的类型,这里创建一个简单的二维码探测器。
创建探测器有几个传入参数:探测器类型、上下文、属性选项:

          /*创建探测器 options 是字典key:
         CIDetectorAccuracy 精度
         CIDetectorTracking 轨迹
         CIDetectorMinFeatureSize 最小特征尺寸
         CIDetectorNumberOfAngles 角度**/
        let dector = CIDetector(ofType: CIDetectorTypeQRCode, context: CIContext(), options: [CIDetectorAccuracy:CIDetectorAccuracyHigh])

然后我们再创建一个CIImage类型的图片,探测器会探测出这张图片里面的所有二维码:

let qrFeatures = dector.featuresInImage(decodeImage!) as! [CIQRCodeFeature]

上面的代码中qrFeatures值是一个数组,元素类型是CIQRCodeFeature(二维码特征),CIQRCodeFeature有个属性messageString表示二维码所代表的信息。
怎么样长按识别二维码是不是很简单。下面的是整个demo的源码,有兴趣的可以参考下:

//
//  ViewController.swift
//  通过滤镜CIFilter生成二维码
//
//  Created by 句芒 on 16/8/17.
//  Copyright © 2016年 fanwei. All rights reserved.
//

import UIKit

class ViewController: UIViewController {

    let imageView = UIImageView(frame: CGRect(x: 30, y: 50, width: 200, height: 200))
    let pictureView = UIImageView(frame: CGRect(x: 50, y: 270, width: 200, height: 200))

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        imageView.image = createQRCodeByCIFilterWithString("句芒二维码发生器", andImageName:"")

        self.view .addSubview(imageView)


        pictureView.image = createQRCodeByCIFilterWithString("http://www.jubaobar.com", andImageName: "jubaobar.jpg")
        self.view.addSubview(pictureView)

        let longTap = UILongPressGestureRecognizer(target: self, action: #selector(longPress))
        self.view .addGestureRecognizer(longTap)
        let data = UIImagePNGRepresentation(pictureView.image!)
        let path = NSHomeDirectory().stringByAppendingString("/Documents/s.png")
        data!.writeToFile(path, atomically: true)
        print(path)
    }

    func longPress(recoginzer:UILongPressGestureRecognizer) {
        let point = recoginzer.locationInView(self.view)
        if imageView.frame.contains(point) {
            return show(decodeQRCode(imageView.image!))
        }
        if pictureView.frame.contains(point) {

            return show(decodeQRCode(pictureView.image!))
        }
    }

    func decodeQRCode(image:UIImage) -> String {
        let decodeImage = CIImage(image: image)
        /*创建探测器 options 是字典key:
         CIDetectorAccuracy 精度
         CIDetectorTracking 轨迹
         CIDetectorMinFeatureSize 最小特征尺寸
         CIDetectorNumberOfAngles 角度**/
        let dector = CIDetector(ofType: CIDetectorTypeQRCode, context: CIContext(), options: [CIDetectorAccuracy:CIDetectorAccuracyHigh])

        let qrFeatures = dector.featuresInImage(decodeImage!) as! [CIQRCodeFeature]
       return qrFeatures.last!.messageString

    }

    func show(message:String) {
        let alert = UIAlertController(title: "二维码", message: message, preferredStyle: .Alert)
        alert.addAction(UIAlertAction(title: "知道了", style:.Cancel, handler: nil))
        self .presentViewController(alert, animated: true, completion: nil)
    }

    func  createQRCodeByCIFilterWithString(message:String,andImageName:String) -> UIImage? {
        if let messageData = message.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) {
            //创建二维码滤镜
            let qrCIFilter = CIFilter(name: "CIQRCodeGenerator")
            //二维码包含的信息
            qrCIFilter!.setValue(messageData, forKey: "inputMessage")
            //L7% M15% Q25% H%30% 纠错级别. 默认值是M
            qrCIFilter!.setValue("H", forKey: "inputCorrectionLevel")
            let qrImage = qrCIFilter?.outputImage
            //创建颜色滤镜主要是了解决二维码不清晰 False color is often used to process astronomical and other scientific data, such as ultraviolet and x-ray images.通常用于处理紫外线,x射线等天文或科学的数据
            let colorFilter = CIFilter(name: "CIFalseColor")
            //输入图片
            colorFilter!.setValue(qrImage, forKey: "inputImage")
            //输入颜色
            colorFilter!.setValue(CIColor(red: 0,green: 0,blue: 0), forKey: "inputColor0")
            colorFilter!.setValue(CIColor(red: 1,green: 1,blue: 1), forKey: "inputColor1")
            var image = UIImage(CIImage: colorFilter!.outputImage!
                .imageByApplyingTransform(CGAffineTransformMakeScale(5, 5)))

            let frame = CGRectMake(0, 0, image.size.width, image.size.height)

            //开启上下文
            UIGraphicsBeginImageContext(frame.size)
            //二维码图片重绘(二维码图片如果不绘制,获取的图片无法反过来创建CIImage)
            image.drawInRect(frame)
            if let myImage = UIImage(named:andImageName) {
                //个性图片尺寸
                let mySize = CGSizeMake(frame.size.width/4, frame.size.height/4)
                //重绘自定义图片
                myImage.drawInRect(CGRectMake(frame.size.width/2-mySize.width/2, frame.size.height/2-mySize.height/2, mySize.width, mySize.height))
            }
            //从上下文获取图片
            image = UIGraphicsGetImageFromCurrentImageContext()
            //关闭上下文
            UIGraphicsEndImageContext()

            return image
        }
        return nil
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

二维码 swift 4

阅读数 308

没有更多推荐了,返回首页