diff --git a/src/main/java/bdv/AbstractSpimSource.java b/src/main/java/bdv/AbstractSpimSource.java index ba8e1b93ed17032580371c1c890e55774753434e..c981e1039da5f2bac258e1e46449e7348ff5f2ab 100644 --- a/src/main/java/bdv/AbstractSpimSource.java +++ b/src/main/java/bdv/AbstractSpimSource.java @@ -1,6 +1,7 @@ package bdv; import mpicbg.spim.data.SequenceDescription; +import mpicbg.spim.data.View; import net.imglib2.RandomAccessible; import net.imglib2.RandomAccessibleInterval; import net.imglib2.RealRandomAccessible; @@ -9,6 +10,7 @@ import net.imglib2.interpolation.randomaccess.NLinearInterpolatorFactory; import net.imglib2.interpolation.randomaccess.NearestNeighborInterpolatorFactory; import net.imglib2.realtransform.AffineTransform3D; import net.imglib2.type.numeric.NumericType; +import net.imglib2.view.Views; import bdv.viewer.Interpolation; import bdv.viewer.Source; @@ -59,7 +61,40 @@ public abstract class AbstractSpimSource< T extends NumericType< T > > implement interpolatorFactories[ iNLinearMethod ] = new NLinearInterpolatorFactory< T >(); } - protected abstract void loadTimepoint( final int timepoint ); + protected void loadTimepoint( final int timepoint ) + { + currentTimepoint = timepoint; + if ( isPresent( timepoint ) ) + { + final T zero = getType().createVariable(); + zero.setZero(); + final View view = sequenceViews.getView( timepoint, setup ); + final AffineTransform3D reg = view.getModel(); + for ( int level = 0; level < currentSources.length; level++ ) + { + final AffineTransform3D mipmapTransform = getMipmapTransforms( setup )[ level ]; + currentSourceTransforms[ level ].set( reg ); + currentSourceTransforms[ level ].concatenate( mipmapTransform ); + currentSources[ level ] = getImage( view, level ); + for ( int method = 0; method < numInterpolationMethods; ++method ) + currentInterpolatedSources[ level ][ method ] = Views.interpolate( Views.extendValue( currentSources[ level ], zero ), interpolatorFactories[ method ] ); + } + } + else + { + for ( int level = 0; level < currentSources.length; level++ ) + { + currentSourceTransforms[ level ].identity(); + currentSources[ level ] = null; + for ( int method = 0; method < numInterpolationMethods; ++method ) + currentInterpolatedSources[ level ][ method ] = null; + } + } + } + + protected abstract AffineTransform3D[] getMipmapTransforms( final int setup ); + + protected abstract RandomAccessibleInterval< T > getImage( final View view, final int level ); @Override public boolean isPresent( final int t ) diff --git a/src/main/java/bdv/BigDataViewer.java b/src/main/java/bdv/BigDataViewer.java index f0b779f25ca3577f4521c46dd0cd31f0a00cf09a..9c86ff48d0779cb8f8ca250638896d56feed89bd 100644 --- a/src/main/java/bdv/BigDataViewer.java +++ b/src/main/java/bdv/BigDataViewer.java @@ -31,7 +31,6 @@ import org.jdom2.output.XMLOutputter; import bdv.export.ProgressWriter; import bdv.export.ProgressWriterConsole; -import bdv.img.openconnectome.OpenConnectomeImageLoader; import bdv.tools.HelpDialog; import bdv.tools.InitializeViewerState; import bdv.tools.RecordMovieDialog; @@ -173,7 +172,7 @@ public class BigDataViewer initSetups( loader, converterSetups, sources ); viewerFrame = new ViewerFrame( width, height, sources, seq.numTimepoints(), - ( ( OpenConnectomeImageLoader ) seq.imgLoader ).getCache() ); + ( ( ViewerImgLoader< ?, ? > ) seq.imgLoader ).getCache() ); viewer = viewerFrame.getViewerPanel(); for ( final ConverterSetup cs : converterSetups ) diff --git a/src/main/java/bdv/SpimSource.java b/src/main/java/bdv/SpimSource.java index 70b34d0655c43308680cca8e9f692e06d4004e18..801db3445fa1f911f143493cfb3c13fb0c9b968d 100644 --- a/src/main/java/bdv/SpimSource.java +++ b/src/main/java/bdv/SpimSource.java @@ -2,9 +2,9 @@ package bdv; import mpicbg.spim.data.SequenceDescription; import mpicbg.spim.data.View; +import net.imglib2.RandomAccessibleInterval; import net.imglib2.realtransform.AffineTransform3D; import net.imglib2.type.numeric.NumericType; -import net.imglib2.view.Views; public class SpimSource< T extends NumericType< T > > extends AbstractSpimSource< T > { @@ -20,40 +20,20 @@ public class SpimSource< T extends NumericType< T > > extends AbstractSpimSource } @Override - protected void loadTimepoint( final int timepoint ) + public T getType() { - currentTimepoint = timepoint; - if ( isPresent( timepoint ) ) - { - final T zero = imgLoader.getImageType().createVariable(); - zero.setZero(); - final View view = sequenceViews.getView( timepoint, setup ); - final AffineTransform3D reg = view.getModel(); - for ( int level = 0; level < currentSources.length; level++ ) - { - final AffineTransform3D mipmapTransform = imgLoader.getMipmapTransforms( setup )[ level ]; - currentSourceTransforms[ level ].set( reg ); - currentSourceTransforms[ level ].concatenate( mipmapTransform ); - currentSources[ level ] = imgLoader.getImage( view, level ); - for ( int method = 0; method < numInterpolationMethods; ++method ) - currentInterpolatedSources[ level ][ method ] = Views.interpolate( Views.extendValue( currentSources[ level ], zero ), interpolatorFactories[ method ] ); - } - } - else - { - for ( int level = 0; level < currentSources.length; level++ ) - { - currentSourceTransforms[ level ].identity(); - currentSources[ level ] = null; - for ( int method = 0; method < numInterpolationMethods; ++method ) - currentInterpolatedSources[ level ][ method ] = null; - } - } + return imgLoader.getImageType(); } @Override - public T getType() + protected RandomAccessibleInterval< T > getImage( final View view, final int level ) { - return imgLoader.getImageType(); + return imgLoader.getImage( view, level ); + } + + @Override + protected AffineTransform3D[] getMipmapTransforms( final int setup ) + { + return imgLoader.getMipmapTransforms( setup ); } } diff --git a/src/main/java/bdv/VolatileSpimSource.java b/src/main/java/bdv/VolatileSpimSource.java index d2dfb10d279230c222817119966157e6332ee331..7739d9e8753db9623481711d427cf4cdd24eaffb 100644 --- a/src/main/java/bdv/VolatileSpimSource.java +++ b/src/main/java/bdv/VolatileSpimSource.java @@ -2,11 +2,10 @@ package bdv; import mpicbg.spim.data.SequenceDescription; import mpicbg.spim.data.View; +import net.imglib2.RandomAccessibleInterval; import net.imglib2.Volatile; import net.imglib2.realtransform.AffineTransform3D; import net.imglib2.type.numeric.NumericType; -import net.imglib2.type.numeric.RealType; -import net.imglib2.view.Views; public class VolatileSpimSource< T extends NumericType< T >, V extends Volatile< T > & NumericType< V > > extends AbstractSpimSource< V > { @@ -24,38 +23,6 @@ public class VolatileSpimSource< T extends NumericType< T >, V extends Volatile< loadTimepoint( 0 ); } - @Override - protected void loadTimepoint( final int timepoint ) - { - currentTimepoint = timepoint; - if ( isPresent( timepoint ) ) - { - final V zero = imgLoader.getVolatileImageType().createVariable(); - zero.setZero(); - final View view = sequenceViews.getView( timepoint, setup ); - final AffineTransform3D reg = view.getModel(); - for ( int level = 0; level < currentSources.length; level++ ) - { - final AffineTransform3D mipmapTransform = imgLoader.getMipmapTransforms( setup )[ level ]; - currentSourceTransforms[ level ].set( reg ); - currentSourceTransforms[ level ].concatenate( mipmapTransform ); - currentSources[ level ] = imgLoader.getVolatileImage( view, level ); - for ( int method = 0; method < numInterpolationMethods; ++method ) - currentInterpolatedSources[ level ][ method ] = Views.interpolate( Views.extendValue( currentSources[ level ], zero ), interpolatorFactories[ method ] ); - } - } - else - { - for ( int level = 0; level < currentSources.length; level++ ) - { - currentSourceTransforms[ level ].identity(); - currentSources[ level ] = null; - for ( int method = 0; method < numInterpolationMethods; ++method ) - currentInterpolatedSources[ level ][ method ] = null; - } - } - } - @Override public V getType() { @@ -66,4 +33,16 @@ public class VolatileSpimSource< T extends NumericType< T >, V extends Volatile< { return nonVolatileSource; } + + @Override + protected RandomAccessibleInterval< V > getImage( final View view, final int level ) + { + return imgLoader.getVolatileImage( view, level ); + } + + @Override + protected AffineTransform3D[] getMipmapTransforms( final int setup ) + { + return imgLoader.getMipmapTransforms( setup ); + } } diff --git a/src/main/java/bdv/img/catmaid/CatmaidImageLoader.java b/src/main/java/bdv/img/catmaid/CatmaidImageLoader.java index 5f56ac92dbcb91544be242dd16dad7a74bce3c77..eeaac44bb89c5264198fde11c421199fb6333f46 100644 --- a/src/main/java/bdv/img/catmaid/CatmaidImageLoader.java +++ b/src/main/java/bdv/img/catmaid/CatmaidImageLoader.java @@ -43,11 +43,11 @@ public class CatmaidImageLoader extends AbstractViewerImgLoader< ARGBType, Volat private double[][] mipmapResolutions; + private AffineTransform3D[] mipmapTransforms; + private long[][] imageDimensions; private int[][] blockDimensions; - - private AffineTransform3D[] mipmapTransforms; private VolatileGlobalCellCache< VolatileIntArray > cache; @@ -163,7 +163,7 @@ public class CatmaidImageLoader extends AbstractViewerImgLoader< ARGBType, Volat } @Override - public AffineTransform3D[] getMipmapTransforms( int setup ) + public AffineTransform3D[] getMipmapTransforms( final int setup ) { return mipmapTransforms; } diff --git a/src/main/java/bdv/img/hdf5/Hdf5ImageLoader.java b/src/main/java/bdv/img/hdf5/Hdf5ImageLoader.java index 526891d2fc8af7b4694f6886620071d11d7161f0..f399244473b0e86a6d10afe0296762521f1e2653 100644 --- a/src/main/java/bdv/img/hdf5/Hdf5ImageLoader.java +++ b/src/main/java/bdv/img/hdf5/Hdf5ImageLoader.java @@ -30,6 +30,7 @@ import bdv.img.cache.VolatileGlobalCellCache; import bdv.img.cache.VolatileGlobalCellCache.LoadingStrategy; import bdv.img.cache.VolatileImgCells; import bdv.img.cache.VolatileImgCells.CellCache; +import bdv.util.MipmapTransforms; import ch.systemsx.cisd.hdf5.HDF5DataSetInformation; import ch.systemsx.cisd.hdf5.HDF5Factory; import ch.systemsx.cisd.hdf5.IHDF5Reader; @@ -140,16 +141,7 @@ public class Hdf5ImageLoader extends AbstractViewerImgLoader< UnsignedShortType, final AffineTransform3D[] mipmapTransforms = new AffineTransform3D[ mipmapResolutions.length ]; for ( int level = 0; level < mipmapResolutions.length; level++ ) - { - final AffineTransform3D mipmapTransform = new AffineTransform3D(); - final double[] resolution = mipmapResolutions[ level ]; - for ( int d = 0; d < 3; ++d ) - { - mipmapTransform.set( resolution[ d ], d, d ); - mipmapTransform.set( 0.5 * ( resolution[ d ] - 1 ), d, 3 ); - } - mipmapTransforms[ level ] = mipmapTransform; - } + mipmapTransforms[ level ] = MipmapTransforms.getMipmapTransformDefault( mipmapResolutions[ level ] ); perSetupMipmapTransforms.add( mipmapTransforms ); final int[][] subdivisions = hdf5Reader.readIntMatrix( getSubdivisionsPath( setup ) ); diff --git a/src/main/java/bdv/img/remote/RemoteImageLoader.java b/src/main/java/bdv/img/remote/RemoteImageLoader.java index c6d937387e3911be48c38ff2b2fcc87c5f21ed89..9046b78247f0e893fbf7b2571d558de2dd53075a 100644 --- a/src/main/java/bdv/img/remote/RemoteImageLoader.java +++ b/src/main/java/bdv/img/remote/RemoteImageLoader.java @@ -28,6 +28,7 @@ import bdv.img.cache.VolatileGlobalCellCache; import bdv.img.cache.VolatileGlobalCellCache.LoadingStrategy; import bdv.img.cache.VolatileImgCells; import bdv.img.cache.VolatileImgCells.CellCache; +import bdv.util.MipmapTransforms; import com.google.gson.Gson; @@ -67,16 +68,7 @@ public class RemoteImageLoader extends AbstractViewerImgLoader< UnsignedShortTyp final double[][] mipmapResolutions = metadata.perSetupMipmapResolutions.get( setup ); final AffineTransform3D[] mipmapTransforms = new AffineTransform3D[ mipmapResolutions.length ]; for ( int level = 0; level < mipmapResolutions.length; level++ ) - { - final AffineTransform3D mipmapTransform = new AffineTransform3D(); - final double[] resolution = mipmapResolutions[ level ]; - for ( int d = 0; d < 3; ++d ) - { - mipmapTransform.set( resolution[ d ], d, d ); - mipmapTransform.set( 0.5 * ( resolution[ d ] - 1 ), d, 3 ); - } - mipmapTransforms[ level ] = mipmapTransform; - } + mipmapTransforms[ level ] = MipmapTransforms.getMipmapTransformDefault( mipmapResolutions[ level ] ); perSetupMipmapTransforms.add( mipmapTransforms ); } cellsDimensions = metadata.createCellsDimensions(); diff --git a/src/main/java/bdv/util/MipmapTransforms.java b/src/main/java/bdv/util/MipmapTransforms.java new file mode 100644 index 0000000000000000000000000000000000000000..cb4dd53bae279d7851906a268f17d793960d6ff3 --- /dev/null +++ b/src/main/java/bdv/util/MipmapTransforms.java @@ -0,0 +1,32 @@ +package bdv.util; + +import net.imglib2.realtransform.AffineTransform3D; + +public class MipmapTransforms +{ + /** + * Compute the transformation (scale and shift) that maps from coordinates + * in a down-scaled image to coordinates in the original image. This assumes + * that each down-scaled pixel is the average of a block of blocks of pixels + * in the original image. For down-scaling by a factor of 2, pixel (0,0,0) + * in the down-scaled image is the average of the 8 pixel block from (0,0,0) + * to (1,1,1) in the original image. + * + * @param resolution + * the down-scaling factors in each dimension. {4,4,2} means + * every pixel in the down-scaled image corresponds to a 4x4x2 + * pixel block in the original image. + * @return transformation from down-scaled image to original image. + */ + public static AffineTransform3D getMipmapTransformDefault( final double[] resolution ) + { + assert resolution.length == 3; + final AffineTransform3D mipmapTransform = new AffineTransform3D(); + for ( int d = 0; d < 3; ++d ) + { + mipmapTransform.set( resolution[ d ], d, d ); + mipmapTransform.set( 0.5 * ( resolution[ d ] - 1 ), d, 3 ); + } + return mipmapTransform; + } +} diff --git a/src/main/java/bdv/viewer/render/MultiResolutionRenderer.java b/src/main/java/bdv/viewer/render/MultiResolutionRenderer.java index e794a060b02b0cb7f7099aa9843ec723806f6c24..7e5aa240e07cee3326b6ed4a9138771c69575d41 100644 --- a/src/main/java/bdv/viewer/render/MultiResolutionRenderer.java +++ b/src/main/java/bdv/viewer/render/MultiResolutionRenderer.java @@ -371,12 +371,12 @@ public class MultiResolutionRenderer ( renderImages[ 0 ][ 0 ].dimension( 0 ) != screenImages[ 0 ][ 0 ].dimension( 0 ) || renderImages[ 0 ][ 0 ].dimension( 1 ) != screenImages[ 0 ][ 0 ].dimension( 1 ) ) ) ) { - renderImages = new ARGBScreenImage[ screenScales.length ][ numVisibleSources ]; + renderImages = new ARGBScreenImage[ screenScales.length ][ n ]; for ( int i = 0; i < screenScales.length; ++i ) { final int w = ( int ) screenImages[ i ][ 0 ].dimension( 0 ); final int h = ( int ) screenImages[ i ][ 0 ].dimension( 1 ); - for ( int j = 0; j < numVisibleSources; ++j ) + for ( int j = 0; j < n; ++j ) { renderImages[ i ][ j ] = ( i == 0 ) ? new ARGBScreenImage( w, h ) :