IOFormat
IOF_v1.3.1_release
|
Custom plugins can be written in C++ only.
If you want to create your own Extractor or Writer plugin, you can by following the API contained in the IOPluginAPI project:
IOPlugin APIs are versioned and each version of IOFormat is only compatible with one version of IOPlugin. All plugins developed with a different IOPlugin version of the one used by IOFormat won't be loaded.
See configuration to know the IOPlugin version compatible with this version of IOFormat.
You must add the IOPlugin Conan package to your plugin dependencies, to get the included and logging libraries. You must link against this package using the classic Conan way. If you want your plugin to be used in IOFormat, it must be declared as a SHARED
library in CMake.
An IOFormat plugin must implement the matching plugin interface: ExtractorPlugin
or WriterPlugin
, depending on the type of plugin you want to make. When the class is done, you must use a plugin-defining macro in order to make it usable by the plugin system of IOFormat. These macros depend on the plugin type:
IOPLUGIN_DECLARE_EXTRACTOR_PLUGIN(PluginClass)
for Extractor plugins.IOPLUGIN_DECLARE_WRITER_PLUGIN(PluginClass)
for Writer plugins.The plugin class should be done in a source file (*.cpp or *.cxx) instead of a header file, because we only want to export the instance.
Example for an extractor plugin:
TestPlugin
, in this example, is the entry point for the extractor plugin. It's up to the methods openDataAccess
and openFile
of this class to instanciate and return the appropriate view according to the format of the opened file.
Have a look on the code example provided with the IOPlugin API.
For example: calling openDataAccess
onto PNG plugin will require the instanciation of an object derived from ImageView
, since PNG is only able to manage 2D Images. On the other hand, a TIFF plugin could possibly be either an object derived from ImageView
or from MultiImageView
, depending of the file content. A TIFF file can contain either an image, thus an ImageView, or a list of independant frames, thus a MultiImageView
.
There are some guidelines common to the two types of plugins:
api
method, it is already returning the API version of the IOplugin version you are using to create your plugin.initLogger
will do nothing, and logLevel
will always return LogLevel::OFF
.There are two different View
factories in the ExtractorPlugin
interface that you can implement in your custom plugin. First, openFile
that takes a path to the source file, and openDataAccess
that takes a DataAccess
from which to decode from. The openDataAccess
variant also takes a format
argument that enables the selection of the format to use to decode the accessor's data. This format is automatically selected using the path's extension in the openFile
variant.
When one of these variants is not supported by your custom plugin, just make the method throw an Error
describing that the feature is not supported.
For both cases, a serie of checks and operations should be done immediately:
format
string parameter to adapt your extraction method to the current situation (i.e. when a plugin handles many different formats).path
or dataAccess
is valid. Data must exist and be available for reading and most of the time for seeking in the case of streams.View
that your plugin should create and return:properties
immediately. You should extract these informations as soon as possible, and not "on the
fly", for thread-safety reasons.If any of these checks/operations fails, an exception will be raised.
The table below should help you determine the kind of View
to return:
View type | Case where this type of view should be created |
---|---|
ImageView | A N-dimension array (e.g a 2D Image, a volume, a sequence of image...) |
MultiImageView | A set of images which may or may be related with each other (shape and type can be different) |
LodImageView | One multi-resolution image (many different resolutions of the same N-Dimensional image) |
DataFrameView | Tabular Data |
Up to you to return the view type corresponding the better to extracted data and which matches your needs.
There are two Writer
factories in the WriterPlugin
interface, all taking the source View
as the first argument. The openFile
one uses a path to specify the writer's output, and will infer the format to use from the file's extension. The openDataAccess
variant use a DataAccess
as its output with its format specified with a format
parameter.
When one of these variants is not supported by your custom plugin, just make the method throw an Error
describing that the feature is not supported.
Ideally, your custom writer should support any kind of View
as an entry, as long as it fits the underlying format. For example a plugin encoding to an image format could take any ImageView
as input. In the image case, the underlying format usually support one particular data layout, but a good plugin should accept different layouts, as long as they are easily adaptable, without damaging the content and without guessing the user intentions. For example, when a plugin uses a format that stores color data in an interleaved order, if the user gives a planar ImageView
(one with a CHANNEL
dimension) as input, it should adapt it, instead of throwing an error saying that the view is unsupported. Another example is MultiImageView
instances, that can be stacked to feed a volume or sequence format, if it is possible.
As long as there is one possibility to adapt the data to match the writer inputs, the plugin should try. However, when there is more than one possibility to adapt the data, the plugin shall raise an exception to ask the user to make a decision.
In order to provide better features and performances, writers created by your custom plugin should not write all the output in one call. An approach using chunked write calls should be preferred. It will avoid hangs-on and blocking operations when using non-filesystem accessors.