一尘不染

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

swift

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

情境

我正在应用的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!))
            }
        }
    }
}

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

我的目标

Literally, just to get the data from the generated QR Code. Most threads
suggest UIImage(ciImage: output) , but this doesn’t have any backing data.

If anyone could help me out with this, that’d be great. And any explanation on
how it works would be wonderful too.

Edit: I don’t believe this is the same as the marked duplicate - The
marked duplicate is about editing an existing image using CI filters and
getting that data and this is about an image that is solely created through CI
filter with no input image - QR Codes. the other answer did not fully relate.


阅读 376

收藏
2020-07-07

共1个答案

一尘不染

You have a couple of issues in your code. You need to convert your string to
data using String Encoding isoLatin1 before passing it to the filter. Another
issue is that to convert your CIImage to data you need to redraw/render your
CIImage and to prevent blurring the image when scaled you need to apply a
transform to the image to increase its size:

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

Playground testing:

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

2020-07-07