What is the best way to get an open image in a plugin?

imagej
plugin
parameters

#1

In an ImageJ plugin, what is the best way to access an already-open image?

At first I tried this:
@Parameter
private ImagePlus imgp = null;

This didn’t work at all. I would always get two popup windows saying “A ImagePlus is required but none exist”, even though I already had an image open.

So next I looked through the examples, and it looks like they all use this:

@Parameter
private Dataset currentData;

final Img<T> image = (Img<T>)currentData.getImgPlus();

This code does actually work, and I can get an ImgPlus out of it. However, ImgPlus’s javadoc says

NOTE: This class is slated for redesign in spring 2016. Use at your own risk! If you need future stability, use ImgLib2 and/or ImageJ 1.x classes.

I’m pretty sure that this refers to ImagePlus, and maybe some other class I’m not aware of.

Also, I’m suspicious of the fact that you need to use a generic Img instead of just an ImgPlus. (I tried, and you really do need to use Img<T>.) This still doesn’t seem like the best (right?) way to access an open image.


#2

I suppose you use java. You can call the already-opened image using

IJ.getImage;

Depended on your application you can add this code in your constructor and assign a variable to this. Or you can use this code in your method.

Hope this will help you out.


#3

Now that I’ve tried a little more, it seems that this method doesn’t produce a pop-up choice when I have 2 or more images open. Instead, it just uses the image in front. What can I do so that the either:

  • the user can select which open image to use, or
  • my program can select which open image to use?

EDIT: The menu I want shows up when I need 2 or more Datasets as input.


#4

Is there a way to get an ImagePlus from the currently open image(s)? (I need it for input to a plugin I am calling out to.)

Looking at this forum post, it looks like I should be able to do it with just
@Parameter
private ImagePlus imgp
but, as I said in my original post, this doesn’t work.


#5

Check the static class IJ. You can find lots of different methods which you can use.

@Parameter
private ImagePlus imgp1
private ImagePlus imgp2

method or constructor
String[] titles = IJ.getImageTitles();
ImagePlus imgp1 = IJ.getImage(titles[0]);
ImagePlus imgp2 = IJ.getImage(titles[1]);

When you’ve got the titles in an instance you can use those strings in a menu if you plan to make an UI.

In you specific forum post the author made the images himself. They are stored in two different instances so he can call them. You don’t have these instances yet, except when you use my example.


#6

Dear @avh.on1,

This refers to ImgPlus and classes that are somehow related to the representation of metadata.

That is intended behavior inherited from ImageJ1, where a plugin/macro/script uses the last active image for processing.

What is your development setup? Are you spinning up an ImageJ instance from within your IDE or are you packaging your plugin as JAR to drop it into an existing ImageJ/Fiji installation? I am asking because this should actually work via the imagej-legacy component…

Best,
Stefan


#7

What is your development setup?

I’m using the maven build system. I test my plugin with mvn -Pexec.


#8

Your first example, using @Parameter, does not work for me. I still get

A ImagePlus is required but none exist

I can’t get code based on your second example to compile. The static IJ class does not have a method named getImageTitles. The static class WindowManager does have a method with this name.

Also, IJ.getImage() does not take a string. It can only return the currently active image.


#9

Does your project depend on imagej-legacy? If not, try to add it an re-run your plugin.


#10

I added imagej-legacy to my pom.xml file and recompiled. This time, the plugin seems to work as expected. Thanks, @stelfrich!

This did have an interesting effect on the version of ImageJ that got compiled. It looks like using imagej-legacy causes ImagJ to be compiled with a different UI toolkit.

I am a bit concerned that I need to use legacy compatibility to get an ImagePlus. Is there a different image container I should be using instead? (One that is native to ImageJ2, scijava, etc.?) The only reason I’m trying to get an ImagePlus in particular is so that my plugin can call the Skeletonize3D plugin.


#11

Not compiled, but started. Adding the imagej-legacy dependency will open up the (well known) ImageJ1 user interface.

Since ImagePlus is the legacy container, that’s exactly how it works. You could use ImageJFunctions.wrap() (from imglib2-ij) instead to convert an Img/RandomAccessibleInterval to ImagePlus.


#12

So, I am having the same issue, trying to access the opened image from inside my plugin (itself built upon one of the tutorials): “ImagePlus required but none exists”. Added the legacy part, didn’t work. I have built some functionality upon ImageProcessor class, so the ultimate goal was to get an ImageProcessor instance and pass it to my function.
Now, my questions is, before I have written too much code, what is the long-term best strategy in terms of design – use of these RandomAccessIterator-like things? I am writing a plugin for ImageJ2.

EDIT: in addition to what I have written, a screenshot of my case. I am opening the image as
WindowManage.getCurrentImage()
But I also haveImagePlus as a @Parameter


#13

I used the RandomAccess, after all. Now this code snippet behaves strangely:

private void extractMatrix() {
    int m= (int)img.max(0);
    int n= (int)img.max(1);
    System.out.println(String.format("[extractMatrix] m= %d, n= %d",m,n));
    final RandomAccess<Integer> r= img.randomAccess();
    System.out.println(String.format("[extractMatrix] obtained randomaccess"));
    g= new int[m][n];
    System.out.println(String.format("[extractMatrix] allocated matrix"));
    for ( int i= 0; i < m; ++i )
        for ( int j= 0; j < n; ++j ) {
            r.setPosition(i,0);
            r.setPosition(j,1);
            g[i][j]= r.get();
            System.out.printf("g[%d][%d]= %d\n",i,j,g[i][j]);
        }
    System.out.println("[Done extracting matrix]");
}

The first three lines of debugging info do get printed, but it feels like it never goes inside the loop, let alone print [Done extracting] thing… I am implementing a plugin of type Command.
What can be the reason of this strange behavior?


#14

Well I found the answer to my post above. The fact is, it was dying with an exception, and the reason is – my grasycale images were opened by ImageJ2 as 3-channel RGBs, and in addition, there was an exception that said “UnsignedByteType cannot be converted to Integer”, although I seemed to have parametrized everything with class “Integer”. When run with a debugger, the randon-access object “r” in my code above has type “UnsignedByteType”, for some reason.
Now my next question is, how to open a 3-channel RGB image automatically as a grayscale, but I guess that question belongs to another branch of the forum.

Lesson: tracing with a debugger + reading the source code lines https://github.com/imglib/imglib2/find/master that your debugger is referring to helps.