IOFormat 1.12.0
Loading...
Searching...
No Matches
Create a Custom Plugin

Custom plugins can be written in C++ only.

An IOFormat plugin must implement the matching plugin interface: ExtractorPlugin or WriterPlugin, or ProtocolPlugin 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:

  • IOFORMAT_DECLARE_EXTRACTOR_PLUGIN(PluginClass) for Extractor plugins.
  • IOFORMAT_DECLARE_WRITER_PLUGIN(PluginClass) for Writer plugins.
  • IOFORMAT_DECLARE_PROTOCOL_PLUGIN(PluginClass)for Protocol 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:

using namespace ioformat;
class TestPlugin final : public ExtractorPlugin
{
// override the interface's methods
};
IOFORMAT_DECLARE_EXTRACTOR_PLUGIN(TestPlugin)
Extractor plugin interface.
Definition ExtractorPlugin.h:22
Global namespace which contains all methods to encode/decode data from/into different resources (file...
Definition Error.h:6

TestPlugin, in this example, is the entry point for the extractor plugin. It's up to the open methods of this class to instanciate and return the appropriate view according to the format of the opened file.

For example: calling the open method of the 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.

Never override the api method of a plugin, it is already returning the API version of the version you are using to create your plugin. Changing it may cause your plugin to not be loaded by IOFormat.

Extractors

Factories

There are multiple variants of the open method of a plugin, with the input type varying:

  • a path to a file as a string
  • a StreamAccess
  • a RandomAccess

In addition, all the open variants take the following arguments:

  • format: the format requested, that may be useful for plugin that handle multiple formats or sub-formats.
  • options: the options given by the user that can affect how the plugin will act.

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.

Preliminary checks and operations

For both cases, a series of checks and operations should be done immediately:

  • Check that the given format string parameter to adapt your extraction method to the current situation (i.e. when a plugin handles many different formats).
  • Check that the input is valid. Data must exist and be available for reading and most of the time for seeking in the case of streams.
  • Check the data content by starting to extract some basic information which will help to determine the type of View that your plugin should create and return:
    • type of the data (UINT8, UINT16, UINT32, ...)
    • number of frames (if supported by the format)
    • number of dimensions of the frame(s)
    • shape of the frame(s)
  • Extract the information to fill the properties immediately. You should extract these informations as soon as possible, and not "on the fly", for thread-safety reasons.
  • Extract the tree of metadata. For some cases it is better to extract all metadata at the opening. And for other cases it is better to build it on-demand.

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.

Writers

Factories

There are multiple variants of the open method of a plugin, with the input type varying:

  • a path to a file as a string
  • a StreamAccess

In addition, all the open variants take the following arguments:

  • format: the format requested, that may be useful for plugin that handle multiple formats or sub-formats.
  • options: the options given by the user that can affect how the plugin will act.

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.

Input adaptation

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.

Performances

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.

Protocols

Protocol plugins enable IOFormat to support many data transfer protocols and to extend them at will.

In addition to the usual informative fields inherited from Plugin, protocol plugins support these additional services:

  • supportedSchemes: a listing of supported URI schemes supported.
  • exists: a method to check if a resource exist.
  • openReader: creates an accessor that will read data from the resource.
  • openWriter: creates a stream that will write data directly to the resource.
  • list: used to list the available resource on a specific host.

All methods, barring supportedSchemes can be marked as unsupported, by throwing the UnsupportedOperation exception. In order to support image opening from an URI, the openReader service must be supported.