【问题标题】:Swift - Image Data From CIImage QR Code / How to render CIFilter OutputSwift - 来自 CIImage QR 码的图像数据/如何呈现 CIFilter 输出
【发布时间】:2018-12-13 04:25:30
【问题描述】:

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

场景

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

我是如何生成二维码的

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 图像关联的数据,因为它没有被渲染,甚至没有与之关联的数据,因为它只是过滤器的输出。 我不知道如何解决这个问题,因为我对图像处理等还很陌生。 :/

我的尝试

filter.outputImage 创建一个cgImage

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!))
            }
        }
    }
}

这也不起作用 - 我的想法是添加一个空白图像,然后在它上面做过滤器,但我可能做得不对。

我的目标

字面意思只是为了从生成的二维码中获取数据。大多数线程建议 UIImage(ciImage: output) ,但这没有任何支持数据。

如果有人能帮我解决这个问题,那就太好了。任何关于它如何工作的解释都会很棒。

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

【问题讨论】:

  • 你只需要重新绘制图像。与标记为重复的解决方案相同
  • 您可以使用此答案stackoverflow.com/a/43011878/2303865中的CIImage扩展图像属性@
  • @LeoDabus 好的,所以我尝试了这个,当在视图上显示我的图像时,它是一个空白图像 - 也许是因为没有输入图像?嗯。有什么想法吗?

标签: ios swift cocoa


【解决方案1】:

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

extension StringProtocol {
    var qrCode: UIImage? {
        guard
            let data = data(using: .isoLatin1),
            let outputImage = CIFilter(name: "CIQRCodeGenerator",
                              parameters: ["inputMessage": data, "inputCorrectionLevel": "M"])?.outputImage
        else { return nil }
        let size = outputImage.extent.integral
        let output = CGSize(width: 250, height: 250)
        let format = UIGraphicsImageRendererFormat()
        format.scale = UIScreen.main.scale
        return UIGraphicsImageRenderer(size: output, format: format).image { _ in outputImage
            .transformed(by: .init(scaleX: output.width/size.width, y: output.height/size.height))
            .image
            .draw(in: .init(origin: .zero, size: output))
        }
    }
}
extension CIImage {
    var image: UIImage { .init(ciImage: self) }
}

游乐场测试:

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

【讨论】:

  • 谢谢,你太棒了。弄清楚了。终于可以继续做其他事情了。非常感谢。
猜你喜欢
  • 2023-03-17
  • 2015-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-06
  • 2012-06-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多