SDK

Adding the SDK to your project

To add our SDK to your own application, you should add it to the build process of your application. Currently we support doing this using CocoaPods or Carthage.

CocoaPods: Adding the SDK to your Podfile

To add the repository to your project, open the Podfile, if it does not exists, first run pod init in the root of your project with Xcode closed.
Edit the target part of your application in the Podfile, so that it contains the following:

                    
pod 'Klippa-Scanner', podspec: 'https://custom-ocr.klippa.com/sdk/ios/specrepo/ExampleUsername/ExamplePassword/KlippaScanner/latest.podspec'
                    
                

The full Podfile might look like this now:

                    
# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'

target 'TestScanner' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!

  # Pods for TestScanner
  pod 'Klippa-Scanner', podspec: 'https://custom-ocr.klippa.com/sdk/ios/specrepo/ExampleUsername/ExamplePassword/KlippaScanner/latest.podspec'

end
                    
                

When you run pod install now, it should download our library as dependency, and with that all dependencies of our library.
Note: this code always uses the latest version, you can also use a specific version to make sure the SDK won't update without your knowledge.

Carthage: Adding the SDK to your Cartfile

To add the repository to your project, open the Cartfile, if it does not exists, create a Cartfile alongside your .xcodeproj or .xcworkspace.
Add the following to your Cartfile:

                    
binary "https://custom-ocr.klippa.com/sdk/ios/carthage/ExampleUsername/ExamplePassword/KlippaScanner.json"
                    
                

When you run carthage update now, it should download our library as dependency, and with that all dependencies of our library.
Note: this code always uses the latest version, you can also use a specific version to make sure the SDK won't update without your knowledge.

Starting the scanner

To start the scanner, import our library in your AppDelegate:

                    
// Add to the top of your file
import KlippaScanner
                    
                

Then init the scanner options inside your launch method, the license is the only required option:

                    
KlippaScanner.setup.license = "replace-with-received-license"
                    
                

In the controller that you want to launch the scanner, implement the ImageScannerControllerDelegate:

                    
// Add to the top of your file
import KlippaScanner

// Your class definition should look like this.
final class ExampleScannerViewController: UIViewController, ImageScannerControllerDelegate {

    // ... Rest of your controller code.

    func startScanner() {
        let scannerViewController = ImageScannerController()
        scannerViewController.imageScannerDelegate = self
        scannerViewController.modalPresentationStyle = .fullScreen
        present(scannerViewController, animated: false)
    }

    func imageScannerController(_ scanner: ImageScannerController, didFailWithError error: Error) {
        switch error {
        case let licenseError as LicenseError:
            print("Got licensing error from SDK: \(licenseError.localizedDescription)")
        default:
            print(error)
        }
    }

    func imageScannerController(_ scanner: ImageScannerController, didFinishScanningWithResult result: ImageScannerResult) {
        // Handle scan results here.
        print("didFinishScanningWithResult");
        print("multipleDocumentsModeEnabled \(result.multipleDocumentsModeEnabled)")
        print("Scanned \(result.images.count) images")
    }

    func imageScannerControllerDidCancel(_ scanner: ImageScannerController) {
        scanner.dismiss(animated: true, completion: nil)
    }

    // ... Rest of your controller code.
}
                    
                

In the place where you want to start the scanner, for example after a button click, call the startScanner method:

                    
startScanner()
                    
                

Customizing the scanner

The SDK has a few customizing settings, the following methods are available:

                    
// The warning message when someone should move closer to a document, should be a string.
KlippaScanner.setup.moveCloserMessage = "Move the camera towards the document"

// The warning message when the camera result is too bright.
KlippaScanner.setup.imageToBrightMessage = "Image too light"

// The warning message when the camera result is too dark.
KlippaScanner.setup.imageToDarkMessage = "Image too dark"

// The primary color of the interface, should be a UIColor.
KlippaScanner.setup.primaryColor = .white

// The accent color of the interface, should be a UIColor.
KlippaScanner.setup.accentColor = .white

// The overlay color (when using document detection), should be a UIColor.
KlippaScanner.setup.overlayColor = UIColor(red: 0.17, green: 0.77, blue: 0.41, alpha: 1.00)

// The color of the background of the warning message, should be a UIColor.
KlippaScanner.setup.warningColor = .red

// The amount of opacity for the overlay, should be a CGFloat.
KlippaScanner.setup.overlayColorAlpha = 0.75

// The amount of seconds the preview should be visible for, should be a Double.
KlippaScanner.setup.previewDuration = 1.0

// Whether the scanner automatically cuts out documents, should be a Boolean.
KlippaScanner.setup.isCropEnabled = true

// The amount of seconds between automatically making scans, should be a Double.
KlippaScanner.setup.autoScanInterval = 10

// Whether the camera has a view finder overlay (a helper grid so the user knows where the document should be), should be a Boolean.
KlippaScanner.setup.isViewFinderEnabled = true
                    
                

Calling the OCR API

It's possible to use the results of the scanner with the OCR API.

To use it, generate a Public API key with our API through your own backend, this makes sure your API key won't be leaked and/or abused.

Edit your Podfile file, so that it contains the following:

                    
pod 'Klippa-OCR-API', podspec: 'https://custom-ocr.klippa.com/sdk/ios/specrepo/ExampleUsername/ExamplePassword/KlippaOCRAPI/latest.podspec'
                    
                

If you are using Carthage, add the folowing to your Cartfile:

                    
binary "https://custom-ocr.klippa.com/sdk/ios/carthage/ExampleUsername/ExamplePassword/KlippaOCRAPI.json"
                    
                

You then have the possibility to call the OCR API client and run it on the images of the scanner.
The following example runs the OCR on every image and then shows the total amount.

                

import UIKit
import KlippaScanner
import KlippaOCRAPI

final class ViewController: UIViewController, ImageScannerControllerDelegate {

    private var loadedScanner = false
    private var totalAmount: Float64 = 0
    private var vSpinner : UIView?

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        if (!loadedScanner) {
            loadedScanner = true
            let scannerViewController = ImageScannerController()
            scannerViewController.imageScannerDelegate = self
            scannerViewController.modalPresentationStyle = .fullScreen
            present(scannerViewController, animated: false)
        }
    }

    func imageScannerController(_ scanner: ImageScannerController, didFailWithError error: Error) {
        print("didFailWithError")
        switch error {
        case let licenseError as LicenseError:
            print("Got licensing error from SDK: \(licenseError.localizedDescription)")
        default:
            print(error)
        }
    }

    func imageScannerController(_ scanner: ImageScannerController, didFinishScanningWithResult result: ImageScannerResult) {
        print("didFinishScanningWithResults")
        print("multipleDocumentsModeEnabled \(result.multipleDocumentsModeEnabled)")
        print("Scanned \(result.images.count) images")
        totalAmount = 0

        let publicAPIKey = ""
        var processedImages = 0
        self.showSpinner(onView: self.view)

        for image in result.images {
            print ("Scanning image \(image.path)")

            let url = URL.init(fileURLWithPath: image.path.replacingOccurrences(of: "file://", with: ""))

            ParsingAPI.parseDocumentWithRequestBuilder(document: url, url: nil, template: nil, pdfTextExtraction: ParsingAPI.PdfTextExtraction_parseDocument(rawValue: "full"), userData: nil, userDataSetExternalId: nil).addHeader(name: "X-Auth-Public-Key", value: publicAPIKey).execute { (response) in

                do {
                    let receipt = try response.get().body
                    if receipt?.data?.amount != nil {
                        self.totalAmount += Float64((receipt?.data?.amount)!) / 100
                    }
                } catch(let e) {
                    if let err = e as? ErrorResponse {
                        switch(err){
                        case ErrorResponse.error(let code, let body, _):
                            print(code)

                            if body != nil {
                                print(String.init(bytes: body!, encoding: String.Encoding.utf8)!)
                            }

                        @unknown default:
                            print("Unknown error")
                        }
                    }
                }

                processedImages += 1
                if processedImages == result.images.count {
                    self.finishedOCRProcessing()
                }
            }
        }
    }

    func showSpinner(onView : UIView) {
         let spinnerView = UIView.init(frame: onView.bounds)
         spinnerView.backgroundColor = UIColor.init(red: 0.5, green: 0.5, blue: 0.5, alpha: 0.5)
         let ai = UIActivityIndicatorView.init(style: .whiteLarge)
         ai.startAnimating()
         ai.center = spinnerView.center

         DispatchQueue.main.async {
             spinnerView.addSubview(ai)
             onView.addSubview(spinnerView)
         }

         vSpinner = spinnerView
     }

    func removeSpinner() {
         DispatchQueue.main.async {
            self.vSpinner?.removeFromSuperview()
            self.vSpinner = nil
         }
    }

    func finishedOCRProcessing() {
        self.removeSpinner()

        let alert = UIAlertController(title: "Scans finished", message: "The total amount of all images is \(totalAmount)", preferredStyle: .alert)
        self.present(alert, animated: true, completion: nil)
    }

    func imageScannerControllerDidCancel(_ scanner: ImageScannerController) {
        print("imageScannerControllerDidCancel")
        scanner.dismiss(animated: true, completion: nil)
    }
}

                
            

Versions

The following versions are available:

Version Podspec include URL Cartfile dependency
0.2.0 https://custom-ocr.klippa.com/sdk/ios/specrepo/ExampleUsername/ExamplePassword/KlippaScanner/0.2.0.podspec binary "https://custom-ocr.klippa.com/sdk/ios/carthage/ExampleUsername/ExamplePassword/KlippaScanner.json" == 0.2.0
0.1.4 https://custom-ocr.klippa.com/sdk/ios/specrepo/ExampleUsername/ExamplePassword/KlippaScanner/0.1.4.podspec binary "https://custom-ocr.klippa.com/sdk/ios/carthage/ExampleUsername/ExamplePassword/KlippaScanner.json" == 0.1.4
0.1.3 https://custom-ocr.klippa.com/sdk/ios/specrepo/ExampleUsername/ExamplePassword/KlippaScanner/0.1.3.podspec binary "https://custom-ocr.klippa.com/sdk/ios/carthage/ExampleUsername/ExamplePassword/KlippaScanner.json" == 0.1.3
0.1.2 https://custom-ocr.klippa.com/sdk/ios/specrepo/ExampleUsername/ExamplePassword/KlippaScanner/0.1.2.podspec binary "https://custom-ocr.klippa.com/sdk/ios/carthage/ExampleUsername/ExamplePassword/KlippaScanner.json" == 0.1.2
0.1.1 https://custom-ocr.klippa.com/sdk/ios/specrepo/ExampleUsername/ExamplePassword/KlippaScanner/0.1.1.podspec binary "https://custom-ocr.klippa.com/sdk/ios/carthage/ExampleUsername/ExamplePassword/KlippaScanner.json" == 0.1.1
0.1.0 https://custom-ocr.klippa.com/sdk/ios/specrepo/ExampleUsername/ExamplePassword/KlippaScanner/0.1.0.podspec binary "https://custom-ocr.klippa.com/sdk/ios/carthage/ExampleUsername/ExamplePassword/KlippaScanner.json" == 0.1.0
0.0.14 https://custom-ocr.klippa.com/sdk/ios/specrepo/ExampleUsername/ExamplePassword/KlippaScanner/0.0.14.podspec binary "https://custom-ocr.klippa.com/sdk/ios/carthage/ExampleUsername/ExamplePassword/KlippaScanner.json" == 0.0.14
0.0.13 https://custom-ocr.klippa.com/sdk/ios/specrepo/ExampleUsername/ExamplePassword/KlippaScanner/0.0.13.podspec binary "https://custom-ocr.klippa.com/sdk/ios/carthage/ExampleUsername/ExamplePassword/KlippaScanner.json" == 0.0.13
0.0.12 https://custom-ocr.klippa.com/sdk/ios/specrepo/ExampleUsername/ExamplePassword/KlippaScanner/0.0.12.podspec binary "https://custom-ocr.klippa.com/sdk/ios/carthage/ExampleUsername/ExamplePassword/KlippaScanner.json" == 0.0.12
0.0.11 https://custom-ocr.klippa.com/sdk/ios/specrepo/ExampleUsername/ExamplePassword/KlippaScanner/0.0.11.podspec binary "https://custom-ocr.klippa.com/sdk/ios/carthage/ExampleUsername/ExamplePassword/KlippaScanner.json" == 0.0.11
0.0.10 https://custom-ocr.klippa.com/sdk/ios/specrepo/ExampleUsername/ExamplePassword/KlippaScanner/0.0.10.podspec binary "https://custom-ocr.klippa.com/sdk/ios/carthage/ExampleUsername/ExamplePassword/KlippaScanner.json" == 0.0.10
0.0.8 https://custom-ocr.klippa.com/sdk/ios/specrepo/ExampleUsername/ExamplePassword/KlippaScanner/0.0.8.podspec binary "https://custom-ocr.klippa.com/sdk/ios/carthage/ExampleUsername/ExamplePassword/KlippaScanner.json" == 0.0.8
0.0.7 https://custom-ocr.klippa.com/sdk/ios/specrepo/ExampleUsername/ExamplePassword/KlippaScanner/0.0.7.podspec binary "https://custom-ocr.klippa.com/sdk/ios/carthage/ExampleUsername/ExamplePassword/KlippaScanner.json" == 0.0.7
0.0.6 https://custom-ocr.klippa.com/sdk/ios/specrepo/ExampleUsername/ExamplePassword/KlippaScanner/0.0.6.podspec binary "https://custom-ocr.klippa.com/sdk/ios/carthage/ExampleUsername/ExamplePassword/KlippaScanner.json" == 0.0.6
0.0.5 https://custom-ocr.klippa.com/sdk/ios/specrepo/ExampleUsername/ExamplePassword/KlippaScanner/0.0.5.podspec binary "https://custom-ocr.klippa.com/sdk/ios/carthage/ExampleUsername/ExamplePassword/KlippaScanner.json" == 0.0.5
0.0.4 https://custom-ocr.klippa.com/sdk/ios/specrepo/ExampleUsername/ExamplePassword/KlippaScanner/0.0.4.podspec binary "https://custom-ocr.klippa.com/sdk/ios/carthage/ExampleUsername/ExamplePassword/KlippaScanner.json" == 0.0.4
0.0.2 https://custom-ocr.klippa.com/sdk/ios/specrepo/ExampleUsername/ExamplePassword/KlippaScanner/0.0.2.podspec binary "https://custom-ocr.klippa.com/sdk/ios/carthage/ExampleUsername/ExamplePassword/KlippaScanner.json" == 0.0.2

Changelog

0.2.0

Changed

  • Build using XCode 12/Swift 5.3

0.1.3

Changed

  • The ImageScannerResult object returned in didFinishScanningWithResult now also contains the cropEnabled variable, indicating the status of the crop button.

0.1.1

Changed

  • A back button has been added in the bottom left corner. It’s visible as long as no photo’s have been taken yet. Pressing the back button dismisses the view controller and calls imageScannerControllerDidCancel on the delegate.

0.1.0

Changed

  • The build system has now been changes to the modern build system, and we now build the library with the option BUILD_LIBRARY_FOR_DISTRIBUTION. We also use XCFrameworks now to package the framework. The Carthage package still links to the traditional fat framework because Carthage does not support XCFramework yet, but the framework is now based on the files from the XCFramework package.

0.0.13

Changed

  • The isMultipleDocumentsModeEnabled option has been added to make a distinction between the multiple documents mode being available at all, and the user toggling the button. allowMultipleDocumentsMode now displays / hides the button whilst isMultipleDocumentsModeEnabled toggles the initial state when the button is visible.

0.0.12

Fixed

  • Fix image preview when cropping pictures that have been taken in landscape.

0.0.11

Changed

  • The primaryColor is now used for the toolbar.
  • The accentColor is used for controls.
  • The overlayColor is used for both the area that will be cropped and the cropping controls.
  • The isAutoScanEnabled and isAutoScanEnabled options have been removed.
  • Reduced the duration of capture animations.
  • The colors for the crop, multiple documents mode and flash toggles have been changed to partially white (disabled state) and fully white (enabled state).

Fixed

  • Pressing the crop-button no longer takes a photo.
  • Fixed inconsistent behavior of isCropEnabled option.
  • Changes to the cropped area were not saved when returning to the camera.
  • The orientation of landscape photos changed to black-white was incorrect.
  • The initial state for allowMultipleDocumentsMode was being ignored.
  • Rotating the photo now also rotates the original picture and not just the cropped area. The cropped area will also be properly rotated.

0.0.10

Added

  • Added default constructor for ImageScannerController.

Changed

  • ImageScannerControllerDelegate now finishes scanning with one object (ImageScannerResult), containing the captured images and the multipleDocumentsModeEnabled property.
  • Added classname to the @objc decorator, to enable Nativescript to discover the correct classes on run time.

0.0.9

Added

  • Added default constructor for ImageScannerController.

Fixed

  • Corrected some typo’s (imageTooDarkMessage, imageTooBrightMessage).

0.0.8

Fixed

  • Combine Swift headers for all archs.

0.0.7

Changed

  • Lower deployment target in Podspec from 11.0 to 10.0.

0.0.6

Changed

  • Lower deployment target from 11.0 to 10.0.

Fixed

  • Minor bugfixes

0.0.5

Fixed

  • Properties of KlippaImage were missing public acccess.

0.0.4

Added

  • Added multiple documents mode (allowMultipleDocumentsMode in KlippaScanner).
  • Added max width, height and quality constraints (imageMaxWidth, imageMaxHeight and imageMaxQuality in KlippaScanner).
  • Added ability to customize the warning text color (warningTextColor in KlippaScanner).

Changed

  • Renamed project from KippaScanner to KlippaScanner.
  • KlippaImage results now also returns the output path (path property in KlippaImage).
  • Lower deployment target from 11.2 to 11.0.

Fixed

  • Clicking the hidden thumbnails button without pictures crashed the camera.
  • Auto scan triggering directly after enabling.

0.0.3

Changed

  • Export more members to Object C for use in projects like NativeScript and React Native.

0.0.2

Changed

  • Updated podspec file to match deployment target.

0.0.1

Fixed

  • Fix UILabel padding extension.