swift generate qr code with transparent background

in my swift 2 app i can generate a QR Code like this:

let data = "1234567890".dataUsingEncoding(NSISOLatin1StringEncoding, allowLossyConversion: false)
let filter = CIFilter(name: "CIQRCodeGenerator")
filter!.setValue(data, forKey: "inputMessage")
filter!.setValue("Q", forKey: "inputCorrectionLevel")
qrcodeImage = filter!.outputImage
let transformedImage = qrcodeImage.imageByApplyingTransform(CGAffineTransformMakeScale(150, 150))
QRCodeImage.image = UIImage(CIImage: transformedImage)

but my QR Code get an white background image, but i would like to have an transparent background.

i tried something like this:

QRCodeImage.backgroundColor = UIColor.clearColor()

but this doesn't work. any idea ? :)

3

8 Answers

It seems like the CIQRCodeGenerator filter always uses black and white.

You can pass the output into a CIMaskToAlpha filter to convert it to transparent:

And first you might want to use CIColorInvert to swap white & black.

2

For transparent background you should (use your instincts and) try like this ,

//Create a CIFalseColor Filter
let colorFilter: CIFilter = CIFilter(name: "CIFalseColor")!
colorFilter.setDefaults()
colorFilter.setValue(yourQRFilter.outputImage!, forKey: "inputImage")
//Then set the background colour like this,
let transparentBG: CIColor = CIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 0.0)
colorFilter.setValue(qrColor, forKey: "inputColor0")
colorFilter.setValue(transparentBG, forKey: "inputColor1")
outputImage = colorFilter.outputImage!

This should yield you QRCode image with transparent background, I hope.

I think that the key will be on the alpha of the background. You can set or reduce alpha, reducing or deleting the transparency. Try something like this:

QRCodeImage.backgroundcolor = UIColor(white: 1, alpha: 0.5)

Hope it helps.

4

this is my code :

func QRImageFromData(_ data: Data) -> UIImage? { let filter = CIFilter(name: "CIQRCodeGenerator") filter?.setValue(data, forKey: "inputMessage") //filter?.setValue("H", forKey: "inputCorrectionLevel") //change qrcode color : #1e3259 let filterFalseColor = CIFilter(name: "CIFalseColor") filterFalseColor?.setDefaults() filterFalseColor?.setValue(filter?.outputImage, forKey: "inputImage") // convert method let cgColor: CGColor? = UIColor(hex: "#1e3259")?.cgColor let qrColor: CIColor = CIColor(cgColor: cgColor!) let transparentBG: CIColor = CIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 0.0) filterFalseColor?.setValue(qrColor, forKey: "inputColor0") filterFalseColor?.setValue(transparentBG, forKey: "inputColor1") if let image = filterFalseColor?.outputImage { let transform = CGAffineTransform(scaleX: 5.0, y: 5.0) return UIImage(ciImage: image.applying(transform), scale: 1.0, orientation: UIImageOrientation.up) } else { return nil }
}

I obtained a qr with a transparent background following this tutorial.

Add these extensions:

extension CIImage { /// Inverts the colors and creates a transparent image by converting the mask to alpha. /// Input image should be black and white. var transparent: CIImage? { return inverted?.blackTransparent } /// Inverts the colors. var inverted: CIImage? { guard let invertedColorFilter = CIFilter(name: "CIColorInvert") else { return nil } invertedColorFilter.setValue(self, forKey: "inputImage") return invertedColorFilter.outputImage } /// Converts all black to transparent. var blackTransparent: CIImage? { guard let blackTransparentFilter = CIFilter(name: "CIMaskToAlpha") else { return nil } blackTransparentFilter.setValue(self, forKey: "inputImage") return blackTransparentFilter.outputImage } /// Applies the given color as a tint color. func tinted(using color: UIColor) -> CIImage? { guard let transparentQRImage = transparent, let filter = CIFilter(name: "CIMultiplyCompositing"), let colorFilter = CIFilter(name: "CIConstantColorGenerator") else { return nil } let ciColor = CIColor(color: color) colorFilter.setValue(ciColor, forKey: kCIInputColorKey) let colorImage = colorFilter.outputImage filter.setValue(colorImage, forKey: kCIInputImageKey) filter.setValue(transparentQRImage, forKey: kCIInputBackgroundImageKey) return filter.outputImage! }
}
extension URL { func qrImage(using color: UIColor) -> UIImage? { let ciImage = qrCIImage?.tinted(using: color) return ciImage != nil ? UIImage(ciImage: ciImage!) : nil } var qrImage: UIImage? { return UIImage(ciImage: qrCIImage!) } /// Creates a QR code for the current URL in the given color. func qrCIImage(using color: UIColor) -> CIImage? { return qrCIImage?.tinted(using: color) } /// Returns a black and white QR code for this URL. var qrCIImage: CIImage? { guard let qrFilter = CIFilter(name: "CIQRCodeGenerator") else { return nil } let qrData = absoluteString.data(using: String.Encoding.ascii) qrFilter.setValue(qrData, forKey: "inputMessage") let qrTransform = CGAffineTransform(scaleX: 12, y: 12) return qrFilter.outputImage?.transformed(by: qrTransform) }
}

And then use like this:

let myChosenColor = UIColor(red:0.93, green:0.31, blue:0.23, alpha:1.00)
let qrURLImage = URL(string: "")?.qrImage(using: myChosenColor)
myQrImageView.image = qrURLImage

Inside myQrImageView.image you will see a qr image with a transparent background:

In addition to answer of @jtbandes i have wrote some code so it would help others as well

extension UIImage { func transparentBackground() -> UIImage? { let context = CIContext(options: nil) let filter = CIFilter(name: "CIMaskToAlpha") filter?.setDefaults() filter?.setValue(self.ciImage, forKey: kCIInputImageKey) if let output = filter?.outputImage, let imageRef = context.createCGImage(output, from: output.extent) { return UIImage(cgImage: imageRef) } return nil } func invertColor() -> UIImage? { let filter = CIFilter(name: "CIColorInvert") filter?.setDefaults() filter?.setValue(self.ciImage, forKey: kCIInputImageKey) if let output = filter?.outputImage { return UIImage(ciImage: output) } return nil }
}

and use it like this

yourUIImage.invertColor()?.transparentBackground()

the transparentBackground() function will remove black color and leave the white where as invertColor() will will swap black with white

extension UIImage { func alpha(_ value: CGFloat) -> UIImage { UIGraphicsBeginImageContextWithOptions(size, false, scale) draw(at: CGPoint.zero, blendMode: .normal, alpha: value) let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()! UIGraphicsEndImageContext() return image }
}

A ready solution in case you're looking for:

enum GeneratorType { case qrCode, barCode, aztecCode var filterName: String { switch self { case .aztecCode: return "CIAztecCodeGenerator" case .barCode: return "CICode128BarcodeGenerator" case .qrCode: return "CIQRCodeGenerator" } }
}
func generateCode(type: GeneratorType, text: String, transform: CGAffineTransform = CGAffineTransform(scaleX: 32.0, y: 32.0), fillColor: UIColor = UIColor.black, backgroundColor: CIColor = CIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 0.0)) -> UIImage? { guard let filter = CIFilter(name: type.filterName) else { return nil } filter.setDefaults() guard let data = text.data(using: String.Encoding.utf8) else { return nil } filter.setValue(data, forKey: "inputMessage") let filterFalseColor = CIFilter(name: "CIFalseColor") filterFalseColor?.setDefaults() filterFalseColor?.setValue(filter.outputImage, forKey: "inputImage") filterFalseColor?.setValue(CIColor(cgColor: fillColor.cgColor), forKey: "inputColor0") filterFalseColor?.setValue(backgroundColor, forKey: "inputColor1") guard let image = filterFalseColor?.outputImage else { return nil } return UIImage(ciImage: image.transformed(by: transform), scale: 1.0, orientation: UIImage.Orientation.up)
}

Usage:

let qrImage = generateCode(type: .qrCode, text: "some text")

Peace!

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

You Might Also Like