Last active
March 23, 2018 13:48
-
-
Save DavidSteuber/a6bf3df8c290ffc3839a to your computer and use it in GitHub Desktop.
Placing a logo image inside a QR Code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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