PhotoPay C SDK enables scanning various payment barcodes on payment slips. SDK includes:
- Real-time data extraction
- Offline, on-device processing for maximum security
Integrating PhotoPay 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 PhotoPay Github page.
You should use PhotoPay C SDK if you are developing:
- Windows desktop applications
- C++, C#, Java, Python, Go or Ruby applications (you wrap the C-API in your target language)
- System requirements
- Integration instructions
- The
Recognizerconcept and theRecognizerRunner - Handling processing events with
RecognitionCallback - List of available recognizers
- Troubleshooting
- FAQ and known issues
- Additional info
- PhotoPay C SDK supports any
x86_64compatible processor- x86, ARM, MIPS, SPARC, Power, Itanium and other non-x86_64-compatible CPUs are not supported
- 20 MB of available hard disk space
- 128 MB of RAM
- the software may work even on systems with less RAM, but may fail to perform recognition of very large images
- PhotoPay 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 PhotoPay C SDK to work on Windows
The PhotoPay C SDK consists of:
- doxygen documentation
- C headers exposing the public API of the SDK
- located in include directory
- dynamic library that contains the implementation of the SDK
- Windows DLL and import lib is available here
In order to be able to use PhotoPay 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 PhotoPay'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 PhotoPay C SDK supports.
On Windows, PhotoPay 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. In order for PhotoPay 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 PhotoPay C SDK on Windows.
Using PhotoPay 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 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
Licenseeto 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 data 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>
-
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 }
-
Create and configure recognizer. For more information about available recognizers, check here
MBCroatiaPdf417PaymentRecognizer * croatiaPdf417PaymentRecognizer = NULL; MBCroatiaPdf417PaymentRecognizerSettings settings; // initialize default settings values croatiaPdf417PaymentRecognizerSettingsDefaultInit( &settings ); // optionally tweak settings for your needs MBRecognizerErrorStatus errorStatus = = croatiaPdf417PaymentRecognizerCreate( &croatiaPdf417PaymentRecognizer, &settings ); if ( errorStatus != MB_RECOGNIZER_ERROR_STATUS_SUCCESS ) { // handle failure }
-
Create and configure recognizer runner
MBRecognizerRunnerSettings runnerSett; recognizerRunnerSettingsDefaultInit( &runnerSett ); MBRecognizerPtr recognizers[] = { croatiaPdf417PaymentRecognizer }; 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
recognizerImageCreateFromRawImageint 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
recognizerImageLoadFromFileMBRecognizerImage* 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.MBCroatiaPdf417PaymentRecognizerResult result; croatiaPdf417PaymentRecognizerResult( &result, croatiaPdf417PaymentRecognizer ); 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 croatiaPdf417PaymentRecognizerDelete( &croatiaPdf417PaymentRecognizer );
PhotoPay 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 holds for other global initialization functions, such as recognizerAPISetCacheLocation
- each thread needs to have their own set of recognizer objects and
RecognizerRunner RecognizerRunnerinitialization must not be performed concurrently neither with initialization of theRecognizerRunneron 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
RecognizerRunnercleanup 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 PhotoPay SDK. Its main purpose is to process the image and extract meaningful information from it. As you will see later, the PhotoPay 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 PhotoPay 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 PhotoPay SDK, their purpose and recommendations how they should be used to get best performance and user experience.
The CroatiaPdf417PaymentRecognizer is recognizer specialized for scanning payment information from 2D PDF417 payment barcodes on croatian payment slips.
In general, you can use the default settings object to configure PDF417 payment barcode recognizer, but in case when you have some special needs, you can change the default settings.
The CroatiaQrPaymentRecognizer is recognizer specialized for scanning payment information from payment QR codes found on some croatian payment slips and invoices.
In general, you can use the default settings object to configure payment QR code recognizer, but in case when you have some special needs, you can change the default settings.
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:
licenseeto 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 PhotoPay 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 PhotoPay 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 PhotoPay 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.
For any other questions, feel free to contact us at help.microblink.com or open a new issue on GitHub.