I’ve posted a couple of issues I uncovered when exploring
how to display IJ2 images. They are all related to the
fact that (per documentation “found on the internet”) the
approved way to display an IJ2 Img is to call
ImageJFunctions.show (img, "title");
That is, IJ2 delegates image display to IJ1, and the issues
I’ve stumbled over are associated with the IJ2–IJ1 interface.
So, is there a native IJ2 mechanism that I should be using
to display IJ2 images (using stock Fiji for real-world work)?
(DisplayService does not appear to have a .show (...) method.)
Thanks, this also works (with createDisplay).
First, both methods (ItemIO.OUTPUT and createDisplay) appear
(at least visually) to display the images the same way (as one
Second, images of signed integral types (I’ve tested ByteType
and IntType) appear to get wrapped / converted to FloatType
(or analogous) images. When displayed, they both show up as
"32-bit," and the pixel values show up (using Fiji’s cursor and
reading the pixel values from Fiji’s status line) as things like
"x=0, y=0, value=-128.0" (note, in particular, the trailing “.0”).
This – converting to FloatType – seems like a reasonable
expedient. No information is lost, and the images display
(UnsignedByteType displays exactly I as would expect; in
particular, the display images are labelled as “8-bit.”)
(My tests were done using an IJ2-style plugin in an auto-updated
Argh, sorry for the confusion! It’s actually the UIService with its show method that I wanted to point out.
I am just thinking out loud because I haven’t had time to confirm this. 8-bit images in ImageJ are represented by a ByteProcessor that is backed by a byte. That is, the negative range of a byte has to be somehow mapped to [128, 255] in “ImageJ1 values” (8-bit images have values in [0, 255]). The same idea holds for other types, I assume: values from a container of UnsignedShortType could be mapped to a ShortProcessor (backed by a short). The only ImageJ1 image type, that can represent negative values is 32-bit, i.e. FloatProcessor backed by a float. Hence, all the signed types that you have mentioned IntType, ByteType need a 32-bit ImageJ image. Otherwise, you wouldn’t be able to map the data into the ImageJ1 concept.
Thanks for the follow-up. Your analysis of the image-conversion
question is consistent with my thinking.
Yes. I’ve now tried:
uiService.show ("title", img);
and it works, as well. (As far as I can tell – when run in a java
plugin launched from Fiji – it does exactly the same thing as displayService.createDisplay ("title", img);,
except for returning void.)
Yes, that makes sense. This was pretty much my thinking when I
was analyzing the related bug in
In any event, the ImageJFunctions.show() bug still stands,
and ought to be addressed somehow. I would suggest (in order
of increasing fanciness):
Remove ImageJFunctions.show() and require the use
of, e.g., UIService.show(), instead.
Have ImageJFunctions.show(img, "title")
convert img to FloatType / GRAY32 (which is what
etc., appear to do).
Refactor the code so that ImageJFunctions.show()
uses the same code path as UIService.show() and
DisplayService.createDisplay() (which, hopefully, are
already using the same code path as one another).
(Could ImageJFunctions.show() simply be rewritten
to delegate to UIService.show(), or is there something
more going on here that would keep this from working?)
Teach IJ1 how to display signed integral images so
that IJ2 can use IJ1 to display them without converting
to FloatType / GRAY32 (which has the cost of the conversion
itself, as well as a cost of up to a factor of four in storage.)
Well, this might be unlikely to happen, but I don’t see a problem
keeping things compatible. Adding classes and/or methods to IJ1
(signed integral display support) would be a non-breaking change.
The only compatibility issue that could arise would be using a new
version of ImageJFunctions.show() with an old IJ1 jar that doesn’t
support the new calls. But, with all of the poms and boms and
mavens and updaters, I don’t see a legitimate reason for this to
The new ImageJFunctions would have the new IJ1 display
functionality as a dependency – you only update the former
if do (and can) update the latter. (This must happen all the
time – a new version of X requires new version of some
I don’t know enough about the usage patterns of ImageJ to know
whether it would be worth the bother to add functionality to IJ1,
and I don’t know whether the cost of the proposed --> FloatType
conversion (not trivial in principle) would be likely to matter in
practice. So maybe the quick fix is the smarter choice.
But the clean fix is certainly doable.
Not at all. See:
I’ve also added a link to the github issue to the related post: