Documentation – Current v24.2

Imatest IT Instructions

Current Documentation

All documentation versions

Introduction

Interface Type:

Watch on YouTube.

Imatest IT (Industrial Testing) is a set of Application Programming Interfaces (APIs) that allow developers to access Imatest’s powerful image quality analysis tools in their own custom applications.

Imatest IT is available for 64-bit Windows, MacOS and Linux, and includes libraries for use with C, C++, Python, Objective-C, .NET (Windows only – including C# and Visual Basic), and LabVIEW. IT also contains standalone executables that can be called from a command line or script. The API libraries perform the exact same calculations as the corresponding GUI-based Imatest Master modules.

Imatest IT is a complete package that includes the module libraries, support documentation, sample code, and complete applications that interface with the modules.

Although Imatest IT operates independently of Imatest Master, we strongly recommend that IT users have at least one Master installation on site. Imatest Ultimate Edition, which includes both IT and Image Master Edition at a significant discount, is the ideal option for most users. As you will see in Step 2 below, setting up your test configuration, an integral part of any IT application, is much easier using Master.

 

Imatest IT Modules

Imatest IT contains twenty image analysis modules:

SFR – measures MTF and related results from manually-specified slanted edges SFRplus – measures MTF, lateral chromatic aberration, distortion, tonal response, and much more using Imatest’s highly-automated SFRplus chart and module
Star – measures MTF and lateral chromatic aberration from a Siemens star chart (usually sinusoidal) Colorcheck – measures color accuracy, noise, tonal response, and more from a 24-patch X-Rite Colorchecker
Stepchart – measures tonal response, gamma, noise, and more from a grayscale stepchart Wedge – measures MTF using hyperbolic wedges, found in the ISO 12233:2000 and eSFR ISO chart
OIS – measures the efficacy of image stabilization Uniformity – measures image uniformity, color shading, and hot/dead pixels from a flat field image
Distortion – measures distortion using a grid or checkerboard pattern eSFR ISO – measures MTF, color accuracy, noise, and tonal response using an enhanced ISO 12233:2014 chart
Blemish – measures visually-significant blemishes from a flat field image Dot Pattern – measures distortion and lateral chromatic aberration from a dot grid pattern (I3A CPIQ-compliant)
Multitest – analyzes images of a large variety of test charts for color accuracy, tonal response, noise, SNR (Signal-to-Noise Ratio) and ISO sensitivity Checkerboard – measures MTF, lateral chromatic aberration, and distortion using a checkerboard target
Random – Module that measures texture quality using the spilled coins or random (spatially-invariant) chart SFRreg – measures MTF and lateral chromatic aberration using one or more automatically-detected SFRreg targets
Log FC – measures the effects of signal processing (MTF as a function of spatial frequency and contrast) using a Log Frequency-Contrast chart Arbitrary Charts – measure a wide array of image quality factors from a chart design unsupported elsewhere in Imatest (including your own custom design).
Stray Light – analyzes images of a small, bright light source that is swept through the field of view to produce normalized metric stray light images and related outputs. Concentric Rings – measures field of view from an ISO 8600-3 chart.

Using Imatest IT

As illustrated in this graphic, working with Imatest IT is a four-step process. Each of these steps is outlined in detail in this article.

Step 1: Prepare Test Environment and Capture Test Targets

Inputs: None
Outputs: Test Image(s)
Imatest’s analysis modules require correctly framed and properly lit images of test targets. Once your test environment is properly set up, capture images of the required test targets for the modules you will be using.

Step 2: Configure INI File w/ Test Image(s)

Inputs: Test Image(s)
Outputs: INI File(s)
Using a sampling of the test images captured in Step 1, use Imatest Master to analyze the image files, choosing the options required for your application, and setting the Regions of Interest (ROIs) for your charts. Once everything is ready, export the INI file and keep it with your application source files.

In Imatest you can use the  Save ini file for  button in the Imatest IT settings window to save an ini file with only the needed sections.

Step 3: Integrate and Call Imatest IT Modules

Inputs: Test Image(s), INI File(s)
Outputs: Analysis Results
Code your application using your preferred programming language and call the module functions with your images and INI file.

Step 4: Process the Results

Inputs: Analysis Results
Outputs: Whatever you need
Load the analysis results and use them however you wish.

 

Installing Imatest IT

If you have not already downloaded Imatest IT, you can do so on the download page.

Next, follow the installation instructions found here.

After Imatest IT has successfully installed, you will need to activate it on your computer. Follow these instructions to activate your node-locked or floating license. If the computer running Imatest IT does not have an internet connection, you can also choose to activate it offline.

Post Installation Tasks

Linux Only – Updating the LD_LIBRARY_PATH

On Linux computers, several paths need to be appended to the LD_LIBRARY_PATH environment variable. To do this, you will need to edit your ~/.bashrc (or similar) file, and include these lines

export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/Imatest/v24.2/IT/bin
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/Imatest/v24.2/IT/libs/library/cpp 
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/MATLAB/MATLAB_Runtime/R2024aruntime/glnxa64 
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/MATLAB/MATLAB_Runtime/R2024a/bin/glnxa64 
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/MATLAB/MATLAB_Runtime/R2024a/sys/os/glnxa64 
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/MATLAB/MATLAB_Runtime/R2024a/sys/opengl/lib/glnxa64

For more information on editing environment variables, see this article.

macOS Only – Updating DYLD_LIBRARY_PATH

On macOS computers, several paths need to be appended to the DYLD_LIBRARY_PATH environment variable by adding these lines to ~/.bash_profile:

export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:/Applications/Imatest/IT/v24.2/bin
export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:/Applications/Imatest/IT/v24.2/libs/library/cpp 
export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:/Applications/MATLAB/MATLAB_Runtime/R2024a/runtime/maci64 
export DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:/Applications/MATLAB/MATLAB_Runtime/R2024a/bin/maci64

(Optional) – Reducing Startup Time w/ the MCR Cache

The first time you use the Imatest IT libraries, they must be unpacked to a temporary directory. This can take several seconds, depending on your system. In some use cases, this can happen on every use, especially if you are using the Imatest IT Acquisition Library.

To prevent the repeated unpacking of the IT libraries, you need to set two more environment variables: MCR_CACHE_ROOT and MCR_CACHE_SIZE. The MCR_CACHE_ROOT variable tells the Matlab Runtime where to extract the Imatest IT libraries. Setting it to a specific location that has write access for all users ensures that this cache will not be deleted by the operating system when it cleans up temporary files. The MCR_CACHE_SIZE variable is the size, in bytes, that the Matlab Runtime cache is allowed to grow to before other libraries are deleted. To keep Imatest IT running at top performance, it should be set to at least 900000000, and will result in much faster startup times for Imatest IT for some users.

Follow the instructions here to add these variables to your environment.
Windows

Variable Name Value
MCR_CACHE_ROOT C:\ProgramData\Imatest\mcr_cache\24.2\IT
MCR_CACHE_SIZE 900000000

Linux

Variable Name Value
MCR_CACHE_ROOT /var/lib/imatest/mcr_cache/24.2/IT
MCR_CACHE_SIZE 900000000

macOS

Variable Name Value
MCR_CACHE_ROOT $HOME/imatest/mcr_cache/24.2/IT
MCR_CACHE_SIZE 900000000

Note that for macOS you will need to create this folder.

Other Additional Installation Steps

Select your preferred interface below to see detailed instructions.

Interface Type:

In order for your application to interface with the Imatest IT C or C++ DLLs, your system needs to know where to find them.

There are two ways to make the Imatest IT C or C++ DLLs available to the system:

  • Add the library’s directory to your system’s PATH or LD_LIBRARY_PATH variable (recommended).
  • Copy the DLLs to the same directory as your application.

Adding to the PATH or LD_LIBRARY_PATH variable

Add the following directory to your system’s PATH (Windows) or LD_LIBRARY_PATH (Linux) variable, depending on which interface you will be using. For instructions on how to do this, see Editing System Environment Variables.

Note: Linux users may already have completed this step by following the Additional Installation Steps above, if you are using the C++ library.

In order for your application to interface with the Imatest IT C or C++ DLLs, your system needs to know where to find them.

There are two ways to make the Imatest IT C or C++ DLLs available to the system:

  • Add the library’s directory to your system’s PATH or LD_LIBRARY_PATH variable (recommended).
  • Copy the DLLs to the same directory as your application.

Adding to the PATH or LD_LIBRARY_PATH variable

Add the following directory to your system’s PATH (Windows) or LD_LIBRARY_PATH (Linux) variable, depending on which interface you will be using. For instructions on how to do this, see Editing System Environment Variables.

Note: Linux users may already have completed this step by following the Additional Installation Steps above, if you are using the C++ library.

Operating System Variable Name Value
Windows PATH C:\Program Files\Imatest\v24.2\IT\libs\library\c
Linux LD_LIBRARY_PATH /usr/local/Imatest/v24.2IT/libs/library/c

Operating System Variable Name Value
Windows PATH C:\Program Files\Imatest\v24.2\IT\libs\library\cpp
Linux LD_LIBRARY_PATH /usr/local/Imatest/v24.2/IT/libs/library/cpp
macOS DYLD_LIBRARY_PATH /Applications/Imatest/IT/v24.2/libs/library/cpp

Copying the Imatest IT DLLs

If you prefer not to change your PATH or LD_LIBRARY_PATH variables, you can also reference the Imatest IT DLLs by copying them to the same directory as your project’s executable.

Visual Studio users can automate this process by adding a Post-Build Event.

  • In the Solution Explorer, right-click on the project and select Properties.
  • Under Configuration Properties and Build Events, choose Post-Build Event.
  • Add the following to the Command Line box:
copy /Y "C:\Program Files\Imatest\v24.2\IT\libs\library\c\imatest_library.dll" ";$(TargetDir)"

Repeat these steps for each configuration in your project.

Now, the imatest_library.dll file will be copied to your project’s target directory automatically and will be able to be loaded by your application.

Copying the Imatest IT DLLs

If you prefer not to change your PATH or LD_LIBRARY_PATH variables, you can also reference the Imatest IT DLLs by copying them to the same directory as your project’s executable.

Visual Studio users can automate this process by adding a Post-Build Event.

  • In the Solution Explorer, right-click on the project and select Properties.
  • Under Configuration Properties and Build Events, choose Post-Build Event.
  • Add the following to the Command Line box:
copy /Y "C:\Program Files\Imatest\v24.2\IT\libs\library\cpp\imatest_library.dll" "$(TargetDir)"

Repeat these steps for each configuration in your project.

Now, the imatest_library.dll file will be copied to your project’s target directory automatically and will be able to be loaded by your application.

In order for your application to interface with the Imatest IT C++ libraries using Objective-C/C++, your system needs to know where to find them.

There are two ways to make the Imatest IT C++ libraries available to the system:

  • Add the library’s directory to your system’s DYLD_LIBRARY_PATH variable.
  • Copy the libraries to the same directory as your application.

Adding to the DYLD_LIBRARY_PATH variable

Add the following folder paths to your system’s DYLD_LIBRARY_PATH variable, depending on which interface you will be using. For instructions on how to do this, see Editing System Environment Variables.

Operating System Variable Name Value
macOS DYLD_LIBRARY_PATH /Applications/Imatest/IT/v24.2/libs/library/cpp
macOS DYLD_LIBRARY_PATH /Applications/Imatest/IT/v24.2/bin

Copying the Imatest IT Libraries

If you prefer not to change your DYLD_LIBRARY_PATH variable, you can also reference the Imatest IT libraries by copying them to the same directory as your project’s executable.

XCode users can automate this process by adding a Copy File and a Run Script Build Phase

  • In the project editor, select your application’s target and then go to the Build Phases pane.
  • Go to the Editor menu and then select Add Build Phase:Add Copy Files Build Phase.
  • In the Copy Files phase, set the Destination to Products Directory.
  • Click the + icon and then click the Add Other… button.
  • Navigate /Applications/Imatest/IT/v24.2/libs/library/cpp/, select libImatest.dylib, press Open and then press Finish.
  • In the Copy Files phase, deselect Copy Sign On Copy.
  • Repeat the process for /Applications/Imatest/IT/v24.2/bin/ShaferFilechck.dylib.
  • In the Run Script phase add install_name_tool -change @loader_path/libImatest.dylib @rpath/libImatest.dylib ${TARGET_BUILD_DIR}/${WRAPPER_NAME}/Contents/MacOS/${TARGETNAME}

The Imatest IT Python Interface is shipped as a Python module. Before referencing it in your scripts, you will need to install it using Python’s package manager. This must be done on the command line, and requires Administrator access. If you don’t know how to open a Command Prompt with Administrator privileges in Windows, see this helpful article.

Note: Imatest IT only supports Python versions 3.9, 3.10, and 3.11 (see IT/Python Supported Python Versions).

First, navigate to the Imatest IT Python library directory.

Windows

cd C:\Program Files\Imatest\v24.2\IT\libs\library\python\

Linux

cd /usr/local/Imatest/v24.2/IT/libs/library/python

macOS

cd /Applications/Imatest/IT/v24.2/libs/library/python

Inside this directory is the IT python package, named imatest_it-24.2.0-py2.py3-none-any.whl for Imatest IT 24.2.0.

Next, run the following command to install the Imatest IT Python module:

Windows (assuming you are running Python 3.9 installed in C:\Program Files\Python39)

C:\Program Files\Python39\python.exe -m pip install --find-links . imatest-it

or supply the *.whl file name to pip, for example

C:\Program Files\Python39\python.exe -m pip install imatest_it-24.2.0-py2.py3-none-any.whl

Linux

sudo python3 -m pip install --find-links . imatest-it

or supply the *.whl file name to pip, for example

sudo python3 -m pip install imatest_it-24.2.0-py2.py3-none-any.whl

macOS

sudo -H python3 -m pip install --find-links . imatest-it

or supply the *.whl file name to pip, for example

sudo -H python3 -m pip install imatest_it-24.2.0-py2.py3-none-any.whl

You will now be able to reference Imatest IT in your Python scripts using the import statement.

There are no more additional installation steps required to use the Imatest IT .NET libraries.

There are no more additional installation steps required to use the Imatest IT .NET libraries.

To simplify calling the Imatest IT EXE programs from the command line or a script file, the Imatest IT bin directory should be part of your PATH environment variable.

Windows In Windows, this is done automatically during installation, but if you are getting errors like “sfr.exe is not recognized as an internal or external command, operable program or batch file” when trying to run the EXE programs, you may need to manually add the bin directory to your PATH environment variable.

Follow these instructions and add C:\Program Files\Imatest\v24.2\IT\bin to the system PATH variable. You will need to open a new command window for the change to take effect.

To simplify calling the Imatest IT EXE programs from the command line or a script file, the Imatest IT bin directory should be part of your PATH environment variable.

Linux On Linux systems, you will need to manually add $PATH:/usr/local/Imatest/v24.2/IT/bin to the PATH variable. See these instructions .

macOS On macOS systems, you will need to manually add $PATH:/Applications/Imatest/IT/v24.2/bin to the PATH variable. See these instructions .

Step 1: Prepare Test Environment and Capture Test Targets

Imatest’s analysis modules require correctly framed and properly lit images of test targets to produce accurate results. For information on setting up your image testing environment, see this article.

Imatest offers a wide range of test charts to improve the accuracy of your image analysis.

Step 2: Configure INI File with Test Image(s)

In addition to the test image, the other important input for Imatest IT module functions is the INI configuration file, which contains settings that describe the input image (such as the ROI [region of interest]), analysis details, and output file locations. Before using Imatest IT in your application, you will need to configure one or more INI files for your specific testing needs.

Creating an INI File with Imatest Master

Imatest IT-specific INI File Settings

To configure Imatest IT-specific settings, choose Settings, then IT & Pass/Fail Settings… from the main window menu bar. For a detailed explanation of the IT-specific settings found in this window, see this article. After you have made your changes, click OK.

Image Analysis INI File Settings

Once you have an image file of your test target that matches the framing and dimensions of the tests you will run using Imatest IT, analyze it using Imatest Master with the module you require. Be sure the image has the same pixel count as the images to be used in your production environment.

Repeat the tests with different settings until you have the results you require.

Exporting the INI File

Once you have configured the IT settings to meet your requirements– including the Region of Interest (ROI), calculation details, output file and folder locations– you can go back to the main Imatest window, and choose INI File Settings then Save Settings… from the menu bar. Choose a location for the INI file and give it a useful name. This file name will be the second input parameter when calling Imatest IT module functions.

In Imatest you can use the  Save ini file for  button in the Imatest IT settings window to save an ini file with only the needed sections.

You can create a file to control up to four modules by selecting the module in each of the boxes on the left, then pressing Save ini file for. The ini section(s) for the module ([sfr] and [sfrreg] in the above example) is included, along with [imatest], [api], [dcraw], [rdraw], and [sqf] and [visnoise], where appropriate.

Step 3: Integrate and Call Imatest IT Modules

Now that your test images and INI files have been prepared, you can integrate your application and analyze the images using Imatest IT’s module functions.

Select your preferred interface below to see detailed instructions.

Interface Type:

Windows (Visual Studio) Project Setup

First, you need to configure your project to be able to find the Imatest IT and b Runtime libraries. To do this, right click on the project and choose Properties. Add the following include directories in the sections under Configuration Properties:

Category Property Value
C/C++ / General Additional Include Directories C:\Program Files\MATLAB\MATLAB Runtime\R2024a\extern\include C:\Program Files\Imatest\v24.2\IT\libs\library\c
Linker / General Additional Include Directories C:\Program Files\MATLAB\MATLAB Runtime\R2024a\extern\lib\win64\microsoft C:\Program Files\Imatest\v24.2\IT\libs\library\c
Linker / Input Additional Dependencies mclmcrrt.lib imatest_library.lib

Note: Imatest only supports 64-bit architectures. You must use the x64 platform configuration when using Imatest IT in your projects. You may need to manually add this platform configuration to your project first. For information on how to do this, see this article.

macOS

Note: For macOS the Imatest IT C library must be used from an Objective-C wrapper. Please see the Objective-C documentation for details.

Initializing the Imatest IT Library

Now that your project references are set up, the next step is to include the imatest_library.h header file. Add this line to the top of your source file:

#include "imatest_library.h"

Next, initialize the MATLAB Runtime application state by calling mclInitializeApplication(const char **options, int count). Most users can ignore the options and count parameters; just pass in NULL and 0, respectively. The function will return 0 if successful, allowing you to trap errors and handle them gracefully. This should only be called once during the life of your application.

#include "imatest_library.h"

int main()
{
    if (!mclInitializeApplication(NULL,0))
    {
        printf("Error: could not initialize application properly.\n");
        return -1001;
    }

    /// ...
}

The last initialization step is to call imatest_libraryInitialize(). This will prepare the Imatest IT library for use. The function also returns 0 if it is successful.

#include "imatest_library.h"

int main()
{
    if (!mclInitializeApplication(NULL,0))
    {
        printf("Error: could not initialize the MATLAB Runtime properly.\n");
        return -1001;
    }

    if(!imatest_libraryInitialize())
    {
        printf("Error: could not initialize the Imatest IT library properly.\n");
        return -1002;
    }

    /// ...
}

Calling the Imatest IT C Library Interface

Now that the MATLAB Runtime and Imatest IT library are all ready to go, the next step is the prepare the arguments that will be passed into the IT module functions. Each of the IT modules has the same method signature (with the exception of OIS). In this example, we will use the sfr function. The signature for the SFR module function looks like this:

bool mlfSfr_shell(int nargout, mxArray** nret, mxArray* inputFile, mxArray* rootDir, mxArray* inputKeys, mxArray* opMode, mxArray* varargin);

The Imatest IT C library encapsulates all input and output arguments inside mxArray types. This is a generic pointer type that can represent any data type. See below for more information on using mxArrays.

The Imatest IT C library parameters are listed here:

Parameter Name Data Type Description
nargout int The number of expected output arguments. This will always be 1 for the JSON result string.
&nret mxArray** [const char*] The output object, which will be a string wrapped in an mxArray.
inputFile mxArray* [const char*] Image file path. A full path name may be used (and is recommended), such as “C:\Program Files\Imatest\v24.2\IT\samples\images\sfr_example.jpg”. If a relative path name is used, the path is relative to your calling program, not the value of the rootDir parameter. Multiple files can be analyzed by using a wildcard (*) symbol in the path. For example, if the inputFile parameter is “C:\Imatest\iPhone6_*.jpg”, all .jpg files in the folder C:\Imatest with filenames beginning with “iPhone6_” will be analyzed.
rootDir mxArray* [const char*] Directory containing your INI file. If you do not pass a file path in as the first item in the varargin parameter, then Imatest IT will use a file named imatest-v2.ini found in this directory as your INI configuration.
inputKeys mxArray* [const char*] This value should always be the string “JSON”. XML output has been deprecated.
opMode mxArray* [const char*] String containing one of the following operation codes, which tells Imatest IT how to analyze your image(s), and how to read the values contained in the varargin parameter. If you are supplying your own full path to an INI file, and it is the first item in the varargin collection, then use one of these values: -7, -8, -10, or -17. If your INI file is named imatest-v2.ini and resides in the directory passed in as rootDir, then use one of these values: -5, -6, -9, and -15. The different opCode values direct how Imatest IT will behave. For more information on the different op modes supported by Imatest IT, see this article.
varargin mxArray* [multiple const char*] This is a catch all array structure for other parameters required by the various opModes. The contents of this array depend on which op mode you are using, and on how many images you will be processing. For information on how to populate this array, see here.

Working with mxArrays

The Imatest IT C library receives and returns data via mxArray pointers. The MATLAB Runtime provides helper methods for allocating, interacting with, and deallocating mxArray structures.

Most of the Imatest IT C library input parameters (with the exception of varargin and raw image data passed in when using direct read mode) are strings (const char*) wrapped as mxArrays. You can create these mxArray pointers by using the mxCreateString(const char *str) function.

Before your program terminates, you must deallocate all of your mxArray pointers using the mxDestroyArray(mxArray *pm) function, and then set the pointers to NULL.

Here is an example of the typical lifecycle of an mxArray string parameter:

// Declare the pointer variable
mxArray *inputFile = NULL;

// Initialize the mxArray with a string
inputFile = mxCreateString("C:\\Program Files\\Imatest\\v24.2\\IT\\samples\\images\\sfr_example.jpg");

// Make calls to Imatest IT library

// ...

// Destroy the mxArray
mxDestroyArray(inputFile);
inputFile = NULL;

The varargin parameter is a Matlab Cell Array containing zero or more additional input parameters, depending on the op mode. To initialize this parameter, use the mxCreateCellMatrix(int rows, int columns) function. You should create the varargin cell array with the exact number of cells required for your op mode. The rows parameter should always be 1, and the columns parameter should be the number of parameters you will be supplying.

You can then set the individual cells using mxSetCell(mxArray *array, int index, mxArray *value), where array is the varargin pointer, index is a zero-based index, and value is an mxArray pointer to the value being added to the array.

The varargin parameter is deallocated in the same way as other mxArrays, and you should not deallocate the individual cells of the array.

mxArray *varargin = NULL, *iniFile = NULL, *inputFile2 = NULL;

iniFile = mxCreateString("C:\\Program Files\\Imatest\\v24.2\\IT\\samples\\cpp\\Imatest_INI\\imatest-v2.ini");
inputFile2 = mxCreateString("C:\\Program Files\\Imatest\\v24.2\\IT\\samples\\images\\sfr_example.jpg");

varargin = mxCreateCellMatrix(1, 2);

mxSetCell(varargin, 0, iniFile);
mxSetCell(varargin, 1, inputFile2);   

// ...

mxDestroyArray(varargin);

Calling Imatest IT Modules

Now that the library is initialized, and all of the input parameters are set up, it is time to call the Imatest IT analysis function. This example uses the SFR module, but the same code can be used to call the rest of the Imatest modules (with the exception of OIS, which has different inputs).

The first parameter will always be 1, and the second is a reference to an mxArray* pointer that will contain the JSON output of the analysis. If the function returns false, it means an error has occurred. Check the stdout and stderr streams for details on what went wrong, and see the section Error Handling below for information on handling errors gracefully.

When the call is successful, the JSON output will reside inside the outputJSON pointer. You can extract the string using the mxArrayToString(const mxArray *array_ptr) function.

if (!mlfSfr_shell(1, &outputJSON, inputFile, rootDir, inputKeys, opMode, varargin))
{
    printf("*** Error calling SFR.  Check output messages for details. ***\n");
}
else
{
    jsonOutput = mxArrayToString(outputJSON);
    printf(jsonOutput);
}

When you are finished making calls to the Imatest IT C library, you then need to make three more function calls to terminate the library and the MATLAB Runtime.

mlfIt_terminate();
imatest_libraryTerminate();
mclTerminateApplication();

Windows (Visual Studio) Project Setup

First, you need to configure your project to be able to find the Imatest IT and MATLAB Runtime libraries. To do this, right click on the project and choose Properties. Add the following include directories in the sections under Configuration Properties:

Category Property Value
C/C++ / General Additional Include Directories C:\Program Files\MATLAB\MATLAB Runtime\R2024a\extern\include C:\Program Files\Imatest\v24.2\IT\libs\library\cpp
Linker / General Additional Include Directories C:\Program Files\MATLAB\MATLAB Runtime\R2024a\extern\lib\win64\microsoft C:\Program Files\Imatest\v24.2\IT\libs\library\cpp
Linker / Input Additional Dependencies mclmcrrt.lib imatest_library.lib

Note: Imatest only supports 64-bit architectures. You must use the x64 platform configuration when using Imatest IT in your projects. You may need to manually add this platform configuration to your project first. For information on how to do this, see this article.

macOS

Note: For macOS the Imatest IT C++ library must be used from an Objective-C wrapper. Please see the Objective-C documentation for details.

Initializing the Imatest IT Library

Now that your project references are set up, the next step is to include the imatest_library.h header file. Add this line to the top of your source file:

#include "imatest_library.h"

Next, initialize the MATLAB Runtime application state by calling mclInitializeApplication(const char **options, int count). Most users can ignore the options and count parameters; just pass in NULL and 0, respectively. The function will return 0 if successful, allowing you to trap errors and handle them gracefully.

#include "imatest_library.h"

int main()
{
    if (!mclInitializeApplication(NULL,0))
    {
        std::cerr << "Error: could not initialize the MATLAB Runtime properly." << std::endl;
        return -1001;
    }

    /// ...
}

The last initialization step is to call imatest_libraryInitialize(). This will prepare the Imatest IT library for use. The function also returns 0 if it is successful.

#include "imatest_library.h'

int main()
{
    if (!mclInitializeApplication(NULL,0))
    {
        std::cerr << "Error: could not initialize the MATLAB Runtime properly." << std::endl;
        return -1001;
    }

    if(!imatest_libraryInitialize())
    {
        std::cerr << "Error: could not initialize the Imatest IT library properly." << std::endl;
        return -1002;
    }

    /// ...
}

Calling the Imatest IT C++ Library Interface

Now that the MATLAB Runtime and Imatest IT library are all ready to go, the next step is the prepare the arguments that will be passed into the IT module functions. Each of the IT modules has the same method signature (with the exception of OIS). In this example, we will use the sfr function. The signature for the SFR module function looks like this:

void sfr_shell(int nargout, mwArray& nret, const mwArray& inputFile, const mwArray& rootDir, const mwArray& inputKeys, const mwArray& opMode, const mwArray& varargin);

The Imatest IT C++ library encapsulates all input and output arguments inside mwArray objects. This is a generic wrapper class that can represent any data type. See below for more information on using mwArrays.

The Imatest IT C++ library parameters are listed here:

Parameter Name Data Type Description
nargout int The number of expected output arguments. This will always be 1 for the JSON result string.
nret mwArray& [const char*] The output object, which will be a string wrapped in an mwArray object.
inputFile mwArray& [const char*] Image file path. A full path name may be used (and is recommended), such as “C:\Program Files\Imatest\v24.2\IT\samples\images\sfr_example.jpg”. If a relative path name is used, the path is relative to your calling program, not the value of the rootDir parameter. Multiple files can be analyzed by using a wildcard (*) symbol in the path. For example, if the inputFile parameter is “C:\Imatest\iPhone6_*.jpg”, all .jpg files in the folder C:\Imatest with filenames beginning with “iPhone6_” will be analyzed.
rootDir mwArray& [const char*] Directory containing your INI file. If you do not pass a file path in as the first item in the varargin parameter, then Imatest IT will use a file named imatest-v2.ini found in this directory as your INI configuration.
inputKeys mwArray& [const char*] This value should always be the string “JSON”. XML output has been deprecated.
opMode mwArray& [const char*] String containing one of the following operation codes, which tells Imatest IT how to analyze your image(s), and how to read the values contained in the varargin parameter. If you are supplying your own full path to an INI file, and it is the first item in the varargin collection, then use one of these values: -7, -8, -10, or -17. If your INI file is named imatest-v2.ini and resides in the directory passed in as rootDir, then use one of these values: -5, -6, -9, and -15. The different opCode values direct how Imatest IT will behave. For more information on the different op modes supported by Imatest IT, see this article.
varargin mwArray& [multiple const char*] This is a catch all array structure for other parameters required by the various op modes. The contents of this array depend on which op mode you are using, and on how many images you will be processing. For information on how to populate this array, see here.

Working with mwArrays

The Imatest IT C++ library receives and returns data via mwArray objects. Unlike the C library, the C++ library’s mwArray class is object-oriented, and also takes care of allocating and deallocating automatically. There is no need to manually destroy the mwArray objects.

Most of the Imatest IT C++ library input parameters (with the exception of varargin and raw image data passed in when using direct read mode) are strings (const char) wrapped as mwArray objects. You can create these mwArray pointers by passing a const char into the constructor.

mwArray opMode("-5");

The varargin parameter is a Matlab Cell Array containing zero or more additional input parameters, depending on the opMode. To initialize this parameter, use the mwArray(int num_rows, int num_cols, mxClassID mxID) constructor, passing 1 for num_rows, the number of extra arguments required as num_cols, and the constant mxCELL_CLASS as mxID. The num_cols value should be the exact number of cells required for your op mode. See this article for more information on populating the varargin parameter.

You can then set the individual cells using the mwArray object’s Get(int row, int column) and Set(const mwArray& arr) methods. Note that the row and column parameters are 1-based indexes.

/// Set the first cell of varargin to be the iniFilePath
varargin.Get(1,1).Set(iniFilePath);

Calling Imatest IT Modules

Now that the library is initialized, and all of the input parameters are set up, it is time to call the Imatest IT analysis function. This example uses the SFR module, but the same code can be used to call the rest of the Imatest modules (with the exception of OIS, which has different inputs).

The first parameter will always be 1, and the second is a reference to an uninitialized mwArray variable that will contain the JSON output of the analysis. If the function throw an exception, it means an error has occurred. Check the exception messages and stdout and stderr streams for details on what went wrong. See the section on Error Handling below for more information on catching and handling exceptions gracefully.

When the call is successful, the JSON output will reside inside the outputJSON pointer. You can extract the string by calling the mwArray.ToString() method, then converting that result to a const char*. Note that you must declare the mwString variable separately for this to work.

sfr_shell(1, outputJSON, inputFile, rootDir, inputKeys, opMode, varargin)
mwString mwStr = outputJSON.ToString();
const char* strOutputJSON = (const char*)mwStr;

std::cout << strOutputJSON << std::endl;

When you are finished making calls to the Imatest IT C++ library, you then need to make three more function calls to terminate the library and the Matlab Runtime.

it_terminate();
imatest_libraryTerminate();
mclTerminateApplication();

XCode Project Setup

First, you need to configure your project to be able to find the Imatest IT and MATLAB Runtime libraries. To do this, in the project editor, go to Build Settings and add the follow paths and linker flags:

Category Property Value
Search Paths Header Search Paths /Applications/Imatest/IT/v24.2/libs/library/cpp /Applications/MATLAB/MATLAB_Runtime/R2024a/extern/include
Search Paths Library Search Paths /Applications/Imatest/IT/v24.2/libs/library/cpp /Applications/MATLAB/MATLAB_Runtime/R2024a/runtime/maci64
Linking Other Linker Flags -lmwmclmcrrt -lImatest

Note: Imatest only supports the x86_64 architecture.

Next, in the General pane,

  1. Go to the Linked Frameworks and Libraries section
  2. Click the + button
  3. Click the Add Other… button
  4. Navigate to /Applications/Imatest/IT/v24.2/libs/library/cpp
  5. select libImatest.dylib and click Open.
  6. Add Cocoa.Framework in a similar fashion if it has not been added.

Adding Symbolic Breakpoints to XCode projects

When the MATLAB Runtime initializes it emits SIGSEGV and SIGBUS. The MATLAB Runtime will properly handle this issue on its own if left to do so. The easiest way deal with this in XCode is to set symbolic break points and add commands that instruct the debugger to ignore these signals. Without these commands, the debugger will break on those signals when the MATLAB Runtime initializes and runs.

  1. Go to Debug:Break Points:Create Symbolic Breakpoint.
  2. In the Symbol field, type NSApplicationMain
  3. Set the Action dropdown to ‘Debugger Command’
  4. In the command field enter process handle –pass true –stop false –notify true SIGSEGV
  5. Check ‘Automatically continue after evaluating’
  6. Repeat steps 1-5 adding another symbolic with the following command process handle –pass true –stop false –notify true SIGBUS

Initializing the Imatest IT Library

Now that your project references are set up, the next step is to include the libImatest.h header file. Add these lines after your other includes and imports:

#define HRESULT HRESULT_MATLAB
#include "libImatest.h"
#include "mclmcrrt.h"
#include "mclcppclass.h"
#undef HRESULT

Note that mclmcrrt.h defines HRESULT, which is also defined by Cocoa headers, so we use the preprocessor to redefine HRESULT in mclmcrrt.h and dependent header files to resolve the conflict.

Next, initialize the MATLAB Runtime application state by calling mclInitializeApplication(const char **options, int count). Most users can ignore the options and count parameters; just pass in NULL and 0, respectively. The function will return 0 if successful, allowing you to trap errors and handle them gracefully. This should only be called once during the life of your application. The last initialization step is to call libImatestInitialize(). This will prepare the Imatest IT library for use. The function also returns 0 if it is successful. Since in Cocoa all non-GUI methods cannot run on the main thread, detach a thread to run the method. The methods below are added to the AppDelegate class for the UI.

- (void) applicationWillFinishLaunching:(NSNotification *)aNotification
{
    NSLog(@"Processing applicationWillFinishLaunching event");
    [NSThread detachNewThreadSelector:@selector(initApp:) toTarget:self withObject:nil];
}

- (void)initApp:(id)param
{
    @autoreleasepool {
        NSLog(@"Executing initialization thread...");
        mclmcrInitialize();

        if (!mclInitializeApplication(NULL,0))
        {
            NSString *stringError =
            [NSString stringWithCString:mclGetLastErrorMessage()
                               encoding:NSMacOSRomanStringEncoding];
            NSLog(@"Initializing the MATLAB Runtime failed");
            NSLog(@"%@", stringError);
            return;
        }
 
        NSLog(@"Initializing Imatest IT library");
        if (!libImatestInitialize()
        {
            NSString *stringError =
            [NSString stringWithCString:mclGetLastErrorMessage()
                               encoding:NSMacOSRomanStringEncoding];
            NSLog(@"Initializing the IT library failed");
            libImatestPrintStackTrace();
            NSLog(@"%@", stringError);
            return;
        }
        NSLog(@"Initialized");


    }
}

Calling the Imatest IT C++ Library Interface

Now that the MATLAB Runtime and Imatest IT library are all ready to go, the next step is the prepare the arguments that will be passed into the IT module functions. Each of the IT modules has the same method signature (with the exception of OIS). In this example, we will use the sfrplus function. The signature for the SFR module function looks like this:

void sfrplus_shell(int nargout, mwArray& nret, const mwArray& inputFile, const mwArray& rootDir, const mwArray& inputKeys, const mwArray& opMode, const mwArray& varargin);

The Imatest IT C++ library encapsulates all input and output arguments inside mwArray objects. This is a generic wrapper class that can represent any data type. See below for more information on using mwArrays.

The Imatest IT C++ library parameters are listed here:

Parameter Name Data Type Description
nargout int The number of expected output arguments. This will always be 1 for the JSON result string.
nret mwArray& [const char*] The output object, which will be a string wrapped in an mwArray object.
inputFile mwArray& [const char*] Image file path. A full path name may be used (and is recommended), such as “C:\Program Files\Imatest\v24.2\IT\samples\images\sfr_example.jpg”. If a relative path name is used, the path is relative to your calling program, not the value of the rootDir parameter. Multiple files can be analyzed by using a wildcard (*) symbol in the path. For example, if the inputFile parameter is “C:\Imatest\iPhone6_*.jpg”, all .jpg files in the folder C:\Imatest with filenames beginning with “iPhone6_” will be analyzed.
rootDir mwArray& [const char*] Directory containing your INI file. If you do not pass a file path in as the first item in the varargin parameter, then Imatest IT will use a file named imatest-v2.ini found in this directory as your INI configuration.
inputKeys mwArray& [const char*] This value should always be the string “JSON”. XML output has been deprecated.
opMode mwArray& [const char*] String containing one of the following operation codes, which tells Imatest IT how to analyze your image(s), and how to read the values contained in the varargin parameter. If you are supplying your own full path to an INI file, and it is the first item in the varargin collection, then use one of these values: -7, -8, -10, or -17. If your INI file is named imatest-v2.ini and resides in the directory passed in as rootDir, then use one of these values: -5, -6, -9, and -15. The different opCode values direct how Imatest IT will behave. For more information on the different op modes supported by Imatest IT, see this article.
varargin mwArray& [multiple const char*] This is a catch all array structure for other parameters required by the various op modes. The contents of this array depend on which op mode you are using, and on how many images you will be processing. For information on how to populate this array, see here.

Working with mwArrays

The Imatest IT C++ library receives and returns data via mwArray objects. Unlike the C library, the C++ library’s mwArray class is object-oriented, and also takes care of allocating and deallocating automatically. There is no need to manually destroy the mwArray objects.

Most of the Imatest IT C++ library input parameters (with the exception of varargin and raw image data passed in when using direct read mode) are strings (const char) wrapped as mwArray objects. You can create these mwArray pointers by passing a const char into the constructor.

mwArray opMode("-5");

The varargin parameter is a Matlab Cell Array containing zero or more additional input parameters, depending on the opMode. To initialize this parameter, use the mwArray(int num_rows, int num_cols, mxClassID mxID) constructor, passing 1 for num_rows, the number of extra arguments required as num_cols, and the constant mxCELL_CLASS as mxID. The num_cols value should be the exact number of cells required for your op mode. See this article for more information on populating the varargin parameter.

You can then set the individual cells using the mwArray object’s Get(int row, int column) and Set(const mwArray& arr) methods. Note that the row and column parameters are 1-based indexes.

/// Set the first cell of varargin to be the iniFilePath
varargin.Get(1,1).Set(iniFilePath);

Calling Imatest IT Modules

Now that the library is initialized, and all of the input parameters are set up, it is time to call the Imatest IT analysis function. This example uses the SFR module, but the same code can be used to call the rest of the Imatest modules (with the exception of OIS, which has different inputs).

The first parameter will always be 1, and the second is a reference to an uninitialized mwArray variable that will contain the JSON output of the analysis. If the function throw an exception, it means an error has occurred. Check the exception messages and stdout and stderr streams for details on what went wrong. See the section on Error Handling below for more information on catching and handling exceptions gracefully.

When the call is successful, the JSON output will reside inside the outputJSON mwArray.

- (void)postTest: (id)param
{
    @autoreleasepool {
        try{
            
            // Declare and initialize outputJSON, fileParam, pathParam, keysParam, modeParam, and varargin mwArray's

            NSLog(@"Running test.");
            sfrplus_shell(1, outputJSON, fileParam, pathParam, keysParam, modeParam, varargin);
            
            // Process JSON returned in outputJSON mwArray 
   
            
        } catch (mwException ex){
            NSLog(@"Error");
            
            NSLog(@"%s", ex.what());
            ex.print_stack_trace();
        }
    }
}

- (void)runTest
{
     // Start a new thread to run sfrplus_shell()
     [NSThread detachNewThreadSelector:@selector(postTest:) toTarget:self withObject:nil];
}

The JSON string returned in outputJSON has UTF-16 encoding. This can be converted to a NSString with the following

auto numel = outputJSON.NumberOfElements();
std::u16string buffer(numel+1, 0);
outputJSON.GetCharData(&abuffer[0], numel);
char* data = (char*)buffer.data();
unsigned long size = buffer.size()*sizeof(char16_t);
NSString* jsonString =[[NSString alloc] initWithBytes:data length:size encoding:NSUTF16LittleEndianStringEncoding];

When you are finished making calls to the Imatest IT C++ library, you then need to make three more function calls (it_terminate(), libImatestTerminate(), and mclTerminateApplication) to terminate the library and the Matlab Runtime.

- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
{
    [NSThread detachNewThreadSelector:@selector(terminateApp:) toTarget:self withObject:sender];
    return NSTerminateLater;
}
-(void)terminateApp:(NSApplication *)theApplication
{
    NSLog(@"Executing termination thread");

    it_terminate();

    libImatestTerminate();

    mclTerminateApplication();
    [theApplication replyToApplicationShouldTerminate: YES];
}

Note: Imatest only supports 64-bit architectures. You must use the 64-bit version of Python when using Imatest IT.

Calling the Imatest IT Python Interface

At the top of your script file, include this line to import the ImatestLibrary class from the imatest.it module:

from imatest.it import ImatestLibrary

Next, create an instance of the ImatestLibrary class. Behind the scenes, the ImatestLibrary constructor will start up the Matlab MCR Runtime and load all the IT libraries into memory. This will take a few seconds the first time you run it, but should be faster on subsequent runs, especially if you have set your system’s environment variables to the recommended values as described above.

from imatest.it import ImatestLibrary

imatestLib = ImatestLibrary()
[/python]
Now that the Matlab MCR and Imatest IT library are all ready to go, the next step is the prepare the arguments that will be passed into the IT module functions. Each of the IT modules has the same method signature (with the exception of OIS). In this example, we will use the <b>sfr</b> function. The signature for the SFR module function looks like this:
[python][/python]
sfr(input_file=None, root_dir=None, op_mode=None, ini_file=None, raw_data=None, json_args=None)

The Imatest IT Python library parameters are listed here:

Parameter Name Data Type Description
input_file string or list Image file path. A full path name may be used (and is recommended), such as “C:\Program Files\Imatest\v24.2\IT\samples\images\sfr_example.jpg”. If a relative path name is used, the path is relative to your calling program, not the value of the root_dir parameter. Multiple files can be analyzed by passing in a list of file names, or by using a wildcard (*) symbol in the path. For example, if the input_file parameter is “C:\Imatest\iPhone6_*.jpg”, all .jpg files in the folder C:\Imatest with filenames beginning with “iPhone6_” will be analyzed.
root_dir string Directory containing your INI file. If you do not pass a file path in as the ini_file parameter, then Imatest IT will use a file named imatest-v2.ini found in this directory as your INI configuration.
op_mode string String containing one of the following operation codes, which tells Imatest IT how to analyze your image(s), or if you are using Direct Read mode. Valid values for the op_mode parameter are found in constants of the ImatestLibrary class: ImatestLibrary.OP_MODE_SEPARATE, ImatestLibrary.OP_MODE_SIGNAL_AVERAGE, ImatestLibrary.OP_MODE_TEMPORAL, and ImatestLibrary.OP_MODE_DIRECT_READ. For more information on the different op modes supported by Imatest IT, see this article.
ini_file string (optional) If you want to use an INI file that is not named imatest-v2.ini, you will need to supply the path to the file as the ini_file parameter.
raw_data string (optional) The raw image data. Only used when using OP_MODE_DIRECT_READ. For more information on direct read mode, see this article.
json_args string (optional) A JSON string containing metadata about how to interpret the image in the raw_data parameter. Only used when using OP_MODE_DIRECT_READ. For more information on direct read mode, see this article.

Calling Imatest IT Modules

Now that the library is initialized, and all of the input parameters are set up, it is time to call the Imatest IT analysis function. This example uses the SFR module, but the same code can be used to call the rest of the Imatest modules (with the exception of OIS, which has different inputs).

It’s easiest to call the sfr using named parameters, as shown below. An exception will be thrown if something goes wrong – you should catch it and handle it gracefully. Check the exception message and stdout and stderr streams for details on what went wrong, and see the Error Handling section below for more information on gracefully handling exceptions.

When the call is successful, the function will return a string containing JSON-encoded output.

from imatest.it import ImatestLibrary
import json

imatestLib = ImatestLibrary()

result = imatestLib.sfr(input_file=input_file,
                        root_dir=root_dir,
                        op_mode=ImatestLibrary.OP_MODE_SEPARATE,
                        ini_file=ini_file)
print(result)

When you are finished making calls to the Imatest IT Python library, you then need to call terminate_library() to unload the library and the Matlab Runtime.

imatestLib.terminate_library();

Running the Imatest IT Python library on macOS

Note: Due to a limitation in how the IT Python library is constructed, you must call any python code via the mwpython.sh script provided by Mathworks at /Applications/MATLAB/MATLAB_Runtime/R2024a/bin. It is recommended that you set the PYTHON_HOME environment variable if you wish to use a particular python interpreter. Also, the only supported means to call mwpython is to call a script directly (not a module using the -m flag in python). For example

export PATH=/Applications/MATLAB/MATLAB_Runtime/R2024a/bin:$PATH
export PYTHON_HOME=/Library/Frameworks/Python.framework/Versions/3.7
mwpython some_script.py

Windows (Visual Studio) Project Setup

To use the Imatest IT .NET libraries in your Visual Studio project, first you need to add a reference to the library DLL in your project.

Once your project is created in Visual Studio, right click on the References section of the Solution Explorer and choose Add Reference….

In the Reference Manager window, choose Browse on the left-hand side, then click the Browse… button at the bottom.

IT_NET_Reference_Window

Navigate to the .NET library directory of your Imatest IT installation (by default, C:\Program Files\Imatest\v24.2\IT\libs\library.NET), choose Imatest.IT.dll, and click the Add button.

Note: You do not need to add the IT.dll reference to your project.

IT_NET_DLL_Selected

Click OK to close the Reference Manager window.

Note: Imatest only supports 64-bit architectures. You must use the x64 platform when running .NET applications. The Any CPU platform will throw runtime errors.

Calling the Imatest IT .NET Interface

At the top of your source code file, add a using statement for Imatest.IT:

using Imatest.IT;

Next, create an instance of the Imatest.IT.Library class. Behind the scenes, the Imatest.IT.Library constructor will start up the Matlab MCR Runtime and load all the IT libraries into memory. This will take a few seconds the first time you run it, but should be faster on subsequent runs, especially if you have set your system’s environment variables to the recommended values as described above.

Imatest.IT.Library implements the IDisposable interface, and we recommend that you wrap your library instance inside of a using statement to ensure that the Dispose() method is called properly. The Dispose() method cleans up the Matlab Runtime, and also releases your floating license seat, if you are using a floating license.

using Imatest.IT;

class Program
{
    static void Main(string[] args)
    {
        using (Library itLib = new Library())
        {
            // ....
        }
    }
}

Now that the Matlab MCR and Imatest IT library are all ready to go, the next step is the prepare the arguments that will be passed into the IT module functions. Each of the IT modules has the same overloaded method signatures (with the exception of OIS). In this example, we will use the SFR.JSON methods. The signatures for the SFR module function looks like this:

string SFR.JSON(string rootDir, string inputFile, OperationMode opMode)
string SFR.JSON(string rootDir, IEnumerable<string> inputFiles, OperationMode opMode)
string SFR.JSON(string rootDir, string inputFile, OperationMode opMode, string iniFilePath)
string SFR.JSON(string rootDir, IEnumerable<string> inputFiles, OperationMode opMode, string iniFilePath)
string SFR.JSON(string rootDir, byte[] inputBytes, DirectReadOptions directReadOptions)
string SFR.JSON(string rootDir, byte[] inputBytes, DirectReadOptions directReadOptions, string iniFilePath)

The Imatest IT .NET library parameters are listed here:

Parameter Name Data Type Description
rootDir string Directory containing your default INI file. If you do not pass a file path in as optional the iniFile parameter, then Imatest IT will use a file named imatest-v2.ini found in this directory as your INI configuration.
inputFile string Image file path. A full path name may be used (and is recommended), such as “C:\Program Files\Imatest\v24.2\IT\samples\images\sfr_example.jpg”. If a relative path name is used, the path is relative to your calling program, not the value of the rootDir parameter. Multiple files can be analyzed by using a wildcard (*) symbol in the path. For example, if the input_file parameter is “C:\Imatest\iPhone6_*.jpg”, all .jpg files in the folder C:\Imatest with filenames beginning with “iPhone6_” will be analyzed.
inputFiles IEnumerable<string> A list of image file paths. Full path names may be used (and are recommended), such as “C:\Program Files\Imatest\v24.2\IT\samples\images\sfr_example.jpg”. If relative path names are used, the path is relative to your calling program, not the value of the rootDir parameter.
opMode OperationMode Enum value for one of the available operation modes, which tells Imatest IT how to analyze your image(s). Valid values for the opMode parameter are: OperationMode.Separate, OperationMode.SignalAverage, and OperationMode.Temporal. For more information on the different op modes supported by Imatest IT, see this article.
iniFile string (optional) If you want to use an INI file that is not named imatest-v2.ini, you will need to supply the path to the file as the iniFile parameter.
inputBytes byte[], ushort[], or uint[] (optional) The raw image data. Only used if you are passing in image data directly using Direct Read Mode. For more information on direct read mode, see this article.
directReadOptions DirectReadOptions (optional) A an object containing metadata about how to interpret the image in the inputBytes parameter. Only used when using Direct Read Mode. For more information on direct read mode, see this article.

Calling Imatest IT Modules

Now that the library is initialized, and all of the input parameters are set up, it is time to call the Imatest IT analysis function. This example uses the SFR module, but the same code can be used to call the rest of the Imatest modules (with the exception of OIS, which has different inputs).

We recommend always wrapping your Imatest IT calls in try/catch blocks. If anything goes wrong, an Exception will be thrown. You should handle these exceptions gracefully. Check the exception message for details on what went wrong, and see the section on Error Handling below for more information.

When the call is successful, the function will return a string containing JSON-encoded output.

using Imatest.IT;

class Program
{
    static void Main(string[] args)
    {
        using (Library itLib = new Library())
        {
            try {
                string result = itLib.SFR.JSON(rootDir, inputFile, OperationMode.Separate, iniFilePath);
            } catch (Exception ex) {
                Console.Out.WriteLine(ex.Message);
            }
        }
    }
}

Windows (Visual Studio) Project Setup

To use the Imatest IT .NET libraries in your Visual Studio project, first you need to add a reference to the library DLL in your project.

Once your project is created in Visual Studio, right click on the References section of the Solution Explorer and choose Add Reference….

In the Reference Manager window, choose Browse on the left-hand side, then click the Browse… button at the bottom.

IT_NET_Reference_Window

Navigate to the .NET library directory of your Imatest IT installation (by default, C:\Program Files\Imatest\v24.2\IT\libs\library.NET), choose Imatest.IT.dll, and click the Add button.

Note: You do not need to add the IT.dll reference to your project.

IT_NET_DLL_Selected

Click OK to close the Reference Manager window.

Note: Imatest only supports 64-bit architectures. You must use the x64 platform when running .NET applications. The Any CPU platform will throw runtime errors.

Calling the Imatest IT .NET Interface

At the top of your source code file, add an Imports statement for Imatest.IT:

Imports Imatest.IT

Next, create an instance of the Imatest.IT.Library class. Behind the scenes, the Imatest.IT.Library constructor will start up the Matlab MCR Runtime and load all the IT libraries into memory. This will take a few seconds the first time you run it, but should be faster on subsequent runs, especially if you have set your system’s environment variables to the recommended values as described above.

Imatest.IT.Library implements the IDisposable interface, and we recommend that you wrap your library instance inside of a Using statement to ensure that the Dispose() method is called properly. The Dispose() method cleans up the Matlab Runtime, and also releases your floating license seat, if you are using a floating license.

Imports Imatest.IT

Module Program
    Sub Main()
        Using itLib = New Library()
            ' ...
        End Using
    End Sub
End Module

Now that the Matlab MCR and Imatest IT library are all ready to go, the next step is the prepare the arguments that will be passed into the IT module functions. Each of the IT modules has the same overloaded method signatures (with the exception of OIS). In this example, we will use the SFR.JSON methods. The signatures for the SFR module function looks like this:

SFR.JSON(String rootDir, String inputFile, OperationMode opMode) As String
SFR.JSON(String rootDir, IEnumerable(Of String) inputFiles, OperationMode opMode) As String
SFR.JSON(String rootDir, String inputFile, OperationMode opMode, String iniFilePath) As String
SFR.JSON(String rootDir, IEnumerable(Of String) inputFiles, OperationMode opMode, String iniFilePath) As String
SFR.JSON(String rootDir, Byte() inputBytes, DirectReadOptions directReadOptions) As String
SFR.JSON(String rootDir, Byte() inputBytes, DirectReadOptions directReadOptions, String iniFilePath) As String

The Imatest IT .NET library parameters are listed here:

Parameter Name Data Type Description
rootDir String Directory containing your default INI file. If you do not pass a file path in as optional the iniFile parameter, then Imatest IT will use a file named imatest-v2.ini found in this directory as your INI configuration.
inputFile String Image file path. A full path name may be used (and is recommended), such as “C:\Program Files\Imatest\v24.2\IT\samples\images\sfr_example.jpg”. If a relative path name is used, the path is relative to your calling program, not the value of the rootDir parameter. Multiple files can be analyzed by using a wildcard (*) symbol in the path. For example, if the input_file parameter is “C:\Imatest\iPhone6_*.jpg”, all .jpg files in the folder C:\Imatest with filenames beginning with “iPhone6_” will be analyzed.
inputFiles IEnumerable(Of String) A list of image file paths. Full path names may be used (and are recommended), such as “C:\Program Files\Imatest\v24.2\IT\samples\images\sfr_example.jpg”. If relative path names are used, the path is relative to your calling program, not the value of the rootDir parameter.
opMode OperationMode Enum value for one of the following operation codes, which tells Imatest IT how to analyze your image(s). Valid values for the opMode parameter are: OperationMode.Separate, OperationMode.SignalAverage, and OperationMode.Temporal. For more information on the different op modes supported by Imatest IT, see this article.
iniFile String (optional) If you want to use an INI file that is not named imatest-v2.ini, you will need to supply the path to the file as the iniFile parameter.
inputBytes Byte(), UShort(), or UInteger() (optional) The raw image data. Only used if you are passing in image data directly using Direct Read Mode. For more information on direct read mode, see this article.
directReadOptions DirectReadOptions (optional) A an object containing metadata about how to interpret the image in the inputBytes parameter. Only used when using Direct Read Mode. For more information on direct read mode, see this article.

Calling Imatest IT Modules

Now that the library is initialized, and all of the input parameters are set up, it is time to call the Imatest IT analysis function. This example uses the SFR module, but the same code can be used to call the rest of the Imatest modules (with the exception of OIS, which has different inputs).

We recommend always wrapping your Imatest IT calls in try/catch blocks. If anything goes wrong, an Exception will be thrown. You should handle these exceptions gracefully. Check the exception message for details on what went wrong, and see the section on Error Handling below for more information.

When the call is successful, the function will return a string containing JSON-encoded output.

Imports Imatest.IT

Module Program
    Sub Main()
        Using itLib = New Library()
            Try
                Dim result = itLib.SFR.JSON(rootDir, imagePath, OperationMode.Separate, iniFilePath)
            Catch ex As Exception
                Console.Out.WriteLine(ex.Message)
            End Try
        End Using
    End Sub
End Module

Calling the Imatest IT EXE Interface

The Imatest IT EXE Library can be called using Windows or Linux script files. We recommend making sure that the IT bin directory is in your PATH variable. On Windows, this should already happen when Imatest IT is installed. You may need to add to your path manually on Linux. For more information on viewing and editing system environment variables, see this article.

All Imatest IT EXE executables accept the following arguments (except for OIS, which uses different inputs):

sfr.exe op-mode input-file bin-directory ini-file [result-directory] [other-images ...]

The Imatest IT EXE library parameters are listed here:

Parameter Name Description
op_mode One of the following operation codes, which tells Imatest IT how to analyze your image(s). Valid values for the op_mode parameter are: -1 (Separate Analysis), -11 (Signal Average Analysis), and -12 (Temporal Noise Analysis). For more information on the different op modes supported by Imatest IT, see this article.
input-file Image file path. A full path name may be used (and is recommended), such as “C:\Program Files\Imatest\v24.2\IT\samples\images\sfr_example.jpg”. If a relative path name is used, the path is relative to your calling program. Multiple files can be analyzed by using a wildcard (*) symbol in the path. For example, if the input_file parameter is “C:\Imatest\iPhone6_*.jpg”, all .jpg files in the folder C:\Imatest with filenames beginning with “iPhone6_” will be analyzed.
bin-directory The location of the Imatest IT bin directory. By default, this will be “C:\Program Files\Imatest\v24.2\IT\bin”.
ini-file The full path to the INI configuration file you will be using.
result-directory The directory where Imatest IT’s output files will be written to.
other-images The path(s) to other images that will be analyzed besides the initial input-file image.

Calling Imatest IT Modules

Imatest IT EXE modules are called using the command line, or in .bat files.

Note: You should not include a trailing ‘\’ when passing in directory names, otherwise you may get an error (see here).

sfr.exe "-1" "C:\ImatestSamples\sfr_example.jpg" "C:\Program Files\Imatest\v24.2\IT\bin" "C:\ImatestSamples\imatest-v2.ini" "C:\ImatestSamples\Results"

When the module is finished running, the result files will be written to the result-directory folder (in this case, C:\ImatestSamples\Results).

Calling the Imatest IT EXE Interface

The Imatest IT EXE Library can be called using macOS or Linux Bash script files. We recommend making sure that the IT bin directory is in your PATH variable.  You may need to add to your path manually on macOS and Linux. For more information on viewing and editing system environment variables, see this article.

All Imatest IT EXE executables accept the following arguments (except for OIS, which uses different inputs):

./run_sfr.sh op-mode input-file bin-directory ini-file [result-directory] [other-images ...]

The Imatest IT EXE library parameters are listed here:

Parameter Name Description
op_mode One of the following operation codes, which tells Imatest IT how to analyze your image(s). Valid values for the op_mode parameter are: -1 (Separate Analysis), -11 (Signal Average Analysis), and -12 (Temporal Noise Analysis). For more information on the different op modes supported by Imatest IT, see this article.
input-file Image file path. A full path name may be used (and is recommended), such as “/Applications/Imatest/IT/v24.2/samples/images/sfr_example.jpg”. If a relative path name is used, the path is relative to your calling program. Multiple files can be analyzed by using a wildcard (*) symbol in the path. For example, if the input_file parameter is “$HOME/Imatest/iPhone6_*.jpg”, all .jpg files in the folder $HOME/Imatest with filenames beginning with “iPhone6_” will be analyzed.
bin-directory The location of the Imatest IT bin directory. By default, this will be “/Applications/Imatest/IT/v24.2/bin” on macOS, and “/usr/local/Imatest/v24.2/IT/bin” on Linux.
ini-file The full path to the INI configuration file you will be using.
result-directory The directory where Imatest IT’s output files will be written to.
other-images The path(s) to other images that will be analyzed besides the initial input-file image.

Calling Imatest IT Modules

Imatest IT EXE modules are called using the command line with the .sh files.

Note: You should not include a trailing ‘\’ when passing in directory names, otherwise you may get an error (see here).

./run_sfr.sh "-1" "$HOME/ImatestSamples/sfr_example.jpg" "/Applications/Imatest/IT/v24.2/bin" "$HOME/ImatestSamples/imatest-v2.ini" "$HOME/ImatestSamples/Results"

When the module is finished running, the result files will be written to the result-directory folder (in this case, $HOME/ImatestSamples/Results).

Step 4: Process the Results

The Imatest IT module functions output their results as JSON, XML, and CSV formatted text files. The C, C++, Python, and .NET libraries also return results as a JSON formatted string to the calling program.

Using the JSON Result in Code

Imatest IT’s JSON result string, which is returned to the calling program, can be parsed and processed using third party JSON libraries. A list of JSON libraries for several languages can be found at json.org.

The result strings are packaged as nested property/value objects, and the first property is always [module]Results, as seen in this excerpt from an SFRplus call:

{
    "sfrplusResults": {
        "version": "Imatest 4.5.14  SFRplus",
        "title": "sfrplus_example.jpg",
        "number_of_regions": [5],
        "HeightPxls": [2592],
        "WidthPxls": [3888],
        "pixels_per_inch": [0],
        "pixels_per_mm": [0],
        "um_per_pixel": [0],
        "CPIQ": {
            "sfrComputerMonitor": {
                "acutance": [0.8444,0.8406,0.7965,0.8583,0.8579],
                "qualityLoss": [0.1755,0.2173,0.9715,0.06028,0.06267]
            },
            "sfrPhoneDisplay": {
                "acutance": [0.8785,0.8747,0.8268,0.8938,0.8935],
                "qualityLoss": [-0.005023,-0.00252,0.4007,0.00336,0.00336]
                    },
            "sfrUHDTVDisplay": {
                "acutance": [0.8287,0.8253,0.7708,0.8466,0.8463],
                "qualityLoss": [0.3724,0.4224,1.621,0.1535,0.1569]
            },
            "sfrSmallPrint": {
                "acutance": [0.6816,0.6807,0.6678,0.6852,0.6859],
                "qualityLoss": [4.755,4.791,5.328,4.606,4.577]
            },
            "sfrLargePrint": {
                "acutance": [0.8654,0.8671,0.8646,0.8658,0.8672],
                "qualityLoss": [0.02288,0.01626,0.02633,0.02126,0.01574]
            }
        },
        "mtfPeak": [1.023,1.007,1,1.045,1.036],
        "mtf50": [0.3389,0.3426,0.3089,0.3512,0.3523],
        "mtf50p": [0.3365,0.3419,0.3089,0.3461,0.3482],

        ...
    }
}

Note: If you analyze multiple files in a single call, only the last file’s results will be returned to the calling program. The others will be written to output files in the Results directory.

If you find that a result you need is missing from the returned JSON, please contact us and we can add it in the next minor release of Imatest IT.

Imatest IT Output Files

Imatest IT also writes its results to text files, which are formatted in XML, CSV, and JSON. By default, these files are written to a Results folder in the same folder as the images themselves. You can change the location by using Imatest Master to change your INI configuration settings, in the Auto mode settings for the modules you will be using:

 

Performance Tip: If you do not need some or all of the output files, you can disable them using the same Auto mode settings window. This will make your Imatest IT calls run a little faster. Just uncheck each of the outputs that you do not require.

Error Handling

Select your preferred interface below to see the best ways to handle errors using Imatest IT.

Interface Type:

In the Imatest C library, if an error occurs within one of the analysis module functions, a false result will be returned. You can then use the mlfGetExceptionID(int nargout, mxArray** errID, mxArray** errName) function to extract an Error ID and Error Name, which map into the Imatest IT Exception Hierarchy.

To make handling these exceptions easier, Imatest IT includes an optional header file, imatest_exception_IDs.h, which maps each of the Error IDs to an enum. To include this header file, add #include “imatest_exception_ids.h” to your source file. You can read more about the Exception Hierarchy here.

Here is an example of how you can catch and gracefully handle exceptions using the Imatest IT C Library:

int retVal;
mxArray *errorID = NULL, *errorName = NULL;
enum ImatestExceptionIDs errorCode;
const char* errorNameStr;

...

if (!mlfSfr_shell(nargout, &outputJSON, inputFile, rootDir, inputKeys, opMode, varargin))
{
    if (mlfGetExceptionID(2, &errorID, &errorName))
    {
        errorCode = (enum ImatestExceptionIDs)mxGetScalar(errorID);
        printf("*** Error ID: %d\n", errorCode);

        switch (errorCode)
        {
            case kImatestFileNotFoundException:
                printf("File not found exception.\n");
                break;
            case kBadFramingException:
                printf("Bad framing exception.\n");
                break;
            default:
                errorNameStr = mxArrayToString(mxGetCell(errorName, 0));
                printf("*** Unexpected Error: %s\n", errorNameStr);
                break;
        }

        mxDestroyArray(errorID);
        mxDestroyArray(errorName);
        retVal = errorCode;
    }
    else {
        printf("*** Unknown Error.\n");
        retVal = -1005;
    }
}
else
{
   retVal = 0;
   ...
}

In the Imatest C++ library, if an error occurs within one of the analysis module functions, an mwException will be thrown. If you catch the exception, then you can use the getExceptionID(int nargout, mwArray& errID, mwArray& errName) function to extract an Error ID and Error Name, which map into the Imatest IT Exception Hierarchy.

To make handling these exceptions easier, Imatest IT includes an optional header file, imatest_exception_IDs.h, which maps each of the Error IDs to an enum. To include this header file, add #include “imatest_exception_ids.h” to your source file. You can read more about the Exception Hierarchy here.

Here is an example of how you can catch and gracefully handle exceptions using the Imatest IT C++ Library:

try
{
    sfr_shell(1, outputJSON, inputFile, rootDir, inputKeys, opMode, varargin)
}
catch (const mwException&  e)
{
    mwArray mwErrorID, mwErrorName;
    mwString mwErrorNameStr;
    getExceptionID(2, mwErrorID, mwErrorName);
    int err = (int)mwErrorID;

    switch (err)
    {
        case imatest::kImatestFileNotFoundException:
            std::cerr << "*** File was not found. Check the file path." << std::endl;
            break;
        case imatest::kBadFramingException:
            std::cerr << "*** Image is not framed correctly." << std::endl;
            break;
        default:
            mwErrorNameStr = mwErrorName.Get(1,1).ToString();
            std::cerr <<  "*** Unexpected Error: " << mwErrorNameStr << std::endl;
            break;
    }

    retVal = err;
}

In the Imatest C++ library, if an error occurs within one of the analysis module functions, an mwException will be thrown. If you catch the exception, then you can use the getExceptionID(int nargout, mwArray& errID, mwArray& errName) function to extract an Error ID and Error Name, which map into the Imatest IT Exception Hierarchy.

To make handling these exceptions easier, Imatest IT includes an optional header file, imatest_exception_IDs.h, which maps each of the Error IDs to an enum. To include this header file, add #include “imatest_exception_ids.h” to your source file. You can read more about the Exception Hierarchy here.

Here is an example of how you can catch and gracefully handle exceptions using the Imatest IT C++ Library with Objective-C++:

- (void)postTest: (id)param
{
    @autoreleasepool {
        try{
            
            // Declare and initialize outputJSON, fileParam, pathParam, keysParam, modeParam, and varargin mwArray's

            NSLog(@"Running test.");
            sfrplus_shell(1, outputJSON, fileParam, pathParam, keysParam, modeParam, varargin);
            
            // Process JSON returned in outputJSON mwArray 
   
            
        } catch (mwException ex) {
            mwArray mwErrorID, mwErrorName;
            mwString mwErrorNameStr;
            getExceptionID(2, mwErrorID, mwErrorName);
            int err = (int)mwErrorID;

            switch (err)
            {
                case imatest::kImatestFileNotFoundException:
                    NSLog(@"*** File was not found. Check the file path.");
                    break;
                case imatest::kBadFramingException:
                    NSLog(@"*** Image is not framed correctly.");
                    break;
                default:
                    mwErrorNameStr = mwErrorName.Get(1,1).ToString();
                    NSLog(@"*** Unexpected Error: %s", (const char*)mwErrorNameStr);
                    break;
            }

            retVal = err;
        }
    }
}

- (void)runTest
{
     // Start a new thread to run sfrplus_shell()
     [NSThread detachNewThreadSelector:@selector(postTest:) toTarget:self withObject:nil];
}

In the Imatest Python library, if an error occurs within one of the analysis module functions, an ImatestException will be thrown. If you catch the exception, then you can get more information about using the error_id, error_name, and message properties.

Here is an example of how you can catch and gracefully handle exceptions using the Imatest IT Python Library. You can use the constants on the ImatestException class to handle certain error types in different ways. In this example, an ImatestException will be thrown because all floating license seats are currently being used:

from imatest.it import ImatestLibrary, ImatestException
...
try:
    result = imatestLib.sfr(input_file=input_file,
                            root_dir=root_dir,
                            op_mode=ImatestLibrary.OP_MODE_SEPARATE,
                            ini_file=ini_file)
except ImatestException as ex:
    if iex.error_id == ImatestException.FloatingLicenseException:
        print("All floating license seats are in use.  Exit Imatest on another computer and try again.")
    elif iex.error_id == ImatestException.LicenseException:
        print("License Exception: " + iex.message)
    else:
        print("*** Error calling sfr: %s" % (iex.message, ))

In the Imatest .NET library, if an error occurs within one of the analysis module functions, an Exception will be thrown. If you catch the exception, then you can get more information about it by calling the ImatestLibrary.GetLastException() and ImatestLibrary.GetExceptionName() methods.

Here is an example of how you can catch and gracefully handle exceptions using the Imatest IT .NET Library:

try
{
    string result = itLib.SFRplus.JSON(rootDir, imagePath, OperationMode.Separate, iniFile);
}
catch (Exception ex)
{
    ImatestException iex = lib.GetLastException();
    string errorName = lib.GetExceptionName();
    if (iex == ImatestException.FloatingLicenseException)
    {
        Console.Out.WriteLine("All floating license seats are in use.  Exit Imatest on another computer and try again.");
    }
    else if (iex == ImatestException.LicenseException)
    {
        Console.Out.WriteLine("License Exception: {0}: {1}", errorName, ex.Message);
    }
    else
    {
        Console.Out.WriteLine("An error has occurred:");
        Console.Out.WriteLine(ex.Message);
    }
}

In the Imatest .NET library, if an error occurs within one of the analysis module functions, an Exception will be thrown. If you catch the exception, then you can get more information about it by calling the ImatestLibrary.GetLastException() and ImatestLibrary.GetExceptionName() methods.

Here is an example of how you can catch and gracefully handle exceptions using the Imatest IT .NET Library:

Try
    Dim result = itLib.SFR.JSON(rootDir, imagePath, OperationMode.Separate, iniFile)
Catch ex As Exception
    Dim iex As ImatestException = library.GetLastException()
    Dim errorName As String = library.GetExceptionName()
    If iex = ImatestException.FloatingLicenseException Then
        Console.Out.WriteLine("All floating license seats are in use.  Exit Imatest on another computer and try again.")
    ElseIf iex = ImatestException.LicenseException Then
        Console.Out.WriteLine("License Exception: {0}: {1}", errorName, ex.Message)
    Else
        Console.Out.WriteLine("An error has occurred:")
        Console.Out.WriteLine(ex.Message)
    End If
End Try

In the Imatest EXE library, if an error occurs within one of the analysis module functions, the return code from the executable will be -1 instead of 0. If you are calling the executable from a batch script, you can check what the return code was to determine if an exception occurred or not.

Here is an example of how you can test for an exception using the Imatest IT EXE Library:

sfr.exe "-1" "'C:\ImatestSamples\sfr_example.jpg'" "'C:\Program Files\Imatest\v24.2\IT\bin'" "'C:\ImatestSamples\imatest-v2.ini'" "'C:\ImatestSamples\Results'"
if %ERRORLEVEL% neq 0 (
    echo '*** Error calling sfr. Check output for details.'
)

In the Imatest EXE library, if an error occurs within one of the analysis module functions, the return code from the executable will be -1 instead of 0. If you are calling the executable from a batch script, you can check what the return code was to determine if an exception occurred or not.

Here is an example of how you can test for an exception using the Imatest IT EXE Library:

./run_sfr.sh "-1" "$HOME/ImatestSamples/sfr_example.jpg" "/Applications/Imatest/IT/v24.2/bin" "$HOME/ImatestSamples/imatest-v2.ini" "$HOME/ImatestSamples/Results"
if [ "$?" -ne "0" ]
    echo '*** Error calling sfr. Check output for details.'
fi

Sample Code

Imatest IT ships with several example projects in C++, Objective-C (macOS only), Python, C#, and Visual Basic. You can find them in the samples folder of your IT installation, along with example images of Imatest test charts that can be used for each of IT’s analysis modules.

Imatest IT for Windows also comes with a sample GUI application that demonstrates integrating the IT .NET libraries in a full-featured GUI application. Using the example images provided in the samples folder, you can experiment with the different analysis modules. It also provides a simple way to interact with the Imatest Acquisition Library. Using this app, you can quickly connect and test any of the supported image capture devices and make sure they are working, without writing any code. The full source code for this app is included in the .NET C# samples folder.The available log levels are:

Advanced Topics

Direct Read Mode and Reading RAW Images

Images can be passed directly into Imatest IT as byte arrays using Direct Read Mode. The images can be processed RGB or RAW. Direct Read Mode is generally much faster than passing in image file paths, since the data is already in memory and does not need to be read from disk. Although it does require more initial setup effort, if your application is speed-critical or high-volume, we strongly recommend using Direct Read Mode.

For detailed instructions on using Imatest IT’s Direct Read Mode, see this article.

Using the Imatest Image Acquisition Library

Images can be directly acquired in your application from supported devices using the Imatest IT Acquisition Library (C, C++, and .NET only).

For more information on the C and C++ version of the Acquisition Library, see this article. For the .NET version, see this article.

Using Pass/Fail Metrics

Pass/Fail results are included in the JSON results for those modules that support it (Blemish, Colorcheck, Distortion, Multitest, SFR, SFRplus, eSFR-ISO, Random, Star, Stepchart, and Uniformity). If you have configured Pass/Fail criteria, and included the Pass/Fail file in your INI file, then the tests will be run, and the results will be included as a separate JSON object called “passfail”.

For more information on implementing Pass/Fail in Imatest, see this article.

Logging Levels and Redirecting Output

By default, the Imatest IT modules print some information to the standard output or console. Logging levels control the nature of the output (to standard out and to log file) and may be selected by INI file control or from the Settings menu on the main window of Imatest Master.

If your application does not have a console, or you want to store this output in another way, it is possible to redirect the standard out and standard error outputs.

Select your preferred interface below to see detailed instructions.

Interface Type:

To redirect output text using the Imatest C or C++ libraries, you need to use the function imatest_libraryInitializeWithHandlers(mclOutputHandlerFcn error_handler, mclOutputHandlerFcn print_handler) instead of imatest_libraryInitialize(), passing in two pointers to functions that will handle the “error” and “standard” outputs, respectively. The functions accept a const char* input, and return an int, which is the number of characters processed.

int stdOutHandler(const char* str)
{
    // Record output
    ...
    return strlen(str);
}

int stdErrHandler(const char* str)
{
    // Record output
    ...
    return strlen(str);
}

if (!imatest_libraryInitializeWithHandlers(stdErrHandler, stdOutHandler))
{
   ...

To redirect output text using the Imatest C or C++ libraries, you need to use the function imatest_libraryInitializeWithHandlers(mclOutputHandlerFcn error_handler, mclOutputHandlerFcn print_handler) instead of imatest_libraryInitialize(), passing in two pointers to functions that will handle the “error” and “standard” outputs, respectively. The functions accept a const char* input, and return an int, which is the number of characters processed.

int stdOutHandler(const char* str)
{
    // Record output
    ...
    return strlen(str);
}

int stdErrHandler(const char* str)
{
    // Record output
    ...
    return strlen(str);
}

if (!imatest_libraryInitializeWithHandlers(stdErrHandler, stdOutHandler))
{
   ...

To redirect output text using the Imatest C++ libraries in Objective-C, you need to use the function libImatestInitializeWithHandlers(mclOutputHandlerFcn error_handler, mclOutputHandlerFcn print_handler) instead of libImatestInitialize(), passing in two pointers to functions that will handle the “error” and “standard” outputs, respectively. The functions accept a const char* input, and return an int, which is the number of characters processed.

int stdOutHandler(const char* str)
{
    // Record output
    ...
    return strlen(str);
}

int stdErrHandler(const char* str)
{
    // Record output
    ...
    return strlen(str);
}

if (!libImatestInitializeWithHandlers(stdErrHandler, stdOutHandler))
{
   ...

To redirect output text using the Imatest Python library, you need to pass in StringIO objects to the ImatestLibrary() constructor, as the stdout and stderr named parameters. You can extract the contents of these objects using the getvalue() method, and should call close() on them at the end of your script.

import StringIO

std_out = StringIO.StringIO()
std_err = StringIO.StringIO()

libImatest = ImatestLibrary(stdout=out_file, stderr=err_file)
# Call library methods …
print std_out.getvalue()
print std_err.getvalue()
std_out.close()
std_err.close()

To redirect output text using the Imatest .NET library, you need to use the Console.SetOut(TextWriter writer) and Console.SetError(TextWriter writer) methods. You must call these methods before creating the Imatest.IT.Library object.

StringWriter stdOut = new StringWriter();
StringWriter stdErr = new StringWriter();
Console.SetOut(stdOut);
Console.SetError(stdErr);

...

string stdOutText = stdOut.ToString();
string stdErrText = stdErr.ToString();
stdOut.Close();
stdErr.Close();

To redirect output text using the Imatest .NET library, you need to use the Console.SetOut(TextWriter writer) and Console.SetError(TextWriter writer) methods. You must call these methods before creating the Imatest.IT.Library object.

Dim stdOut As New StringWriter()
Dim stdErr As New StringWriter()

Console.SetOut(stdout)
Console.SetError(stderr)

...

Dim stdOutStr As String = stdOut.ToString()
Dim stdErrStr As String = stdErr.ToString()
stdOut.Close()
stdErr.Close()

To redirect output using the Imatest IT EXE interface, use the typical command line syntax you normally would use. For example,

sfr.exe "-1" "C:\ImatestSamples\sfr_example.jpg" "C:\Program Files\Imatest\v24.2\IT\bin" "C:\ImatestSamples\imatest-v2.ini" "C:\ImatestSamples\Results" > "C:\ImatestSamples\Results\sfr_output.log" 2&>&1

will redirect stdout and stderr streams to “C:\ImatestSamples\Results\sfr_output.log”.

To redirect output using the Imatest IT EXE interface, use the typical command line syntax you normally would use. For example,

./run_sfr.sh "-1" "$HOME/ImatestSamples/sfr_example.jpg" "/Applications/Imatest/IT/v24.2/bin" "$HOME/ImatestSamples/imatest-v2.ini" "$HOME/ImatestSamples/Results" > "$HOME/ImatestSamples/Results/sfr_output.log" 2&>&1

will redirect stdout and stderr streams to “$HOME/ImatestSamples/Results/sfr_output.log”.

Advanced: Asynchronous Programming with Imatest IT .NET

With the Imatest IT .NET library, you can easily use write asynchronous module calls in your custom applications using the .NET Framework’s async and await keywords along with Imatest IT .NET’s JSONAsync() methods.

Making these simple changes can have dramatic effect on the responsiveness of applications, especially if they are GUI-based. To see the difference in action, run the Imatest IT .NET Sample Application found at C:\Program Files\Imatest\v24.2\IT\samples.NET\ImatestITSampleProject\ImatestITSampleProject.exe and try both the Run and Run Async buttons. You will notice the application appears to freeze when using the non-async version, but is fully responsive when using the async methods.

Altering Existing Imatest IT .NET Code to be Asynchronous

There are only three changes that need to be made to convert single-threaded code into asynchronous code.:

  • Add an async modifier to the signature in which the asynchronous code will be called.
  • Add the await in front of the Imatest IT method call.
  • Change the Imatest IT method call to use the new Async version.

Below is a code snippet of synchronous code making a simple call to the SFRPlus module:

protected void TestImage()
{
    using (Library lib = new Library())
    {
        string rootDir = @"C:\ImatestSamples\";
        string imagePath = @"C:\ImatestSamples\sfrplus_example.jpg";

        // Call Imatest IT library with JSON output
        string result = lib.SFRplus.JSON(rootDir, imagePath, OperationMode.Separate);

        Console.Out.WriteLine(result);
    }
}

Below is the same code that has been converted to call the SFRplus module asynchronously:

protected async void TestImage()
{
    using (Library lib = new Library())
    {
        string rootDir = @"C:\ImatestSamples\";
        string imagePath = @"C:\ImatestSamples\sfrplus_example.jpg";

        // Call Imatest IT library with JSON output
        string result = await lib.SFRplus.JSONAsync(rootDir, imagePath, OperationMode.Separate);

        // Continue other operations that do not rely on the result value of the test

        Console.Out.WriteLine(result);
    }
}

Initializing the Imatest IT .NET Libraries Asynchronously

The Imatest IT .NET and Imatest Acquisition Library classes have static CreateAsync() methods that can be called using the await keyword:

public async void InitializeApplication()
{
    /// Inside application initialization code

    /// The await keyword will automatically start a new thread to initialize the library,
    /// while code in the main thread continues to execute until the itLib object is
    /// actually used.
    Library itLib = await Library.CreateAsync();

    /// Continue initializing the rest of the application while the background thread
    /// initializes the rest of the application

    ...

    /// The main thread will wait here until the secondary thread is completed and the
    /// Library.CreateAsync() method has returned a Library object.
    await itLib.SFRplus.JSONAsync(rootDir, inputFile, OperationMode.Separate); 

    /// At this point only the main thread is running
}

Parallel Processing

Imatest IT now allows you to analyze several different images in parallel,
using the new parallel_analyzer function.

Interface Type:

Coming soon…

To use the parallel_analyzer, first create a list of analysis tasks that need to be run. Each task will be assigned to a different parallel process. The number of available concurrent processes depends on how many cores your machine has, though you can tell Imatest IT to use fewer cores if you need.

The parallel_analyzer_shell() C++ interface

The signature of the parallel_analyzer_shell() function is as follows:

parallel_analyzer_shell(int nargout, mwArray& results, const mwArray& tasks, const mwArray& iniFileName, const mwArray& runParallel, const mwArray& numWorkers);
Parameter Name Data Type Description
nargout int The number of expected output arguments. This will be set to 1.
results mwArray& [const char*] The serialized JSON object array wrapped in a mwArray
tasks const mwArray& [mxSTRUCT_CLASS] The array of analysis tasks to run. For further information see below.
iniFileName const mwArray& [const char*] The path for the Imatest INI file used for analysis
runParallel const mwArray& [bool] A boolean set to true if parallel analysis is desired, otherwise set to false for serial operation.
numWorkers const mwArray& [int] The number of child processes to spawn.

The tasks array is a mwArray of ClassID mxSTRUCT_CLASS. This data type has named fields, as with C++ structs. Each element of the task array has these fields:

input – The supplied image in the form of file path(s) or numeric array(s)
analysisID – An integer that tells IT which module to run. The allowed values are defined in the ImatestAnalysisIDs enum (see <IT installation root>\libs\library\cpp\Imatest_analysis_ids.h):
imatest::BLEMISH_ANALYSIS_ID
imatest::CHECKERBOARD_ANALYSIS_ID
imatest::COLORCHECK_ANALYSIS_ID
imatest::DISTORTION_ANALYSIS_ID
imatest::DOTPATTERN_ANALYSIS_ID
imatest::ESFRISO_ANALYSIS_ID
imatest::MULTITEST_ANALYSIS_ID
imatest::RANDOM_ANALYSIS_ID
imatest::SFR_ANALYSIS_ID
imatest::SFRPLUS_ANALYSIS_ID
imatest::SFRREG_ANALYSIS_ID
imatest::STAR_ANALYSIS_ID
imatest::UNIFORMITY_ANALYSIS_ID
imatest::WEDGE_ANALYSIS_ID
jsonMetaData – Image meta data in the form of serialized JSON object string. This field only needs to be filled when numeric arrays are being supplied.

An example of the creation of the tasks array for four image files is available in the parallel_analyzer sample project (<IT installation root>\samples\cpp\parallel_analyzer\main.cpp). In this example, the tasks array is created with

 mwSize numRows = 4; // There are 4 images to test
 mwSize numCols = 1;
 int numFields = 3;
 const char* fieldNames[] = {"input\0", "analysisID\0", "jsonMetadata\0"};

 mwArray tasks(numRows, numCols, numFields, fieldNames);
[/cpp]
To supply values to the individual tasks, we make use of the Get(const char* fieldName, int numIndices, int index1, ...) accessor for mxSTRUCT_CLASS mwArrays:
[cpp][/cpp]
// define the first task
tasks.Get("input", 1, 1).Set(mwArray(".\\sfrplus_example.jpg"));
tasks.Get("analysisID", 1, 1).Set(sfrplusID);

// define the second task
tasks.Get("input", 1, 2).Set(mwArray(".\\blemish_example.jpg"));
tasks.Get("analysisID", 1, 2).Set(blemishID);

//define the third task
tasks.Get("input", 1, 3).Set(mwArray(".\\colorcheck_example.jpg"));
tasks.Get("analysisID", 1, 3).Set(colorcheckID);

//define the fourth task
tasks.Get("input", 1, 4).Set(mwArray(".\\esfriso_example.jpg"));
tasks.Get("analysisID", 1, 4).Set(esfrisoID);

It is important to note that this array is 1-indexed.

Creation of the remaining inputs is simpler; we use the mwArray contructors for scalar numeric values and strings.

mwArray iniFileName("..\\Imatest_INI\\imatest-v2.ini");

mwArray runParallel(true);

mwArray numWorkers(2);

Lastly, we call parallel_analyzer_shell() with the inputs.

mwArray out;
parallel_analyzer_shell(1, out, tasks, iniFileName, runParallel, numWorkers);

The results will be returned in the out mwArray, which contains a JSON encoded string that can be parsed into an object array with one result object per task. Each result object has this form:

{
   "data": {
      "dateRun": "18-Sep-2017 10:26:59",
      "ini_file_name": "C:\\images\\ini_file\\imatest-v2.ini",
      "ini_time_size": "18-Sep-2017 10:26:45 21822B  MD5 = ac109f86b635bd5b4344d252969e64a7",
      "version": "Imatest 5.0.0  SFRplus",
      "title": "sfrplus_0123.jpg",
      "image_path_name": "C:\\images\\sfrplus_0123.jpg",

      ...
   },
   "errorID": "",
   "errorMessage": "",
   "errorReport": ""
}

If any exceptions occurred during processing, they will be reported in the errorID, errorMessage, and errorReport properties. While handling your results, you should always check whether the errorID property is empty or not before working with the data property.

In addition to the parallel_analyzer sample, IT also includes a C++ sample project that implements parallel processing using the Boost.Interprocess Library (<IT installation root>\samples\cpp\CPP_parallel_test_project). More information can be found in this article.

To use the parallel_analyzer, first create a list of analysis tasks that need to be run. Each task will be assigned to a different parallel process. The number of available concurrent processes depends on how many cores your machine has, though you can tell Imatest IT to use fewer cores if you need.

The parallel_analyzer_shell() C++ interface

The signature of the parallel_analyzer_shell() function is as follows:

parallel_analyzer_shell(int nargout, mwArray& results, const mwArray& tasks, const mwArray& iniFileName, const mwArray& runParallel, const mwArray& numWorkers);
Parameter Name Data Type Description
nargout int The number of expected output arguments. This will be set to 1.
results mwArray& [const char*] The serialized JSON object array wrapped in a mwArray
tasks const mwArray& [mxSTRUCT_CLASS] The array of analysis tasks to run. For further information see below.
iniFileName const mwArray& [const char*] The path for the Imatest INI file used for analysis
runParallel const mwArray& [bool] A boolean set to true if parallel analysis is desired, otherwise set to false for serial operation.
numWorkers const mwArray& [int] The number of child processes to spawn.

The tasks array is a mwArray of ClassID mxSTRUCT_CLASS. This data type has named fields, as with C++ structs. Each element of the task array has these fields:

input – The supplied image in the form of file path(s) or numeric array(s)
analysisID – An integer that tells IT which module to run. The allowed values are defined in the ImatestAnalysisIDs enum (see <IT installation root>/libs/library/cpp/Imatest_analysis_ids.h):
imatest::BLEMISH_ANALYSIS_ID
imatest::CHECKERBOARD_ANALYSIS_ID
imatest::COLORCHECK_ANALYSIS_ID
imatest::DISTORTION_ANALYSIS_ID
imatest::DOTPATTERN_ANALYSIS_ID
imatest::ESFRISO_ANALYSIS_ID
imatest::MULTITEST_ANALYSIS_ID
imatest::RANDOM_ANALYSIS_ID
imatest::SFR_ANALYSIS_ID
imatest::SFRPLUS_ANALYSIS_ID
imatest::SFRREG_ANALYSIS_ID
imatest::STAR_ANALYSIS_ID
imatest::UNIFORMITY_ANALYSIS_ID
imatest::WEDGE_ANALYSIS_ID
jsonMetaData – Image meta data in the form of serialized JSON object string. This field only needs to be filled when numeric arrays are being supplied.

An example of the creation of the tasks array for four image files is available in the parallel_analyzer sample project (<IT installation root>\samples\cpp\parallel_analyzer\main.cpp). In this example, the tasks array is created with

 mwSize numRows = 4; // There are 4 images to test
 mwSize numCols = 1;
 int numFields = 3;
 const char* fieldNames[] = {"input\0", "analysisID\0", "jsonMetadata\0"};

 mwArray tasks(numRows, numCols, numFields, fieldNames);

To supply values to the individual tasks, we make use of the Get(const char* fieldName, int numIndices, int index1, …) accessor for mxSTRUCT_CLASS mwArrays:

// define the first task
tasks.Get("input", 1, 1).Set(mwArray(".\\sfrplus_example.jpg"));
tasks.Get("analysisID", 1, 1).Set(sfrplusID);

// define the second task
tasks.Get("input", 1, 2).Set(mwArray(".\\blemish_example.jpg"));
tasks.Get("analysisID", 1, 2).Set(blemishID);

//define the third task
tasks.Get("input", 1, 3).Set(mwArray(".\\colorcheck_example.jpg"));
tasks.Get("analysisID", 1, 3).Set(colorcheckID);

//define the fourth task
tasks.Get("input", 1, 4).Set(mwArray(".\\esfriso_example.jpg"));
tasks.Get("analysisID", 1, 4).Set(esfrisoID);

It is important to note that this array is 1-indexed.

Creation of the remaining inputs is simpler; we use the mwArray contructors for scalar numeric values and strings.

mwArray iniFileName("..\\Imatest_INI\\imatest-v2.ini");

mwArray runParallel(true);

mwArray numWorkers(2);

Lastly, we call parallel_analyzer_shell() with the inputs.

mwArray out;
parallel_analyzer_shell(1, out, tasks, iniFileName, runParallel, numWorkers);

The results will be returned in the out mwArray, which contains a JSON encoded string that can be parsed into an object array with one result object per task. Each result object has this form:

{
   "data": {
      "dateRun": "18-Sep-2017 10:26:59",
      "ini_file_name": "C:\\images\\ini_file\\imatest-v2.ini",
      "ini_time_size": "18-Sep-2017 10:26:45 21822B  MD5 = ac109f86b635bd5b4344d252969e64a7",
      "version": "Imatest 5.0.0  SFRplus",
      "title": "sfrplus_0123.jpg",
      "image_path_name": "C:\\images\\sfrplus_0123.jpg",

      ...
   },
   "errorID": "",
   "errorMessage": "",
   "errorReport": ""
}

If any exceptions occurred during processing, they will be reported in the errorID, errorMessage, and errorReport properties. While handling your results, you should always check whether the errorID property is empty or not before working with the data property.

To use the parallel_analyzer, first create a list of analysis tasks that need to be run. Each task will be assigned to a different parallel process. The number of available concurrent processes depends on how many cores your machine has, though you can tell Imatest IT to use fewer cores if you need.

The task file

In the stand-alone executable version of parallel_analyzer, the list of tasks is supplied in the form of a JSON encoded file. In this JSON file, the list of tasks is represented by a JSON object array, where each individual task is an object within that array. For each task the following fields need to be defined:

input – The supplied image in the form of file path(s) or numeric array(s)
analysisID – An integer that tells IT which module to run. The allowed values are defined below:

Module Value
Blemish 1
Checkerboard 2
Colorcheck 3
Distortion 4
Dotpattern 5
eSFRiso 6
Multitest 7
Random 8
SFR 9
SFRplus 10
SFRreg 11
Star 12
Uniformity 13
Wedge 14

jsonMetaData – Image meta data in the form of serialized JSON object. This field only needs to be filled when numeric arrays are being supplied.

As an example, suppose that there are two files named blemish_example.jpg and sfrplus_example.jpg in the current working directory that need to be analyzed by the Blemish and SFRplus modules, respectively. The contents of this tasks file is then

[
    {
        "input": "blemish_example.jpg",
        "analysisID": 1,
        "jsonMetadata": ""
    },
    {
        "input": "sfrplus_example.jpg",
        "analysisID": 10,
        "jsonMetadata": ""
    }
]

The parallel_analyzer_exe interface

The signature of the parallel_analyze executable is as follows:

parallel_analyzer_exe taskFileName iniFileName runParallel numWorkers [-o|--output_filename <filename>]

The required inputs are
taskFileName: The path to the JSON task file (see the Task File section below).

iniFileName: The path to the Imatest INI file

runParallel: A boolean value that is 1 if the user wants parallel processing and 0 if serial processing is desired.

numWorkers: An integer value indicating the number of child processes to invoke for analysis. The maximum value is the number of physical cores.

with remaining optional input
-o|–output_filename<filename>: Supply the full file path for the file into which the results are saved. Note that either ‘-o’ or ‘–output_filename’ can be used. If this optional input is not supplied, the results are saved to a file named ‘results_<current date and time>.json’.

Continuing the above example, suppose that the task file (tasks.json) from above is in our Documents folder with the two image files and our INI file (imatest-v2.ini). The call to run the two tasks in parallel on two processes would be

cd %HOMEPATH%\Documents
C:\Program Files\Imatest\v24.2\IT\bin\parallel_analyzer_exe.exe tasks.json imatest-v2.ini 1 2

The results will be saved to a JSON encoded file in the form of a JSON object array with one result object per task. Each result object has this form:

{
   "data": {
      "dateRun": "18-Sep-2017 10:26:59",
      "ini_file_name": "C:\\images\\ini_file\\imatest-v2.ini",
      "ini_time_size": "18-Sep-2017 10:26:45 21822B  MD5 = ac109f86b635bd5b4344d252969e64a7",
      "version": "Imatest 5.0.0  SFRplus",
      "title": "sfrplus_0123.jpg",
      "image_path_name": "C:\\images\\sfrplus_0123.jpg",

      ...
   },
   "errorID": "",
   "errorMessage": "",
   "errorReport": ""
}

If any exceptions occurred during processing, they will be reported in the errorIDerrorMessage, and errorReport properties. While handling your results, you should always check whether the errorID property is empty or not before working with the data property.

To use the parallel_analyzer, first create a list of analysis tasks that need to be run. Each task will be assigned to a different parallel process. The number of available concurrent processes depends on how many cores your machine has, though you can tell Imatest IT to use fewer cores if you need.

The task file

In the stand-alone executable version of parallel_analyzer, the list of tasks is supplied in the form of a JSON encoded file. In this JSON file, the list of tasks is represented by a JSON object array, where each individual task is an object within that array. For each task the following fields need to be defined:

input – The supplied image in the form of file path(s) or numeric array(s)
analysisID – An integer that tells IT which module to run. The allowed values are defined below:

Module Value
Blemish 1
Checkerboard 2
Colorcheck 3
Distortion 4
Dotpattern 5
eSFRiso 6
Multitest 7
Random 8
SFR 9
SFRplus 10
SFRreg 11
Star 12
Uniformity 13
Wedge 14

jsonMetaData – Image meta data in the form of serialized JSON object. This field only needs to be filled when numeric arrays are being supplied.

As an example, suppose that there are two files named blemish_example.jpg and sfrplus_example.jpg in the current working directory that need to be analyzed by the Blemish and SFRplus modules, respectively. The contents of this tasks file is then

[
    {
        "input": "blemish_example.jpg",
        "analysisID": 1,
        "jsonMetadata": ""
    },
    {
        "input": "sfrplus_example.jpg",
        "analysisID": 10,
        "jsonMetadata": ""
    }
]

The parallel_analyzer_exe interface

The signature of the parallel_analyze executable is as follows:

./run_parallel_analyzer.sh taskFileName iniFileName runParallel numWorkers [-o|--output_filename FILENAME]

The required inputs are
taskFileName: The path to the JSON task file (see the Task File section below).

iniFileName: The path to the Imatest INI file

runParallel: A boolean value that is 1 if the user wants parallel processing and 0 if serial processing is desired.

numWorkers: An integer value indicating the number of child processes to invoke for analysis. The maximum value is the number of physical cores.

with remaining optional input
-o|–output_filename<filename>: Supply the full file path for the file into which the results are saved. Note that either ‘-o’ or ‘–output_filename’ can be used. If this optional input is not supplied, the results are saved to a file named ‘results_<current date and time>.json’.

Continuing the above example, suppose that the task file (tasks.json) from above is in our Documents folder with the two image files and our INI file (imatest-v2.ini). The call on macOS to run the two tasks in parallel on two processes would be

cd ~/Documents
/Applications/Imatest/IT/v24.2/bin/run_parallel_analyzer.sh ./tasks.json ./imatest-v2.ini 1 2

And on Linux the command would be

cd ~/Documents
/usr/local/Imatest/v24.2/IT/bin/run_parallel_analyzer.sh ./tasks.json ./imatest-v2.ini 1 2

The results will be saved to a JSON encoded file in the form of a JSON object array with one result object per task. Each result object has this form:

{
   "data": {
      "dateRun": "18-Sep-2017 10:26:59",
      "ini_file_name": "C:\\images\\ini_file\\imatest-v2.ini",
      "ini_time_size": "18-Sep-2017 10:26:45 21822B  MD5 = ac109f86b635bd5b4344d252969e64a7",
      "version": "Imatest 5.0.0  SFRplus",
      "title": "sfrplus_0123.jpg",
      "image_path_name": "C:\\images\\sfrplus_0123.jpg",

      ...
   },
   "errorID": "",
   "errorMessage": "",
   "errorReport": ""
}

If any exceptions occurred during processing, they will be reported in the errorIDerrorMessage, and errorReport properties. While handling your results, you should always check whether the errorID property is empty or not before working with the data property.

Imatest IT allows you to analyze several different images in parallel, using the new parallel_analyzer function.

To use the parallel_analyzer, first create a list of analysis tasks that need to be run. Each task will be assigned to a different parallel process. The number of available concurrent processes depends on how many cores your machine has, though you can tell Imatest IT to use fewer cores if you need.

To create an analysis task, use the new_parallel_task function:

ImatestLibrary.new_parallel_task(image_files=None, image_data=None, analysis_type=None, image_data_meta_data=None)
Parameter Name Data Type Description
image_files str or list of strs Either a file path to an image, or a list of file paths
image_data str/bytes or array.array (numerical) If you are providing raw image data, use this argument, which is either the read value of the image in str (Python 2.7) or bytes (Python 3.6, 3.7) form. If using image_data, you must include the image_data_meta_data argument, which you can get by calling ImatestLibrary.build_json_args()
analysis_type enum A flag telling Imatest IT which module to run. Valid values are constants on the ImatestLibrary class: ImatestLibrary.BLEMISH_ANALYSIS ImatestLibrary.CHECKERBOARD_ANALYSIS ImatestLibrary.COLORCHECK_ANALYSIS ImatestLibrary.DISTORTION_ANALYSIS ImatestLibrary.DOTPATTERN_ANALYSIS ImatestLibrary.ESFRISO_ANALYSIS ImatestLibrary.MULTITEST_ANALYSIS ImatestLibrary.RANDOM_ANALYSIS ImatestLibrary.SFR_ANALYSIS ImatestLibrary.SFRPLUS_ANALYSIS ImatestLibrary.SFRREG_ANALYSIS ImatestLibrary.STAR_ANALYSIS ImatestLibrary.UNIFORMITY_ANALYSIS ImatestLibrary.WEDGE_ANALYSIS
image_data_meta_data dict A dict object containing the direct read meta data, used to help interpret the raw byte data, and obtained by calling ImatestLibrary.build_json_args(). Required if using the image_data argument, not needed if using image_files.

add each of your tasks to a list, then call ImatestLibrary.parallel_analyser, passing in the path to your INI file, True for run_parallel, and the number of worker processes you’d like to use:

ini_file = r'C:\images\ini_file\imatest-v2.ini'

tasks = []
tasks.append(library.new_parallel_task(image_files=r'C:\images\sfrplus_0123.jpg', analysis_type=ImatestLibrary.SFRPLUS_ANALYSIS))
tasks.append(library.new_parallel_task(image_files=[r'C:\images\blemish_0001.jpg', r'C:\images\blemish_0002.jpg', r'C:\images\blemish_0003.jpg'], analysis_type=ImageLibrary.BLEMISH_ANALYSIS))
....

result = library.parallel_analyzer(tasks=tasks, ini_file=ini_file, run_parallel=True, num_workers=4)

The result will be a JSON encoded string that can be parsed into an array of result objects using json.loads(result). Each result object has this form:

{
   "data": {
      "dateRun": "18-Sep-2017 10:26:59",
      "ini_file_name": "C:\\images\\ini_file\\imatest-v2.ini",
      "ini_time_size": "18-Sep-2017 10:26:45 21822B  MD5 = ac109f86b635bd5b4344d252969e64a7",
      "version": "Imatest 5.0.0  SFRplus",
      "title": "sfrplus_0123.jpg",
      "image_path_name": "C:\\images\\sfrplus_0123.jpg",

      ...
   },
   "errorID": "",
   "errorMessage": "",
   "errorReport": ""
}

If any exceptions occurred during processing, they will be reported in the errorID, errorMessage, and errorReport properties. While handling your results, you should always check whether the errorID property is empty or not before working with the data property:

resultArr = json.loads(result)

for task_result in result_arr:
   if task_result['errorID']:
      # Gracefully handle the error
   else:
      result_data = task_result['data']
      # Process the results in the result_data dictionary

Imatest IT allows you to analyze several different images in parallel, using the new ParallelAnalyzer.Execute() method.

To use the ParallelAnalyzer, first create a List of ImatestTasks objects that contain images to be analyzed. Each task will be assigned to a different parallel process. The number of available concurrent worker processes depends on how many cores your machine has, though you can tell Imatest IT to use fewer workers if you need.

To create an ImatestTask, use one of the overloaded ImatestTask.Create() methods:

public static ImatestTask Create(string imageFilePath, ImatestModule module);
public static ImatestTask Create(IEnumerable<string> imageFilePaths, ImatestModule module);
public static ImatestTask Create(byte[] imageData, ImatestModule module, DirectReadOptions imageMetaData);
public static ImatestTask Create(UInt16[] imageData, ImatestModule module, DirectReadOptions imageMetaData);
public static ImatestTask Create(UInt32[] imageData, ImatestModule module, DirectReadOptions imageMetaData);
Parameter Name Data Type Description
imageFilePath string A file path to an image
imageFilePaths IEnumerable<string> A collection of file paths to images
imageData byte[], UInt16[], UInt32[] Raw image data (if you are using direct read mode)
module enum (ImatestLibrary) A flag telling Imatest IT which module to run. Valid values are contained in the ImatestModule enum: ImatestModule.Blemish ImatestModule.Checkerboard ImatestModule.Colorcheck ImatestModule.Distortion ImatestModule.DotPattern ImatestModule.eSFRISO ImatestModule.Multitest ImatestModule.Random ImatestModule.SFR ImatestModule.SFRplus ImatestModule.SFRreg ImatestModule.Star ImatestModule.Uniformity ImatestModule.Wedge
imageMetaData DirectReadOptions An instance of the DirectReadOptions class that contains image meta data, used to help interpret the raw byte data.

Add each of your tasks to a collection of type ImatestTask, then call Library.ParallelAnalyzer.Execute(), passing in the path to your INI file for iniFilePath, true for runInParallel, and the number of worker processes you’d like to use:

string inFile = "C:\\images\\ini_file\\imatest-v2.ini";

List<ImatestTask> lstTasks = new List<ImatestTask>();
lstTasks.Add(ImatestTask.Create("C:\\images\\sfrplus_0123.jpg", ImatestModule.SFRplus));
lstTasks.Add(ImatestTask.Create(new List<string>() { "C:\\image\\blemish_0001.jpg", "C:\\images\\blemish_0002.jpg", "C:\\images\\blemish_0003.jpg" }, ImatestModule.Blemish));
....

string result = library.ParallelAnalyzer.Execute(lstTasks, iniFile, true, 2);

The result will be a JSON encoded string that can be parsed into an array of result objects using any .NET JSON library. Each result object has this form:

{
   "data": {
      "dateRun": "18-Sep-2017 10:26:59",
      "ini_file_name": "C:\\images\\ini_file\\imatest-v2.ini",
      "ini_time_size": "18-Sep-2017 10:26:45 21822B  MD5 = ac109f86b635bd5b4344d252969e64a7",
      "version": "Imatest 5.0.0  SFRplus",
      "title": "sfrplus_0123.jpg",
      "image_path_name": "C:\\images\\sfrplus_0123.jpg",

      ...
   },
   "errorID": "",
   "errorMessage": "",
   "errorReport": ""
}

If any exceptions occurred during processing, they will be reported in the errorID, errorMessage, and errorReport properties. While handling your results, you should always check whether the errorID property is empty or not before working with the data property.

Imatest IT allows you to analyze several different images in parallel, using the new ParallelAnalyzer.Execute() method.

To use the ParallelAnalyzer, first create a List of ImatestTasks objects that contain images to be analyzed. Each task will be assigned to a different parallel process. The number of available concurrent worker processes depends on how many cores your machine has, though you can tell Imatest IT to use fewer workers if you need.

To create an ImatestTask, use one of the overloaded ImatestTask.Create() methods:

Public Shared Function Create(imageFilePath As String, [module] As ImatestModule) As ImatestTask
Public Shared Function Create(imageFilePaths As IEnumerable(Of String), [module] As ImatestModule) As ImatestTask
Public Shared Function Create(imageData() As Byte, [module] As ImatestModule, imageMetaData As DirectReadOptions) As ImatestTask
Public Shared Function Create(imageData() As UShort, [module] As ImatestModule, imageMetaData As DirectReadOptions) As ImatestTask
Public Shared Function Create(imageData() As UInteger, [module] As ImatestModule, imageMetaData As DirectReadOptions) As ImatestTask
Parameter Name Data Type Description
imageFilePath string A file path to an image
imageFilePaths IEnumerable<string> A collection of file paths to images
imageData byte[], UInt16[], UInt32[] Raw image data (if you are using direct read mode)
module enum (ImatestLibrary) A flag telling Imatest IT which module to run. Valid values are contained in the ImatestModule enum: ImatestModule.Blemish ImatestModule.Checkerboard ImatestModule.Colorcheck ImatestModule.Distortion ImatestModule.DotPattern ImatestModule.eSFRISO ImatestModule.Multitest ImatestModule.Random ImatestModule.SFR ImatestModule.SFRplus ImatestModule.SFRreg ImatestModule.Star ImatestModule.Uniformity ImatestModule.Wedge
imageMetaData DirectReadOptions An instance of the DirectReadOptions class that contains image meta data, used to help interpret the raw byte data.

Add each of your tasks to a collection of type ImatestTask, then call Library.ParallelAnalyzer.Execute(), passing in the path to your INI file for iniFilePath, true for runInParallel, and the number of worker processes you’d like to use:

Dim iniFilePath As String
Dim lstTasks As New List(Of ImatestTask)()
Dim result As String

iniFilePath = "C:\\images\\ini_file\\imatest-v2.ini"

lstTasks.Add(ImatestTask.Create("C:\\images\\sfrplus_0123.jpg", ImatestModule.SFRplus))
lstTasks.Add(ImatestTask.Create("C:\\image\\blemish_0001.jpg" ImatestModule.Blemish))

List<ImatestTask> lstTasks = new List<ImatestTask>();
lstTasks.Add(ImatestTask.Create("C:\\images\\sfrplus_0123.jpg", ImatestModule.SFRplus));
lstTasks.Add(ImatestTask.Create(new List<string>() { "C:\\image\\blemish_0001.jpg", "C:\\images\\blemish_0002.jpg", "C:\\images\\blemish_0003.jpg" }, ImatestModule.Blemish));
....

result = library.ParallelAnalyzer.Execute(lstTasks, iniFilePath, True, 4)

The result will be a JSON encoded string that can be parsed into an array of result objects using any .NET JSON library. Each result object has this form:

{
   "data": {
      "dateRun": "18-Sep-2017 10:26:59",
      "ini_file_name": "C:\\images\\ini_file\\imatest-v2.ini",
      "ini_time_size": "18-Sep-2017 10:26:45 21822B  MD5 = ac109f86b635bd5b4344d252969e64a7",
      "version": "Imatest 5.0.0  SFRplus",
      "title": "sfrplus_0123.jpg",
      "image_path_name": "C:\\images\\sfrplus_0123.jpg",

      ...
   },
   "errorID": "",
   "errorMessage": "",
   "errorReport": ""
}

If any exceptions occurred during processing, they will be reported in the errorID, errorMessage, and errorReport properties. While handling your results, you should always check whether the errorID property is empty or not before working with the data property.

Arbitrary Charts Module

Imatest IT now allows you to call the Arbitrary Charts module in using the new arbitrary_charts functions. For more information on the Arbitrary Charts modules, see this article.

Interface Type:

Coming soon…

Coming soon…

The function prototype for Arbitrary Charts is

 arbitrary_charts_shell(int nargout, mwArray& output, const mwArray& inputData, const mwArray& chartFile, const mwArray& iniFile, const mwArray& averageMode, const mwArray& optionsJson)

where the parameters are defined in the following table:

nargoutintAlways set this to 1. This parameter indicates the number of desired outputs.

Parameter Name Data Type Description
output mwArray(const char*) This will contains the results in the form of a JSON-encoded UTF-16 string.
inputData mwArray The input image data. This can be in the form of a single image file path, a mwArray of type mxCELL_CLASS containing multiple image paths, or a mwArray of type mxCELL_CLASS containing numeric arrays.
chartFile mwArray(const char*) The file path to the chart definition file (see https://www.imatest.com/docs/arbitrary-charts/definitions/).
iniFile mwArray(const char*) The file path to the INI file.
averageMode mwArray(int) || mwArray(const char*) This parameter allows you to specify whether if groups of files are averaged (averageMode == 1) or not (averageMode == 0).
optionsJson mwArray(const char*) This parameter is a JSON-encoded string that contains descriptive meta-data for the image. See below for more information.

To begin, declare the iniFileParam and chartFileParam variables and supply the fully-qualified paths to INI and chart definition files.

- (void)runTest: (id)param
{
    @autoreleasepool {
        try{
            
            
            mwArray iniFileParam("/some/folder/imatest-v2.ini");
            mwArray chartFileParm("/some/folder/chart_definition.json");

Next the images need to be supplied either as one or more image files, or as image data arrays. If you want to supply more than one image file at a time you will need to first construct an mwArray of type mxCELL_CLASS. For example, if you had three images inputDataParam would be constructed as follows:

           mwArray inputDataParam(3, 1, mxCELL_CLASS);
           inputDataParam.Get(1, 1).Set(mwArray("/some/folder/image1.jpg"));
           inputDataParam.Get(1, 2).Set(mwArray("/some/folder/image2.jpg"));
           inputDataParam.Get(1, 3).Set(mwArray("/some/folder/image3.jpg"));

Alternatively, if you had only a single image file, you can construct inputDataParam by passing the image file path directly to the mwArray constructor

            mwArray inputDataParam("/some/folder/image.jpg");

If you are supplying more than one image, you can specify whether the images should be averaged (averageMode == 1) or analyzed separately (averageMode == 0) using the averageModeParam, which can be set to contain a numeric value or a string such as


The remaining parameter to construct is optionsJson. The JSON properties defined in the optionsJson parameter are defined in the table below.

Option Name Data Type Required? Description
width int image data arrays only The width of the image in pixels.
height int image data arrays only The height of the image in pixels.
encoding string Yes The data encoding format of the image data. For now the options are (case-insensitive):’intensity’, ‘sRGB’, ‘adobe_rgb’, ‘wide_gamut_rgb’, ‘pro_photo_rgb’, ‘apple_rgb’, ‘colormatch’, ‘rec_709_full’, ‘rec_709_legal’, ‘rec_2020_full’, ‘rec_2020_legal’, ‘aces’. Use ‘intensity’ for 1-channel grayscale data, while the others are for standard RGB encodings.
fileroot string image data arrays only The file path to the source image file.
extension string image data arrays only The file extension to the source image file.
serial_number string No A string containing the serial number.
part_number string No A string containing the part number.
crop_borders double array No A 1 x 4 double array indicating the crop borders ( [Left Top Right Bottom] ).
lens_to_chart_distance_cm double No The lens to chart distance in cm.
chart_height_cm double No The chart height in cm.

In this example, image files are being supplied, so we are only required to supply the image encoding, for example:

           mwArray optionsJsonParam("{\"encoding\":\"sRGB\"}");

Lastly, we call arbitrary_charts_shell and supply the parameters that have been constructed

            // Call the library function
            mwArray output
            arbitrary_charts_shell(1, output, inputDataParam, chartFileParm, iniFileParam, averageModeParam, optionsJsonParam);

            // Extract the JSON-encoded string.
            // Note that the mwArray contains only UTF-16 strings, which we must load into an NSString
            auto numel = out.NumberOfElements();
            std::u16string buffer(numel+1, 0);
            out.GetCharData(&buffer[0], numel);
            char* data = (char*)buffer.data();
            unsigned long size = buffer.size()*sizeof(char16_t);
            NSString* jsonString =[[NSString alloc] initWithBytes:data length:size encoding:NSUTF16LittleEndianStringEncoding];
            
            // Process results            
        } catch (mwException ex){
            NSLog(@"Error");
            
            NSLog(@"%s", ex.what());
            ex.print_stack_trace();
        }
    }
}

The result will be a JSON-encoded string of this form:

{
    "Info": {
        "Timestamp": "04-Oct-2017 09:09:08",
        "Version": "Imatest 5.1.0.25883 Alpha ",
        "Build": "2017-10-03",
        "Calculation_time_seconds": [44.36107732]
    },
    "Results_array_sources": "C:\\images\\P1858_combination_chart_example.jpg",
    "Results": {
...
    }
}

First, create an image options dictionary by calling ImatestLibrary.get_arbitrary_charts_options():

ImatestLibrary.get_arbitrary_charts_options(self, width=None, height=None, encoding=None, filename=None, extension=None, pixel_size=None)
Parameter Name Data Type Description
width int Image width (in pixels)
height int Image height (in pixels)
encoding str The pixel encoding (i.e., “srgb”, “intensity”)
filename str (direct read only) The name of the file, used for results file names.
extension str (direct read only) The extension key used to decode the direct read image bytes, as configured in the Read Raw screen of Imatest Master.
pixel_size enum (direct read only) The pixel size of the direct read image. Use one of these constants: ImatestLibrary.PIXEL_SIZE_8_BIT_UNSIGNED ImatestLibrary.PIXEL_SIZE_16_BIT_UNSIGNED ImatestLibrary.PIXEL_SIZE_32_BIT_UNSIGNED

Once you have the options object, you can then call the one of the arbitrary_charts functions:

ImatestLibrary.arbitrary_charts_separate(self, image_files=None, image_data=None, chart_file=None, ini_file=None, options=None)
ImatestLibrary.arbitrary_charts_signal_average(self, image_files=None, image_data=None, chart_file=None, ini_file=None, options=None)

The arbitrary_charts_separate function will analyze multiple inputs separately, while the arbitrary_charts_signal_average function will combine two images’ results into a single signal averaged result.

Parameter Name Data Type Description
image_files str or list of strs Either a file path to an image, or a list of file paths
image_data str/bytes or array.array (numerical) If you are providing raw image data, use this argument, which is the read value of the image in bytes (Python 3.9, 3.10, 3.11) form. If using image_data, you must include the required parameters into the ImatestLibrary.get_arbitrary_charts_options() method
chart_file str The path to the chart definition file.
ini_file str The path to the INI file.
options dict The dict object returned by calling ImatestLibrary.get_arbitrary_charts_options().

The result will be a JSON-encoded string, which can be converted to a dict using json.loads(), of this form:

{
    "Info": {
        "Timestamp": "04-Oct-2017 09:09:08",
        "Version": "Imatest 5.1.0.25883 Alpha ",
        "Build": "2017-10-03",
        "Calculation_time_seconds": [44.36107732]
    },
    "Results_array_sources": "C:\\images\\P1858_combination_chart_example.jpg",
    "Results": {
     ...
    }
}

First, create an ArbitraryChartOptions object:

ArbitraryChartOptions arbChartOptions = new ArbitraryChartOptions();
arbChartOptions.Encoding = ImageEncoding.sRGB;
arbChartOptions.Width = 1296;
arbChartOptions.Height = 808;
Property Name Data Type Description
Width int Image width (in pixels)
Height int Image height (in pixels)
Encoding enum (ImageEncoding) The pixel encoding: ImageEncoding.sRGB ImageEncoding.Intensity
Filename string (direct read only) The name of the file, used for results file names.
Extension string (direct read only) The extension key used to decode the direct read image bytes, as configured in the Read Raw screen of Imatest Master.

Once you have the ArbitraryChartOptions object, you can then call the one of the ArbitraryCharts methods:

public string Separate(string inputFile, string chartFile, string iniFile, ArbitraryChartOptions options);
public string Separate(IEnumerable<string> inputFiles, string chartFile, string iniFile, ArbitraryChartOptions options);
public string Separate(byte[] imageData, string chartFile, string iniFile, ArbitraryChartOptions options);
public string Separate(ushort[] imageData, string chartFile, string iniFile, ArbitraryChartOptions options);
public string Separate(uint[] imageData, string chartFile, string iniFile, ArbitraryChartOptions options);
public Task<string> SeparateAsync(string inputFile, string chartFile, string iniFile, ArbitraryChartOptions options);
public Task<string> SeparateAsync(IEnumerable<string> inputFiles, string chartFile, string iniFile, ArbitraryChartOptions options);
public Task<string>; SeparateAsync(byte[] imageData, string chartFile, string iniFile, ArbitraryChartOptions options);
public Task<string> SeparateAsync(ushort[] imageData, string chartFile, string iniFile, ArbitraryChartOptions options);
public Task<string> SeparateAsync(uint[] imageData, string chartFile, string iniFile, ArbitraryChartOptions options);
public string SignalAverage(IEnumerable<string> inputFiles, string chartFile, string iniFile, ArbitraryChartOptions options);
public Task<string> SignalAverageAsync(IEnumerable<string> inputFiles, string chartFile, string iniFile, ArbitraryChartOptions options);

The ArbitraryCharts.Separate methods will analyze multiple inputs separately, while the ArbitraryCharts.SignalAverage method will combine two images’ results into a single signal averaged result.

Parameter Name Data Type Description
inputFile(s) string or IEnumberable Either a file path to an image, or a list of file paths
imageData byte[], UInt16[], UInt32[] Raw image data (if you are using direct read mode)
chartFile str The path to the chart definition file.
iniFile str The path to the INI file.
options dict The ArbitraryChartOptions object.

The result will be a JSON-encoded string, which can be parsed using any .NET JSON library, of this form:

{
    "Info": {
        "Timestamp": "04-Oct-2017 09:09:08",
        "Version": "Imatest 5.1.0.25883 Alpha ",
        "Build": "2017-10-03",
        "Calculation_time_seconds": [44.36107732]
    },
    "Results_array_sources": "C:\\images\\P1858_combination_chart_example.jpg",
    "Results": {
...
    }
}

First, create an ArbitraryChartOptions object:

Dim arbChartOptions As ArbitraryChartOptions
arbChartOptions = new ArbitraryChartOptions()
arbChartOptions.Encoding = ImageEncoding.sRGB
arbChartOptions.Width = 1296
arbChartOptions.Height = 808
Property Name Data Type Description
Width int Image width (in pixels)
Height int Image height (in pixels)
Encoding enum (ImageEncoding) The pixel encoding: ImageEncoding.sRGB ImageEncoding.Intensity
Filename string (direct read only) The name of the file, used for results file names.
Extension string (direct read only) The extension key used to decode the direct read image bytes, as configured in the Read Raw screen of Imatest Master.

Once you have the ArbitraryChartOptions object, you can then call the one of the ArbitraryCharts methods:

Public Function Separate(inputFile As String, chartFile As String, iniFile As String, options As ArbitraryChartOptions) As String
Public Function Separate(inputFiles As IEnumerable(Of String), chartFile As String, iniFile As String, options As ArbitraryChartOptions) As String
Public Function Separate(imageData() As Byte, chartFile As String, iniFile As String, options As ArbitraryChartOptions) As String
Public Function Separate(imageData() As UShort, chartFile As String, iniFile As String, options As ArbitraryChartOptions) As String
Public Function Separate(imageData() As UInteger, chartFile As String, iniFile As String, options As ArbitraryChartOptions) As String
Public Function SeparateAsync(inputFile As String, chartFile As String, iniFile As String, options As ArbitraryChartOptions) As Task(Of String)
Public Function SeparateAsync(inputFiles As IEnumerable(Of String), chartFile As String, iniFile As String, options As ArbitraryChartOptions) As Task(Of String)
Public Function SeparateAsync(imageData() As Byte, chartFile As String, iniFile As String, options As ArbitraryChartOptions) As Task(Of String)
Public Function SeparateAsync(imageData() As UShort, chartFile As String, iniFile As String, options As ArbitraryChartOptions) As Task(Of String)
Public Function SeparateAsync(imageData() As UInteger, chartFile As String, iniFile As String, options As ArbitraryChartOptions) As Task(Of String)
Public Function SignalAverage(inputFiles As IEnumerable(Of String), chartFile As String, iniFile As String, options As ArbitraryChartOptions) As String
Public Function SignalAverageAsync(inputFiles As IEnumerable(Of String), chartFile As String, iniFile As String, options As ArbitraryChartOptions) As Task(Of String)

The ArbitraryCharts.Separate methods will analyze multiple inputs separately, while the ArbitraryCharts.SignalAverage method will combine two images’ results into a single signal averaged result.

Parameter Name Data Type Description
inputFile(s) string or IEnumberable Either a file path to an image, or a list of file paths
imageData byte[], UInt16[], UInt32[] Raw image data (if you are using direct read mode)
chartFile str The path to the chart definition file.
iniFile str The path to the INI file.
options dict The ArbitraryChartOptions object.

The result will be a JSON-encoded string, which can be parsed using any .NET JSON library, of this form:

{
    "Info": {
        "Timestamp": "04-Oct-2017 09:09:08",
        "Version": "Imatest 5.1.0.25883 Alpha ",
        "Build": "2017-10-03",
        "Calculation_time_seconds": [44.36107732]
    },
    "Results_array_sources": "C:\\images\\P1858_combination_chart_example.jpg",
    "Results": {
...
    }
}

The Arbitrary Charts IT/EXE module has the following command-line interface

Usage: user_defined_charts.exe inputData chartFile iniFile averageMode optionsJsonFile

Positional arguments:
    inputData   the image file path
    chartFile   the chart definition file path
    iniFile     the Imatest INI file path
    averageMode  specify whether if groups of files are averaged (averageMode == 1) or not (averageMode == 0).
    optionsJsonFile  the file path to a JSON-encoded file that specifies the allowed options (see below)
    

The optionsJsonFile input corresponds to a JSON-encoded file with the following object properties:

Option Name Data Type Required? Description
encoding string Yes The data encoding format of the image data. For now the options are (case-insensitive):’intensity’, ‘sRGB’, ‘adobe_rgb’, ‘wide_gamut_rgb’, ‘pro_photo_rgb’, ‘apple_rgb’, ‘colormatch’, ‘rec_709_full’, ‘rec_709_legal’, ‘rec_2020_full’, ‘rec_2020_legal’, ‘aces’. Use ‘intensity’ for 1-channel grayscale data, while the others are for standard RGB encodings.
serial_number string No A string containing the serial number.
part_number string No A string containing the part number.
crop_borders double array No A 1 x 4 double array indicating the crop borders ( [Left Top Right Bottom] ).
lens_to_chart_distance_cm double No The lens to chart distance in cm.

To run the Arbitrary Charts module on a single image, as an example we can analyze using the sample image and chart definition file included with the C++ Arbitrary Charts sample. The image that is used in the sample has an sRGB encode. So we produce a JSON file that we arbitrarily name “options.json” and add the following contents

{
  "encoding": "sRGB"
}

We then run user_defined_charts.exe with

user_defined_charts.exe "C:\Program Files\Imatest\v24.2\IT\samples\cpp\arbitrary_charts\P1858_combination_chart_example.jpg" "C:\Program Files\Imatest\v24.2\IT\samples\cpp\arbitrary_charts\P1858_combination_variant.json" "C:\Program Files\Imatest\v24.2\IT\samples\cpp\Imatest_INI\imatest-v2.ini" "0" "options.json"

JSON results are saved to %HOMEDRIVE%%HOMEPATH%\Results by default.

The Arbitrary Charts IT/EXE module has the following command-line interface

Usage: user_defined_charts inputData chartFile iniFile averageMode optionsJsonFile

Positional arguments:
    inputData   the image file path
    chartFile   the chart definition file path
    iniFile     the Imatest INI file path
    averageMode  specify whether if groups of files are averaged (averageMode == 1) or not (averageMode == 0).
    optionsJsonFile  the file path to a JSON-encoded file that specifies the allowed options (see below)

The optionsJsonFile input corresponds to a JSON-encoded file with the following object properties:

Option Name Data Type Required? Description
encoding string Yes The data encoding format of the image data. For now the options are (case-insensitive):’intensity’, ‘sRGB’, ‘adobe_rgb’, ‘wide_gamut_rgb’, ‘pro_photo_rgb’, ‘apple_rgb’, ‘colormatch’, ‘rec_709_full’, ‘rec_709_legal’, ‘rec_2020_full’, ‘rec_2020_legal’, ‘aces’. Use ‘intensity’ for 1-channel grayscale data, while the others are for standard RGB encodings.
serial_number string No A string containing the serial number.
part_number string No A string containing the part number.
crop_borders double array No A 1 x 4 double array indicating the crop borders ( [Left Top Right Bottom] ).
lens_to_chart_distance_cm double No The lens to chart distance in cm.

To run the Arbitrary Charts module on a single image, as an example we can analyze using the sample image and chart definition file included with the Objective-C Arbitrary Charts sample provided for macOS, or the C++ Arbitrary Charts sample for Linux. The image that is used in the sample has an sRGB encode. So we produce a JSON file that we arbitrarily name “options.json” and add the following contents

{
  "encoding": "sRGB"
}

We then execute run_user_defined_charts.sh with

./run_user_defined_charts.sh "/Applications/Imatest/IT/v24.2/samples/images/P1858_combination_chart_example.jpg" "/Applications/Imatest/IT/v24.2/samples/images/P1858_combo_variant.json" "/Applications/Imatest/IT/v24.2/samples/Objective-C/Imatest_INI/imatest-v2.ini" "0" "options.json" 

JSON results are saved to $HOME/Results by default.

Concentric Rings Module

Interface Type:

Coming soon …

The signature of the concentric_rings_shell() function is as follows:

concentric_rings_shell(int nargout, mwArray& jsonManifest, const mwArray& imagePaths, const mwArray& iniFile);
Parameter Name Data Type Description
nargout int Number of output arguments. Set to 1.
jsonManifest mwArray& [const char*] The serialized JSON object array wrapped in a mwArray
imagePaths const mwArray& [const char*] A mwArray of type mxCELL_CLASS that contains a list of image file path strings or a mwArray of type mxCHAR_CLASS for a single image file path string
iniFile const mwArray& [const char*] The path for the Imatest INI file used for analysis

Single Image Example

For the case of a single image, it is simpler to assign the imagePaths to an mwArray of type mxCHAR_CLASS, like the following

// iniFilePath is the file path for the Imatest INI file
mwArray iniFilePath("..\\Imatest_INI\\imatest-v2.ini");

mwArray imagePaths(".\\concentric_rings_example.png");

mwArray jsonManifestFileList;
concentric_rings_shell(1, jsonManifestFileList, imagePaths, iniFilePath);

Multiple Images Example

For multiple images to be analyzed as a batch of separate images, the imagePaths parameter needs to be an mwArray of type mxCELL_CLASS, like as follows:

// iniFilePath is the file path for the Imatest INI file
mwArray iniFilePath("..\\Imatest_INI\\imatest-v2.ini");

mwArray imagePaths(1, 2, mxCELL_CLASS);
// The mwArray::Get() accessor uses a 1-based index with a prototype of the form
 // Get(num_indices, index1, ...)
imagePaths.Get(1, 1).Set(mwArray(".\\concentric_rings_example_1.png"));
imagePaths.Get(1, 2).Set(mwArray(".\\concentric_rings_example_2.png"));

mwArray jsonManifestFileList;
concentric_rings_shell(1, jsonManifestFileList, imagePaths, iniFilePath);

JSON Output

The jsonManifestFileList variable in the examples above contains a JSON encoded object with the following fields

{
    "summaryFiles": [
         // A list of file paths to the summary files for this run, which contain the results and settings used
     ],
    "plotFiles": [
        // A list of file paths to plots saved for this run.
    ]
}

Each file in “summaryFiles” is a JSON encoded object that includes results information as well as details of the analysis execution. The JSON object is as follows with “…” used to omit details for the sake of brevity.

{
  "concentric_ring": {
    "imatest": {
      ...
      "ini_file": {
        "filename": ...,
        "md5": ..."
      },
      ...
    },
    "inputs": {
      "image_file": {
        "filename": ...,
        "md5": ...
      },
      "settings": {
        ...
        }
      }
    },
    "results": {
      "regmark_data": {
        ...
      },
      "summary": {
        "fov": {
          ...
        },
        "field_angle": {
          ...
        }
      },
      "raw_data": {
        ...
      }
    }
  }
}

The signature of the concentric_rings_shell() function is as follows:

concentric_rings_shell(int nargout, mwArray& jsonManifest, const mwArray& imagePaths, const mwArray& iniFile);
Parameter Name Data Type Description
nargout int Number of output arguments. Set to 1.
jsonManifest mwArray& [const char*] The serialized JSON object array wrapped in a mwArray
imagePaths const mwArray& [const char*] A mwArray of type mxCELL_CLASS that contains a list of image file path strings or a mwArray of type mxCHAR_CLASS for a single image file path string
iniFile const mwArray& [const char*] The path for the Imatest INI file used for analysis

Single Image Example

For the case of a single image, it is simpler to assign the imagePaths to an mwArray of type mxCHAR_CLASS, like the following:

NSString* samplesRootPath = [[[[@__FILE__ stringByDeletingLastPathComponent] stringByDeletingLastPathComponent] stringByDeletingLastPathComponent] stringByDeletingLastPathComponent];
NSString* imageFolderPath = [[samplesRootPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"images"];

NSString* iniFolderPath = [samplesRootPath stringByAppendingPathComponent:@"Imatest_INI"];
NSString* iniFilePath = [iniFolderPath stringByAppendingPathComponent:@"imatest-v2.ini"];
NSString* imageFilePath = [imageFolderPath stringByAppendingPathComponent:@"concentric_rings_example.png"];

// iniFile is the file path for the Imatest INI file
mwArray iniFileParam([iniFilePath cStringUsingEncoding:NSASCIIStringEncoding]);

// In the next example, we utilize the fileListInput parameter instead
mwArray imagePathsInput([imageFilePath cStringUsingEncoding:NSASCIIStringEncoding]);

mwArray jsonManifest;
concentric_rings_shell(1, jsonManifest, imagePathsInput, iniFileParam);

Multiple Images Example

For multiple images to be analyzed as a batch of separate images, the imagePaths parameter needs to be an mwArray of type mxCELL_CLASS, like as follows:

NSString* samplesRootPath = [[[[@__FILE__ stringByDeletingLastPathComponent] stringByDeletingLastPathComponent] stringByDeletingLastPathComponent] stringByDeletingLastPathComponent];
NSString* imageFolderPath = [[samplesRootPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"images"];

NSString* iniFolderPath = [samplesRootPath stringByAppendingPathComponent:@"Imatest_INI"];
NSString* iniFilePath = [iniFolderPath stringByAppendingPathComponent:@"imatest-v2.ini"];
NSString* imageFilePath1 = [imageFolderPath stringByAppendingPathComponent:@"concentric_rings_example_1.png"];
NSString* imageFilePath2 = [imageFolderPath stringByAppendingPathComponent:@"concentric_rings_example_2.png"];

// iniFile is the file path for the Imatest INI file
mwArray iniFileParam([iniFilePath cStringUsingEncoding:NSASCIIStringEncoding]);

// In the next example, we utilize the imagePathsInput parameter instead
mwArray imagePathsInput(1, 2, mxCELL_CLASS);
// The mwArray::Get() accessor uses a 1-based index with a prototype of the form
// Get(num_indices, index1, ...)
imagePathsInput.Get(1, 1).Set(mwArray([imageFilePath1 cStringUsingEncoding:NSASCIIStringEncoding]));
imagePathsInput.Get(1, 2).Set(mwArray([imageFilePath2 cStringUsingEncoding:NSASCIIStringEncoding]));

mwArray jsonManifest;
concentric_rings_shell(1, jsonManifest, imagePathsInput, iniFileParam);

JSON Output

The jsonManifestFileList variable in the examples above contains a JSON encoded object with the following fields

{
    "summaryFiles": [
         // A list of file paths to the summary files for this run, which contain the results and settings used
     ],
    "plotFiles": [
        // A list of file paths to plots saved for this run.
    ]
}

Each file in “summaryFiles” is a JSON encoded object that includes results information as well as details of the analysis execution. The JSON object is as follows with “…” used to omit details for the sake of brevity.

{
  "concentric_ring": {
    "imatest": {
      ...
      "ini_file": {
        "filename": ...,
        "md5": ..."
      },
      ...
    },
    "inputs": {
      "image_file": {
        "filename": ...,
        "md5": ...
      },
      "settings": {
        ...
        }
      }
    },
    "results": {
      "regmark_data": {
        ...
      },
      "summary": {
        "fov": {
          ...
        },
        "field_angle": {
          ...
        }
      },
      "raw_data": {
        ...
      }
    }
  }
}

Concentric Ring analysis is accomplished using one of the following overloaded methods in Imatest.IT.Library.ConcentricRings:

string JSON(string iniFilePath, string[] imageFilePaths)
string JSON(string iniFilePath, string imageFilePath)
async Task<string> JSONAsync(string iniFilePath, string[] imageFilePaths)
async Task<string> JSONAsync(string iniFilePath, string imageFilePath)

Example

Below is an example Concentric Rings analysis with exception handling details omitted with “…” for the sake of brevity.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Imatest.IT;

namespace Imatest.IT.Samples.ConcentricRings
{
    class Program
    {
        /*
        * This code will execute the Imatest Concentric Rings function on the file
        * 'concentric_rings_example.png' which should be a capture of a concentric rings test chart.
        *
        * */
        public const string EXAMPLE_IMAGE = "concentric_rings_example.png";

        static void Main(string[] args)
        {
            using (Library lib = new Library())
            {
                try
                {
                    DirectoryInfo currentDirectory = new DirectoryInfo(Directory.GetCurrentDirectory());

                    string rootDir = currentDirectory.Parent.Parent.Parent.FullName;
                    string iniFilePath = Path.Combine(rootDir, "imatest-v2.ini");

                    // C:\Program Files\Imatest\v24.2\IT\samples\images
                    string sampleImagesDir = Path.Combine(currentDirectory.Parent.Parent.Parent.Parent.Parent.Parent.FullName, "images");

                    List<string> imagePaths = new List<string> {
                        Path.Combine(sampleImagesDir, EXAMPLE_IMAGE),
                    };

                    // Call Imatest IT library with JSON output
                    string jsonManifestFileList = lib.ConcentricRings.JSON(iniFilePath, imagePaths.ToArray());

                    Console.Out.WriteLine(result);
                }
                catch (Exception ex)
                {
                    ...
                }
            }
            Console.Out.WriteLine("Press enter to exit...");
            Console.In.Read();
        }
    }
}

JSON Output

The jsonManifestFileList variable in the examples above contains a JSON encoded object with the following fields

{
    "summaryFiles": [
         // A list of file paths to the summary files for this run, which contain the results and settings used
     ],
    "plotFiles": [
        // A list of file paths to plots saved for this run.
    ]
}

Each file in “summaryFiles” is a JSON encoded object that includes results information as well as details of the analysis execution. The JSON object is as follows with “…” used to omit details for the sake of brevity.

{
  "concentric_ring": {
    "imatest": {
      ...
      "ini_file": {
        "filename": ...,
        "md5": ..."
      },
      ...
    },
    "inputs": {
      "image_file": {
        "filename": ...,
        "md5": ...
      },
      "settings": {
        ...
        }
      }
    },
    "results": {
      "regmark_data": {
        ...
      },
      "summary": {
        "fov": {
          ...
        },
        "field_angle": {
          ...
        }
      },
      "raw_data": {
        ...
      }
    }
  }
}

Concentric Ring analysis is accomplished using one of the following overloaded methods in Imatest.IT.Library.ConcentricRings:

JSON(iniFilePath as String, imageFilePaths as String()) as String
string JSON(iniFilePath as String, string imageFilePath as String) as String
<Awaitable> JSONAsync(iniFilePath as String, string[] imageFilePaths) as Task(Of String)
<Awaitable> JSONAsync(iniFilePath as String, imageFilePath as String) as Task(Of String)

Example

Below is an example Concentric Rings analysis with exception handling details omitted with “…” for the sake of brevity.

Imports System.IO
Imports Imatest.IT


Module Program
    ' In this example program, the image files should be located
    ' in the same directory as this example script, and the 'imatest-v2.ini' file
    ' should be located in the "ini_file" directory in the Python samples directory.
    '
    ' Certain diagnostic lines are written to standard out for diag.
    '

    Public Const EXAMPLE_IMAGE As String = "concentric_rings_example.png"

    Public Sub Main()
        Using library = New Library()
            Try
                Dim currentDirectory As DirectoryInfo
                Dim rootDir As String
                Dim iniFilePath As String
                Dim sampleImagesDir As String
                Dim jsonManifestFileList As String
                Dim imagePaths(1) As String

                currentDirectory = New DirectoryInfo(Directory.GetCurrentDirectory())
                rootDir = currentDirectory.Parent.Parent.Parent.FullName
                iniFilePath = Path.Combine(rootDir, "imatest-v2.ini")
                ' C:\Program Files\Imatest\v24.2\IT\samples\images
                sampleImagesDir = Path.Combine(currentDirectory.Parent.Parent.Parent.Parent.Parent.Parent.FullName, "images")

                imagePaths(0) = Path.Combine(sampleImagesDir, EXAMPLE_IMAGE)

                ' Call Imatest IT library with JSON output
                jsonManifestFileList = library.ConcentricRings.JSON(iniFilePath, imagePaths)

                Console.Out.WriteLine(result)

            Catch ex As Exception
                ...
            End Try
        End Using

        Console.Out.WriteLine("Press enter to exit...")
        Console.In.Read()
    End Sub
End Module

JSON Output

The jsonManifestFileList variable in the examples above contains a JSON encoded object with the following fields

{
    "summaryFiles": [
         // A list of file paths to the summary files for this run, which contain the results and settings used
     ],
    "plotFiles": [
        // A list of file paths to plots saved for this run.
    ]
}

Each file in “summaryFiles” is a JSON encoded object that includes results information as well as details of the analysis execution. The JSON object is as follows with “…” used to omit details for the sake of brevity.

{
  "concentric_ring": {
    "imatest": {
      ...
      "ini_file": {
        "filename": ...,
        "md5": ..."
      },
      ...
    },
    "inputs": {
      "image_file": {
        "filename": ...,
        "md5": ...
      },
      "settings": {
        ...
        }
      }
    },
    "results": {
      "regmark_data": {
        ...
      },
      "summary": {
        "fov": {
          ...
        },
        "field_angle": {
          ...
        }
      },
      "raw_data": {
        ...
      }
    }
  }
}

Concentric Rings IT/EXE has the following command line interface:

Concentric Rings IT/EXE
Usage: concentric_rings_exe [OPTIONS] ini-file image-paths...

Positionals:
  ini-file TEXT REQUIRED      The path to the Imatest INI file.
  image-paths TEXT ... REQUIRED
                              One or more image file paths 

Options:
  -h,--help                   Print this help message and exit
  -v,--version                Display program version information and exit
  --echo-result-manifest      After a successful run, echo the result manifest json to stdout.

Example

concentric_rings_exe "path\to\imatest-v2.ini" "another\path\my_image.jpg"

Concentric Rings IT/EXE has the following command line interface:

Concentric Rings IT/EXE
Usage: concentric_rings_exe [OPTIONS] ini-file image-paths...

Positionals:
  ini-file TEXT REQUIRED      The path to the Imatest INI file.
  image-paths TEXT ... REQUIRED
                              One or more image file paths 

Options:
  -h,--help                   Print this help message and exit
  -v,--version                Display program version information and exit
  --echo-result-manifest      After a successful run, echo the result manifest json to stdout.

Example

./run_concentric_rings_exe.sh "path/to/imatest-v2.ini"  "another/path/to/my_image.jpg"

Stray Light Module

Interface Type:

Coming soon…

The signature of the stray_light_shell() function is as follows:

stray_light_shell(int nargout, mwArray& jsonManifest, const mwArray& iniFilePath, const mwArray& configInput, const mwArray& fileListInput)
Parameter Name Data Type Description
nargout int The number of expected output arguments. This will be set to 1.
jsonManifest mwArray& [const char*] The serialized JSON object array wrapped in a mwArray
iniFilePath const mwArray& [const char*] The path for the Imatest INI file used for analysis
configInput const mwArray& [const char*] An mwArray containing either a file path to a Stray Light config file (*.slconfig), or a Stray Light config in the form of a JSON-encoded string
fileListInput const mwArray& [const char*] A mwArray of type mxCELL_CLASS that contains a list of image file path strings

The stray_light_shell() function has two mutually exclusive use cases:

  • Input only a list of file paths via the fileListInput parameter, with configInput left an empty mwArray. This is a simplified interface that provides the bare-minimum information for analysis: the image files.
  • Construct an imatest::stray_light::Config object and pass it in through the configInput parameter, which provides a means to input source field angles and azimuth angles associated with each input image file.

File list input example

In the example below, we set up a Stray Light analysis and supply only a list of files (see the Stray Light C++ sample for more details). Each file is assumed to be of a separate capture condition in this analysis.

// In the next example, we utilize the fileListInput parameter instead (and leave the ConfigInput parameter empty).

// iniFilePath is the file path for the Imatest INI file
mwArray iniFilePath("..\\Imatest_INI\\imatest-v2.ini");

mwArray fileListInput(4, 1, mxCELL_CLASS);
// The mwArray::Get() accessor uses a 1-based index with a prototype of the form
// Get(num_indices, index1, ...)
fileListInput.Get(1, 1).Set(mwArray(".\\cap031_Az_90_Fa_0.png"));
fileListInput.Get(1, 2).Set(mwArray(".\\cap039_Az_90_Fa_8.png"));
fileListInput.Get(1, 3).Set(mwArray(".\\cap058_Az_90_Fa_27.png"));
fileListInput.Get(1, 4).Set(mwArray(".\\cap061_Az_90_Fa_30.png"));

// Call the library function
mwArray jsonManifest;
stray_light_shell(1, jsonManifest, iniFilePath, mwArray(), fileListInput);

When stray_light_shell() completes, the results are returned in the jsonManifest mwArray as a JSON-encoded string. By default, this JSON object is structured as follows:

{
    "masks": [
        // ... file paths to saved masks ...
    ],
    "metric_images" : [
        // ... file paths to saved metric images ...
    ],
    "plots" : [
        // ... file paths to saved plots ...
    ],
    "videos" : [
        // ... file paths to saved videos ...
    ],
    "results" : [
        // ... file paths to saved results files ...
    ]
}

where each field in the JSON object contains an array of path strings.

Config input example

The next example (also borrowed from the Stray Light C++ sample) make use of the Config and CaptureConfig defined in the imatest::stray_light namespace (see StrayLightConfig.h/.cpp and StrayLightCaptureConfig.h/.cpp included in <IT install root>/libs/library/cpp).

using imatest::stray_light::Config;
using imatest::stray_light::CaptureConfig;

// iniFilePath is the file path for the Imatest INI file
mwArray iniFilePath("..\\Imatest_INI\\imatest-v2.ini");

// First we construct a imatest::stray_light::Config.
// In this example we have 4 images taken with the following capture conditions:
// ".\\cap031_Az_90_Fa_0.png":
//    source field angle: 0 degrees
//    source azimuth angle: 90 degrees
// ".\\cap039_Az_90_Fa_8.png":
//    source field angle: 8 degrees
//    source azimuth angle: 90 degrees
// ".\\cap058_Az_90_Fa_27.png":
//    source field angle: 27 degrees
//    source azimuth angle: 90 degrees
// ".\\cap061_Az_90_Fa_30.png":
//    source field angle: 30 degrees
//    source azimuth angle: 90 degrees

Config config;
config.runName = "Test run";
config.comment = "Test run within the Imatest IT sample for Stray Light";
config.captures.emplace_back(CaptureConfig({ ".\\cap031_Az_90_Fa_0.png" }, 0, 90, "On-Axis"));
config.captures.emplace_back(CaptureConfig({ ".\\cap039_Az_90_Fa_8.png" }, 8, 90, "Mid-Field"));
config.captures.emplace_back(CaptureConfig({ ".\\cap058_Az_90_Fa_27.png" }, 27, 90, "Edge Of FOV"));
config.captures.emplace_back(CaptureConfig({ ".\\cap061_Az_90_Fa_30.png" }, 30, 90, "Out Of FOV"));

mwArray configInput(config);

// Call the library function
mwArray jsonManifest;
stray_light_shell(1, jsonManifest, iniFilePath, configInput, mwArray());

with the results returned as JSON encoded string within the jsonManifest mwArray, as before.

The signature of the stray_light_shell() function is as follows:

stray_light_shell(int nargout, mwArray& jsonManifest, const mwArray& iniFilePath, const mwArray& configInput, const mwArray& fileListInput)
Parameter Name Data Type Description
nargout int The number of expected output arguments. This will be set to 1.
jsonManifest mwArray& [const char*] The serialized JSON object array wrapped in a mwArray
iniFilePath const mwArray& [const char*] The path for the Imatest INI file used for analysis
configInput const mwArray& [const char*] An mwArray containing either a file path to a Stray Light config file (*.slconfig), or a Stray Light config in the form of a JSON-encoded string
fileListInput const mwArray& [int] A mwArray of type mxCELL_CLASS that contains a list of image file path strings

The stray_light_shell() function has two mutually exclusive use cases:

  • Input only a list of file paths via the fileListInput parameter, with configInput left an empty mwArray. This is a simplified interface that provides the bare-minimum information for analysis: the image files.
  • Construct an imatest::stray_light::Config object and pass it in through the configInput parameter, which provides a means to input source field angles and azimuth angles associated with each input image file.

File list input example

In the example below, we set up a Stray Light analysis and supply only a list of files (see the Stray Light Objective-C sample for more details). Each file is assumed to be of a separate capture condition in this analysis.

// In the next example, we utilize the fileListInput parameter instead (and leave the ConfigInput parameter empty).

NSString* samplesRootPath = [[[@__FILE__ stringByDeletingLastPathComponent] stringByDeletingLastPathComponent] stringByDeletingLastPathComponent];
NSString* imageFolderPath = [[samplesRootPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"images"];

NSString* iniFolderPath = [samplesRootPath stringByAppendingPathComponent:@"Imatest_INI"];
NSString* iniFilePath = [iniFolderPath stringByAppendingPathComponent:@"imatest-v2.ini"];
NSString* imageFilePath1 = [imageFolderPath stringByAppendingPathComponent:@"cap031_Az_90_Fa_0.png"];
NSString* imageFilePath2 = [imageFolderPath stringByAppendingPathComponent:@"cap039_Az_90_Fa_8.png"];
NSString* imageFilePath3 = [imageFolderPath stringByAppendingPathComponent:@"cap058_Az_90_Fa_27.png"];
NSString* imageFilePath4 = [imageFolderPath stringByAppendingPathComponent:@"cap061_Az_90_Fa_30.png"];

// iniFile is the file path for the Imatest INI file
mwArray iniFileParam([iniFilePath cStringUsingEncoding:NSASCIIStringEncoding]);

mwArray fileListInput(4, 1, mxCELL_CLASS);
// The mwArray::Get() accessor uses a 1-based index with a prototype of the form
// Get(num_indices, index1, ...)
fileListInput.Get(1, 1).Set(mwArray([imageFilePath1 cStringUsingEncoding:NSASCIIStringEncoding]));
fileListInput.Get(1, 2).Set(mwArray([imageFilePath2 cStringUsingEncoding:NSASCIIStringEncoding]));
fileListInput.Get(1, 3).Set(mwArray([imageFilePath3 cStringUsingEncoding:NSASCIIStringEncoding]));
fileListInput.Get(1, 4).Set(mwArray([imageFilePath4 cStringUsingEncoding:NSASCIIStringEncoding]));
// Call the library function
mwArray jsonManifest;
stray_light_shell(1, jsonManifest, iniFilePath, mwArray(), fileListInput);

When stray_light_shell() completes, the results are returned in the jsonManifest mwArray as a JSON-encoded string. By default, this JSON object is structured as follows:

{
    "masks": [
        // ... file paths to saved masks ...
    ],
    "metric_images" : [
        // ... file paths to saved metric images ...
    ],
    "plots" : [
        // ... file paths to saved plots ...
    ],
    "videos" : [
        // ... file paths to saved videos ...
    ],
    "results" : [
        // ... file paths to saved results files ...
    ]
}

where each field in the JSON object contains an array of path strings.

Config input example

The next example (also borrowed from the Stray Light C++ sample) make use of the Config and CaptureConfig defined in the imatest::stray_light namespace (see StrayLightConfig.h/.cpp and StrayLightCaptureConfig.h/.cpp included in <IT install root>/libs/library/cpp).

NSString* samplesRootPath = [[[@__FILE__ stringByDeletingLastPathComponent] stringByDeletingLastPathComponent] stringByDeletingLastPathComponent];
NSString* imageFolderPath = [[samplesRootPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"images"];
NSString* iniFolderPath = [samplesRootPath stringByAppendingPathComponent:@"Imatest_INI"];

NSString* iniFilePath = [iniFolderPath stringByAppendingPathComponent:@"imatest-v2.ini"]; NSString* imageFilePath1 = [imageFolderPath stringByAppendingPathComponent:@"cap031_Az_90_Fa_0.png"];
NSString* imageFilePath2 = [imageFolderPath stringByAppendingPathComponent:@"cap039_Az_90_Fa_8.png"];
NSString* imageFilePath3 = [imageFolderPath stringByAppendingPathComponent:@"cap058_Az_90_Fa_27.png"];
NSString* imageFilePath4 = [imageFolderPath stringByAppendingPathComponent:@"cap061_Az_90_Fa_30.png"];

// iniFile is the file path for the Imatest INI file
mwArray iniFileParam([iniFilePath cStringUsingEncoding:NSASCIIStringEncoding]);

// First we construct a imatest::stray_light::Config.
// In this example we have 4 images taken with the following capture conditions:
// "cap031_Az_90_Fa_0.png":
//    source field angle: 0 degrees
//    source azimuth angle: 90 degrees
// "cap039_Az_90_Fa_8.png":
//    source field angle: 8 degrees
//    source azimuth angle: 90 degrees
// "cap058_Az_90_Fa_27.png":
//    source field angle: 27 degrees
//    source azimuth angle: 90 degrees
// "cap061_Az_90_Fa_30.png":
//    source field angle: 30 degrees
//    source azimuth angle: 90 degrees

imatest::stray_light::Config config;

config.runName = "Test run";

config.comment = "Test run within the Imatest IT sample for Stray Light";

config.captures.emplace_back(imatest::stray_light::CaptureConfig({ [imageFilePath1 cStringUsingEncoding:NSASCIIStringEncoding] }, 0, 90, "On-Axis")); 
config.captures.emplace_back(imatest::stray_light::CaptureConfig({ [imageFilePath2 cStringUsingEncoding:NSASCIIStringEncoding] }, 8, 90, "Mid-Field")); 
config.captures.emplace_back(imatest::stray_light::CaptureConfig({ [imageFilePath3 cStringUsingEncoding:NSASCIIStringEncoding] }, 27, 90, "Edge Of FOV")); 
config.captures.emplace_back(imatest::stray_light::CaptureConfig({ [imageFilePath4 cStringUsingEncoding:NSASCIIStringEncoding] }, 30, 90, "Out Of FOV")); 

mwArray configInputParam(config); // Call the library function 
mwArray jsonManifest; 
stray_light_shell(1, jsonManifest, iniFileParam, configInputParam, mwArray());

with the results returned as JSON encoded string within the jsonManifest mwArray, as before.

Stray light analysis can proceed a few different ways depending on what additional testing condition data is available.

  • Input only a list of file paths via the fileList input parameter. This is a simplified interface that provides the bare-minimum information for analysis: the image files.
  • Construct an StrayLightConfig object and pass it in through the config input parameter, which provides a means to input source field angles and azimuth angles associated with each input image file.
  • Provide a file path to a serialized StrayLightConfig (i.e. a JSON-encoded file with the extension *.slconf).

The StrayLightConfig class has the following properties:

Property Name Data Type Description
Captures IEnumerable<StrayLightCaptureConfig> The collection of captures used for this analysis.
RunName string An optional run name to assign to this analysis.
Comment string An optional comment about the configuration, test setup, etc.

, where the StrayLightCaptureConfig class has the properties

Property Name Data Type Description
ImagePaths IEnumerable<string> The collection of image file paths all taken at this source field angle and source azimuth angle.
SourceFieldAngleDeg double The source field angle in degrees.
SourceAzimuthAngleDeg double The source azimuth angle in degrees.
Comment string An optional comment for this collection of images.

Depending on the input data source, analysis can then proceed via one of the overloaded methods in the Imatest.IT.Library.StrayLight library methods:

string Batch(string iniFilePath, StrayLightConfig config)
async Task<string> BatchAsync(string iniFilePath, StrayLightConfig config)
string Batch(string iniFilePath, string configFilePath)
async Task<string> BatchAsync(string iniFilePath, string configFilePath)
string Batch(string iniFilePath, String[] fileList)
async Task<string> BatchAsync(string iniFilePath, String[] fileList)

To demonstrate the functionality, below we walk through an example (which is largely identical to the example installed at <IT install root>/samples/.NET/C#/StrayLight, but with details omitted with … for brevity). To set up the analysis we initiate an Imatest.IT.Library instance and define the Imatest INI and image file paths.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization.Json;
using System.Threading.Tasks;

using MathWorks.MATLAB.NET.Arrays;
using Imatest.IT;

class Program
{
    public const string EXAMPLE_IMAGE_1 = "cap031_Az_90_Fa_0.png";
    public const string EXAMPLE_IMAGE_2 = "cap039_Az_90_Fa_8.png";
    public const string EXAMPLE_IMAGE_3 = "cap058_Az_90_Fa_27.png";
    public const string EXAMPLE_IMAGE_4 = "cap061_Az_90_Fa_30.png";
    static void Main(string[] args)
    {
        using (Library lib = new Library())
        {
            try
            {
                DirectoryInfo currentDirectory = new DirectoryInfo(Directory.GetCurrentDirectory());
                string rootDir = ... ;
                string iniFilePath = Path.Combine(rootDir, "imatest-v2.ini");

                string sampleImagesDir = ... ;
                List<string> imagePaths = new List<string> {
                    Path.Combine(sampleImagesDir, EXAMPLE_IMAGE_1),
                    Path.Combine(sampleImagesDir, EXAMPLE_IMAGE_2),
                    Path.Combine(sampleImagesDir, EXAMPLE_IMAGE_3),
                    Path.Combine(sampleImagesDir, EXAMPLE_IMAGE_4)
                };

next we construct a List<StrayLightCaptureConfig> from the image file paths

                List<StrayLightCaptureConfig> captureConfigs = new List<StrayLightCaptureConfig>();

                foreach (string imagePath in imagePaths) {
                    captureConfigs.Add(new StrayLightCaptureConfig(new List<string> { imagePath }));
                } 

and then construct a StrayLightConfig instance from the List<StrayLightCaptureConfig>.

                StrayLightConfig config = new StrayLightConfig(captureConfigs);  

Lastly we supply the StrayLightConfig instance and the INI file path to Imatest.IT.StrayLight.Batch() and execute

                // Call Imatest IT library with JSON output
                string result = lib.StrayLight.Batch(iniFilePath, config);

                Console.Out.WriteLine(result);
            }
            catch (Exception ex)
            {

                ...

            }
        }
        
       }
}

Imatest.IT.StrayLight.Batch() will return a JSON-encoded string of the form

{
    "masks": [
        // ... file paths to saved masks ...
    ],
    "metric_images" : [
        // ... file paths to saved metric images ...
    ],
    "plots" : [
        // ... file paths to saved plots ...
    ],
    "videos" : [
        // ... file paths to saved videos ...
    ],
    "results" : [
        // ... file paths to saved results files ...
    ]
}

which lists the file paths of any file produced by the analysis.

Stray light analysis can proceed a few different ways depending on what additional testing condition data is available.

  • Input only a list of file paths via the fileList input parameter. This is a simplified interface that provides the bare-minimum information for analysis: the image files.
  • Construct an StrayLightConfig object and pass it in through the config input parameter, which provides a means to input source field angles and azimuth angles associated with each input image file.
  • Provide a file path to a serialized StrayLightConfig (i.e. a JSON-encoded file with the extension *.slconf).

The StrayLightConfig class has the following properties:

Property Name Data Type Description
Captures IEnumerable<StrayLightCaptureConfig> The collection of captures used for this analysis.
RunName string An optional run name to assign to this analysis.
Comment string An optional comment about the configuration, test setup, etc.

, where the StrayLightCaptureConfig class has the properties

Property Name Data Type Description
ImagePaths IEnumerable<string> The collection of image file paths all taken at this source field angle and source azimuth angle.
SourceFieldAngleDeg double The source field angle in degrees.
SourceAzimuthAngleDeg double The source azimuth angle in degrees.
Comment string An optional comment for this collection of images.

Depending on the input data source, analysis can then proceed via one of the overloaded methods in the Imatest.IT.Library.StrayLight library methods:

Public Function Batch(iniFilePath as String, config as StrayLightConfig) as  String
Public Function BatchAsync(iniFilePath as String, config as StrayLightConfig) As Task(Of String) 
Public Function Batch(iniFilePath as String, configFilePath as String) as String
Public Function BatchAsync(iniFilePath as String, configFilePath as String) As Task(Of String)
Public Function Batch(string iniFilePath, fileList as String()) as String
Public Function BatchAsync(iniFilePath as String, fileList as String()) As Task(Of String)

To demonstrate the functionality, below we walk through an example (which is largely identical to the example installed at <IT install root>/samples/.NET/VB.NET/StrayLight, but with details omitted with … for brevity). To set up the analysis we initiate an Imatest.IT.Library instance, declare needed variables, and define the Imatest INI and image file paths.

Imports System.IO
Imports Imatest.IT


Module Program

    Public Const EXAMPLE_IMAGE_1 As String = "cap031_Az_90_Fa_0.png"
    Public Const EXAMPLE_IMAGE_2 As String = "cap039_Az_90_Fa_8.png"
    Public Const EXAMPLE_IMAGE_3 As String = "cap058_Az_90_Fa_27.png"
    Public Const EXAMPLE_IMAGE_4 As String = "cap061_Az_90_Fa_30.png"

    Public Sub Main()
        Using library = New Library()
            Try
                Dim currentDirectory As DirectoryInfo
                Dim rootDir As String
                Dim iniFilePath As String
                Dim sampleImagesDir As String
                Dim result As String
                Dim captureConfigs(3) As StrayLightCaptureConfig
                Dim captureConfig As StrayLightConfig

                rootDir = ...
                iniFilePath = Path.Combine(rootDir, "imatest-v2.ini")
                sampleImagesDir = ...

next we construct the StrayLightCaptureConfig array from the image file paths

                captureConfigs(0) = New StrayLightCaptureConfig(New String() {Path.Combine(sampleImagesDir, EXAMPLE_IMAGE_1)})
                captureConfigs(1) = New StrayLightCaptureConfig(New String() {Path.Combine(sampleImagesDir, EXAMPLE_IMAGE_2)})
                captureConfigs(2) = New StrayLightCaptureConfig(New String() {Path.Combine(sampleImagesDir, EXAMPLE_IMAGE_3)})
                captureConfigs(3) = New StrayLightCaptureConfig(New String() {Path.Combine(sampleImagesDir, EXAMPLE_IMAGE_4)})


and then construct a StrayLightConfig instance from the List<StrayLightCaptureConfig>.

                captureConfig = New StrayLightConfig(captureConfigs)

Lastly we supply the StrayLightConfig instance and the INI file path to Imatest.IT.StrayLight.Batch() and execute

                ' Call Imatest IT library with JSON output without Stray Light Config values
                result = library.StrayLight.Batch(iniFilePath, captureConfig)

            Catch ex As Exception
                ...
            End Try
        End Using

    End Sub
End Module


Imatest.IT.StrayLight.Batch() will return a JSON-encoded string of the form

{
    "masks": [
        // ... file paths to saved masks ...
    ],
    "metric_images" : [
        // ... file paths to saved metric images ...
    ],
    "plots" : [
        // ... file paths to saved plots ...
    ],
    "videos" : [
        // ... file paths to saved videos ...
    ],
    "results" : [
        // ... file paths to saved results files ...
    ]
}

which lists the file paths of any file produced by the analysis.

The Stray Light IT/EXE module has the following command-line interface

 stray_light_exe --help
Usage: stray_light_exe [--echo-result-manifest] [--help] iniFilePath [configFilePath] [imageFileList] 

Analyze stray light images via the stray light module

Positional arguments:
	iniFilePath   		The full path to the INI file.
	configFilePath		The full path to the analysis config file.
	imageFileList 		The full path to all image files to analyze.

Options:
	--echo-result-manifest		After a successful run, echo the result manifest json to stdout.
	-h, --help            		Display this help information.

The Stray Light IT/EXE interface has two mutually exclusive use cases:

  • Input only a list of file paths via the imageFileList parameter, with configFilePath left an empty string. This is a simplified interface that provides the bare-minimum information for analysis: the image files.
  • Supply a file path to an *.slconf file, which provides a means to input source field angles and azimuth angles associated with each input image file. *.slconf are a JSON encoded file that can be generated from a StrayLightConfig object in the IT/Python interface, or the equivalent class in the C++, C# or VB.NET interfaces. This *.slconf file provides more information to the Stray Light module and thus a richer analysis.

To execute stray_light_shell.exe, supply the require filed paths as below

stray_light_exe.exe "imatest-v2.ini" "my_capture.slconf"

The Stray Light IT/EXE module has the following command-line interface

 stray_light_exe --help
Usage: stray_light_exe [--echo-result-manifest] [--help] iniFilePath [configFilePath] [imageFileList] 

Analyze stray light images via the stray light module

Positional arguments:
	iniFilePath   		The full path to the INI file.
	configFilePath		The full path to the analysis config file.
	imageFileList 		The full path to all image files to analyze.

Options:
	--echo-result-manifest		After a successful run, echo the result manifest json to stdout.
	-h, --help            		Display this help information.

The Stray Light IT/EXE interface has two mutually exclusive use cases:

  • Input only a list of file paths via the imageFileList parameter, with configFilePath left an empty string. This is a simplified interface that provides the bare-minimum information for analysis: the image files.
  • Supply a file path to an *.slconf file, which provides a means to input source field angles and azimuth angles associated with each input image file. *.slconf are a JSON encoded file that can be generated from a StrayLightConfig object in the IT/Python interface, or the equivalent class in the C++, C# or VB.NET interfaces. This *.slconf file provides more information to the Stray Light module and thus a richer analysis.

To execute stray_light_shell.exe, supply the require filed paths as below

./run_stray_light_exe.sh "imatest-v2.ini" "my_capture.slconf"

Troubleshooting