BlinkID C SDK enables scanning various identity documents including driving licenses, national identity cards, passports and others. SDK includes:
- Real-time data extraction
- Offline, on-device processing for maximum security
- Front and back side data capture and comparison
- Extraction of face, document, and signature photo
Integrating BlinkID C SDK into your app requires experience with native development with the C language. If you are looking for native or specific cross-platform SDKs with built-in UX and camera management, please go to the BlinkID Github page. If you want to use BlinkID as a backend service on your Linux servers, please go here.
You should use BlinkID C SDK if you are developing:
- Windows, Linux or macOS desktop applications
- Custom hardware that runs a Linux-based OS on an Intel-compatible CPU, such as airport document readers and ATM machines
- C++, C#, Java, Python, Go or Ruby applications (you wrap the C-API in your target language)
- Server-side solutions where quick runtime is essential and a docker-based integration cannot meet your performance or compliance needs
- mobile apps that run on native code and need to work without the extra overhead incurred by Objective C (iOS) or Java (Android) callbacks
- System requirements
- Integration instructions
- The
Recognizer
concept and theRecognizerRunner
- Handling processing events with
RecognitionCallback
- List of available recognizers
- Troubleshooting
- FAQ and known issues
- Additional info
- BlinkID C SDK supports any
x86_64
compatible processor- x86, ARM, MIPS, SPARC, Power, Itanium and other non-x86_64-compatible CPUs are not supported
- the exception is only Apple Silicon Macs, which are ARM-based, but supported
- 20 MB of available hard disk space
- 1 GB of RAM
- the software may work even on systems with less RAM, but may fail to perform recognition of very large images
- pure barcode recognition (no OCR) should also work on systems with around 128 MB of free RAM
- BlinkID C SDK is compiled for following Android ABIs:
armeabi-v7a
,arm64-v8a
,x86
andx86_64
- Not supported ABIs:
armeabi
,mips
andmips64
- Note about
armeabi-v7a
:- only devices that have processor with support for Advanced SIMD (NEON) and VFPv4 are supported
- this means that certain
armeabi-v7a
CPUs, such as NVIDIA Tegra 2 are not supported
- all iOS devices that have iOS 11.0 or newer are supported.
- BlinkID C SDK supports 64-bit Intel-based and Apple Silicon-based Macs with Mac OS X 10.15 (Catalina) or newer
- Note that SDK may work on earlier versions of MacOS, but we do not give any support nor guarantees for that.
- BlinkID C SDK supports Linux distributions that have GLIBC 2.26 or newer
- OpenSSL v1.1.1 is required to be installed on the system, as well as CA certificates
- both
libssl.so.1.1
andlibcrypto.so.1.1
must be available - for axample, on CentOS 7, you can install OpenSSL v1.1.1 by enabling EPEL repo and installing the package
openssl11
with commandsudo yum install openssl11
- for example, on Ubuntu, you can install OpenSSL v1.1.1 with
sudo apt install libssl1.1 ca-certificates
- both
- additionally, for running bundled demo apps, a
libjpeg v8
is required- this is a dependency of the demo apps, not the SDK itself
- BlinkID C SDK supports only 64-bit Windows 10
- 32-bit version of Windows 10, as well as Windows 8.1 and earlier versions are not supported
- Visual C++ 2022 redistributable package is required for BlinkID C SDK to work on Windows
- BlinkID C SDK requires Android 4.1 (API level 16) or newer. The binary has been built with the latest NDK version available at the time of the release, but due to the C API, it should be both forward and backward compatible with any NDK version.
- BlinkID C SDK supports iOS 11.0 or newer. The binary has been built using the latest Xcode version available at the time of the release.
The BlinkID C SDK consists of:
- doxygen documentation
- C headers exposing the public API of the SDK
- dynamic library that contains the implementation of the SDK
- resources that BlinkID requires at runtime
In order to be able to use BlinkID in your application, you first need to configure your build system to be able to find the API headers so that your code will be able to use BlinkID's API functions. You also need to configure your build system to link with the dynamic library. Since there is no standard build system for C language, we created the most common examples for every OS BlinkID C SDK supports.
On Linux, please make sure that you instruct your compiler to search for headers in include directory and to link with libRecognizerApi.so
, which is located in Linux lib folder. Also, make sure that your Linux distribution has OpenSSL
installed (libssl.so.1.1
and libcrypto.so.1.1
need to be available). When running your app, make sure that libRecognizerApi.so
is available in library search path by installing it to the default library directory (usually /usr/lib
) or by setting LD_LIBRARY_PATH
environment variable to folder containing the libRecognizerApi.so
. While deploying your application, make sure that you also include the resources that are needed at runtime. You will need to provide path to folder containing those resources during the initialization of the SDK.
Please check the Linux sample-app for an example of integration of BlinkID C SDK on Linux.
On MacOS, BlinkID C SDK is available as dynamic framework. You can simply drag and drop the framework in your Xcode project and Xcode should automatically setup header and framework search paths for you. While deploying your application, make sure that you also include the resources that are needed at runtime. You will need to provide path to folder containing those resources during the initialization of the SDK.
Please check the MacOS sample-app for an example of integration of BlinkID C SDK on MacOS.
On Windows, BlinkID C SDK is available as dynamic library. You need to instruct your compiler to search for headers in include directory and link with RecognizerApi.lib
, which is located in Windows lib folder. When running your app, make sure that RecognizerApi.dll
is available in the same directory as your application's executable file. While deploying your application, make sure that you also include the resources that are needed at runtime. You will need to provide path to folder containing those resources during the initialization of the SDK. In order for BlinkID C SDK to work, a Visual C++ 2022 redistributable package needs to be installed on the system.
Please check the Windows sample-app for an example of integration of BlinkID C SDK on Windows.
On Android, please make sure that you instruct your compiler to search for headers in include directory and to link with libRecognizerApi.so
for each android ABI. Libraries for all supported Android ABIs are located in Android lib folder. When running your app, make sure that you load the RecognizerApi
in Java code prior loading your own library, otherwise you will get UnsatisfiedLinkException
. While deploying your application, make sure to include the resources in your app's assets. You can put the resource files into any folder within your app's assets. You will need to provide path to folder containing those resources during the initialization of the SDK. On Android, this path must be relative with respect to your app's assets folder. Also, make sure that you initialize the BlinkID C SDK with your application's context using recognizerAPIInitializeAndroidApplication
before making any other API calls.
Please check the Android sample-app for an example of integration of BlinkID C SDK on Android.
On iOS, BlinkID C SDK is available as dynamic framework. You can simply drag and drop the framework in your Xcode project and Xcode should automatically setup header and framework search paths for you. While deploying your application, make sure that you also include the resources that are needed at runtime. You will need to provide path to folder containing those resources during the initialization of the SDK.
Please check the iOS sample-app for an example of integration of BlinkID C SDK on iOS.
Using BlinkID C SDK in your app requires a valid license key.
You can obtain a free trial license key by registering to Microblink dashboard. After registering, you will be able to generate a license key for your app.
- On Android, the license key is bound to the application ID of your app.
- On iOS, the license key is bound to the bundle identifier of your app.
- On Linux, the license key is bound to the machine ID of the computer that will run your app.
- you can obtain the ID by running a license request tool. This utility will print the machine ID as
Licensee
to the standard output and also into fileMicroblinkLicenseRequest.txt
- if you need a linux license eligible for multiple machines, please contact us
- you can obtain the ID by running a license request tool. This utility will print the machine ID as
- On MacOS, the license key is bound to the Mac's UUID
- you can obtain the ID by running a license request tool. This utility will print the machine ID as
Licensee
to the standard output and also into fileMicroblinkLicenseRequest.txt
- if you need a macOS license eligible for multiple machines, please contact us
- you can obtain the ID by running a license request tool. This utility will print the machine ID as
- On Windows, the license key is bound to the Windows product ID
- you can obtain the ID by running a license request tool. This utility will print the product ID as
Licensee
to the standard output and also into fileMicroblinkLicenseRequest.txt
- if you need a Windows license eligible for multiple machines, please contact us
- you can obtain the ID by running a license request tool. This utility will print the product ID as
Keep in mind: Under our License Management Program a public network access is required.
We’re only asking you to do this so we can validate your trial license key. Scanning or data extraction of identity documents still happens offline, on the device itself. Once the validation is complete, you can continue using the SDK in offline mode (or over a private network) until the next check. If there is a network error during trial license check, functions recognizerAPIUnlock*
will fail with MB_RECOGNIZER_ERROR_STATUS_NETWORK_ERROR
error code and functions recognizerRunnerRecognizeFrom*
will immediately return with MB_RECOGNIZER_RESULT_STATE_EMPTY
. Note that License Management Program can be disabled for production licenses - in that case no Internet connection will be required for SDK to work.
-
Make sure that you have set up your build system and obtained the license key.
-
Include a main SDK header, which provides all API functions:
#include <RecognizerApi.h>
-
(Android only) initialize Android JNI context. This is required on Android in order for license validation and resource loading to work.
// jniEnv is of type "JNIEnv *" and available to every JNI funcion // context is of type "jobject" and must point to instance "android.content.Context" java object. It is recommended to use application context // to avoid memory leaks. For more information, please see: https://android-developers.googleblog.com/2009/01/avoiding-memory-leaks.html recognizerAPIInitializeAndroidApplication( jniEnv, context );
-
(Desktop platforms only) define the location of cache folder. This is required to store some cache files when online licenses are used. On mobile platforms those files are stored into app's private folder, but on desktop platforms it is required to define a unique folder in order to avoid clashes with other applications using the same SDK.
recognizerAPISetCacheLocation( "/path/to/cache/folder" );
-
Insert your license key
MBRecognizerErrorStatus errorStatus = recognizerAPIUnlockWithLicenseKey( "Add license key here" ); if ( errorStatus != MB_RECOGNIZER_ERROR_STATUS_SUCCESS ) { // handle failure }
-
Set path to folder containing resources required by the library. The function
recognizerAPISetResourcesLocation
requires absolute path to folder containing all files fromresources/non-android
folder from the distribution on all platforms except Android. On Android it requires relative path to folder withinassets
containing all files from theresources/android
folder from the distribution. For more information about that, check the Android sample-appMBRecognizerErrorStatus errorStatus = recognizerAPISetResourcesLocation( "/path/to/resources/non-android" ); if ( errorStatus != MB_RECOGNIZER_ERROR_STATUS_SUCCESS ) { // handle failure }
-
Create and configure recognizer. For more information about available recognizers, check here
MBBlinkIdRecognizer * blinkIdRecognizer = NULL; MBBlinkIdRecognizerSettings settings; // initialize default settings values blinkIdRecognizerSettingsDefaultInit( &settings ); // optionally tweak settings for your needs MBRecognizerErrorStatus errorStatus = = blinkIdRecognizerCreate( &blinkIdRecognizer, &settings ); if ( errorStatus != MB_RECOGNIZER_ERROR_STATUS_SUCCESS ) { // handle failure }
-
Create and configure recognizer runner
MBRecognizerRunnerSettings runnerSett; recognizerRunnerSettingsDefaultInit( &runnerSett ); MBRecognizerPtr recognizers[] = { blinkIdRecognizer }; runnerSett.numOfRecognizers = 1; runnerSett.recognizers = recognizers; MBRecognizerRunner * recognizerRunner = NULL; errorStatus = recognizerRunnerCreate( &recognizerRunner, &runnerSett ); if ( errorStatus != MB_RECOGNIZER_ERROR_STATUS_SUCCESS ) { // handle failure }
-
Prepare the image to be recognized. Image first needs to be created from from memory. To create image from memory buffer use
recognizerImageCreateFromRawImage
int image_width, image_height, image_stride; MBByte * image_buffer; // populate above variables (i.e. by loading image file or capturing image with camera) MBRecognizerImage * img; MBRecognizerErrorStatus status = recognizerImageCreateFromRawImage( &img, image_buffer, image_width, image_height, image_stride, MB_RAW_IMAGE_TYPE_BGR ); if ( status != MB_RECOGNIZER_ERROR_STATUS_SUCCESS ) { printf( "Failed to create image. Reason: %s", recognizerErrorToString( status ) ); }
Alternatively, you can load the image from file using the
recognizerImageLoadFromFile
MBRecognizerImage* img; MBRecognizerErrorStatus status = recognizerImageLoadFromFile( &img, "path/to/image.jpg" ); if ( status != MB_RECOGNIZER_ERROR_STATUS_SUCCESS ) { printf( "Failed to load image from file. Reason: %s", recognizerErrorToString( status ) ); }
-
Once you have created an image, you can perform recognition using method
recognizerRunnerRecognizeFromImage
.MBRecognizerResultState resultState = recognizerRunnerRecognizeFromImage( recognizerRunner, imageWrapper.recognizerImage, MB_FALSE, NULL ); if ( resultState != MB_RECOGNIZER_RESULT_STATE_EMPTY ) { // obtain results from recognizers (see Step 4) }
-
Obtain result structure from each of the recognizers. If some recognizer's result's state is
MB_RECOGNIZER_RESULT_STATE_VALID
, then it contains recognized data.MBBlinkIdRecognizerResult result; blinkIdRecognizerResult( &result, blinkIdRecognizer ); if ( result.baseResult.state == MB_RECOGNIZER_RESULT_STATE_VALID ) { // you can use data from the result }
-
Finally, when done, clean the memory. Each structure has method for releasing it.
recognizerImageDelete( &img ); recognizerRunnerDelete( &recognizerRunner ); // make sure that recognizers are deleted *AFTER* recognizerRunner blinkIdRecognizerDelete( &blinkIdRecognizer );
BlinkID C SDK can be used in a thread-safe manner, however some synchronization may be required on your side. The functions that are used for setting the license key are not thread-safe and should not be used concurrently from different threads. Furthermore, recognizers and RecognizerRunner should not be shared between different threads without synchronization. Each Recognizer, when associated with RecognizerRunner
can only be used from the single thread at the time. This means that if you plan to process multiple images in different threads in parallel, you should use specific RecognizerRunner
and recognizer objects for each of your threads. Failure to do so will result in undefined behaviour. Also, initialization of the RecognizerRunner
should not be done concurrently with initialization of different RecognizerRunner
or concurrently with image processing (even with different RecognizerRunner
). However, once initialized, different instances of RecognizerRunner
can be safely used concurrently from different threads as long as they are not using the same instances of recognizers.
So, to summarize:
- license key should be set before launching any threads - this is not thread safe
- this also hold for other global initialization functions, such as recognizerAPIInitializeAndroidApplication on Android and recognizerAPISetCacheLocation
- each thread needs to have their own set of recognizer objects and
RecognizerRunner
RecognizerRunner
initialization must not be performed concurrently neither with initialization of theRecognizerRunner
on different thread nor with image processing- image processing can be safely performed concurrently on different threads, provided that:
- each thread uses its own instance of
RecognizerRunner
- recognizer objects are not shared between those instances
- each thread uses its own instance of
RecognizerRunner
cleanup must not be performed concurrently
This section will first describe what is a Recognizer
and how it should be used to perform recognition of the still images and video frames. Next, we will describe what is a RecognizerRunner
and how it can be used to tweak the recognition procedure.
The Recognizer
is the basic unit of processing within the BlinkID SDK. Its main purpose is to process the image and extract meaningful information from it. As you will see later, the BlinkID SDK has lots of different Recognizer
objects that have various purposes.
Each Recognizer
has a Result
object, which contains the data that was extracted from the image. The Result
for each specific Recognizer
can be obtained by creating a specific Result
structure (each Recognizer
has its own unique Result
structure) and filling its contents by calling the <recognizerName>RecognizerResult
function (each Recognizer
has its own unique function for obtaining the results.) The pointers set by the result obtaining function are valid as long as the associated Recognizer
object is alive, i.e. until <recognizerName>RecognizerDelete
function is called. Keep that in mind while developing your application.
Every Recognizer
is a stateful object that can be in two possible states: idle state and working state.
While in idle state, you are allowed to call <recognizerName>RecognizerUpdate
function which will update Recognizer's
properties according to given settings.
After you create a RecognizerRunner
with array containing your recognizer, the state of the Recognizer
will change to working state, in which Recognizer
object will be used for processing. While being in working state, it is not possible to call function <recognizerName>RecognizerUpdate
with it as a parameter (calling it will crash your app). If you need to change configuration of your recognizer while its being used, you need to create a new Recognizer
of the same type with your modified configuration and replace the original Recognizer
within the RecognizerRunner
by calling its recognizerRunnerUpdateSettings
method.
While Recognizer
object works, it changes its internal state and its result. The Recognizer
object's Result
always starts in MB_RECOGNIZER_RESULT_STATE_EMPTY
state. When corresponding Recognizer
object performs the recognition of given image, its Result
can either stay in MB_RECOGNIZER_RESULT_STATE_EMPTY
state (in case Recognizer
failed to perform recognition), move to MB_RECOGNIZER_RESULT_STATE_UNCERTAIN
state (in case Recognizer
performed the recognition, but not all mandatory information was extracted), move to MB_RECOGNIZER_RESULT_STATE_STAGE_VALID
(in case multi-stage Recognizer
performed some stage of the recognition, such as scanning the front side of the document) or move to MB_RECOGNIZER_RESULT_STATE_VALID
state (in case Recognizer
performed recognition and all mandatory information was successfully extracted from the image).
The RecognizerRunner
is the object that manages the chain of individual Recognizer
objects within the recognition process. It's created by recognizerRunnerCreate
function, which requires a settings structure which contains an array of Recognizer
objects that will be used for processing and a MBBool allowMultipleResults
member indicating whether multiple Recognizer
objects are allowed to have their Results
enter the MB_RECOGNIZER_RESULT_STATE_VALID
state.
To explain further the allowMultipleResults
parameter, we first need to understand how RecognizerRunner
performs image processing.
When the recognizerRunnerRecognizeFromImage
function is called, it processes the image with the first Recognizer
in chain. If the Recognizer's
Result
object changes its state to MB_RECOGNIZER_RESULT_STATE_VALID
, then if the allowMultipleResults
parameter is MB_FALSE
, the recognition chain will be broken and recognizerRunnerRecognizeFromImage
function will immediately return. If the allowMultipleResults
parameter is MB_TRUE
, then the image will also be processed with other Recognizer
objects in chain, regardless of the state of their Result
objects. If, after processing the image with the first Recognizer
in chain, its Result
object's state is not changed to Valid
, the RecognizerRunner
will use the next Recognizer
object in chain for processing the image and so on - until the end of the chain (if no results become valid or always if allowMultipleResults
parameter is MB_TRUE
) or until it finds the Recognizer
that has successfully processed the image and changed its Result's
state to MB_RECOGNIZER_RESULT_STATE_VALID
(if allowMultipleResults
parameter is MB_FALSE
).
You cannot change the order of the Recognizer
objects within the chain - no matter the order in which you give Recognizer
objects to RecognizerRunner
, they are internally ordered in a way that provides best possible performance and accuracy.
Also, in order for BlinkID SDK to be able to order Recognizer
objects in recognition chain in the best way possible, it is not allowed to have multiple instances of Recognizer
objects of the same type within the chain. Attempting to do so will crash your application.
Processing events, also known as Recognition callbacks are purely intended for giving processing feedback on UI. If you do not plan developing any UI, you will most probably not need to use Recognition callbacks.
Callbacks for all possible events are bundled into the MBRecognitionCallback
structure. We suggest checking for more information about available callbacks in the doxygen documentation.
This section will give a list of all Recognizer
objects that are available within BlinkID SDK, their purpose and recommendations how they should be used to get best performance and user experience.
The BarcodeRecognizer
is recognizer specialized for scanning various types of barcodes.
As you can see from the doxygen documentation, you can enable multiple barcode symbologies within this recognizer, however keep in mind that enabling more barcode symbologies affects scanning performance - the more barcode symbologies are enabled, the slower the overall recognition performance. Also, keep in mind that some simple barcode symbologies that lack proper redundancy, such as Code 39, can be recognized within more complex barcodes, especially 2D barcodes, like PDF417.
The IdBarcodeRecognizer
is recognizer specialized for scanning barcodes from various ID cards.
You can find the list of the currently supported documents here.
The BlinkIdRecognizer
scans and extracts data from the single side of the supported document.
You can find the list of the currently supported documents here. For detailed information about which fields can be extracted from each document, check this link.
We will continue expanding this recognizer by adding support for new document types in the future. Star this repo to stay updated.
Use BlinkIdCombinedRecognizer
for scanning both sides of the supported document. First, it scans and extracts data from the front, then scans and extracts data from the back, and finally, combines results from both sides.
The BlinkIdCombinedRecognizer
also performs data matching and returns a flag if the extracted data captured from the front side matches the data from the back.
You can find the list of the currently supported documents here. For detailed information about which fields can be extracted from each document, check this link.
We will continue expanding this recognizer by adding support for new document types in the future. Star this repo to stay updated.
In case of problems with the integration of the SDK, first make sure that you have tried integrating the SDK exactly as described in integration instructions.
If you have followed the instructions to the letter and you still have the problems, please try modifying a sample app so that it will reproduce the issue you are having and then contact us at help.microblink.com.
If you are getting "invalid license key" error or having other license-related problems (e.g. some feature is not enabled that should be), first check the output of your program. All license-related problems are logged to the standard output for each platform (ADB on Android, NSLog on iOS, stdout
on desktop platforms).
When you have to determine what is the license-related problem or you simply do not understand the log, you should contact us help.microblink.com. When contacting us, please make sure you provide following information:
licensee
to which your license key is bound- for more information about obtaining the
licensee
, check Obtaining a license key
- for more information about obtaining the
- license key that is causing problems
- please stress out that you are reporting problem to the BlinkID C SDK
- please add information about the operating system and its version
- if unsure about the problem, you should also provide excerpt from program output containing the license error
If you are having problems with scanning certain items, undesired behaviour on specific device(s), crashes inside BlinkID or anything unmentioned, please do as follows:
- Contact us at help.microblink.com describing your problem and provide following information:
- Log from the program output
- high resolution scan/photo of the item that you are trying to scan
- information about the operating system and its version
- please stress out that you are reporting problem related to the BlinkID C SDK
- in case of a crash, please provide a crash trace or even a coredump file
After switching from trial to production license I get error This entity is not allowed by currently active license!
when I create a specific Recognizer
object.
Each license key contains information about which features are allowed to use and which are not. This error indicates that your production license does not allow using of specific Recognizer
object. You should contact support to check if provided license is OK and that it really contains all features that you have purchased.
Please check that you have correctly set the license key and that you have correctly set the path to resources that need to be loaded at runtime. For more information, see performing your first scan article
If you are using trial license key or production license key under License Management Program, it will require Internet connection to periodically validate the license key. Scanning or data extraction of identity documents still happens offline, on the device itself. For more information, check Obtaining a license key paragraph.
This can happen if online license is used, which requires server permission for unlocking the SDK and the server is not reachable. First, make sure that your system has CA certificates installed. Most systems have that as soon as OpenSSL package is installed, however, Ubuntu-based Linux distribution contain CA certificates in ca-certificates
package. You can install that by issuing command sudo apt install ca-certificates
.
If this didn't fix your problem, make sure that the licensing server is reachable by issuing command ping baltazar.microblink.com
. If the server is reachable, but you are still getting network error, please contact us
This error happens when JVM fails to load some native method from native library. First make sure that you have loaded RecognizerApi
in Java prior loading your native library. This should be added to Java class that interacts with your native library that uses BlinkID. For example:
static {
System.loadLibrary("RecognizerApi");
System.loadLibrary("myLibUsingRecognizerApi");
}
Also, make sure that you have correctly combined BlinkID SDK with third party SDKs that contain native code, i.e. that your final app contains matching ABIs for all libraries that ended up in the final library. For more information about that, check this article in our BlinkID Android SDK documentation.
If you are getting this error also in our integration demo app, then it may indicate a bug in the SDK that is manifested on specific device. Please report that to our support team.
Make sure that you have initialized the SDK with your app's Application context before calling any other API function. For more information about that, check this article in our BlinkID Android SDK documentation.
For any other questions, feel free to contact us at help.microblink.com or open a new issue on GitHub.