Backward compatibility is one of ImageJ's most important goals. It must remain possible to use existing plugins and macros with new versions of ImageJ.

ImageJ Legacy

The ImageJ2 project is a complete redesign of ImageJ, with no dependency on ImageJ 1.x. However, to facilitate backwards compatibility, there is an ImageJ Legacy component (source on GitHub) which provides extensions for ImageJ2 and ImageJ1 to operate in harmony.

The ImageJ legacy layer provides the following extensions:

  • It makes ImageJ 1.x usable headless from the command line.
  • It wraps the ImageJ 1.x UI as a SciJava user interface.
  • It translates between ImageJ1 and ImageJ2 data structures on demand.

ImageJ2 currently uses the ImageJ 1.x user interface by default, since many users need to retain access to ImageJ1 plugins.

The ImageJ legacy UI

The legacy layer converts ImageJ1 into a SciJava-compatible user interface by implementing the UserInterface interface via the LegacyUI class.

However, things are complicated by the fact that ImageJ1 was not designed with such requirements in mind. The legacy layer uses a bytecode manipulation library called Javassist to rewrite portions of ImageJ1 at runtime, in order to facilitate integration and extension. See the ij1-patcher project for details.

Translation of data structures

Each ImageDisplay has a linked ImagePlus, kept in sync by the LegacyImageMap. Whenever the need arises, the legacy layer syncs the linked data objects. In order to maintain reasonable performance, every opportunity is taken to avoid data translation by making data changes in place, and only on demand (lazily, with caching). The legacy layer reuses data by reference when feasible—in particular, when image planes are stored in primitive arrays—but in some cases the data must be copied (e.g., for ROIs).

Currently, automatic synchronization is disabled as it has negative performance implications. The planned solution to the performance problems is to implement a wrapping layer, instead of relying on up-front pixel-wise translation.

In the mean time, full synchronization can be forced by setting a imagej.legacy.sync system property. This can be done in a running ImageJ instance, for example by running the following as a BeanShell script:

System.setProperty("imagej.legacy.sync", "true");

Updating ImageJ commands to the new paradigm

The eventual goal is to migrate all core ImageJ1 plugins to the ImageJ2 paradigm. Many ImageJ1 plugins have been already been updated in this fashion; see the imagej-ops and imagej-plugins-commands repositories in particular.

See also

  • The ImageJDev talk from the ImageJ 2010 Conference, for a historical perspective on how this approach to compatibility evolved over time.