Is there a way to generate QR code image on iOS

38,680

Solution 1

Since iOS 7, you can use a Core Image filter to generate QR images. See the final tip here:

- (CIImage *)createQRForString:(NSString *)qrString {
    NSData *stringData = [qrString dataUsingEncoding: NSISOLatin1StringEncoding];

    CIFilter *qrFilter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
    [qrFilter setValue:stringData forKey:@"inputMessage"];

    return qrFilter.outputImage;
}

Solution 2

For Obj-C version that perfectly works for me, I've mixed answers पवन and Teja Kumar Bethina:

NSString *qrString = @"My string to encode";
NSData *stringData = [qrString dataUsingEncoding: NSUTF8StringEncoding];

CIFilter *qrFilter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
[qrFilter setValue:stringData forKey:@"inputMessage"];
[qrFilter setValue:@"H" forKey:@"inputCorrectionLevel"];

CIImage *qrImage = qrFilter.outputImage;
float scaleX = self.qrImageView.frame.size.width / qrImage.extent.size.width;
float scaleY = self.qrImageView.frame.size.height / qrImage.extent.size.height;

qrImage = [qrImage imageByApplyingTransform:CGAffineTransformMakeScale(scaleX, scaleY)];

self.qrImageView.image = [UIImage imageWithCIImage:qrImage
                                             scale:[UIScreen mainScreen].scale
                                       orientation:UIImageOrientationUp];

Solution 3

Using Swift 2

import UIKit
import CoreImage

func createQRFromString(str: String) -> CIImage? {
    let stringData = str.dataUsingEncoding(NSUTF8StringEncoding)
    
    let filter = CIFilter(name: "CIQRCodeGenerator")
    
    filter?.setValue(stringData, forKey: "inputMessage")
    
    filter?.setValue("H", forKey: "inputCorrectionLevel")
    
    return filter?.outputImage
}

if let img = createQRFromString("Hello world program created by someone") {
    let somImage = UIImage(CIImage: img, scale: 1.0, orientation: UIImageOrientation.Down)
}

enter image description here

Swift 3.0

import UIKit
import CoreImage

func createQRFromString(_ str: String) -> CIImage? {
        let stringData = str.data(using: String.Encoding.utf8)
        
        let filter = CIFilter(name: "CIQRCodeGenerator")
        
        filter?.setValue(stringData, forKey: "inputMessage")
        
        filter?.setValue("H", forKey: "inputCorrectionLevel")
        
        if let img = createQRFromString("Hello world program created by someone") {
            let somImage = UIImage(ciImage: img, scale: 1.0, orientation: UIImageOrientation.down)
        }
        
        return filter?.outputImage
    }

if let img = createQRFromString("Hello world program created by someone") {
            let somImage = UIImage(ciImage: img, scale: 1.0, orientation: UIImageOrientation.down)
        }

Swift 4.2

private func createQRFromString(str: String) -> CIImage? {
        let stringData = str.data(using: .utf8)
        
        let filter = CIFilter(name: "CIQRCodeGenerator")
        filter?.setValue(stringData, forKey: "inputMessage")
        filter?.setValue("H", forKey: "inputCorrectionLevel")
        
        return filter?.outputImage
    }
    
    var qrCode: UIImage? {
        if let img = createQRFromString(str: "Hello world program created by someone") {
            let someImage = UIImage(
                ciImage: img,
                scale: 1.0,
                orientation: UIImage.Orientation.down
            )
            return someImage
        }
        
        return nil
    }

Xcode 12.4 or Swift version >= 5.2

import UIKit
import CoreImage

func createQRFromString(str: String) -> CIImage? {
  let stringData = str.data(using: .utf8)
  
  let filter = CIFilter(name: "CIQRCodeGenerator")
  
  filter?.setValue(stringData, forKey: "inputMessage")
  
  filter?.setValue("H", forKey: "inputCorrectionLevel")
  
  return filter?.outputImage
}

if let img = createQRFromString(str: "Hello world program created by someone") {
  let somImage = UIImage(ciImage: img, scale: 1.0, orientation: .down)
}

Solution 4

It has been a while since this question was asked and a number of almost perfect answers have been given already. However I had to tweak and combine several answers to get it working perfectly for AppleTV 4K, iPhone X and iPadPro using Xcode 9.2 in 2018. Here's the code if anyone needs it.

@IBOutlet weak var qrCodeBox: UIImageView!

func createQRFromString(_ str: String, size: CGSize) -> UIImage {
    let stringData = str.data(using: .utf8)

  let qrFilter = CIFilter(name: "CIQRCodeGenerator")!
  qrFilter.setValue(stringData, forKey: "inputMessage")
  qrFilter.setValue("H", forKey: "inputCorrectionLevel")

  let minimalQRimage = qrFilter.outputImage!
  // NOTE that a QR code is always square, so minimalQRimage..width === .height
  let minimalSideLength = minimalQRimage.extent.width

  let smallestOutputExtent = (size.width < size.height) ? size.width : size.height
  let scaleFactor = smallestOutputExtent / minimalSideLength
  let scaledImage = minimalQRimage.transformed(
    by: CGAffineTransform(scaleX: scaleFactor, y: scaleFactor))

  return UIImage(ciImage: scaledImage, 
                 scale: UIScreen.main.scale, 
                 orientation: .up)
}

override func viewDidLoad() {
    super.viewDidLoad()
    let myQRimage = createQRFromString("https://www.apple.com", 
                      size: qrCodeBox.frame.size)
    qrCodeBox.image = myQRimage
}

Solution 5

Code to generate QR image in Swift 2.0.

let reqStr = “string to convert as QR code”
let data = reqStr.dataUsingEncoding(NSISOLatin1StringEncoding, allowLossyConversion: false)

let filter = CIFilter(name: "CIQRCodeGenerator")
filter!.setValue(data, forKey: "inputMessage")

let qrImage:CIImage = filter!.outputImage!

//qrImageView is a IBOutlet of UIImageView        
let scaleX = qrImageView.frame.size.width / qrImage.extent.size.width
let scaleY = qrImageView.frame.size.height / qrImage.extent.size.height

let resultQrImage = qrImage.imageByApplyingTransform(CGAffineTransformMakeScale(scaleX, scaleY))
qrImageView.image = UIImage(CIImage: resultQrImage)
Share:
38,680
user1561181
Author by

user1561181

Updated on April 09, 2021

Comments

  • user1561181
    user1561181 about 3 years

    Is there a standard way to generate a QR code and attach it to a mail item from iOS client app (no server code)?

  • Royston Yinkore
    Royston Yinkore about 10 years
    The image is blurry. How do i fix?
  • quarac
    quarac about 10 years
    Look in the link for the function: createNonInterpolatedUIImageFromCIImage
  • T Blank
    T Blank over 9 years
    You should be using NSISOLatin1StringEncoding rather than UTF-8 according to the docs.
  • quarac
    quarac over 9 years
    Thanks Travis, answer updated with NSISOLatin1StringEncoding, docs are in developer.apple.com/library/mac/documentation/GraphicsImagin‌​g/…
  • kevinl
    kevinl about 9 years
    if the qr code is blurry, try this. CIImage *image = [self createQRForString:qrString]; CGAffineTransform transform = CGAffineTransformMakeScale(5.0f, 5.0f); // Scale by 5 times along both dimensions CIImage *output = [image imageByApplyingTransform: transform];
  • vichhai
    vichhai over 8 years
    @kevinl: your code work fine on the simulator. But for the real devices it's still blur. What should I do to make it clear?
  • NSDeveloper
    NSDeveloper over 8 years
    ZXing is a choice for generate QRCode and this is a good answer.
  • Yogendra Patel
    Yogendra Patel about 7 years
    You are sure to ZXing libarary avaliable for QR Code in iOS? @Avivo
  • jpat827
    jpat827 almost 7 years
    ZXingObjC is an Objective C implementation of ZXing. It should be usable with Swift by using a bridging header file.
  • haxpor
    haxpor over 6 years
    I use kevin's solution to make image not blur, it works on real device.
  • Ben Baron
    Ben Baron over 5 years
    There's actually a small bug here. You have to multiply scaledImage by UIScreen.main.scale or the final UIImage will be too small. For example on an iPhone X with screen scale of 3.0, if you try and make a 300x300 QR code the final UIImage will be 100x100 if you use this code as-is.
  • Albert Renshaw
    Albert Renshaw over 4 years
    @kevinl To add on to what Kevin has said, you can also apply, to any imageView that may be scaling arbitrarily (like a scrollview zoom), a nearest neighbor interpolation since all visual data in a QR Code is orthogonal, this will cause sharp/crisp edges when scaling, set the .layer.minificationFilter and .layer.magnificationLayer to kCAFilterNearest
  • Albert Renshaw
    Albert Renshaw about 4 years
    Note: Make Sure you convert the CIImage to a UIImage using CGContext, if you just use UIImage imageWithCIImage: you will get a bmp formatted image which causes contentMode to fail on certain architectures. For example, on my iPhone-11 (arm64) aspectFit worked with the UIImage from CIImage but on my iPhone-X (armv7s) it failed and fell back to scaleToFill (which makes QR codes not work). Detailed Explanation here: stackoverflow.com/a/15886422/2057171
  • Kilian
    Kilian almost 3 years
    @AlbertRenshaw Thank you! Without doing that I wasn't able to see any image at all inside of a SwiftUI view.