
DigitalZoom C++ library
v1.3.2
Table of contents
- Overview
- Versions
- Library files
- DigitalZoom class description
- DigitalZoom class declaration
- getVersion method
- initVFilter method
- setParam method
- getParam method
- getParams method
- executeCommand method
- processFrame method
- setMask method
- encodeSetParamCommand method of VFilter class
- encodeCommand method of VFilter class
- decodeCommand method of VFilter class
- decodeAndExecuteCommand method
- Data structures
- VFilterParams class description
- Build and connect to your project
- Portability
- Example
Overview
DigitalZoom C++ library implements digital zoom using bicubic interpolation provided by the ImageResizer module (SIMD-optimized; ImageResizer uses OpenMP and the G2D library only if they are found at build time). The library supports digital zoom level from x1 to x20. The library depends on VFilter library (provides interface for video filter) and ImageResizer library. VFilter depends on Frame and ConfigReader libraries. All these libraries are separate repositories: they have to be placed next to the DigitalZoom repository (see Build and connect to your project). The library doesn’t have third-party dependencies to be installed in OS. Additionally test application depends on SimpleUI library to provide user interface. The library uses C++17 standard.
DigitalZoom is general-purpose software: it is not tied to any sector or application, and the developer of a program decides what the program does with it.
Versions
Table 1 - Library versions.
| Version | Release date | What’s new |
|---|---|---|
| 1.0.0 | 25.02.2024 | First version of the library. |
| 1.0.1 | 24.03.2024 | - VFilter class updated. - Documentation updated. |
| 1.0.2 | 21.05.2024 | - VFilter class updated. - Documentation updated. |
| 1.0.3 | 19.07.2024 | - VFilter class updated. - CMake updated. |
| 1.1.0 | 23.07.2024 | - Files structure changed. |
| 1.2.0 | 07.04.2026 | - OpenCV dependency removed from the library. - ImageResizer module used for image resizing (bicubic interpolation). - TYPE parameter is no longer supported. |
| 1.2.1 | 26.08.2026 | - ImageResizer submodule updated. |
| 1.3.0 | 12.09.2026 | - ImageResizer submodule updated. - Added number of threads control. |
| 1.3.2 | 18.10.2026 | - Sub-repositories removed: the Frame, ConfigReader, VFilter, ImageResizer and SimpleUI repositories have to be cloned next to the DigitalZoom repository. - Fixed: DigitalZoom::getVersion() returned the version of the VFilter class, it returns the version of the DigitalZoom class now. - Fixed: -Ofast, -march=native, /fp:fast and /arch:AVX2 are not used any more. With these options a build with GCC calculated the size of the zoomed part with an approximated reciprocal (the picture was changed at level 1.0), builds with MSVC and Clang gave a different size of the zoomed part for some levels (for example 185 / 3.7), the checks of NaN were removed and the library could not be built for ARM64 with a cross compiler. The result is the same on all compilers now. - setParam(…) and initVFilter(…) reject NaN, infinity and values outside of the valid range (a NaN level, a NaN mode and a number of threads outside of the int range were accepted or caused undefined behavior). initVFilter(…) changes nothing if a value is invalid. - processFrame(…) checks the data pointer and the data size of the frame before the pixels are read or written, calculates the sizes with 64-bit integers, returns FALSE instead of throwing std::bad_alloc and measures the processing time with a monotonic clock. - Strict compiler warnings, exploit mitigation compiler and linker options, standard C++ only. The warning D9025 of MSVC is fixed. - The test application has the –selftest mode with automatic tests and returns a non-zero exit code on errors. - Documentation updated. |
Library files
The library supplied by source code only. The user would be given a set of files in the form of a CMake project (repository). The repository structure is shown below:
CMakeLists.txt --------------- Main CMake file of the library.
src -------------------------- Folder with source code of the library.
CMakeLists.txt ----------- CMake file of the library.
DigitalZoom.cpp ---------- C++ implementation file.
DigitalZoom.h ------------ Header file which includes DigitalZoom class declaration.
DigitalZoomVersion.h ----- Header file which includes version of the library.
DigitalZoomVersion.h.in -- CMake service file to generate version file.
test ------------------------- Folder for test application.
CMakeLists.txt ----------- CMake file for test application.
main.cpp ----------------- Source code file of test application.
DigitalZoom class description
DigitalZoom class declaration
The DigitalZoom class declared in DigitalZoom.h file. Class declaration:
namespace rapidpixel
{
/// Digital zoom class.
class DigitalZoom : public VFilter
{
public:
/// Default constructor.
DigitalZoom() = default;
/// Class destructor.
~DigitalZoom() override = default;
/// Copy and move operations are deleted: the object owns a mutex.
DigitalZoom(const DigitalZoom& src) = delete;
DigitalZoom(DigitalZoom&& src) = delete;
DigitalZoom& operator=(const DigitalZoom& src) = delete;
DigitalZoom& operator=(DigitalZoom&& src) = delete;
/// Get the version of the DigitalZoom class.
static std::string getVersion();
/// Initialize digital zoom.
bool initVFilter(VFilterParams& params) override;
/// Set digital zoom parameter.
bool setParam(VFilterParam id, float value) override;
/// Get the value of a specific VFilter parameter.
float getParam(VFilterParam id) override;
/// Get the structure containing all VFilter parameters.
void getParams(VFilterParams& params) override;
/// Execute a VFilter action command.
bool executeCommand(VFilterCommand id) override;
/// Process frame (Perform digital zoom).
bool processFrame(rapidpixel::Frame& frame) override;
/// Set mask for filter.
bool setMask(rapidpixel::Frame mask) override;
/// Decode and execute command.
bool decodeAndExecuteCommand(uint8_t* data, int size) override;
};
}
getVersion method
The getVersion() static method returns string of current class version. Method declaration:
static std::string getVersion();
Method can be used without DigitalZoom class instance:
std::cout << "DigitalZoom version: " << rapidpixel::DigitalZoom::getVersion();
Console output:
DigitalZoom version: 1.3.2
initVFilter method
The initVFilter(…) method initializes digital zoom. Method uses only parameters: mode, level and custom1 from VFilterParams class. All other params will be ignored. The values are checked like in setParam(…) method. Field custom1 (number of threads) is used only if it is >= 1: a smaller value (the default value of the structure is 0) keeps the current number of threads (a new object is single threaded). Method declaration:
bool initVFilter(VFilterParams& params) override;
| Parameter | Value |
|---|---|
| params | VFilterParams class object. Method uses only parameters: mode, level and custom1 fields of VFilterParams class. The default values of the structure are not valid: level must be set (from 1.0 to 20.0). |
Returns: TRUE if the video filter initialized or FALSE if a value is not valid (mode is not 0 or 1, level is outside of the range from 1.0 to 20.0 or is NaN, custom1 is >= 1 and does not fit into int, for example +infinity). If FALSE is returned nothing is changed.
setParam method
The setParam (…) method sets new parameters value. The library provides thread-safe setParam(…) method call. This means that the setParam(…) method can be safely called from any thread. Method declaration:
bool setParam(VFilterParam id, float value) override;
| Parameter | Description |
|---|---|
| id | Parameter ID according to VFilterParam enum. Method supports only parameters: MODE, LEVEL and CUSTOM_1. Other parameters will not be set. |
| value | Parameter value. Value depends on parameter ID (see Table 3). NaN, infinity and values outside of the valid range are rejected. |
Returns: TRUE if the parameter was set or FALSE if not (the parameter is not supported or the value is not valid). If FALSE is returned the parameter is not changed.
getParam method
The getParam(…) method returns parameter value. The library provides thread-safe getParam(…) method call. This means that the getParam(…) method can be safely called from any thread. Reading of CUSTOM_1 waits for the frame which is processed at that moment by processFrame(…) method. Method declaration:
float getParam(VFilterParam id) override;
| Parameter | Description |
|---|---|
| id | Parameter ID according to VFilterParam enum. Method supports parameters: MODE, LEVEL, PROCESSING_TIME_MCSEC, TYPE (always 0) and CUSTOM_1. For other parameters the method will return -1. |
Returns: parameter value or -1 if the parameters doesn’t exist.
getParams method
The getParams(…) method is designed to obtain all digital zoom params. The library provides thread-safe getParams(…) method call. This means that the getParams(…) method can be safely called from any thread. The method waits for the frame which is processed at that moment by processFrame(…) method. Method declaration:
void getParams(VFilterParams& params) override;
| Parameter | Description |
|---|---|
| params | Reference to VFilterParams object to store params. Method will fill parameters: mode, level, processingTimeMcSec and custom1 (number of threads). Field type will be set to 0, fields custom2 and custom3 will be set to -1.0. |
executeCommand method
The executeCommand(…) method executes video filter (digital zoom) action command. The library provides thread-safe executeCommand(…) method call. This means that the executeCommand(…) method can be safely called from any thread. Method declaration:
bool executeCommand(VFilterCommand id) override;
| Parameter | Description |
|---|---|
| id | Command ID according to VFilterCommand enum. Method supports only ON and OFF commands. |
Returns: TRUE if the command executed or FALSE if not.
processFrame method
The processFrame(…) method designed to process frame (digital zoom). The method cuts the central part of the frame (the frame size divided by the zoom level) and scales it back to the frame size. The width, height, frameId and sourceId of the frame do not change. The library provides thread-safe processFrame(…) method call. This means that the processFrame(…) method can be safely called from any thread: the calls are executed one after another. The library can not check that the data pointer of the frame is valid for frame.size bytes: the caller guarantees it. Method declaration:
bool processFrame(rapidpixel::Frame& frame) override;
| Parameter | Description |
|---|---|
| frame | Reference to Frame object. Pixel format must be BGR24, RGB24 or YUV24 (3 bytes per pixel). Width and height must be >= 16 pixels, the data pointer must not be nullptr and the data size (size field) must be >= width * height * 3. The maximum size of the frame is limited by ImageResizer: 65536 x 65536 pixels. |
Returns: TRUE if frame processed (digital zoom) or FALSE if not (the frame is not valid or memory could not be allocated). If filter disabled the method will return TRUE without video frame processing. If FALSE is returned the frame is not changed, except an error of the G2D hardware of ImageResizer (the content of the frame is undefined then).
setMask method
The setMask(…) method designed to set video filter mask. Mask not supported by DigitalZoom class. Method declaration:
bool setMask(rapidpixel::Frame mask) override;
| Parameter | Description |
|---|---|
| mask | Filter mask is Frame object with GRAY pixel format. Mask not supported by DigitalZoom class. |
Returns: TRUE in any cases.
encodeSetParamCommand method of VFilter class
The encodeSetParamCommand(…) static method encodes command to change any VFilter parameter value remote. To control any video filter remotely, the developer has to design his own protocol and according to it encode the command and deliver it over the communication channel. To simplify this, the VFilter class contains static methods for encoding the control command. The VFilter class provides two types of commands: a parameter change command (SET_PARAM) and an action command (COMMAND). encodeSetParamCommand(…) designed to encode SET_PARAM command. Method declaration:
static void encodeSetParamCommand(uint8_t* data, int& size, VFilterParam id, float value);
| Parameter | Description |
|---|---|
| data | Pointer to data buffer for encoded command. Must not be nullptr. The buffer must be valid for 11 bytes. |
| size | Size of encoded data. Size will be 11 bytes. Set to 0 if data is nullptr (nothing is written). |
| id | Parameter ID according to VFilterParam enum. The ID is not checked by the method: decodeCommand(…) rejects an ID which is not in the enum. |
| value | Parameter value. The value is not checked by the method. |
encodeSetParamCommand(…) is static and can be used without VFilter class instance. This method used on client side (control system). Command encoding example:
// Buffer for encoded data.
uint8_t data[11];
// Size of encoded data.
int size = 0;
// Parameter value.
float outValue = 3.0f;
// Encode command.
rapidpixel::VFilter::encodeSetParamCommand(data, size, rapidpixel::VFilterParam::LEVEL, outValue);
encodeCommand method of VFilter class
The encodeCommand(…) static method encodes action command for VFilter remote control. To control any video filter remotely, the developer has to design his own protocol and according to it encode the command and deliver it over the communication channel. To simplify this, the VFilter class contains static methods for encoding the control command. The VFilter class provides two types of commands: a parameter change command (SET_PARAM) and an action command (COMMAND). encodeCommand(…) designed to encode COMMAND (action command). Method declaration:
static void encodeCommand(uint8_t* data, int& size, VFilterCommand id);
| Parameter | Description |
|---|---|
| data | Pointer to data buffer for encoded command. Must not be nullptr. The buffer must be valid for 7 bytes. |
| size | Size of encoded data. Size will be 7 bytes. Set to 0 if data is nullptr (nothing is written). |
| id | Command ID according to VFilterCommand enum. The ID is not checked by the method: decodeCommand(…) rejects an ID which is not in the enum. |
encodeCommand(…) is static and can be used without VFilter class instance. This method used on client side (control system). Command encoding example:
// Buffer for encoded data.
uint8_t data[7];
// Size of encoded data.
int size = 0;
// Encode command.
rapidpixel::VFilter::encodeCommand(data, size, rapidpixel::VFilterCommand::ON);
decodeCommand method of VFilter class
The decodeCommand(…) static method decodes command on video filter side (on edge device). The method checks the pointer, the size (exactly 11 bytes for SET_PARAM and 7 bytes for COMMAND), the version, the data type and the ID (it must be in the enum). The output arguments are changed only if the command is decoded. Method declaration:
static int decodeCommand(uint8_t* data, int size, VFilterParam& paramId, VFilterCommand& commandId, float& value);
| Parameter | Description |
|---|---|
| data | Pointer to input command. Must not be nullptr. The buffer must be valid for size bytes. |
| size | Size of command. Must be 11 bytes for SET_PARAM and 7 bytes for COMMAND (action command). |
| paramId | VFilter parameter ID according to VFilterParam enum. After decoding SET_PARAM command the method will return parameter ID. |
| commandId | VFilter command ID according to VFilterCommand enum. After decoding COMMAND the method will return command ID. |
| value | VFilter parameter value (after decoding SET_PARAM command). The value is not checked by the method. |
Returns: 0 - in case decoding COMMAND (action command), 1 - in case decoding SET_PARAM command or -1 in case errors.
decodeAndExecuteCommand method
The decodeAndExecuteCommand(…) method decodes and executes command encoded by encodeSetParamCommand(…) and encodeCommand(…) methods on video filter side. The library provides thread-safe decodeAndExecuteCommand(…) method call. This means that the decodeAndExecuteCommand(…) method can be safely called from any thread. Method declaration:
bool decodeAndExecuteCommand(uint8_t* data, int size) override;
| Parameter | Description |
|---|---|
| data | Pointer to input command. Must not be nullptr. The buffer must be valid for size bytes. |
| size | Size of command. Must be 11 bytes for SET_PARAM or 7 bytes for COMMAND. |
Returns: TRUE if command decoded (SET_PARAM or COMMAND) and executed (action command or set param command). FALSE if the command is not valid (nullptr, wrong size, version, data type or ID) or is not supported or the value of the parameter is not valid (see setParam(…)). If FALSE is returned the parameters are not changed.
Data structures
VFilterCommand enum
Enum declaration:
enum class VFilterCommand
{
/// Reset image filter algorithm.
RESET = 1,
/// Enable filter.
ON,
/// Disable filter.
OFF
};
Table 2 - Action commands description.
| Command | Description |
|---|---|
| RESET | Not supported by DigitalZoom class. |
| ON | Enable digital zoom. |
| OFF | Disable digital zoom. |
VFilterParam enum
Enum declaration:
enum class VFilterParam
{
/// Filter mode: 0 - off, 1 - on. Depends on implementation.
MODE = 1,
/// Enhancement level for particular filter, as a percentage from
/// 0% to 100%. May have another meaning depends on implementation.
LEVEL,
/// Processing time in microseconds. Read only parameter.
PROCESSING_TIME_MCSEC,
/// Type of the filter. Depends on the implementation.
TYPE,
/// VFilter custom parameter. Custom parameters used when particular image
/// filter has specific unusual parameter.
CUSTOM_1,
/// VFilter custom parameter. Custom parameters used when particular image
/// filter has specific unusual parameter.
CUSTOM_2,
/// VFilter custom parameter. Custom parameters used when particular image
/// filter has specific unusual parameter.
CUSTOM_3
};
Table 3 - Params description.
| Parameter | Access | Description |
|---|---|---|
| MODE | read / write | Digital zoom mode: 0 - disabled, 1 - enabled. Other values (and NaN) are rejected. |
| LEVEL | read / write | Digital zoom level. Valid values from 1.0 to 20.0. Other values (and NaN) are rejected. |
| PROCESSING_TIME_MCSEC | read only | Processing time in microseconds. Read only parameter. Used to check performance of digital zoom. |
| TYPE | read only | Always 0. Not supported by DigitalZoom class (bicubic interpolation is used). |
| CUSTOM_1 | read / write | Number of threads for processing. Value 1 (the default state of the object) keeps resizing single threaded. Values <= 0 mean “as many threads as OpenMP makes available”. The limit is never larger than omp_get_max_threads(). Valid values: any number that fits into int (a fractional part is cut off). NaN, infinity and values outside of the int range are rejected. Reading returns the number of threads which the resizer may use (always >= 1). |
| CUSTOM_2 | read / write | Not supported by DigitalZoom class. |
| CUSTOM_3 | read / write | Not supported by DigitalZoom class. |
VFilterParams class description
VFilterParams class declaration
The VFilterParams class is used to provide video filter parameters structure. Also VFilterParams provides possibility to write/read params from JSON files (JSON_READABLE macro) and provides methods to encode and decode params. VFilterParams interface class declared in VFilter.h file. Class declaration:
class VFilterParams
{
public:
/// Filter mode: 0 - off, 1 - on. Depends on implementation.
int mode{1};
/// Enhancement level for particular filter, as a percentage from
/// 0% to 100%. May have another meaning depends on implementation.
float level{0.0f};
/// Processing time in microseconds. Read only parameter.
int processingTimeMcSec{0};
/// Type of the filter. Depends on the implementation.
int type{0};
/// VFilter custom parameter. Custom parameters used when particular image
/// filter has specific unusual parameter.
float custom1{0.0f};
/// VFilter custom parameter. Custom parameters used when particular image
/// filter has specific unusual parameter.
float custom2{0.0f};
/// VFilter custom parameter. Custom parameters used when particular image
/// filter has specific unusual parameter.
float custom3{0.0f};
/// Macro from ConfigReader to make params readable / writable from JSON.
JSON_READABLE(VFilterParams, mode, level, type, custom1, custom2, custom3)
/// Encode (serialize) params.
bool encode(uint8_t* data, int bufferSize, int& size,
VFilterParamsMask* mask = nullptr);
/// Decode (deserialize) params.
bool decode(uint8_t* data, int dataSize);
};
Table 4 - VFilterParams class fields description is related to VFilterParam enum description.
| Field | type | Description |
|---|---|---|
| mode | int | Digital zoom mode: 0 - disabled, 1 - enabled. |
| level | float | Digital zoom level. Valid values from 1.0 to 20.0. |
| processingTimeMcSec | int | Processing time in microseconds. Read only parameter. Used to check performance of digital zoom. |
| type | int | Always 0. Not supported by DigitalZoom class (bicubic interpolation is used). |
| custom1 | float | Number of threads for processing. Value 1 (the default state of the object) keeps resizing single threaded. Values <= 0 mean “as many threads as OpenMP makes available”. The limit is never larger than omp_get_max_threads(). In initVFilter(…) only, a value below 1 (the structure default is 0) is treated as “not specified” and keeps the current number of threads, so that an integrator who never touched custom1 does not silently get every core. |
| custom2 | float | VFilter custom parameter. Custom parameters used when particular image filter has specific unusual parameter. |
| custom3 | float | VFilter custom parameter. Custom parameters used when particular image filter has specific unusual parameter. |
Note: VFilterParams class fields listed in Table 4 have to reflect params set/get by methods setParam(…) and getParam(…). The values of the fields are only transported by the VFilterParams class (JSON, serialization): they are not checked against any range, the video filter implementation validates them.
Serialize VFilter params
VFilterParams class provides method encode(…) to serialize VFilter params. Serialization of VFilterParams is necessary in case when video filter parameters have to be sent via communication channels. Method provides options to exclude particular parameters from serialization. To do this method inserts binary mask (1 byte) where each bit represents particular parameter and decode(…) method recognizes it. Method declaration:
bool encode(uint8_t* data, int bufferSize, int& size, VFilterParamsMask* mask = nullptr);
| Parameter | Value |
|---|---|
| data | Pointer to data buffer. Must not be nullptr. The buffer must be valid for bufferSize bytes. |
| bufferSize | Data buffer size. Buffer size must be >= 32 bytes. |
| size | Size of encoded data. The size is 4 bytes of header plus 4 bytes for each encoded field. Set to 0 if the method fails. |
| mask | Parameters mask - pointer to VFilterParamsMask structure. VFilterParamsMask (declared in VFilter.h file) determines flags for each field (parameter) declared in VFilterParams class. If user wants to exclude any parameters from serialization, he can put a pointer to the mask. If the user wants to exclude a particular parameter from serialization, he should set the corresponding flag in the VFilterParamsMask structure to false. If the pointer is nullptr all parameters are encoded. |
Returns: TRUE if params encoded (serialized) or FALSE if not (data is nullptr or buffer size < 32). If FALSE is returned nothing is written to the buffer. Integer and float fields are stored as raw 4 bytes values in the byte order of the host.
VFilterParamsMask structure declaration:
struct VFilterParamsMask
{
/// Serialize mode field.
bool mode{true};
/// Serialize level field.
bool level{true};
/// Serialize processingTimeMcSec field.
bool processingTimeMcSec{true};
/// Serialize type field.
bool type{true};
/// Serialize custom1 field.
bool custom1{true};
/// Serialize custom2 field.
bool custom2{true};
/// Serialize custom3 field.
bool custom3{true};
};
Example without parameters mask:
// Prepare parameters.
rapidpixel::VFilterParams params;
params.level = 80.0f;
// Encode (serialize) params.
int bufferSize = 128;
uint8_t buffer[128];
int size = 0;
if (!params.encode(buffer, bufferSize, size))
{
std::cout << "Can't encode params" << std::endl;
}
Example with parameters mask:
// Prepare parameters.
rapidpixel::VFilterParams params;
params.level = 80.0f;
// Prepare mask.
rapidpixel::VFilterParamsMask mask;
// Exclude level.
mask.level = false;
// Encode (serialize) params.
int bufferSize = 128;
uint8_t buffer[128];
int size = 0;
if (!params.encode(buffer, bufferSize, size, &mask))
{
std::cout << "Can't encode params" << std::endl;
}
Deserialize VFilter params
VFilterParams class provides method decode(…) to deserialize params. Deserialization of VFilterParams is necessary in case when it is needed to receive params via communication channels. Method automatically recognizes which parameters were serialized by encode(…) method. Method declaration:
bool decode(uint8_t* data, int dataSize);
| Parameter | Value |
|---|---|
| data | Pointer to data buffer with serialized params. Must not be nullptr. The buffer must be valid for dataSize bytes. |
| dataSize | Size of serialized params. The method checks the data type, the version (major and minor) and the size (it must be equal to the size defined by the mask in the data). |
Returns: TRUE if params decoded (deserialized) or FALSE if not (data is nullptr, wrong data type, version or size, unknown flag in the mask). If FALSE is returned the object is not changed. Fields which are not serialized (not selected by the mask) are set to zero. The values of the fields are not checked against any range.
Example:
// Prepare parameters.
rapidpixel::VFilterParams params1;
params1.level = 80.0f;
// Encode (serialize) params.
int bufferSize = 128;
uint8_t buffer[128];
int size = 0;
if (!params1.encode(buffer, bufferSize, size))
{
std::cout << "Can't encode params" << std::endl;
}
// Decode (deserialize) params.
rapidpixel::VFilterParams params2;
if (!params2.decode(buffer, size))
{
std::cout << "Can't decode params" << std::endl;
}
Read params from JSON file and write to JSON file
VFilter depends on the ConfigReader library which provides method to read params from JSON file and to write params to JSON file. Example of writing and reading params to JSON file:
// Prepare random params.
rapidpixel::VFilterParams params1;
params1.mode = 1;
params1.level = 10.1f;
params1.processingTimeMcSec = 10;
params1.type = 2;
params1.custom1 = 22.3f;
params1.custom2 = 23.4f;
params1.custom3 = 24.5f;
// Save to JSON.
rapidpixel::ConfigReader configReader1;
if (!configReader1.set(params1, "Params"))
{
std::cout << "Can't set params" << std::endl;
}
if (!configReader1.writeToFile("VFilterParams.json"))
{
std::cout << "Can't write to file" << std::endl;
}
// Read params from file.
rapidpixel::ConfigReader configReader2;
if (!configReader2.readFromFile("VFilterParams.json"))
{
std::cout << "Can't read from file" << std::endl;
}
rapidpixel::VFilterParams params2;
if (!configReader2.get(params2, "Params"))
{
std::cout << "Can't get params" << std::endl;
}
VFilterParams.json will look like (the field processingTimeMcSec is not written to the file):
{
"Params": {
"mode": 1,
"level": 10.100000381469727,
"type": 2,
"custom1": 22.299999237060547,
"custom2": 23.399999618530273,
"custom3": 24.5
}
}
Build and connect to your project
Build stand alone
The repository does not contain sub-repositories. The libraries DigitalZoom depends on (Frame, ConfigReader, VFilter and ImageResizer) and the library used by the test application (SimpleUI) must be cloned into the same folder as DigitalZoom. The folder structure must be:
<work folder>
DigitalZoom
Frame
ConfigReader
VFilter
ImageResizer
SimpleUI
Typical commands to build the library and the test application (use the URLs of the repositories provided to you):
git clone <DigitalZoom repository URL>
git clone <Frame repository URL>
git clone <ConfigReader repository URL>
git clone <VFilter repository URL>
git clone <ImageResizer repository URL>
git clone <SimpleUI repository URL>
cd DigitalZoom
mkdir build
cd build
cmake ..
make
On Windows use cmake --build . --config Release instead of make. If DigitalZoom is the top-level CMake project, the main CMakeLists.txt file adds the folders ../Frame, ../ConfigReader, ../VFilter and ../ImageResizer (in this order) before the library itself and the folder ../SimpleUI before the test application. If a folder does not exist CMake stops with an error.
CMake options
Table 5 - CMake options of the repository. In the options below ${PARENT} is the prefix defined by the top-level project (empty if DigitalZoom is the top-level project).
| Option | Default | Description |
|---|---|---|
| ${PARENT}_DIGITAL_ZOOM | ON | Build the library. |
| ${PARENT}_DIGITAL_ZOOM_TEST | ON (stand alone), OFF (included in other project) | Build the test application. |
| ${PARENT}_SUBMODULE_CACHE_OVERWRITE | ON | Forced rewriting of the options above in the CMake cache. The top-level project sets it to OFF when it includes DigitalZoom as a sub-repository. |
| CMAKE_BUILD_TYPE | Release (if not specified) | Build type. |
The library has no SIMD code of its own. The options of the dependencies (for example IMAGERESIZER_ENABLE_SIMD of the ImageResizer library) are described in their documentation. If ImageResizer is built with OpenMP or with the G2D library, a program that links DigitalZoom needs these libraries too; CMake adds them through the ImageResizer target.
Connect to your project
If you want connect DigitalZoom to your CMake project as source code you can make follow. For example, if your repository has structure:
CMakeLists.txt
src
CMakeList.txt
yourLib.h
yourLib.cpp
Create folder 3rdparty in your repository and copy the repository folders of DigitalZoom and of the libraries it depends on (Frame, ConfigReader, VFilter and ImageResizer) there. New structure of your repository:
CMakeLists.txt
src
CMakeList.txt
yourLib.h
yourLib.cpp
3rdparty
DigitalZoom
Frame
ConfigReader
VFilter
ImageResizer
Create CMakeLists.txt file in 3rdparty folder. CMakeLists.txt should contain:
cmake_minimum_required(VERSION 3.13)
################################################################################
## 3RD-PARTY
## dependencies for the project
################################################################################
project(3rdparty LANGUAGES CXX)
################################################################################
## SETTINGS
## basic 3rd-party settings before use
################################################################################
# To inherit the top-level architecture when the project is used as a submodule.
SET(PARENT ${PARENT}_YOUR_PROJECT_3RDPARTY)
# Disable self-overwriting of parameters inside included subdirectories.
SET(${PARENT}_SUBMODULE_CACHE_OVERWRITE OFF CACHE BOOL "" FORCE)
################################################################################
## CONFIGURATION
## 3rd-party submodules configuration
################################################################################
SET(${PARENT}_SUBMODULE_FRAME ON CACHE BOOL "" FORCE)
if (${PARENT}_SUBMODULE_FRAME)
SET(${PARENT}_FRAME ON CACHE BOOL "" FORCE)
SET(${PARENT}_FRAME_TEST OFF CACHE BOOL "" FORCE)
endif()
SET(${PARENT}_SUBMODULE_CONFIG_READER ON CACHE BOOL "" FORCE)
if (${PARENT}_SUBMODULE_CONFIG_READER)
SET(${PARENT}_CONFIG_READER ON CACHE BOOL "" FORCE)
SET(${PARENT}_CONFIG_READER_EXAMPLES OFF CACHE BOOL "" FORCE)
SET(${PARENT}_CONFIG_READER_TESTS OFF CACHE BOOL "" FORCE)
endif()
SET(${PARENT}_SUBMODULE_VFILTER ON CACHE BOOL "" FORCE)
if (${PARENT}_SUBMODULE_VFILTER)
SET(${PARENT}_VFILTER ON CACHE BOOL "" FORCE)
SET(${PARENT}_VFILTER_TEST OFF CACHE BOOL "" FORCE)
SET(${PARENT}_VFILTER_EXAMPLE OFF CACHE BOOL "" FORCE)
endif()
SET(${PARENT}_SUBMODULE_IMAGE_RESIZER ON CACHE BOOL "" FORCE)
if (${PARENT}_SUBMODULE_IMAGE_RESIZER)
SET(${PARENT}_IMAGE_RESIZER ON CACHE BOOL "" FORCE)
SET(${PARENT}_IMAGE_RESIZER_EXAMPLE OFF CACHE BOOL "" FORCE)
endif()
SET(${PARENT}_SUBMODULE_DIGITAL_ZOOM ON CACHE BOOL "" FORCE)
if (${PARENT}_SUBMODULE_DIGITAL_ZOOM)
SET(${PARENT}_DIGITAL_ZOOM ON CACHE BOOL "" FORCE)
SET(${PARENT}_DIGITAL_ZOOM_TEST OFF CACHE BOOL "" FORCE)
endif()
################################################################################
## INCLUDING SUBDIRECTORIES
## Adding subdirectories according to the 3rd-party configuration
################################################################################
if (${PARENT}_SUBMODULE_FRAME)
add_subdirectory(Frame)
endif()
if (${PARENT}_SUBMODULE_CONFIG_READER)
add_subdirectory(ConfigReader)
endif()
if (${PARENT}_SUBMODULE_VFILTER)
add_subdirectory(VFilter)
endif()
if (${PARENT}_SUBMODULE_IMAGE_RESIZER)
add_subdirectory(ImageResizer)
endif()
if (${PARENT}_SUBMODULE_DIGITAL_ZOOM)
add_subdirectory(DigitalZoom)
endif()
File 3rdparty/CMakeLists.txt adds the folders of the libraries to your project in the order of their dependencies (Frame and ConfigReader before VFilter) and then the folder DigitalZoom, and excludes the test application and the examples from compiling (by default the test application is excluded from compiling if DigitalZoom is included as sub-repository). When DigitalZoom is included in another project it does not add its dependencies: the project must add them (this file does it). If a dependency is missing the build stops with an error that a header of the dependency is not found (for example VFilter.h: No such file or directory). Your repository new structure will be:
CMakeLists.txt
src
CMakeList.txt
yourLib.h
yourLib.cpp
3rdparty
CMakeLists.txt
DigitalZoom
Frame
ConfigReader
VFilter
ImageResizer
Next you need include folder 3rdparty in main CMakeLists.txt file of your repository. Add string at the end of your main CMakeLists.txt:
add_subdirectory(3rdparty)
Next you have to include DigitalZoom library in your src/CMakeLists.txt file:
target_link_libraries(${PROJECT_NAME} DigitalZoom)
Done!
Portability
The library has no CPU specific code and does not depend on the byte order for the pixels of the frame: it copies bytes of the frame and passes them to the ImageResizer library. The SIMD kernels belong to ImageResizer, which selects them at run time (CMake option IMAGERESIZER_ENABLE_SIMD of that library). The commands (encodeSetParamCommand(…), encodeCommand(…)) and the serialized params (VFilterParams::encode(…)) store int and float values in the byte order of the host: the sender and the receiver must have the same byte order. The library is written in standard C++17 and was built and run with MSVC 2022 (Windows, x86-64), GCC 12 and 13 and Clang 15 and 18 (Linux, x86-64) and GCC 13 for AArch64 (Linux, run in an emulator). The result of the zoom (the pixels of the frame) is the same in all these builds.
Example
The example creates artificial image and provides user interface to control mode and level params. The example is a part of the test application (folder test). If the test application is started with the –selftest parameter it does not show the window: it runs the automatic tests of the library and returns exit code 0 if all tests passed.
#include <cstring>
#include <iostream>
#include <string>
#include "DigitalZoom.h"
#include "SimpleUi.h"
using rapidpixel::Color;
using rapidpixel::SimpleUiDraw;
using rapidpixel::SimpleUiWindow;
using rapidpixel::DigitalZoom;
using rapidpixel::Fourcc;
using rapidpixel::Frame;
using rapidpixel::VFilterParam;
using rapidpixel::VFilterParams;
int main()
{
std::cout << "DigitalZoom v" << DigitalZoom::getVersion() << std::endl;
// Prepare source artificial image.
const int width = 1280;
const int height = 720;
Frame frame(width, height, Fourcc::BGR24);
SimpleUiDraw::fillCircle(frame, width / 2, height / 2, height / 2, Color{255, 0, 0});
SimpleUiDraw::fillCircle(frame, width / 2, height / 2, height / 3, Color{0, 255, 0});
SimpleUiDraw::fillCircle(frame, width / 2, height / 2, height / 4, Color{0, 0, 255});
SimpleUiDraw::fillCircle(frame, width / 2, height / 2, height / 5, Color{255, 0, 0});
SimpleUiDraw::fillCircle(frame, width / 2, height / 2, height / 7, Color{0, 255, 0});
SimpleUiDraw::fillCircle(frame, width / 2, height / 2, height / 8, Color{0, 0, 255});
SimpleUiDraw::fillCircle(frame, width / 2, height / 2, height / 9, Color{255, 0, 0});
SimpleUiDraw::fillCircle(frame, width / 2, height / 2, height / 10, Color{0, 255, 0});
// Create digital zoom object and params.
DigitalZoom zoom;
VFilterParams params;
SimpleUiWindow win("DigitalZoom");
win.show();
// Main loop.
while (win.isOpen())
{
Frame resultFrame(width, height, Fourcc::BGR24);
std::memcpy(resultFrame.data, frame.data, static_cast<size_t>(frame.size));
// Digital zoom.
if (!zoom.processFrame(resultFrame))
{
std::cout << "Can't process the frame" << std::endl;
return 1;
}
// Get digital zoom params (VFilterParams).
zoom.getParams(params);
// Draw params.
const Color textColor{0, 255, 255};
SimpleUiDraw::drawText(resultFrame, 5, 25, "[1]Mode: " + std::string(params.mode == 0 ? "OFF" : "ON"), textColor);
SimpleUiDraw::drawText(resultFrame, 5, 50, "[2/3]Level: " + std::to_string(params.level), textColor);
SimpleUiDraw::drawText(resultFrame, 5, 75, "Type: BICUBIC", textColor);
SimpleUiDraw::drawText(resultFrame, 5, 100, "Time, mcsec: " + std::to_string(params.processingTimeMcSec), textColor);
// Show results.
win.render(resultFrame);
// Process keyboard events. The level is limited by the library: a
// step outside of the range is rejected and the level is not changed.
switch (win.getKey(30))
{
case 27:
return 0;
case '1':
if (!zoom.setParam(VFilterParam::MODE, static_cast<float>(1 - params.mode)))
{
std::cout << "Can't set the mode" << std::endl;
}
break;
case '2':
zoom.setParam(VFilterParam::LEVEL, params.level - 0.1f);
break;
case '3':
zoom.setParam(VFilterParam::LEVEL, params.level + 0.1f);
break;
default:
break;
}
}
return 0;
}
Example user interface:
