Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
kingst committed Mar 26, 2019
0 parents commit e199db4
Show file tree
Hide file tree
Showing 56 changed files with 4,626 additions and 0 deletions.
37 changes: 37 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# OS X
.DS_Store

# Xcode
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata/
*.xccheckout
profile
*.moved-aside
DerivedData
*.hmap
*.ipa

# Bundler
.bundle

# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts

Carthage/Build

# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
#
# Note: if you ignore the Pods directory, make sure to uncomment
# `pod install` in .travis.yml
#
# Pods/
22 changes: 22 additions & 0 deletions CardScan.podspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
Pod::Spec.new do |s|
s.name = 'CardScan'
s.version = '1.0.4032'
s.summary = 'Scan credit cards'
s.description = <<-DESC
CardScan is a library for scanning credit cards.
DESC

s.homepage = 'https://cardscan.io'
s.license = { :type => 'BSD', :file => 'LICENSE' }
s.author = { 'Sam King' => '[email protected]' }
s.source = { :git => 'https://github.com/getbouncer/cardscan-ios.git', :tag => s.version.to_s }
s.social_media_url = 'https://twitter.com/stk'

s.ios.deployment_target = '11.0'
s.swift_version = '4.2'

s.source_files = 'CardScan/Classes/**/*'
s.resources = ['CardScan/Assets/*.xcassets', 'CardScan/Assets/*.storyboard']

s.frameworks = 'AVKit', 'CoreML', 'VideoToolbox', 'Vision', 'UIKit', 'AVFoundation'
end
Empty file added CardScan/Assets/.gitkeep
Empty file.
6 changes: 6 additions & 0 deletions CardScan/Assets/Assets.xcassets/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "baseline_arrow_back_ios_white_24pt_1x.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "baseline_arrow_back_ios_white_24pt_2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "baseline_arrow_back_ios_white_24pt_3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
},
"properties" : {
"template-rendering-intent" : "template"
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "baseline_highlight_white_24pt_1x.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "baseline_highlight_white_24pt_2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "baseline_highlight_white_24pt_3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
},
"properties" : {
"template-rendering-intent" : "template"
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 23 additions & 0 deletions CardScan/Assets/Assets.xcassets/flashlight.imageset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "flashlight.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "[email protected]",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "[email protected]",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
202 changes: 202 additions & 0 deletions CardScan/Assets/CardScan.storyboard

Large diffs are not rendered by default.

Empty file added CardScan/Classes/.gitkeep
Empty file.
51 changes: 51 additions & 0 deletions CardScan/Classes/CornerView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import UIKit

public class CornerView: UIView {

func drawCorners(_ regionFrame: CGRect){
let maskShapeLayer = CAShapeLayer()
let maskPath = CGMutablePath()

let boundX = self.bounds.origin.x
let boundY = self.bounds.origin.y
let boundWidth = self.bounds.width
let boundHeight = self.bounds.height

let cornerMultiplier = CGFloat(0.1)
let cornerLength = regionFrame.width * cornerMultiplier

//top left corner
maskPath.move(to: self.bounds.origin)
maskPath.addLine(to: CGPoint(x: boundX + cornerLength, y: boundY))
maskPath.addLine(to: CGPoint(x: boundX + cornerLength, y: boundY + cornerLength))
maskPath.addLine(to: CGPoint(x: boundX, y: boundY + cornerLength))
maskPath.closeSubpath()

//top right corner
maskPath.move(to: CGPoint(x: boundWidth - cornerLength, y: boundY))
maskPath.addLine(to: CGPoint(x: boundWidth, y: boundY))
maskPath.addLine(to: CGPoint(x: boundWidth, y: boundY + cornerLength))
maskPath.addLine(to: CGPoint(x:boundWidth - cornerLength, y: boundY + cornerLength))
maskPath.closeSubpath()

//bottom left corner
maskPath.move(to: CGPoint(x: boundX, y: boundHeight - cornerLength))
maskPath.addLine(to: CGPoint(x: boundX + cornerLength, y: boundHeight - cornerLength))
maskPath.addLine(to: CGPoint(x: boundX + cornerLength, y: boundHeight))
maskPath.addLine(to: CGPoint(x: boundX, y: boundHeight))
maskPath.closeSubpath()

//bottom right corner
maskPath.move(to: CGPoint(x: boundWidth - cornerLength, y: boundHeight - cornerLength))
maskPath.addLine(to: CGPoint(x: boundWidth, y: boundHeight - cornerLength))
maskPath.addLine(to: CGPoint(x: boundWidth, y: boundHeight))
maskPath.addLine(to: CGPoint(x: boundWidth - cornerLength, y: boundHeight))
maskPath.closeSubpath()

maskShapeLayer.path = maskPath
self.layer.mask = maskShapeLayer

}


}
60 changes: 60 additions & 0 deletions CardScan/Classes/CreditCardUtils.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import Foundation

struct CreditCardUtils {
// https://en.wikipedia.org/wiki/Luhn_algorithm
// assume 16 digits are for MC and Visa (start with 4, 5) and 15 is for Amex
// which starts with 3
static func luhnCheck(_ cardNumber: String) -> Bool {
if cardNumber.count == 0 {
return false
} else if cardNumber.count == 16 && !cardNumber.starts(with: "4") && !cardNumber.starts(with: "5") {
return false
} else if cardNumber.count == 15 && !cardNumber.starts(with: "3") {
return false
}

var sum = 0
let reversedCharacters = cardNumber.reversed().map { String($0) }
for (idx, element) in reversedCharacters.enumerated() {
guard let digit = Int(element) else { return false }
switch ((idx % 2 == 1), digit) {
case (true, 9): sum += 9
case (true, 0...8): sum += (digit * 2) % 9
default: sum += digit
}
}
return sum % 10 == 0
}

static func format(number: String) -> String {
if number.count == 16 {
return format16(number: number)
} else if number.count == 15 {
return format15(number: number)
} else {
return number
}
}

static func format15(number: String) -> String {
var displayNumber = ""
for (idx, char) in number.enumerated() {
if idx == 4 || idx == 10 {
displayNumber += " "
}
displayNumber += String(char)
}
return displayNumber
}

static func format16(number: String) -> String {
var displayNumber = ""
for (idx, char) in number.enumerated() {
if (idx % 4) == 0 && idx != 0 {
displayNumber += " "
}
displayNumber += String(char)
}
return displayNumber
}
}
49 changes: 49 additions & 0 deletions CardScan/Classes/DetectedBox.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import Foundation

/**
Data structure to keep track of each box that the model detects.

Note: the rect member is in the image's coordinate system.
*/

struct DetectedBox {
let rect: CGRect
let row: Int
let col: Int
let confidence: Double
let numRows: Int
let numCols: Int
let boxSize: CGSize
let cardSize: CGSize
let imageSize: CGSize

init(row: Int, col: Int, confidence: Double, numRows: Int, numCols: Int,
boxSize: CGSize, cardSize: CGSize, imageSize: CGSize) {

// Resize the box to transform it from the model's coordinates into
// the image's coordinates
let w = boxSize.width * imageSize.width / cardSize.width
let h = boxSize.height * imageSize.height / cardSize.height
let x = (imageSize.width - w) / CGFloat(numCols-1) * CGFloat(col)
let y = (imageSize.height - h) / CGFloat(numRows-1) * CGFloat(row)
self.rect = CGRect(x: x, y: y, width: w, height: h)
self.row = row
self.col = col
self.confidence = confidence
self.numRows = numRows
self.numCols = numCols
self.boxSize = boxSize
self.cardSize = cardSize
self.imageSize = imageSize
}

func move(row: Int, col: Int) -> DetectedBox? {
if row < 0 || row >= self.numRows || col < 0 || col >= self.numCols {
return nil
}
return DetectedBox(row: row, col: col, confidence: self.confidence,
numRows: self.numRows, numCols: self.numCols,
boxSize: self.boxSize, cardSize: self.cardSize,
imageSize: self.imageSize)
}
}
Loading

0 comments on commit e199db4

Please sign in to comment.