Generating Basic QR Codes in Swift 3.0

šŸ»TheDev
6 min readOct 11, 2016

--

QR codes are a type of 2D barcode that was originally developed for use in the Japanese car industry. Encoding URLs, promoting virtual stores, accessing cryptocurrency wallets, adding new contacts to messaging platforms ā€” QR codes (or some variants of them) provide a streamlined approach to working with various types of data.

Facebookā€™s take on a QR code v. The Snapcode

Lets look at using static data to create our code ā€” for example, a String.

Thanks to the Core Image framework, generating a simple QR code takes only a few lines of code

In the code above weā€™ve created a function called generateQRCode(from:) which returns an optional UIImage.

In this function, we first want to convert our string to a Data object (which is simply a MutableCollection of bytes). This object will contain our stringā€™s representation using some given encoding. In this case, we use ISO Latin 1; however, ASCII or UTF-8 works too.

This is the heart of QR code generation

Now, create an instance of CoreImage filter using the parameter name ā€œCIQRCodeGenerator.ā€

Essentially, weā€™ve initialized a CIFilter object, one for the specific filter called ā€œCIQRCodeGenerator.ā€ This parameter name lets us reference Swiftā€™s built-in filter for QR code generation through the Core Image framework. After creating a filter with the CIFilter method in Swift, you must call setDefaults() or setValue(_:forKey:) to set parameters individually.

Core Image Filter Reference: CIQRCodeGenerator

After creating a filter with the CIFilter method in Swift, you must call setDefaults() or setValue(_:forKey:) to set parameters individually.

This might seem esoteric, to some degree, and it probably should, given the underlying levels of complexity. Take a closer look at the next line:

Data, in this case, is our functionā€™s string argument

Here, we pass our data constant ā€” which is simply an encoded version of our string ā€” to set the value for the key ā€œinputMessage.ā€ This step is crucial and it works in this manner because the parameters of a CIFilter object are set and retrieved through the use of key-value pairs.

Done! Well, not quite.

To recap, weā€™ve passed our generateQRCode(from:) function a string which weā€™ve then encoded into a data object. Then, weā€™ve created a CIFilter object of the specific kind ā€œCIQRCodeGenerator.ā€ Finally, weā€™ve used our data object to set the value for the key ā€œinputMessageā€ which represents the data input used in our QR code generation. Essentially, weā€™ve retrieved a specific template, gathered all of the necessary components, but still havenā€™t returned anything.

We create our final CIImage by applying a transform and return it as a UIImage

Donā€™t worry about the transform nonsense; weā€™ll get to that in just a moment (weā€™re using it to get rid of the blur in our resulting QR code).

Focus on unwrapping the output. Why are we doing this? Itā€™s because filter ā€” which is our CIFilter ā€” returns an optional CIImage (again, feel free to disregard the .applying(transform) at the end there, for now).

In this particular case, CIFilter ultimately produces a CIImage object using a string as an input. In order to have the image properly displayed in the imageView outlet, we cast it as a UIImage. Finally, we get the following:

Core Image + a few lines of code + some logic = šŸ”³

Oh no! Why is our QR code so freaking blurry? Since our CIImage is made up of points, the resulting UIImage is scaled to fit our UIImageView, which results in a lack of clarity. This is where the transform part comes in!

Note that the current scale is set to x: 1, y: 1 ā€” this is exactly what weā€™ll be working with to fix this blur

We create an affine transformation matrix which we will use to scale our QR code. This is simply a struct used in drawing 2D graphics. In short, this matrix links two coordinate systems by specifying how points in one coordinate system map to points in another. Then, we apply it when we unwrap the resulting optional CIImage.

The key here are the two scale values ā€” x and y. Weā€™ve set them both to 1, and this is precisely the reason why weā€™ve created a QR code of such exceptionally poor quality. What if we try changing both values (scaleX and scaleY) to 100?

Now thatā€™s what Iā€™m talking about!

Weā€™ve successfully scaled up our UIImage. To be honest, weā€™ve simply used an arbitrarily large number. If we want to be more elaborate with the scaling, we can figure out our desired scaling factor programmatically. So what is this scaling factor?

Well, actually, itā€™s always equal to the ratio of an image viewā€™s width and the original QR codeā€™s width. In our example, this translates to:

In order to get the width and height of our QR code, we create a CIImage and assign it to the qrCodeImage variable

Weā€™ve added three new lines of code. First, weā€™ve created a CIImage object by calling outputImage on our CIFilter object. Since this method returns an optional value, weā€™ve unwrapped it using a guard statement. Next, weā€™ve set up two constants for our two axes (x and y). As mentioned above, scaleX and scaleY are simply equal to the ratios of our image viewā€™s width and height and our QR codeā€™s width and height, respectively. Finally, weā€™ve passed these two ratios as parameters to CGAffineTransform to get an adequately scaled affine transformation matrix (i.e. transform). We then call applying(transform) on our outputImage to get the following result:

Finally, we have a usable QR code image!

Another thing we couldā€™ve done during our QR code generation is set the value for error correction. This is done via the key ā€œinputCorrectionLevel.ā€

Similarly to how weā€™ve used setValue for ā€œinputMessage,ā€ we call setValue to pass a value to ā€œinputCorrectionLevelā€

This parameter controls the amount of additional data encoded in the output image to provide error correction. It is equal to ā€œMā€ by default, and changing this parameter affects the resulting QR code shape. Higher levels result in larger output images but allow larger areas of the code to be damaged.

Here you can see the effects of using different input correction levels. Note: we have not changed the data input (string)

Thatā€™s it for the basics! You have now mastered QR code generation in Swift.

Thereā€™s a lot more to QR codes in Swift, but this is it for our tutorial. Thank you for reading this simple overview of QR generation in Swift!

--

--