欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

iOS生成二维码(中间包含图片),长按识别二维码(Swift)

程序员文章站 2022-05-26 16:13:08
在ios中有个类cifilter,通过这个类可以创建各种特定的过滤器,今天我们主要介绍一种二维码发生器(ciqrcodegenerator)滤镜,通过这个滤镜可以自动生成我们需要的二维码。 首先我们...

在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("https://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.
    }


}