diff --git a/src/napari_imagej/types/converters/images.py b/src/napari_imagej/types/converters/images.py index 0030f138..e91e0ed8 100644 --- a/src/napari_imagej/types/converters/images.py +++ b/src/napari_imagej/types/converters/images.py @@ -10,7 +10,7 @@ from jpype import JArray, JByte from napari.layers import Image from napari.utils.colormaps import Colormap -from numpy import ones +from numpy import ones, uint8 from scyjava import Priority from xarray import DataArray @@ -59,6 +59,16 @@ def _image_layer_to_dataset(image: Image, **kwargs) -> "jc.Dataset": :param image: a napari Image layer :return: a Dataset """ + # Define dimension order if necessary + if "dim_order" not in kwargs: + # NB "dim_i"s will be overwritten later + dim_order = [f"dim_{i}" for i in range(len(image.data.shape))] + # if RGB, last dimension is Channel + if image.rgb: + dim_order[-1] = "Channel" + + kwargs["dim_order"] = dim_order + # Construct a dataset from the data dataset: "jc.Dataset" = nij.ij.py.to_dataset(image.data, **kwargs) @@ -86,8 +96,16 @@ def _image_layer_to_dataset(image: Image, **kwargs) -> "jc.Dataset": # Add name dataset.setName(image.name) - # Add color table, if the image uses a custom colormap - if image.colormap.name != "gray": + + # Set RGB + if ( + image.rgb + and dataset.dimensionIndex(jc.Axes.CHANNEL) > -1 + and image.dtype == uint8 + ): + dataset.setRGBMerged(True) + # or add color table, if the image uses a custom colormap + elif image.colormap.name != "gray": color_table = _colormap_to_color_table(image.colormap) dataset.initializeColorTables(1) dataset.setColorTable(color_table, 0) diff --git a/src/napari_imagej/widgets/widget_utils.py b/src/napari_imagej/widgets/widget_utils.py index 8a2f88fb..2d30638a 100644 --- a/src/napari_imagej/widgets/widget_utils.py +++ b/src/napari_imagej/widgets/widget_utils.py @@ -168,13 +168,14 @@ def __init__(self, title: str, choices: List[Layer], required=True): class DimsComboBox(QFrame): """A QFrame used to map the axes of a Layer to dimension labels""" + # NB: Strings correspond to supported net.imagej.axis.Axes types dims = [ [], ["X"], ["Y", "X"], ["Z", "Y", "X"], - ["T", "Y", "X", "C"], - ["T", "Z", "Y", "X", "C"], + ["Time", "Y", "X", "Channel"], + ["Time", "Z", "Y", "X", "Channel"], ] def __init__(self, combo_box: LayerComboBox): @@ -199,7 +200,12 @@ def update(self, index: int): # Determine the selected layer selected = self.selection_box.combo.itemData(index) # Guess dimension labels for the selection - guess = self.dims[len(selected.data.shape)] + ndim = len(selected.data.shape) + if isinstance(selected, Image) and selected.rgb: + guess = list(self.dims[ndim - 1]) + guess.append("Channel") + else: + guess = self.dims[ndim] # Create dimension selectors for each dimension of the selection. for i, g in enumerate(guess): self.layout().addWidget( @@ -220,7 +226,8 @@ def provided_labels(self): class DimSelector(QWidget): """A QWidget providing potential labels for each dimension""" - choices = ["X", "Y", "Z", "T", "C", "Unspecified"] + # NB: Strings correspond to supported net.imagej.axis.Axes types + choices = ["X", "Y", "Z", "Time", "Channel", "Unspecified"] def __init__(self, title: str, guess: str): # Define widget layout diff --git a/tests/widgets/test_menu.py b/tests/widgets/test_menu.py index bc607791..3a076b4c 100644 --- a/tests/widgets/test_menu.py +++ b/tests/widgets/test_menu.py @@ -328,9 +328,10 @@ def test_advanced_data_transfer( assert not button.isEnabled() # Add an image to the viewer - sample_data = numpy.ones((100, 100, 3)) + sample_data = numpy.ones((100, 100, 3), dtype=numpy.uint8) image: Image = Image(data=sample_data, name="test_to") current_viewer().add_layer(image) + assert image.rgb asserter(lambda: button.isEnabled()) # Add some rois to the viewer @@ -374,6 +375,8 @@ def check_active_display(): dataset = ij.display().getActiveDisplay().getActiveView().getData() if not dataset.getName() == "test_to": return False + if not dataset.isRGBMerged(): + return False rois = dataset.getProperties().get("rois") return rois is not None @@ -447,7 +450,7 @@ def test_modification_in_imagej(asserter, qtbot, ij, gui_widget: NapariImageJMen # Add some data to the viewer sample_data = numpy.ones((100, 100, 3), dtype=numpy.uint8) - image: Image = Image(data=sample_data, name="test_to") + image: Image = Image(data=sample_data, name="test_to", rgb=False) current_viewer().add_layer(image) # Press the button, handle the Dialog