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 ? :)
38 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.
2For 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.
4this 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 = qrURLImageInside 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!