Menu

PluginDevFAQ

Abyssary

General Questions

Why are my color images gray? In which dimension are my color channels? What's it with the strange CImg and CImgList behaviour?

All these questions are related.
CImg is the basic image class and has 4 dimensions (width, height, depth and spectrum).
Color channels are supposed to be saved in the last (spectrum dimension) so a standard flat RGB images would be saved in a CImg of size (w x h x 1 x 3).

But for some of our use cases 4 dimensions were not enough so we use CImgList as standard image format. Each CImgList can contain multiple CImg instances so we have a 5 dimensional array.

We use this 5. dimension to index different semantic channels (e.g. color or components of a vector field). The standard dimension assignment in charon is now width(x) X height(y) X depth(z) X time(t) x channels.

Unfortunately the index for a single CImg inside a CImgList comes first when one wants to access individual pixels, so indexing works like this:

CImgList<T> img ;
T val = img(v,x,y,z,t) ;

or this:

CImg<T>& img2 = img[v] ;
T val = img2(x,y,z,t) ;

Even if you only work with one dimensional gray images. Try to build your code so that
it will work on all dimensions. The cimg_forXYZC makros etc. make this quite easy.

How do I set a parameter to the same value in two different plugins?

The ObjectInspector supports so called parameter references.
You can enter @pluginname.parametername as the parameter value to reference the
parameter of another plugin. For parameter types which don't support text input (like int or float)
you can enter this string into the wpr file using a texteditor.

Development Questions

How should i display (debug) information?

Use the sout stream object. It behaves like std::cout and is available in the plugins namespace.
Everything you stream to sout will be printed in the tuchulcha log window.
For excessive debug output you could add a verbose() Parameter.

My plugin encountered an unrecoverable error. Should i call exit() or abort()?

No! Call the ParameteredObject::raise(std::string) function with a meaningfull error message.
Alternatively you can throw any exception which derives from std::exception.
The error messages you provide will be shown in the log window

Why does my code run much slower after encapsulating it in a charon plugin?

Accessing Parameters and Slots can be an expensive operation.
Try to work with references, especially inside loops. For example use something like this:

const CImgList<T>& in = myInputSlot() ;
CImgList<T>& out = myOutputSlot() ;
float value v = myFloatParameter() ;
cimglist_for(in,l) {
//do something
out(l) = in(l) + v ;
}

My code is still to slow. Can i run workflows in parallel?

Well you can always run several tuchulcha instances.
Workflow execution itself is strictly single-threaded, so only one plugin is run at a time.
But of course you can use as many threads as you like inside a plugin. Putting a
#pragma omp parallel for before a loop may already speed up your code (but don't forget to link against the OpenMP libs!).
It is even possible to do GPU calculations with CUDA or OpenCL inside a plugin.

Meh. CImg seems dump. Can't you use OpenCV or (insert library) instead?

We can and we do! charon is not limited to specific image processing libraries.
We even have converter functions to change from CImg to cv::Mat and vice versa.

How can i declare a Slot as optional or multislot inside the code?

As a reminder: A workflow will refuse to run if there is a plugin with unconnected slots.
You can declare an input slot as optional to remove this restriction.
InputSlot\<T> has a constructor with 2 bool values as arguments (both default to false).
The first sets the optional flag, the second the multislot flag.
Call them in the constructor of your plugin.
When you do so, check if a slot is connected by calling slotname.connected() at runtime
before you use the contents of that slot.
A multislot can be take multiple inputs. You can iterate over them with the slots []operator.

Can i use Qt in my plugins?

Yes, but widget creation and destruction can get quite tricky.
tuchlcha_run which actually runs all workflows has already it's own qt event loop.
The workflow itself is executed in the main thread of the QApplication.
That means that if you create or modify any widgets, these changes will only be visible
after the workflow execution is finished.

The easiest use case is to create a modal dialog in the plugins execute function.
After you call dialog.exec() (which should derive from QDialog) the executin will
pause, you can do something in the gui and once you close the dialog the execution will continue.

For persistent qt windows, have a look at the already existing qt plugins like
ArgosDisplay or CustomColorMask.
Here Qt is used to control the parameters of small plugins which are usefull for visualization
in the ArgosDisplay plugin.

Most important: Don't create any widgets in the plugin constructor; do it in the execute function.
Tuchulcha runs every plugin constructor once during startup to initialize the plugin database, but it will also delete the plugin without returning to the QEventLoop.
This can cause all sorts of resource or memory leaks which will crash the plugin loader.
Also create a (important!) virtual destructor for the plugin and delete your widget correctly.

windows specific questions

Why do i get so many "conversion from A to B" errors in Visual Studio?

This is the case because each templated plugin get compiled thrice with T as double, float and int. Conversions between these types cause that error.
Try to use T as type when doing calculations or cast your results to T when dealing
with Slots. If that does not help you can deactivate this warning with the /w compiler flag
or bis using the #pragma warning compiler directives.

By the way: The size of a std::vector etc. is defined as size_t, not int!

My plugin doesn't get loaded. Tuchulcha says something about missing dependencies

Open the dll with Dependency Walker.
This way you can see which other dlls are missing, if the build type is correct and if you have linked against the correct charon-core.dll
tuchulcha_run.exe may also crash with confusing error messages if the plugin was linked against the wrong version of charon-core.dll

Why do i experience strange crashes somewhere in the windows runtime library?

You have probably mixed debug and release configurations.
tuchulcha in release mode can theoretically load plugins which where compiled in debug mode and vice versa.

But the runtime libraries are incompatible (especially regarding std::string, the biggest offender in our case) so you will experience crashes sooner or later.

My Plugin is derived from some other class and now i get masses of 'unresolved external symbol' errors

We use a preprocessor definition to decide which symbols get exportet into the plugin dll.
You may notice that for a plugin names 'myplugin' the definition 'myplugin_EXPORTS' gets added (assuming that you used the templategenerator to create your CMakeList.txt).
If you have a plugin 'myderivedplugin' which uses 'myplugin' you have to manually add
'myplugin_EXPORTS' to your project. The best place to do so is the CMakeLists.txt of myderivedplugin or in the pluginname.cpp before the .


Related

Wiki: Home

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.