├── .gitignore ├── LICENSE ├── QRPlayground.playground ├── Contents.swift ├── Resources │ └── swiftlee_qr_logo.png └── contents.xcplayground └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xccheckout 23 | *.xcscmblueprint 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | *.ipa 28 | *.dSYM.zip 29 | *.dSYM 30 | 31 | ## Playgrounds 32 | timeline.xctimeline 33 | playground.xcworkspace 34 | 35 | # Swift Package Manager 36 | # 37 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 38 | # Packages/ 39 | # Package.pins 40 | # Package.resolved 41 | .build/ 42 | 43 | # CocoaPods 44 | # 45 | # We recommend against adding the Pods directory to your .gitignore. However 46 | # you should judge for yourself, the pros and cons are mentioned at: 47 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 48 | # 49 | # Pods/ 50 | 51 | # Carthage 52 | # 53 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 54 | # Carthage/Checkouts 55 | 56 | Carthage/Build 57 | 58 | # fastlane 59 | # 60 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 61 | # screenshots whenever they are needed. 62 | # For more information about the recommended setup visit: 63 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 64 | 65 | fastlane/report.xml 66 | fastlane/Preview.html 67 | fastlane/screenshots/**/*.png 68 | fastlane/test_output 69 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Antoine van der Lee 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /QRPlayground.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | //: A UIKit based Playground for presenting user interface 2 | 3 | import UIKit 4 | import PlaygroundSupport 5 | import CoreImage 6 | 7 | extension URL { 8 | 9 | /// Creates a QR code for the current URL in the given color. 10 | func qrImage(using color: UIColor, logo: UIImage? = nil) -> CIImage? { 11 | let tintedQRImage = qrImage?.tinted(using: color) 12 | 13 | guard let logo = logo?.cgImage else { 14 | return tintedQRImage 15 | } 16 | 17 | return tintedQRImage?.combined(with: CIImage(cgImage: logo)) 18 | } 19 | 20 | /// Returns a black and white QR code for this URL. 21 | var qrImage: CIImage? { 22 | guard let qrFilter = CIFilter(name: "CIQRCodeGenerator") else { return nil } 23 | let qrData = absoluteString.data(using: String.Encoding.ascii) 24 | qrFilter.setValue(qrData, forKey: "inputMessage") 25 | 26 | let qrTransform = CGAffineTransform(scaleX: 12, y: 12) 27 | return qrFilter.outputImage?.transformed(by: qrTransform) 28 | } 29 | } 30 | 31 | extension CIImage { 32 | /// Inverts the colors and creates a transparent image by converting the mask to alpha. 33 | /// Input image should be black and white. 34 | var transparent: CIImage? { 35 | return inverted?.blackTransparent 36 | } 37 | 38 | /// Inverts the colors. 39 | var inverted: CIImage? { 40 | guard let invertedColorFilter = CIFilter(name: "CIColorInvert") else { return nil } 41 | 42 | invertedColorFilter.setValue(self, forKey: "inputImage") 43 | return invertedColorFilter.outputImage 44 | } 45 | 46 | /// Converts all black to transparent. 47 | var blackTransparent: CIImage? { 48 | guard let blackTransparentFilter = CIFilter(name: "CIMaskToAlpha") else { return nil } 49 | blackTransparentFilter.setValue(self, forKey: "inputImage") 50 | return blackTransparentFilter.outputImage 51 | } 52 | 53 | /// Applies the given color as a tint color. 54 | func tinted(using color: UIColor) -> CIImage? 55 | { 56 | guard 57 | let transparentQRImage = transparent, 58 | let filter = CIFilter(name: "CIMultiplyCompositing"), 59 | let colorFilter = CIFilter(name: "CIConstantColorGenerator") else { return nil } 60 | 61 | let ciColor = CIColor(color: color) 62 | colorFilter.setValue(ciColor, forKey: kCIInputColorKey) 63 | let colorImage = colorFilter.outputImage 64 | 65 | filter.setValue(colorImage, forKey: kCIInputImageKey) 66 | filter.setValue(transparentQRImage, forKey: kCIInputBackgroundImageKey) 67 | 68 | return filter.outputImage! 69 | } 70 | } 71 | 72 | extension CIImage { 73 | 74 | /// Combines the current image with the given image centered. 75 | func combined(with image: CIImage) -> CIImage? { 76 | guard let combinedFilter = CIFilter(name: "CISourceOverCompositing") else { return nil } 77 | let centerTransform = CGAffineTransform(translationX: extent.midX - (image.extent.size.width / 2), y: extent.midY - (image.extent.size.height / 2)) 78 | combinedFilter.setValue(image.transformed(by: centerTransform), forKey: "inputImage") 79 | combinedFilter.setValue(self, forKey: "inputBackgroundImage") 80 | return combinedFilter.outputImage! 81 | } 82 | } 83 | 84 | final class QRViewController : UIViewController { 85 | let swiftLeeOrangeColor = UIColor(red:0.93, green:0.31, blue:0.23, alpha:1.00) 86 | let swiftLeeLogo = UIImage(named: "swiftlee_qr_logo.png")! 87 | 88 | override func loadView() { 89 | guard let qrURLImage = URL(string: "https://www.avanderlee.com")?.qrImage(using: swiftLeeOrangeColor, logo: swiftLeeLogo) else { return } 90 | let imageView = UIImageView(image: UIImage(ciImage: qrURLImage)) 91 | imageView.contentMode = .center 92 | imageView.layer.backgroundColor = UIColor.white.cgColor 93 | self.view = imageView 94 | } 95 | } 96 | // Present the view controller in the Live View window 97 | PlaygroundPage.current.liveView = QRViewController() 98 | -------------------------------------------------------------------------------- /QRPlayground.playground/Resources/swiftlee_qr_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AvdLee/QR-Code-Custom/3a9bf809b0e7ab0a7bc99bb14951819003a60d8d/QRPlayground.playground/Resources/swiftlee_qr_logo.png -------------------------------------------------------------------------------- /QRPlayground.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # QR-Code-Custom 2 | ![Swift Version](https://img.shields.io/badge/Swift-4.2-F16D39.svg?style=flat) [![Twitter](https://img.shields.io/badge/twitter-@Twannl-blue.svg?style=flat)](https://twitter.com/twannl) 3 | 4 | A playground demonstrating a way to create a custom QR code with a custom color and logo in Swift. 5 | 6 | Related to a blog post on [SwiftLee](https://www.avanderlee.com) called [QR Code generation with a custom logo and color using Swift](https://www.avanderlee.com/swift/qr-code-generation-swift/). --------------------------------------------------------------------------------