Swift-来自CIImage QR代码的图像数据/如何呈现CIFilter输出

时间:2018-07-04 17:27:17

标签: ios swift cocoa

我遇到这个问题已有一段时间了,在这里看了几十个答案,似乎找不到任何有用的东西。

场景

我正在应用的iOS端生成QR码,并希望将此QR码发送到我当前正在开发的WatchKit扩展程序中。

我如何生成QR码

func createQR(with string: String) {

    if let filter = CIFilter(name: "CIQRCodeGenerator") {

        //set the data to the contact data
        filter.setValue(string, forKey: "inputMessage")
        filter.setValue("L", forKey: "inputCorrectionLevel")

        if let codeImage = filter.outputImage {
            return UIImage(ciImage: codeImage);
        }
    }
}

我接下来要做什么

我想从QR图像中获取数据,以便可以将其发送到Apple Watch应用,如下所示:

let data = UIImagePNGRepresentation(QRCodeImage);

但是,总是返回nil,因为没有图像数据支持过滤器的输出。

  

注意:我知道没有与CI图像关联的数据,因为它尚未渲染,甚至没有与之关联的数据,因为它只是过滤器的输出。 我不知道该如何解决,因为我在图像处理等方面还很陌生。 :/

我尝试过的

cgImage创建一个filter.outputImage

func createQR(with string: String) {
    if let filter = CIFilter(name: "CIQRCodeGenerator") {

        //set the data to the contact data
        filter.setValue(contactData, forKey: "inputMessage")
        filter.setValue("L", forKey: "inputCorrectionLevel")

        if let codeImage = filter.outputImage {
            let context = CIContext(options: nil)
            if let cgImage = context.createCGImage(codeImage, from: codeImage.extent) {
                self.QRCode = UIImage(cgImage: cgImage)
            }
        }
    }
}
  

但是这不起作用,似乎也没有,因为视图上的图像是空白的。

创建空白CIImage作为输入图像

func update(with string: String) {
    let blankCiImage = CIImage(color: .white) //This probably isn't right...
    if let filter = CIFilter(name: "CIQRCodeGenerator") {

        filter.setValue(contactData, forKey: "inputMessage")
        filter.setValue("L", forKey: "inputCorrectionLevel")
        filter.setValue(blankCiImage, forKey: kCIInputImageKey)

        if let codeImage = filter.outputImage {
            let context = CIContext(options: nil)
            if let cgImage = context.createCGImage(codeImage, from: codeImage.extent) {
                self.contactCode = UIImage(cgImage: cgImage)
                print(self.contactCode!)
                print(UIImagePNGRepresentation(self.contactCode!))
            }
        }
    }
}
  

这也不起作用-我的想法是向其添加空白图像,然后在其上方进行过滤,但是我可能做得不好。

我的目标

从字面上看,只是为了从生成的QR码中获取数据。大多数线程建议使用UIImage(ciImage: output),但这没有任何后备数据。

如果有人可以帮助我解决这个问题,那就太好了。并且任何有关其工作原理的解释都将很棒。

编辑:我不认为这与标记的重复项相同-标记的重复项是关于使用CI过滤器编辑现有图像并获取该数据,而这是关于仅通过CI过滤器创建,没有输入图像-QR码。另一个答案并不完全相关。

1 个答案:

答案 0 :(得分:3)

您的代码中有几个问题。您需要先使用String Encoding isoLatin1将字符串转换为数据,然后再将其传递给过滤器。另一个问题是,要将CIImage转换为数据,您需要重绘/渲染CIImage并防止在缩放时模糊图像,您需要对图像进行变换以增加其大小:

extension String {
    var qrCode: UIImage? {
        guard
            let data = data(using: .isoLatin1),
            let filter = CIFilter(name: "CIQRCodeGenerator")
            else { return nil }
        filter.setValue(data, forKey: "inputMessage")
        filter.setValue("M", forKey: "inputCorrectionLevel")
        guard let image = filter.outputImage
            else { return nil }
        let size = image.extent.integral
        let output = CGSize(width: 250, height: 250)
        let matrix = CGAffineTransform(scaleX: output.width / size.width, y: output.height / size.height)
        UIGraphicsBeginImageContextWithOptions(output, false, 0)
        defer { UIGraphicsEndImageContext() }
        UIImage(ciImage: image.transformed(by: matrix))
            .draw(in: CGRect(origin: .zero, size: output))
        return UIGraphicsGetImageFromCurrentImageContext()
    }
}

游乐场测试:

let link = "https://stackoverflow.com/questions/51178573/swift-image-data-from-ciimage-qr-code-how-to-render-cifilter-output?noredirect=1"
let image = link.qrCode!
let data =  image.jpegData(compressionQuality: 1)  // 154785 bytes

enter image description here