imagej / imagej-legacy

ImageJ+ImageJ2 compatibility layer
https://imagej.net/libs/imagej-legacy
BSD 2-Clause "Simplified" License
16 stars 25 forks source link

User-Created Rectangular ROIs Cannot be Used in Code #222

Closed sudgy closed 4 years ago

sudgy commented 4 years ago

When a user selects a rectangular ROI, and then code calls the ImagePlus' getRoi() and tries to iterate over it, the code throws a NullPointerException. Here is a simple plugin that can be used to reproduce the bug:

import java.awt.Point;

import org.scijava.command.Command;
import org.scijava.plugin.Plugin;
import ij.ImagePlus;
import ij.process.FloatProcessor;
import ij.gui.WaitForUserDialog;

@Plugin(type = Command.class, menuPath = "Plugins > Bad ROI")
public class BadROI implements Command {
    @Override
    public void run() {
        ImagePlus img = new ImagePlus("", new FloatProcessor(500, 500));
        img.show();
        WaitForUserDialog dialog = new WaitForUserDialog("Foo"); // Select an ROI here
        dialog.show();
        for (Point p : img.getRoi()) {} // Code crashes here
    }
}

The interesting thing is that this only crashes when a rectangular ROI is selected. With any other type of ROI, it works correctly.

imagejan commented 4 years ago

This is an issue of imagej1.

Stack Trace ``` java.lang.NullPointerException at ij.gui.Roi$RoiPointsIteratorMask.(Roi.java:2332) at ij.gui.Roi.iterator(Roi.java:2306) at java_lang_Iterable$iterator.call(Unknown Source) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:117) at Script3.run(Script3.groovy:9) at org.scijava.plugins.scripting.groovy.GroovyScriptEngine.eval(GroovyScriptEngine.java:303) at org.scijava.plugins.scripting.groovy.GroovyScriptEngine.eval(GroovyScriptEngine.java:122) at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:264) at org.scijava.script.ScriptModule.run(ScriptModule.java:160) at org.scijava.module.ModuleRunner.run(ModuleRunner.java:168) at org.scijava.module.ModuleRunner.call(ModuleRunner.java:127) at org.scijava.module.ModuleRunner.call(ModuleRunner.java:66) at org.scijava.thread.DefaultThreadService$3.call(DefaultThreadService.java:238) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) ```

The reason is likely mask being null at the reported line here:

https://github.com/imagej/imagej1/blob/1dc384577de2a8dcccf6bb69b6d14700cc61f908/ij/gui/Roi.java#L2332

Rectangular ROIs seem to return null for their getMask() method, as shown by this Groovy script:

import ij.gui.OvalRoi
roi = new OvalRoi(0,0,10,10)
println roi.getMask() // ip[width=10, height=10, bits=8, min=0.0, max=255.0]

import ij.gui.Roi
roi = new Roi(0,0,10,10)
println roi.getMask() // null

@rasband any comments?

rasband commented 4 years ago

getMask() returns null because Rectangular ROIs do not need a mask. Here is the code for Roi.getMask():

   /** Always returns null for rectangular Roi's */
   public ImageProcessor getMask() {
      if (cornerDiameter>0)
         return (new ShapeRoi(new RoundRectangle2D.Float(x, y, width, height, cornerDiameter, cornerDiameter))).getMask();
      else
         return null;
   }
imagejan commented 4 years ago

Thanks @rasband for the quick reply. I see the point why rectangular ROIs don't need a mask. Nevertheless, the original issue – that iterating over all points inside the ROI throws an exception – is not yet solved, so I reopen this issue.

rasband commented 4 years ago

This bug is fixed in the ImageJ 1.52s5 daily build. The Roi Iterator now creates the mask needed to iterate over the points in a rectangular ROI. Code changes are at https://github.com/imagej/imagej1/commit/a8cb324b96c40bfbc843809a8d625371fee3504e