Skip to content

Instantly share code, notes, and snippets.

@DavidSteuber
Last active March 23, 2018 13:48
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DavidSteuber/a6bf3df8c290ffc3839a to your computer and use it in GitHub Desktop.
Save DavidSteuber/a6bf3df8c290ffc3839a to your computer and use it in GitHub Desktop.
Placing a logo image inside a QR Code
//
// main.swift
// SmyrnaQR
//
// Created by David Steuber on 5/14/15.
// Copyright (c) 2015 David Steuber.
//
import Foundation
import QuartzCore
// The data sources and destination for the QR Code to be created
let smyrnaIn = "/Users/david/Desktop/theSmyrnaCowboy.png"
let smyrnaOut = "/Users/david/Desktop/theSmyrnaCowboyQR.png"
let smyrnaSize = CGRect(x: 0.0,y: 0.0,width: 1600.0,height: 1600.0)
let smyrnaURL: NSData = "https://www.youtube.com/user/theSMYRNAcowboy".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!
// Quick Response code generator set to use high error
// correction for scanning damaged codes
func qrCodeWithMessage(data: NSData) -> CIImage? {
let qrEncoder = CIFilter(name: "CIQRCodeGenerator", withInputParameters: ["inputMessage":data, "inputCorrectionLevel":"H"])
let ciImage = qrEncoder.outputImage
return ciImage
}
// This is all it takes to load a file and turn it into a CGImage
func loadImageFromFile (path: String) -> CGImage? {
let url = NSURL.fileURLWithPath(path)
let imageSource = CGImageSourceCreateWithURL(url, nil)
return CGImageSourceCreateImageAtIndex(imageSource, 0, nil)
}
// This will be used to create a CGImage from the CIImage that contains
// the QR Code and as the drawing context to merge the two images.
func createBitmapContext (size: CGRect) -> CGContext! {
let context = CGBitmapContextCreate(nil,
Int(size.width),
Int(size.height),
8,
0,
CGColorSpaceCreateDeviceRGB(),
CGBitmapInfo(CGImageAlphaInfo.PremultipliedLast.rawValue))
CGContextSetInterpolationQuality(context, kCGInterpolationNone)
CGContextSetShouldAntialias(context, false)
return context
}
// Turn a CIImage into a CGImage
func createCGImage(ci: CIImage) -> CGImage? {
let cgContext = createBitmapContext(ci.extent())
let context = CIContext(CGContext: cgContext, options: nil)
CGContextDrawImage(cgContext, ci.extent(), context.createCGImage(ci, fromRect: ci.extent()))
return CGBitmapContextCreateImage(cgContext)
}
func saveImage(path: String, image: NSData) {
image.writeToFile(path, atomically: true)
}
// You can also create a CGImageDestination with a URL to save a step
func getImageFileData(image: CGImage) -> NSData? {
var pngDataRef = CFDataCreateMutable(nil, 0)
var pngDest = CGImageDestinationCreateWithData(pngDataRef, kUTTypePNG, 1, nil)
CGImageDestinationAddImage(pngDest, image, nil)
CGImageDestinationFinalize(pngDest)
return pngDataRef
}
// Draw the QR Code first, then draw the logo ontop of it. Painter's model.
// Drawing the logo in the middle of the QR Code damages it. But it is still able
// to be scanned thanks to the error correction.
func main() {
let cgContext = createBitmapContext(smyrnaSize)
let cgSmyrnaQR = createCGImage(qrCodeWithMessage(smyrnaURL)!)
let cgSmyrnaLogo = loadImageFromFile(smyrnaIn)
let logoPosition = CGRect(x: 650.0, y: 650.0, width: 300.0, height: 300.0)
CGContextDrawImage(cgContext, smyrnaSize, cgSmyrnaQR)
CGContextDrawImage(cgContext, logoPosition, cgSmyrnaLogo)
let cgOutputImage = CGBitmapContextCreateImage(cgContext)
let pngData = getImageFileData(cgOutputImage)
saveImage(smyrnaOut, pngData!)
}
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment