NOTICE! This is a static HTML version of a legacy ImageJ Trac ticket.

The ImageJ project now uses GitHub Issues for issue tracking.

Please file all new issues there.

Ticket #513 (closed defect: fixed)

Opened 2011-05-11T15:21:37-05:00

Last modified 2011-05-19T13:26:34-05:00

Image::Type::HSB Stack plugin results display poorly

Reported by: bdezonia Owned by: bdezonia
Priority: major Milestone: biweekly-2011: May-09 to May-20
Component: Display API Version:
Severity: serious Keywords:
Cc: Blocked By:


If you load clown and run the Image::Type:HSB Stack plugin the results are displayed strangely. IJ2 still thinks it has a color image and it colors the three channels R, G, and B.

Change History

comment:1 Changed 2011-05-11T15:57:49-05:00 by bdezonia

While running in the debugger I can see that LegacyImageMap::reconcileDifferences() is getting called 3 times. After the first two calls the data has a Z slider and is greyscale. After the 3rd call the slider is labeled Channel and the data is displayed as color.

I'm not exactly whether it should treat it as color or not here but trying to have it both ways is a problem. Investigate why image map prodded numerous times for same Dataset/ImagePlus pair.

comment:2 Changed 2011-05-11T16:57:09-05:00 by bdezonia

  • Owner changed from bdezonia to curtis
  • Status changed from new to assigned

After debugging I'm left with the opinion that even though channels == 3 the Dataset is not composite and yet a CompositeXYProjector is being used to display the data. This might point to code that has yet to be written. Passing ticket onto someone who can clarify.

Note that the reconcileDifferences() code is getting called many times because ij1 repeatedly calls show() / updateAndDraw() / repaint() while its processing. So we repeatedly get called. The sequence of steps to convert clown to an HSB stack is a good test that can bear out how the legacy layer can be improved. Maybe the legacy layer should know whether its in the middle of running an IJ1 plugin and avoid processing all the updateAndDraw() calls.

comment:3 Changed 2011-05-12T12:57:03-05:00 by bdezonia

Note that if you remove repaintWindow() from the LegacyManager the behavior is different. It still calls reconcileDifferences() a few times but results are a greyscale Z stack. However, removing it causes Delete Slice to not work. Doing further investigation.

comment:4 Changed 2011-05-12T13:26:08-05:00 by bdezonia

This issue points out a basic problem with the legacy layer. What we really need to do is not override the drawing methods of ImagePlus but rather the data changing methods.

If we were notified of ImagePlus::setStack() calls and had the legacy layer make very targeted changes to parallel Datasets then perhaps the performance hits would be avoided. And Delete Slice would work.

As a complication of overriding setStack() it is called within the constructors of ImagePlus. So our legacy layer would be called with an ImagePlus that was not completely constructed. We either are very careful with what we do with it and defer computations until later. Or we avoid this issue by getting Wayne's help to modify IJ1 classes as needed to call internal helpers rather than public methods within their constructors. This is good practice but not sure we can get those changes.

comment:5 Changed 2011-05-13T13:24:15-05:00 by bdezonia

  • Owner changed from curtis to bdezonia

After more thorough IJ1 code review I think all we need to track is updateAndDraw() and repaintWindow() in ImagePlus. repaintWindow() is used in a couple places where no changes are being made (*listed below) but otherwise is used to indicate that a change to an ImagePlus has taken place.

After discussion with Curtis it is apparent that reconcileDifferences() should get moved outside LegacyImageMap to where we can detect a plugin has completed. LegacyImageMap should just record which Datasets need reconciliation and then called only once.

  • list of repaintWindow() calls where reconciliation would not be necessary
    • magnification on an ImageCanvas
    • magnification while running the Orthogonal Views plugin
    • magnification via the Zoom plugin
    • setting the canvas color or border via an Options dialog

These calls could be hooked and measures taken to avoid reconciliation. But also they seem to be things that we are replacing in IJ2 and so maybe they'll never be called.

comment:6 Changed 2011-05-13T16:08:32-05:00 by bdezonia

Changed design of plugin calling mechanism to call create and/or reconcile of Datasets as little as possible. The bug is still apparent.

comment:7 Changed 2011-05-13T17:01:35-05:00 by bdezonia

I am writing this up as I can't likely fix this before a 4 day weekend.

I'm pretty sure I've found the problem. The original DatasetView is color for clown (rgbmerged true and channel == 3). Running the HSB Stack plugin turns the Dataset into a greyscale Z stack (channel == 1). But nobody tells SwingImageDisplay to rebuild the view. So the old view with the old color projector is fed the new gray Dataset. It displays in color.

We need to probably create a new kind of event (DatasetTypeChangedEvent?). Have certain plugins generate these (such as from the Image :: Type submenu). Then SwingImageDisplay can catch them and rebuild a view if its dataset has changed type.

comment:8 Changed 2011-05-13T17:01:49-05:00 by bdezonia

  • Status changed from assigned to accepted

comment:9 Changed 2011-05-13T17:02:11-05:00 by bdezonia

  • Summary changed from Image::Type::HSB STack plugin results display poorly to Image::Type::HSB Stack plugin results display poorly

comment:10 Changed 2011-05-17T13:29:52-05:00 by bdezonia

Made a couple new events (DatasetRGBChangedEvent and DatasetTypeCHangedEvent). Made Datset throw these at appropriate times. Changed DatasetView to listen for these two events and when detected to call rebuild().

These changes took place after the JHotDraw code was merged in. Due to bugs in that code I am unable to test this fix. Keeping open for now.

comment:11 Changed 2011-05-18T10:37:45-05:00 by bdezonia

I am able to do some testing. Converting from isRgbMerged() == true images to an HSB stack via the Type :: HSB Stack plugin resulted in an image that displays as red no matter which of the channels is selected and only shows the first channel's data values. I've verified all three channels of data are present and different but only the first is getting selected for display since none of the channels are set to composite.

It is not clear to me if we have a multichannel image as to whether it should always be composited with colors. Or if you could view each channel in grayscale somehow. Or if you could view each channel as a separate color. So not sure of the status of this bug.

As a workaround I have changed DatasetHarmonizer to setCompositeChannelCount() to the number of channels present in the Dataset. Now things display as composited in color and channel slider makes no difference.

comment:12 Changed 2011-05-18T14:44:23-05:00 by bdezonia

Made DatasetHarmonizer::harmonize() correctly set composite channel count. When this is done this rendering bug still exists.

Have debugged code and can't see what the problem is. Have confirmed that CompositeXYProjector::map() is creating correct ARGB pixel values and that LUTs are separately red, green, and blue for the 1st three channels.

Can't see where but somewhere there must be an assumption that only the first channel should be drawn. That is how its behaving but still does not make logical sense knowing data is correctly generated.

comment:13 Changed 2011-05-18T14:49:05-05:00 by bdezonia

Or its like the data gets drawn the first time. Then changing sliders fires a drawing event and work is done but the screen is not refreshed. Like someone is forgetting to invalidate something.

comment:14 Changed 2011-05-19T11:25:48-05:00 by bdezonia

Verified that the display's ARGBScreenImage reference is getting correctly changed upon a rebuild(). Thought maybe the ARGBScreenImage reference was not changing and that we were drawing into one that was not tied to a display. Not the case.

comment:15 Changed 2011-05-19T12:05:39-05:00 by bdezonia

BTW, now simply loading T1 Head sample and trying to scroll through it's slices exhibits the issue. Graphics are never updated and you have only the first slice displayed. This was working a couple(?) days ago.

I will update my code to latest repository contents and try again. Cannot at the moment as the build is broken.

comment:16 Changed 2011-05-19T13:10:33-05:00 by bdezonia

  • Status changed from accepted to closed
  • Resolution set to fixed

Curtis found sliders not updating issue by 6a3b5a8d65250312f33d3b948c63604acea1308f.

The converted HSB stack now draws in 3 separate colors (r,g,b), one for each channel. Ideally this should draw in grayscale.

I will now close this bug and create a separate ticket for getting the color correct.

comment:17 Changed 2011-05-19T13:26:34-05:00 by bdezonia

Curtis fix was to make sure SwingDisplayWindow::update() was updating all its views. Before it was only updating the label.