我已经遇到这个问题已有一段时间了,在这里看了几十个答案,似乎找不到任何有用的答案。
我正在应用的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因为没有图像数据支持过滤器的输出。
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) } } } }
但这似乎行不通,因为视图上的图像是空白的。
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.
UIImage(ciImage: output)
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.
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