|  |  |  | // Copyright © 2022 Rangeproof Pty Ltd. All rights reserved. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import UIKit | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | enum QRCode { | 
					
						
							|  |  |  |     /// Generates a QRCode for the give string | 
					
						
							|  |  |  |     /// | 
					
						
							|  |  |  |     /// **Note:** If the `hasBackground` value is true then the QRCode will be black and white and | 
					
						
							|  |  |  |     /// the `withRenderingMode(.alwaysTemplate)` won't work correctly on some iOS versions (eg. iOS 16) | 
					
						
							|  |  |  |     static func generate(for string: String, hasBackground: Bool) -> UIImage { | 
					
						
							|  |  |  |         let data = string.data(using: .utf8) | 
					
						
							|  |  |  |         var qrCodeAsCIImage: CIImage | 
					
						
							|  |  |  |         let filter1 = CIFilter(name: "CIQRCodeGenerator")! | 
					
						
							|  |  |  |         filter1.setValue(data, forKey: "inputMessage") | 
					
						
							|  |  |  |         qrCodeAsCIImage = filter1.outputImage! | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         guard !hasBackground else { | 
					
						
							|  |  |  |             let filter2 = CIFilter(name: "CIFalseColor")! | 
					
						
							|  |  |  |             filter2.setValue(qrCodeAsCIImage, forKey: "inputImage") | 
					
						
							|  |  |  |             filter2.setValue(CIColor(color: .black), forKey: "inputColor0") | 
					
						
							|  |  |  |             filter2.setValue(CIColor(color: .white), forKey: "inputColor1") | 
					
						
							|  |  |  |             qrCodeAsCIImage = filter2.outputImage! | 
					
						
							|  |  |  |              | 
					
						
							|  |  |  |             let scaledQRCodeAsCIImage = qrCodeAsCIImage.transformed(by: CGAffineTransform(scaleX: 6.4, y: 6.4)) | 
					
						
							|  |  |  |             return UIImage(ciImage: scaledQRCodeAsCIImage) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         let filter2 = CIFilter(name: "CIColorInvert")! | 
					
						
							|  |  |  |         filter2.setValue(qrCodeAsCIImage, forKey: "inputImage") | 
					
						
							|  |  |  |         qrCodeAsCIImage = filter2.outputImage! | 
					
						
							|  |  |  |         let filter3 = CIFilter(name: "CIMaskToAlpha")! | 
					
						
							|  |  |  |         filter3.setValue(qrCodeAsCIImage, forKey: "inputImage") | 
					
						
							|  |  |  |         qrCodeAsCIImage = filter3.outputImage! | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         let scaledQRCodeAsCIImage = qrCodeAsCIImage.transformed(by: CGAffineTransform(scaleX: 6.4, y: 6.4)) | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         // Note: It looks like some internal method was changed in iOS 16.0 where images | 
					
						
							|  |  |  |         // generated from a CIImage don't have the same color information as normal images | 
					
						
							|  |  |  |         // as a result tinting using the `alwaysTemplate` rendering mode won't work - to | 
					
						
							|  |  |  |         // work around this we convert the image to data and then back into an image | 
					
						
							|  |  |  |         let imageData: Data = UIImage(ciImage: scaledQRCodeAsCIImage).pngData()! | 
					
						
							|  |  |  |         return UIImage(data: imageData)! | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |