diff --git a/pom.xml b/pom.xml
index 19d6933..4018202 100644
--- a/pom.xml
+++ b/pom.xml
@@ -98,6 +98,8 @@
gpl_v3
BigDataViewer developers.
+ 10.4.14
+
sign,deploy-to-scijava
diff --git a/src/main/java/bdv/ij/CreateXmlForImarisPlugIn.java b/src/main/java/bdv/ij/CreateXmlForImarisPlugIn.java
new file mode 100644
index 0000000..aea4626
--- /dev/null
+++ b/src/main/java/bdv/ij/CreateXmlForImarisPlugIn.java
@@ -0,0 +1,171 @@
+/*-
+ * #%L
+ * Fiji plugins for starting BigDataViewer and exporting data.
+ * %%
+ * Copyright (C) 2014 - 2023 BigDataViewer developers.
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+package bdv.ij;
+
+import java.awt.FileDialog;
+import java.awt.Frame;
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.swing.JFileChooser;
+import javax.swing.filechooser.FileFilter;
+
+import org.scijava.command.Command;
+import org.scijava.plugin.Plugin;
+
+import bdv.BigDataViewer;
+import bdv.ij.util.ProgressWriterIJ;
+import bdv.img.imaris.Imaris;
+import bdv.spimdata.SpimDataMinimal;
+import bdv.spimdata.XmlIoSpimDataMinimal;
+import bdv.viewer.ViewerOptions;
+import ij.IJ;
+import ij.ImageJ;
+import ij.Prefs;
+import mpicbg.spim.data.SpimDataException;
+
+@Plugin(type = Command.class,
+ menuPath = "Plugins>BigDataViewer>Create XML for Imaris file")
+public class CreateXmlForImarisPlugIn implements Command
+{
+ static String lastDatasetPath = "";
+
+ public static void main( final String[] args )
+ {
+ ImageJ.main( args );
+ new CreateXmlForImarisPlugIn().run();
+ }
+ @Override
+ public void run()
+ {
+ if ( Prefs.setIJMenuBar )
+ System.setProperty( "apple.laf.useScreenMenuBar", "true" );
+
+ File file = null;
+
+ if ( Prefs.useJFileChooser )
+ {
+ final JFileChooser fileChooser = new JFileChooser();
+ fileChooser.setSelectedFile( new File( lastDatasetPath ) );
+ fileChooser.setFileFilter( new FileFilter()
+ {
+ @Override
+ public String getDescription()
+ {
+ return "ims files";
+ }
+
+ @Override
+ public boolean accept( final File f )
+ {
+ if ( f.isDirectory() )
+ return true;
+ if ( f.isFile() )
+ {
+ final String s = f.getName();
+ final int i = s.lastIndexOf('.');
+ if (i > 0 && i < s.length() - 1) {
+ final String ext = s.substring(i+1).toLowerCase();
+ return ext.equals( "ims" );
+ }
+ }
+ return false;
+ }
+ } );
+
+ final int returnVal = fileChooser.showOpenDialog( null );
+ if ( returnVal == JFileChooser.APPROVE_OPTION )
+ file = fileChooser.getSelectedFile();
+ }
+ else // use FileDialog
+ {
+ final FileDialog fd = new FileDialog( ( Frame ) null, "Open", FileDialog.LOAD );
+ fd.setDirectory( new File( lastDatasetPath ).getParent() );
+ fd.setFile( new File( lastDatasetPath ).getName() );
+ final AtomicBoolean workedWithFilenameFilter = new AtomicBoolean( false );
+ fd.setFilenameFilter( new FilenameFilter()
+ {
+ private boolean firstTime = true;
+
+ @Override
+ public boolean accept( final File dir, final String name )
+ {
+ if ( firstTime )
+ {
+ workedWithFilenameFilter.set( true );
+ firstTime = false;
+ }
+
+ final int i = name.lastIndexOf( '.' );
+ if ( i > 0 && i < name.length() - 1 )
+ {
+ final String ext = name.substring( i + 1 ).toLowerCase();
+ return ext.equals( "ims" );
+ }
+ return false;
+ }
+ } );
+ fd.setVisible( true );
+ if ( !workedWithFilenameFilter.get() )
+ {
+ fd.setFilenameFilter( null );
+ fd.setVisible( true );
+ }
+ final String filename = fd.getFile();
+ if ( filename != null )
+ {
+ file = new File( fd.getDirectory() + filename );
+ }
+ }
+
+ if ( file != null )
+ {
+ try
+ {
+ final String imsFilename = file.getAbsolutePath();
+ lastDatasetPath = imsFilename;
+ final SpimDataMinimal spimData = Imaris.openIms( imsFilename );
+ final String xmlFilename = xmlFilename( imsFilename );
+ new XmlIoSpimDataMinimal().save( spimData, xmlFilename );
+ IJ.showMessage( "created " + xmlFilename );
+ }
+ catch ( final IOException | SpimDataException e )
+ {
+ throw new RuntimeException( e );
+ }
+ }
+ }
+
+ private static String xmlFilename( String s )
+ {
+ String f = s.endsWith( ".ims" ) ? s.substring( 0, s.length() - 4 ) : s;
+ if ( !new File( f + ".xml" ).exists() )
+ return f + ".xml";
+
+ int i = 2;
+ while ( new File( f + i + ".xml" ).exists() )
+ ++i;
+ return f + i + ".xml";
+ }
+}
diff --git a/src/main/java/bdv/ij/ExportImagePlusPlugIn.java b/src/main/java/bdv/ij/ExportImagePlusPlugIn.java
index 69c56fc..a100e5d 100644
--- a/src/main/java/bdv/ij/ExportImagePlusPlugIn.java
+++ b/src/main/java/bdv/ij/ExportImagePlusPlugIn.java
@@ -55,6 +55,9 @@
import bdv.spimdata.SequenceDescriptionMinimal;
import bdv.spimdata.SpimDataMinimal;
import bdv.spimdata.XmlIoSpimDataMinimal;
+import bdv.img.imagestack.ImageStackImageLoader;
+import bdv.img.n5.N5ImageLoader;
+import bdv.img.virtualstack.VirtualStackImageLoader;
import fiji.util.gui.GenericDialogPlus;
import ij.IJ;
import ij.ImageJ;
@@ -63,6 +66,7 @@
import ij.gui.DialogListener;
import ij.gui.GenericDialog;
import mpicbg.spim.data.generic.sequence.BasicViewSetup;
+import mpicbg.spim.data.generic.sequence.TypedBasicImgLoader;
import mpicbg.spim.data.registration.ViewRegistration;
import mpicbg.spim.data.registration.ViewRegistrations;
import mpicbg.spim.data.sequence.Channel;
@@ -139,19 +143,44 @@ public void run()
progressWriter.out().println( "starting export..." );
// create ImgLoader wrapping the image
- final ImagePlusImgLoader< ? > imgLoader;
- switch ( imp.getType() )
+ final TypedBasicImgLoader< ? > imgLoader;
+ final Runnable clearCache;
+ final boolean isVirtual = imp.getStack() != null && imp.getStack().isVirtual();
+ if ( isVirtual )
{
- case ImagePlus.GRAY8:
- imgLoader = ImagePlusImgLoader.createGray8( imp, params.minMaxOption, params.rangeMin, params.rangeMax );
- break;
- case ImagePlus.GRAY16:
- imgLoader = ImagePlusImgLoader.createGray16( imp, params.minMaxOption, params.rangeMin, params.rangeMax );
- break;
- case ImagePlus.GRAY32:
- default:
- imgLoader = ImagePlusImgLoader.createGray32( imp, params.minMaxOption, params.rangeMin, params.rangeMax );
- break;
+ final VirtualStackImageLoader< ?, ?, ? > il;
+ switch ( imp.getType() )
+ {
+ case ImagePlus.GRAY8:
+ il = VirtualStackImageLoader.createUnsignedByteInstance( imp );
+ break;
+ case ImagePlus.GRAY16:
+ il = VirtualStackImageLoader.createUnsignedShortInstance( imp );
+ break;
+ case ImagePlus.GRAY32:
+ default:
+ il = VirtualStackImageLoader.createFloatInstance( imp );
+ break;
+ }
+ imgLoader = il;
+ clearCache = il.getCacheControl()::clearCache;
+ }
+ else
+ {
+ switch ( imp.getType() )
+ {
+ case ImagePlus.GRAY8:
+ imgLoader = ImageStackImageLoader.createUnsignedByteInstance( imp );
+ break;
+ case ImagePlus.GRAY16:
+ imgLoader = ImageStackImageLoader.createUnsignedShortInstance( imp );
+ break;
+ case ImagePlus.GRAY32:
+ default:
+ imgLoader = ImageStackImageLoader.createFloatInstance( imp );
+ break;
+ }
+ clearCache = () -> {};
}
final int numTimepoints = imp.getNFrames();
@@ -174,8 +203,7 @@ public void run()
timepoints.add( new TimePoint( t ) );
final SequenceDescriptionMinimal seq = new SequenceDescriptionMinimal( new TimePoints( timepoints ), setups, imgLoader, null );
- Map< Integer, ExportMipmapInfo > perSetupExportMipmapInfo;
- perSetupExportMipmapInfo = new HashMap<>();
+ final Map< Integer, ExportMipmapInfo > perSetupExportMipmapInfo = new HashMap<>();
final ExportMipmapInfo mipmapInfo = params.setMipmapManual
? new ExportMipmapInfo( params.resolutions, params.subdivisions )
: autoMipmapSettings;
@@ -189,7 +217,6 @@ public void run()
// required for all original planes contributing to a "plane of
// blocks" at the current level. If this is more than 1/4 of
// available memory, use the loopback image.
- final boolean isVirtual = imp.getStack().isVirtual();
final long planeSizeInBytes = imp.getWidth() * imp.getHeight() * imp.getBytesPerPixel();
final long ijMaxMemory = IJ.maxMemory();
final int numCellCreatorThreads = Math.max( 1, PluginHelper.numThreads() - 1 );
@@ -228,7 +255,7 @@ public void afterEachPlane( final boolean usedLoopBack )
final long actuallyFree = max - total + free;
if ( actuallyFree < max / 2 )
- imgLoader.clearCache();
+ clearCache.run();
}
}
@@ -291,12 +318,6 @@ protected static class Parameters
final File hdf5File;
- final MinMaxOption minMaxOption;
-
- final double rangeMin;
-
- final double rangeMax;
-
final boolean deflate;
final boolean split;
@@ -308,7 +329,7 @@ protected static class Parameters
public Parameters(
final boolean setMipmapManual, final int[][] resolutions, final int[][] subdivisions,
final File seqFile, final File hdf5File,
- final MinMaxOption minMaxOption, final double rangeMin, final double rangeMax, final boolean deflate,
+ final boolean deflate,
final boolean split, final int timepointsPerPartition, final int setupsPerPartition )
{
this.setMipmapManual = setMipmapManual;
@@ -316,9 +337,6 @@ public Parameters(
this.subdivisions = subdivisions;
this.seqFile = seqFile;
this.hdf5File = hdf5File;
- this.minMaxOption = minMaxOption;
- this.rangeMin = rangeMin;
- this.rangeMax = rangeMax;
this.deflate = deflate;
this.split = split;
this.timepointsPerPartition = timepointsPerPartition;
@@ -332,12 +350,6 @@ public Parameters(
static String lastChunkSizes = "{32,32,4}, {16,16,8}, {8,8,8}";
- static int lastMinMaxChoice = 2;
-
- static double lastMin = 0;
-
- static double lastMax = 65535;
-
static boolean lastSplit = false;
static int lastTimepointsPerPartition = 0;
@@ -350,12 +362,6 @@ public Parameters(
protected Parameters getParameters( final double impMin, final double impMax, final ExportMipmapInfo autoMipmapSettings )
{
- if ( lastMinMaxChoice == 0 ) // use ImageJs...
- {
- lastMin = impMin;
- lastMax = impMax;
- }
-
while ( true )
{
final GenericDialogPlus gd = new GenericDialogPlus( "Export for BigDataViewer" );
@@ -367,15 +373,6 @@ protected Parameters getParameters( final double impMin, final double impMax, fi
gd.addStringField( "Hdf5_chunk_sizes", lastChunkSizes, 25 );
final TextField tfChunkSizes = ( TextField ) gd.getStringFields().lastElement();
- gd.addMessage( "" );
- final String[] minMaxChoices = new String[] { "Use ImageJ's current min/max setting", "Compute min/max of the (hyper-)stack", "Use values specified below" };
- gd.addChoice( "Value_range", minMaxChoices, minMaxChoices[ lastMinMaxChoice ] );
- final Choice cMinMaxChoices = (Choice) gd.getChoices().lastElement();
- gd.addNumericField( "Min", lastMin, 0 );
- final TextField tfMin = (TextField) gd.getNumericFields().lastElement();
- gd.addNumericField( "Max", lastMax, 0 );
- final TextField tfMax = (TextField) gd.getNumericFields().lastElement();
-
gd.addMessage( "" );
gd.addCheckbox( "split_hdf5", lastSplit );
final Checkbox cSplit = ( Checkbox ) gd.getCheckboxes().lastElement();
@@ -390,59 +387,37 @@ protected Parameters getParameters( final double impMin, final double impMax, fi
gd.addMessage( "" );
PluginHelper.addSaveAsFileField( gd, "Export_path", lastExportPath, 25 );
-// gd.addMessage( "" );
-// gd.addMessage( "This Plugin is developed by Tobias Pietzsch (pietzsch@mpi-cbg.de)\n" );
-// Bead_Registration.addHyperLinkListener( ( MultiLineLabel ) gd.getMessage(), "mailto:pietzsch@mpi-cbg.de" );
-
final String autoSubsampling = ProposeMipmaps.getArrayString( autoMipmapSettings.getExportResolutions() );
final String autoChunkSizes = ProposeMipmaps.getArrayString( autoMipmapSettings.getSubdivisions() );
- gd.addDialogListener( new DialogListener()
- {
- @Override
- public boolean dialogItemChanged( final GenericDialog dialog, final AWTEvent e )
+ gd.addDialogListener( ( dialog, e ) -> {
+ gd.getNextBoolean();
+ gd.getNextString();
+ gd.getNextString();
+ gd.getNextBoolean();
+ gd.getNextNumber();
+ gd.getNextNumber();
+ gd.getNextBoolean();
+ gd.getNextString();
+ if ( e instanceof ItemEvent && e.getID() == ItemEvent.ITEM_STATE_CHANGED && e.getSource() == cManualMipmap )
{
- gd.getNextBoolean();
- gd.getNextString();
- gd.getNextString();
- gd.getNextChoiceIndex();
- gd.getNextNumber();
- gd.getNextNumber();
- gd.getNextBoolean();
- gd.getNextNumber();
- gd.getNextNumber();
- gd.getNextBoolean();
- gd.getNextString();
- if ( e instanceof ItemEvent && e.getID() == ItemEvent.ITEM_STATE_CHANGED && e.getSource() == cMinMaxChoices )
+ final boolean useManual = cManualMipmap.getState();
+ tfSubsampling.setEnabled( useManual );
+ tfChunkSizes.setEnabled( useManual );
+ if ( !useManual )
{
- final boolean enable = cMinMaxChoices.getSelectedIndex() == 2;
- tfMin.setEnabled( enable );
- tfMax.setEnabled( enable );
+ tfSubsampling.setText( autoSubsampling );
+ tfChunkSizes.setText( autoChunkSizes );
}
- else if ( e instanceof ItemEvent && e.getID() == ItemEvent.ITEM_STATE_CHANGED && e.getSource() == cManualMipmap )
- {
- final boolean useManual = cManualMipmap.getState();
- tfSubsampling.setEnabled( useManual );
- tfChunkSizes.setEnabled( useManual );
- if ( !useManual )
- {
- tfSubsampling.setText( autoSubsampling );
- tfChunkSizes.setText( autoChunkSizes );
- }
- }
- else if ( e instanceof ItemEvent && e.getID() == ItemEvent.ITEM_STATE_CHANGED && e.getSource() == cSplit )
- {
- final boolean split = cSplit.getState();
- tfSplitTimepoints.setEnabled( split );
- tfSplitSetups.setEnabled( split );
- }
- return true;
}
+ else if ( e instanceof ItemEvent && e.getID() == ItemEvent.ITEM_STATE_CHANGED && e.getSource() == cSplit )
+ {
+ final boolean split = cSplit.getState();
+ tfSplitTimepoints.setEnabled( split );
+ tfSplitSetups.setEnabled( split );
+ }
+ return true;
} );
- final boolean enable = lastMinMaxChoice == 2;
- tfMin.setEnabled( enable );
- tfMax.setEnabled( enable );
-
tfSubsampling.setEnabled( lastSetMipmapManual );
tfChunkSizes.setEnabled( lastSetMipmapManual );
if ( !lastSetMipmapManual )
@@ -461,9 +436,6 @@ else if ( e instanceof ItemEvent && e.getID() == ItemEvent.ITEM_STATE_CHANGED &&
lastSetMipmapManual = gd.getNextBoolean();
lastSubsampling = gd.getNextString();
lastChunkSizes = gd.getNextString();
- lastMinMaxChoice = gd.getNextChoiceIndex();
- lastMin = gd.getNextNumber();
- lastMax = gd.getNextNumber();
lastSplit = gd.getNextBoolean();
lastTimepointsPerPartition = ( int ) gd.getNextNumber();
lastSetupsPerPartition = ( int ) gd.getNextNumber();
@@ -489,14 +461,6 @@ else if ( resolutions.length != subdivisions.length )
continue;
}
- final MinMaxOption minMaxOption;
- if ( lastMinMaxChoice == 0 )
- minMaxOption = MinMaxOption.TAKE_FROM_IMAGEPROCESSOR;
- else if ( lastMinMaxChoice == 1 )
- minMaxOption = MinMaxOption.COMPUTE;
- else
- minMaxOption = MinMaxOption.SET;
-
String seqFilename = lastExportPath;
if ( !seqFilename.endsWith( ".xml" ) )
seqFilename += ".xml";
@@ -510,6 +474,7 @@ else if ( lastMinMaxChoice == 1 )
final String hdf5Filename = seqFilename.substring( 0, seqFilename.length() - 4 ) + ".h5";
final File hdf5File = new File( hdf5Filename );
- return new Parameters( lastSetMipmapManual, resolutions, subdivisions, seqFile, hdf5File, minMaxOption, lastMin, lastMax, lastDeflate, lastSplit, lastTimepointsPerPartition, lastSetupsPerPartition ); }
+ return new Parameters( lastSetMipmapManual, resolutions, subdivisions, seqFile, hdf5File, lastDeflate, lastSplit, lastTimepointsPerPartition, lastSetupsPerPartition );
+ }
}
}
diff --git a/src/main/java/bdv/ij/OpenImarisPlugIn.java b/src/main/java/bdv/ij/OpenImarisPlugIn.java
index 32cbfeb..ebaf600 100644
--- a/src/main/java/bdv/ij/OpenImarisPlugIn.java
+++ b/src/main/java/bdv/ij/OpenImarisPlugIn.java
@@ -43,7 +43,7 @@
import ij.Prefs;
@Plugin(type = Command.class,
- menuPath = "Plugins>BigDataViewer>Open Imaris (experimental)")
+ menuPath = "Plugins>BigDataViewer>Open Imaris")
public class OpenImarisPlugIn implements Command
{
static String lastDatasetPath = "";
diff --git a/src/main/java/bdv/ij/export/imgloader/ImagePlusImgLoader.java b/src/main/java/bdv/ij/export/imgloader/ImagePlusImgLoader.java
index 667555d..32dcd5a 100644
--- a/src/main/java/bdv/ij/export/imgloader/ImagePlusImgLoader.java
+++ b/src/main/java/bdv/ij/export/imgloader/ImagePlusImgLoader.java
@@ -57,6 +57,7 @@
*
* @author Tobias Pietzsch <tobias.pietzsch@gmail.com>
*/
+@Deprecated
public class ImagePlusImgLoader< T extends Type< T > > implements TypedBasicImgLoader< T >
{
public static enum MinMaxOption