Developing ImageJ plugins with SBT using sbt-imagej
November 23, 2014Posted by on
ImageJ is open source image processing and analysis software. It is written primarily in Java. One of its killer features is the ability to be extended by adding plugins. Simple plugins are just a couple lines of macro code in a text file. Complex ones built from thousands lines of code a packaged in a Java jar with a special manifest. They can depend on external libraries or other plugins. Packaged plugins can be written in Java, Scala, or other JVM languages.
Developing ImageJ plugins is quite simple. Though, one annoyance comes when you want to run/debug your plugin from within ImageJ. This is due to the way ImageJ discovers plugins and dependencies. It looks into its runtime directory for subdirectory called `plugins`. Then searches the `plugins` directory (or its direct subdirectories) for jars and other files containing plugins. The annoyance is that you have to package the plugin you are working on into a jar and then copy it, and possibly also all dependencies, to ImageJ `plugins` directory.
Good thing is that you can run ImageJ from you project pointing a custom runtime directory you create. You just need to copy your plugin jars there every time you build you project and run ImageJ. It is handy to have a tool that does all the work, even better if it integrates with your IDE of choice.
sbt-imagej plugin for SBT
I am using SBT as my build system. It is works with Scala, Java, and other languages. It is much simpler than Ant or Maven, in a way it is similar to Gradle.
In the past I creating a couple of ImageJ plugins project in SBT. The setup for preparing ImageJ for testing a plugin was quite similar. I was just copying and pasting configuration to new projects. Since SBT plugins are relatively easy to create, I decided to write one for development of ImageJ plugins, called sbt-imagej. The idea was to have tool that is easy to setup that works in most cases with ability to customize, if needed. Using the sbt-imagej plugin is as simple as declaring and enabling it in your build. Here is a complete example of SBT build file (`build.sbt`) that can build, setup, and run ImageJ project:
// Your project information name := "awesome-imagej-plugin" version := "1.0" // Add dependency on ImageJ libraryDependencies += "net.imagej" % "ij" % "1.49k" // Enable sbt-imagej plugin tasks enablePlugins(SbtImageJ)
The only thing that needs to be added to `build.sbt` is the line containing `enablePlugins(SbtImageJ)`. This enables two tasks `ijRun`, `ijPrepareRun`, and a bunch of customization options.
To let SBT know where to find `SbtImageJ`, you will also need to add `sbt-imagej` declaration to `project/settings.sbt` file:
addSbtPlugin("net.sf.ij-plugins" % "sbt-imagej" % "2.0.0")
Though not strictly necessary, it is also recommended specifying which version of SBT you are using, so also add `project/build.properties` with a single line:
Those three files: `build.sbt`, `project/settings.sbt`, and `project/build.properties` constitute complete specification of a SBT build project. It can be used in IntelliJ IDEA, Eclipse, and NetBeans.
The sbt-imagej plugin provides two tasks:
- `ijPrepareRun` – it builds your plugin and copies it to proper directory, but does not run ImageJ. It is intended to be run from your IDE before run/debug.
- `ijRun` – to builds your plugin, copies it to proper directory (using `ijPrepareRun`) and runs ImageJ. It is intended for running from a command prompt.
There is also a bunch of configuration options, they are described on the sbt-imagej project page.
OK but where do you put your source code. SBT, by default, is using the same directory structure as Maven and Gradle. Your sources are in `src\main`. If you are using Java, the code will go into `src\main\java`. If you are using Scala, into `src\main\scala`, and so on. One important thing to keep in mind is that resources go into `src\main\resources`, so your plugin manifest needs to go into `src\main\resources\plugin.properties`. You can see that in the example project. It contains two plugins that add effects to color images “Sepia Tone”, and “Vignette”. The plugin manifest src\main\resources\plugin.properties looks as follows:
Plugins>Effects, "Sepia Tone", effects.SepiaTonePlugIn Plugins>Effects, "Vignette", effects.VignettePlugIn
It indicates that the plugins will be install under ImageJ menu `Plugin > Effects`.
You can write ImageJ plugins in different languages. For the sake of illustration one plugin is written in Java (src/main/java/effects/VignettePlugIn.java) and the other in Scala (src/main/scala/effects/ SepiaTonePlugIn.scala)
You can find complete example project in the `sbt-imagej` example directory.
Using SBT from command line
To run the example code from SBT command prompt, start SBT (in the project directory) and type command `ijRun`. This will download needed dependencies, build the plugins, package them, copy jar to `plugins` directory, and start ImageJ with plugins loaded into menu Plugins > Effect.
Integrating with an IDE
The basic idea of integration is to execute ` ijPrepareRun` before run/debug. It can be done from all major IDEs: Eclipse, IntelliJ IDEA, and NetBeans. IntelliJ IDEA, and NetBeans support SBT projects, you can load them directly using Scala plugins for each IDE. Eclipse requires additional step of generating Eclipse project from SBT project.
You will need to add two plugins to IDEA “Scala” (for loading SBT projects into IDE) and “SBT” (for executing SBT tasks). To add the plugins select File > Settings > Plugins > Browse Repositories. In the search box type “SBT” then install “Scala” and “SBT” plugins. Restart IDE.
Load/import the example projects. To run or debug ImageJ you will need to create new run configuration. Select Run > Edit Configurations. Then:
- Click on “+” in top left to create new configuration and select “Application”
- Give you configuration a name, say “ImageJ”
- As the main class select ij.ImageJ (The ImageJ’s main class)
- Select your working directory, here we use the default value “sandbox”
- Select the module, here it is called “example”
- Now the critical part. In the “Before launch” configuration are in the bottom, click on “+” and select “SBT”. Replace the content of the combo box typing “ijPrepareRun” hit Enter (it is important) then click OK.
At his point you should have your run/debug configuration ready.
Click OK to save it.
Now you can run or debug ImageJ with your plugin. First you run can take a bit longer as SBT setups the build, after that, runs should be pretty quick. You can of cause also run in debug mode too, putting breakpoints in your plugin code.
Unlike IntelliJ IDEA or NetBeans, at the time of writing, Eclipse cannot directly read SBT projects. However you can generate Eclipse project using sbteclipse plugin. Then you load it into Eclipse as any other project.
Eclipse cannot directly run SBT tasks, but it can run Ant targets, so we use a simple Ant target to start SBT task. A sample Ant file is provided with the example. So right click on the `build.xml` and select “Run as Ant build…”. In the Edit Configuration dialog select “sbt-imagej-run” and click Run.
Same thing works for debug.
Similar to IntelliJ IDEA, NetBeans can load SBT projects directly using its Scala plugin. So first install the plugin, actually it is divided in several smaller plugins, so you will need to install all the pieces. Go to Tools > Plugins > Available Plugins. In the search box type “Scala”, select all the plugins in “Scala” category and click “Install”. After you restart NetBeans you will be able to simply load SBT project as regular NetBeans project.
To build and run ImageJ you will use SBT console provided by the Scala plugin. In the console type `ijRun` and press “Enter”
For the debugging in NetBeans you will need to attach debugger to the running process.
Testing ImageJ plugins during development requires packaging and copying around plugin jars and dependencies. sbt-imagej plugin for SBT simplifies project setup. It can build and copy files as needed. It can also be integrated into your IDE run/debug process. You can find additional information about, including custom settings, on the sbt-imagej project page.