Table of Contents
calculateOutputSubImageChapter Objectives
This chapter gives an introduction to programming, implementing and registering user-defined data types for voxels:
See Section 8.2.3, “Examples with Registered Voxel Types” for code examples.
ML modules normally implement algorithms on integer or floating
point typed voxels, such as MLint8,
MLuint16 or MLfloat. To
support all these types, the image processing parts of ML modules
algorithms normally use templates. However, it is not very efficient to
integrate new basic data types because each new data type requires the
recompilation of all modules and of the ML itself and the size of the
generated code grows for each new voxel type. Moreover, precompiled
modules from other sites cannot be used on the new voxel types.
To solve this problem the ML provides some specialized data types for voxels, the so-called Carrier Types. They do not implement specific functionality, but provide just an interface to the operations of any other voxel type. A carrier type can be configured to use any user-defined or predefined voxel data type.
This means:
All modules which compile the carrier types can use registered voxel types, even if they were created or registered after module compilation.
The number of registered voxel types is potentially unlimited.
A programmer can add his own voxel types.
A module can use carrier types to handle arbitrary voxel types or it can suppress the use of carrier types.
An image processing algorithm can use operations such as +, -, *, /, etc., however, it is not obvious what the registered operations really do on the data. It also might be a "no operation" or e.g., a lexicographical comparison operator or "" on vector components.
An image processing algorithm can also use explicit voxel types without carrier types which is less universal, but usually faster, because the carrier types are not used as interfaces.
Only a limited number of carrier types is implemented/compiled, and their sizes cannot be changed. Hence a registered voxel type uses the smallest fitting carrier type that can store the information of a registered type. Therefore, voxels with a carrier type might need more memory than their registered type imply which requires some precautions (see Section 8.4, “Traps and Pitfalls When Using Registered Voxel Types”).
The following voxel types are already registered in the ML:
Complex numbers use float, double and long double floating
point arithmetics. They make the standard C++ complex data type
available and are implemented in the ML as a template class
MLTComplexTypeInfos in
project MLTypeExtensions.
quaterniond, and
quaternionld.
Quaternions use float, double and long double floating point
arithmetics. They make the quaternion data type (from project
MLLinearAlgebra ) available and are
implemented in the ML as a template class MLTQuaternionTypeInfos in
project MLTypeExtensions.
vecf3 and
vec3,
vecf4 and
vec4,
vecf5 and
vec5,
vecf6 and
vec6,
vecf7 and
vec7,
vecf8 and
vec8,
vecf9 and
vec9,
vecf10 and
vec10,
vecf16 and
vec16,
vecf32 and
vec32, and
vecf64 and
vec64.
ScalarVectorTemplate
(from project MLLinearAlgebra ) for higher
vector dimensions and for float and double data types. They are
implemented in the ML as specializations of the template class
MLTDoubleVectorTypeInfos in project
MLTypeExtensions.matf3 and
mat3,
matf4 and
mat4,
matf5 and
mat5, and
matf6 and
mat6.
MLTMatrixTypeInfos in project
MLTypeExtensions. The used base types can be
found in the project
MLLinearAlgebra..For the registration of these classes, the class TypeInfosBase has been implemented in the project
MLTypeExtensions.
There are three different voxel types that need to be distinguished if you want to understand how the ML works in detail.
Standard Voxel Types
Standard voxel types are the "normal" data types. They are available in many programming languages, such as signed and unsigned 8, 16, 32 and/or 64 bit sized integers, float, double and long double types. They are also the most typical types used for image voxels.
Carrier Voxel Types
Carrier voxel types are interface types that most ML modules handle and compile in the same way as they compile/handle standard voxel types. To the compiler, the behavior of standard voxel types and carrier voxel types is almost identical. That means: carrier voxel types can be added, subtracted, multiplied, cast, shifted and so on as integer or double types can. Carrier voxel types "carry" the data for a registered voxel type and use the functions they provide to operate on that data. Only a limited number of carrier types exists, so the size of a carrier type is always greater than or equal to the size of the data of its carried registered voxel type.
Registered Voxel Types
Registered voxel types are loaded to the application code at runtime. Each registered type provides a function table with basic functions for data addition, subtraction, multiplication, shift and so on. A precompiled carrier type uses these functions to manipulate data such as the voxels of an image. Registered voxel types are indirectly used by a carrier type; their size is always smaller than or equal to the size of the carrier types that use them.
See Section 8.5.1, “About the Difference Between Standard, Carrier and Registered Voxel Types” for a detailed voxel type discussion.
© 2011 MeVis Medical Solutions AG