Page history Edit this page How do I edit this website?

PlugIn Design Guidelines

This section is out of date, potentially misleading or invalid. Be careful with any instructions here. When in doubt, ask for help from the community.

Key concepts

We favor a style of ImageJ plugin design that enables execution of the plugin:

  • From the menus.
  • From a macro.
  • From any other plugin or script.

The key point is to separate the setup from the execution. For the purpose, we place the setup within the run method (any dialogs, for example) and the execution in another method.

A second key point is never to show images unless within the run method. There’s nothing more annoying than a plugin that assumes there is no other plugin running, or that its invocation will happen always from the menus.

If possible, provide a method that leaves the validation to the caller, and that returns a strongly-typed object (see the duplicateAndScale method in the example below).

If you cannot use a GenericDialog for input for some reason, make your code scriptable by providing static methods with String parameters (so they can be called via the call() macro function), and insert code like this into the interactive (i.e. the run method, not the methods that are called from macros, scripts or other plugins) parts of the code:

if (Recorder.record) {
        String command = "call(\"Duplicate_and_Scale.duplicateAndScale\", \"Scaled\");";
        Recorder.recordString(command);
}

Example java plugin

For example, a plugin that duplicates and scales an image:

/* Paste into the Script Editor, or save as Duplicate_and_Scale.java into the plugins folder */
import ij.plugin.PlugIn;
import ij.IJ;
import ij.ImagePlus;
import ij.gui.GenericDialog;
import ij.process.ImageProcessor;

/** Duplicate and scale the current image. */
public class Duplicate_and_Scale implements PlugIn {

    /** Ask for parameters and then execute.*/
    public void run(String arg) {
        // 1 - Obtain the currently active image:
        ImagePlus imp = IJ.getImage();
        if (null == imp) return;

        // 2 - Ask for parameters:
        GenericDialog gd = new GenericDialog("Scale");
        gd.addNumericField("width:", imp.getWidth(), 0);
        gd.addNumericField("height:", imp.getHeight(), 0);
        gd.addStringField("name:", imp.getTitle());
        gd.showDialog();
        if (gd.wasCanceled()) return;

        // 3 - Retrieve parameters from the dialog
        int width = (int)gd.getNextNumber();
        int height = (int)gd.getNextNumber();
        String name = gd.getNextString();

        // 4 - Execute!
        Object[] result = exec(imp, name, width, height);

        // 5 - If all went well, show the image:
        if (null != result) {
            ImagePlus scaled = (ImagePlus) result[1];
            scaled.show();
        }
    }

    /**
        * Execute the plugin functionality: duplicate and scale the given image.
        * @return an Object[] array with the name and the scaled ImagePlus.
        * Does NOT show the new, scaled image; just returns it.
        */
    public Object[] exec(ImagePlus imp, String newName, int width, int height) {
        // 0 - Check validity of parameters
        if (null == imp) return null;
        if (width <= 0 || height <= 0) return null;
        if (null == newName) newName = imp.getTitle();

        // 1 - Perform the duplication and resizing
        ImagePlus scaled = duplicateAndScale(imp, newName, width, height);

        // 2 - Return the new name and the scaled image
        return new Object[]{newName, scaled};
    }

    /**
        * Execute the plugin functionality: duplicate and scale the given image, without validation.
        * @return the scaled ImagePlus.
        * Does NOT show the new, scaled image; just returns it.
        */
    public static ImagePlus duplicateAndScale(ImagePlus imp, String newName, int width, int height) {
        ImageProcessor ip = imp.getProcessor().resize(width, height);
        return new ImagePlus(newName, ip);
    }
}

Compiling the plugin

Using the Script Editor

The easiest way to compile and run the plugin is to use the Script Editor: Call FileNewScript, select Java in the Language menu, and paste the source. Then, compile and run the plugin by calling Run in the Run menu.

The hard way

You can save the java code in a java file with the same name of the class. For the above it would be Duplicate_and_Scale.java.

To compile the plugin, you have several options:

  • If you saved the java file into the plugins/ directory inside the Fiji directory, after HelpRefresh Menus, it will appear in the Plugins menu.
  • Call PluginsCompile and Run and specify the where you saved the file.
  • Compile it from a terminal with
./fiji --javac plugins/Duplicate_and_Scale.java

For this to work, you have to save the java file into the plugins/ directory, or you have to copy the class files into said directory after compilation. For the plugin to appear in the Plugins menu, you have to call HelpRefresh Menus, or to restart Fiji.

Running the plugin

If you pasted the source into the Script Editor, you can run the plugin using the Run>Run menu entry.

Otherwise, after HelpRefresh Menus, or a Fiji restart, there will be a menu item called Duplicate and Scale in the Plugins menu.

From a macro

To run the plugin from a macro, do:

IJ.run("Duplicate and Scale", "name=[scaled copy] width=500 height=700");

From a java plugin

To run the plugin from another java plugin, do:

ImagePlus source = ...; // any image

Duplicate_and_Scale das = new Duplicate_and_Scale();
Object[] result = das.exec(source, "Scaled Copy", 500, 700);
if (null != result) {
	String name = (String) result[0];
	ImagePlus scaled = (ImagePlus) result[1];
}

or use the static method:

ImagePlus source = ...; // any image
ImagePlus scaled = Duplicate_and_Scale.duplicateAndScale(source, 500, 700);

From javascript

To run the plugin from a javascript, do:

var source = ...; // any image
var das = new Duplicate_and_Scale();
var result = das.exec(source, "Scaled Copy", 500, 700);
if (result) {
	var name = result[0];
	var imp = result[1];
}

As a special case, since the above example plugin needs only one image, we can provide such image semidirectly with the new Thread-safe current image concept. Keep in mind that then the plugin will show the new scaled image, not return it!

    var source = ...; // any image
    IJ.run(source, "Duplicate and Scale", "name=[scaled copy] width=500 height=700");

Above, ImageJ’s macro system provides the source image as the return value of the IJ.getImage() call within the plugin’s run method. Then, the macro arguments are fed directly into the GenericDialog entries of the same name, and the rest of the run method calls the exec method without ever showing the dialog.