imagej / imagej-legacy

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

ImagePlus conversion leads to multiple compatible inputs being listed #230

Open imagejan opened 4 years ago

imagejan commented 4 years ago

Consider this Groovy script (run after opening e.g. the Blobs sample image):

#@ ObjectService os
#@ ConvertService cs

import ij.ImagePlus
import net.imagej.Dataset
import net.imagej.ImgPlus
import net.imagej.display.ImageDisplay
import ij.WindowManager

imp = WindowManager.getActiveImage()

def printAvailableObjects(type) {
    println "       $type direct:"
    os.getObjects(type).each {
        println "           --- ${it.class} $it"
    }

    println "       $type converted:"
    cs.getCompatibleInputs(type).each {
        println "           --- ${it.class} $it"
    }
}

println "***** Before conversion:"
printAvailableObjects(ImagePlus.class)

img = cs.convert(imp, Dataset.class)

println "***** After conversion:"
printAvailableObjects(ImagePlus.class)

null

which will output:

***** Before conversion:
        class ij.ImagePlus direct:
        class ij.ImagePlus converted:
            --- class net.imagej.legacy.convert.ImageTitleToImagePlusConverter$ImageTitle blobs.gif
***** After conversion:
        class ij.ImagePlus direct:
        class ij.ImagePlus converted:
            --- class net.imagej.legacy.convert.ImageTitleToImagePlusConverter$ImageTitle blobs.gif
            --- class net.imagej.DefaultDataset blobs.gif
            --- class net.imagej.display.DefaultImageDisplay [net.imagej.display.DefaultDatasetView@50305626]

Consistently, when using a script like this one:

#@ ImagePlus imp1
#@ ImagePlus imp2

... three options will be shown for each parameter, despite a single image being open (because the AbstractInputHarvester uses the same mechanism to retrieve compatible inputs).

image

imagejan commented 4 years ago

With a different variation of these scripts, it can happen that a reference to a Dataset and its DefaultImageDisplay remains present even if all image windows have been closed.

To reproduce:

  1. Run this Groovy script:
    
    #@ ObjectService os
    #@ ConvertService cs
    #@ OpService ops
    #@ DatasetService ds
    #@ UIService ui

import ij.ImagePlus import net.imagej.Dataset import net.imagej.ImgPlus import net.imagej.display.ImageDisplay import ij.WindowManager

img = ops.create().img([32, 64] as int[])

def printAvailableObjects(type) { println " $type direct:" os.getObjects(type).each { println " --- ${it.class} $it" }

println "       $type converted:"
cs.getCompatibleInputs(type).each {
    println "           --- ${it.class} $it"
}

}

println "***** Before showing:" printAvailableObjects(ImagePlus.class)

ui.show(img)

println "***** After showing:" printAvailableObjects(ImagePlus.class)

null


<details>
<summary>Output (as expected)</summary>

Before showing: class ij.ImagePlus direct: class ij.ImagePlus converted: After showing: class ij.ImagePlus direct: class ij.ImagePlus converted: --- class net.imagej.legacy.convert.ImageTitleToImagePlusConverter$ImageTitle --- class net.imagej.DefaultDataset --- class net.imagej.display.DefaultImageDisplay [net.imagej.display.DefaultDatasetView@670929a6]


</details>

2. Run this second script, make some choice for the inputs, and click OK:

```groovy
#@ ImagePlus imp1
#@ ImagePlus imp2
  1. Close the image window

  2. Run the script from step 1.) again, and observe this output:

***** Before showing:
        class ij.ImagePlus direct:
        class ij.ImagePlus converted:
            --- class net.imagej.DefaultDataset <unnamed data>
            --- class net.imagej.display.DefaultImageDisplay [net.imagej.display.DefaultDatasetView@6968dbc3]
***** After showing:
        class ij.ImagePlus direct:
        class ij.ImagePlus converted:
            --- class net.imagej.legacy.convert.ImageTitleToImagePlusConverter$ImageTitle 
            --- class net.imagej.DefaultDataset <unnamed data>
            --- class net.imagej.DefaultDataset <unnamed data>
            --- class net.imagej.display.DefaultImageDisplay [net.imagej.display.DefaultDatasetView@6968dbc3]
            --- class net.imagej.display.DefaultImageDisplay [net.imagej.display.DefaultDatasetView@3863b7a8]