Chapter 6. ImageJ Plugins for Developers

In the previous chapter you saw how to install a plugin that is available for download from the developer website. We also introduced some of them that are potentially useful in a wide range of applications. This chapter includes the following:

  • A brief description of ImageJ plugin architecture with examples
  • A walk through some common operations
  • A guide for developing ImageJ plugins using the Eclipse IDE

This chapter will require prior programming experience, ideally with Java, but there is nothing here outside the concepts handled by other object oriented programming languages.

A sample plugin

We will start digging into this topic by analyzing the following plugin code. That will give us a nice starting point to introduce the different aspects for developing ImageJ plugins:

import ij.*;
import ij.process.*;
import ij.gui.*;
import java.awt.*;
import ij.plugin.*;
import ij.plugin.frame.*;

public class Test_Plugin implements PlugIn {
    public void run(String arg) {
        int width = 300;
   	     int height = 300;   	 
ImageProcessor ip = new ByteProcessor(width, height);
  ip.setColor(Color.black);
   	   ip.fill();
       for(int x = 0; x < width; x++) {
   	    for(int y = 0; y < height; y++) {
   	      if (x == y || (width - x) == y)
   	        ip.putPixel(x, y, 255);
   	     }
   	   }
   	   ImagePlus imp = new ImagePlus("Result image", ip);    
   	   imp.show();
    }
}

First things first: this is a plugin, and not a macro. To edit it, navigate to Plugins | New | Plugin. A sample skeleton will be opened and you just need to fill in the run(arg) method (previously, delete the example code that is inside it). When you are done, save the plugin in the ImageJ plugins folder of your working ImageJ installation. The editor is smart enough to change the name of your class to match the name of the file, as Java requires. Also, your class name must contain at least one underscore (_), or ImageJ will not find it. Remember to use the .java extension for the file.

Tip

For advanced users: if you build a JAR file and place inside it plugins.config file that defines which classes are plugins, then there is no need of underscore in the name. In any case, this option is outside the scope of this book, but we wanted to place this warning here, so that you do not think that the underscore is always mandatory.

After completing these steps, you will have a .java file in your plugins folder. Now you need to compile it so that ImageJ can run it. This is done from the editing window, by navigating to File | Compile and then Run (Ctrl + R). If you do not have a Java Development Kit installed in your computer, then ImageJ will offer to download the Compiler.jar plugin, which will allow you to compile new plugins without the need to modify your Java installation. Click on OK on the dialog that shows up if that happens, as you will need it.

If everything has gone according to the plan, now you will also have a Test_Plugin.class file in your plugins folder, and the following screenshot will be displayed:

A sample plugin

We have just run our first ImageJ plugin developed by ourselves. This time, we had to do it from the Compile and Run menu options in the editor window. As the .class file is now in your plugins folder, the next time you restart ImageJ you will see a Test Plugin option in the Plugin menu in the main ImageJ window. Let's go through the code in small chunks, so that you understand what we are doing.

Tip

You can also find your plugin in the ImageJ menus without the need of a restart if you navigate to Help | Refresh Menus. Throughout this text, we will always speak of restarting ImageJ, but bear in mind that you can always use this option.

The first lines include all the necessary library imports and are added automatically by the ImageJ proposed skeleton. If you need to use some other library, put your import here. Then we declare our Test_Plugin class, which implements an interface called PlugIn. There are several ways to code ImageJ plugins, depending on which interface we are implementing, but in this book we are going to focus on two of them: PlugIn and PlugInFilter. Depending on the purpose of our plugin, we will be using one or the other.

The PlugIn interface needs us to implement just one method, run(String arg), that is immediately executed when the plugin is run. The PlugInFilter needs two methods, setup(String arg, ImagePlus imp) and run(ImageProcessor ip). The setup method is the first one that is being run and checks whether the image to which the plugin is being applied (the ImagePlus object passed as reference) has certain properties. Note that we are ignoring the String arg parameter, as it is outside the scope of this book and is not really needed to build powerful plugins. We can make the following distinction: a PlugIn interface implementation can be run in a standalone fashion and the PlugInFilter is applied to an already opened image, just similar to what a macro does. This is a very rough division but it is the one we will use in this book. We will work a bit with the PlugInFilter interface next in this section. For now, let's keep going through our code.

In the run method of our example we create a new square (300 x 300) ImageProcessor object. This is an abstract class that needs to be instantiated depending on the type of image we want to use. In this case, as we are working with a simple 8-bit image, we create a ByteProcessor object with width and height as parameters. We can also use a ShortProcessor object (16-bit unsigned data), BinaryProcessor (similar to ByteProcessor, but its pixel values can only take two values: 0 or 255), FloatProcessor (32-bit floating point values), or ColorProcessor (32-bit RGB image). Once the ImageProcessor object has been created, we can start using its methods to modify its pixel values.

The next thing we do is to set the color chooser to black (ip.setColor(Color.black)) and fill the current ROI with it (ip.fill()). As we have not defined any ROI, this method fills the whole image with the black color.

Next we create two nested for loops (one for the x axis, another for the y axis) and iterate through all the image pixels, by setting those belonging to either diagonal with the ip.putPixel(x, y, value) method to 255.

Tip

If you work with a FloatProcessor object, use the putPixelValue method that accepts a double value as the value parameter type.

After this step, the actual processing is finished. All that is left is to create an ImagePlus object with a title and the pixel contents of the ImageProcessor object and show it on the screen. An ImagePlus object also contains the image's metadata, such as the spatial scale or the calibration. Note that the run method for this interface does not return anything. You must compute all the resulting images and show them on the screen.

Tip

In summary, the philosophy of ImageJ plugin development is to treat ImageJ as an imaging processing library (ij.jar and all its contents), and as a platform that takes care of all the common nuisances (image reading, displaying, saving, and so on) associated with image processing.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset