diff --git a/pom.xml b/pom.xml index a49ce776..ecc5ed77 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ sc.fiji bigdataviewer-core - 10.2.1-SNAPSHOT + 10.2.1-SNAPSHOT BigDataViewer Core BigDataViewer core classes with minimal dependencies. diff --git a/src/main/java/bdv/export/DownsampleBlock.java b/src/main/java/bdv/export/DownsampleBlock.java index 8f43abb2..b71de212 100644 --- a/src/main/java/bdv/export/DownsampleBlock.java +++ b/src/main/java/bdv/export/DownsampleBlock.java @@ -6,13 +6,13 @@ * %% * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -29,8 +29,11 @@ package bdv.export; import java.util.Arrays; -import net.imglib2.Cursor; -import net.imglib2.RandomAccess; + +import gnu.trove.iterator.TLongLongIterator; +import gnu.trove.map.hash.TLongLongHashMap; +import gnu.trove.set.TLongSet; +import net.imglib2.*; import net.imglib2.img.array.ArrayImgs; import net.imglib2.loops.ClassCopyProvider; import net.imglib2.type.numeric.RealType; @@ -39,15 +42,23 @@ public interface DownsampleBlock< T extends RealType< T > > { + enum DownsamplingMethod + { + Average, + Centre, + Mode + } + void downsampleBlock( final RandomAccess< T > in, final Cursor< T > out, final int[] dimensions ); static < T extends RealType< T > > DownsampleBlock< T > create( final int[] blockDimensions, final int[] downsamplingFactors, - final Class< ? > pixelTypeClass, + final DownsamplingMethod downsamplingMethod, + final Class< ? > pixelTypeClass, final Class< ? > inAccessClass ) { - return DownsampleBlockInstances.create( blockDimensions, downsamplingFactors, pixelTypeClass, inAccessClass ); + return DownsampleBlockInstances.create( blockDimensions, downsamplingFactors, downsamplingMethod, pixelTypeClass, inAccessClass ); } } @@ -60,7 +71,8 @@ class DownsampleBlockInstances public static < T extends RealType< T > > DownsampleBlock< T > create( final int[] blockDimensions, final int[] downsamplingFactors, - final Class< ? > pixelTypeClass, + DownsampleBlock.DownsamplingMethod downsamplingMethod, + final Class< ? > pixelTypeClass, final Class< ? > inAccessClass ) { if ( provider == null ) @@ -68,7 +80,20 @@ public static < T extends RealType< T > > DownsampleBlock< T > create( synchronized ( DownsampleBlockInstances.class ) { if ( provider == null ) - provider = new ClassCopyProvider<>( Imp.class, DownsampleBlock.class, int[].class, int[].class ); + { + switch ( downsamplingMethod ) + { + case Average: + provider = new ClassCopyProvider<>( AverageDownsampler.class, DownsampleBlock.class, int[].class, int[].class ); + break; + case Centre: + provider = new ClassCopyProvider<>( CentreDownsampler.class, DownsampleBlock.class, int[].class, int[].class ); + break; + case Mode: + provider = new ClassCopyProvider<>( ModeDownsampler.class, DownsampleBlock.class, int[].class, int[].class ); + break; + } + } } } @@ -78,7 +103,7 @@ public static < T extends RealType< T > > DownsampleBlock< T > create( return provider.newInstanceForKey( key, blockDimensions, downsamplingFactors ); } - public static class Imp< T extends RealType< T > > implements DownsampleBlock< T > + public static class AverageDownsampler< T extends RealType< T > > implements DownsampleBlock< T > { private final int n; @@ -90,7 +115,7 @@ public static class Imp< T extends RealType< T > > implements DownsampleBlock< T private final RandomAccess< DoubleType > acc; - public Imp( + public AverageDownsampler( final int[] blockDimensions, final int[] downsamplingFactors ) { @@ -120,13 +145,11 @@ public void downsampleBlock( { downsampleBlock3D( acc, dimensions[ 0 ], dimensions[ 1 ], dimensions[ 2 ], in ); writeOutput3D( out, dimensions[ 0 ], dimensions[ 1 ], dimensions[ 2 ], acc ); - } - else if ( n == 2 ) + } else if ( n == 2 ) { downsampleBlock2D( acc, dimensions[ 0 ], dimensions[ 1 ], in ); writeOutput2D( out, dimensions[ 0 ], dimensions[ 1 ], acc ); - } - else + } else { downsampleBlock1D( acc, dimensions[ 0 ], in ); writeOutput1D( out, dimensions[ 0 ], acc ); @@ -247,4 +270,465 @@ private void writeOutput1D( acc.move( -asx, 0 ); } } + + public static class CentreDownsampler< T extends RealType< T > > implements DownsampleBlock< T > + { + private final int n; + + private final int[] downsamplingFactors; + + private final double[] accumulator; + + private final RandomAccess< DoubleType > acc; + + public CentreDownsampler( + final int[] blockDimensions, + final int[] downsamplingFactors ) + { + n = blockDimensions.length; + if ( n < 1 || n > 3 ) + throw new IllegalArgumentException(); + + this.downsamplingFactors = downsamplingFactors; + + accumulator = new double[ ( int ) Intervals.numElements( blockDimensions ) ]; + + final long[] dims = new long[ n ]; + Arrays.setAll( dims, d -> blockDimensions[ d ] ); + acc = ArrayImgs.doubles( accumulator, dims ).randomAccess(); + } + + @Override + public void downsampleBlock( + final RandomAccess< T > in, + final Cursor< T > out, // must be flat iteration order + final int[] dimensions ) + { + clearAccumulator(); + + if ( n == 3 ) + { + downsampleBlock3D( acc, dimensions[ 0 ], dimensions[ 1 ], dimensions[ 2 ], in ); + writeOutput3D( out, dimensions[ 0 ], dimensions[ 1 ], dimensions[ 2 ], acc ); + } else if ( n == 2 ) + { + downsampleBlock2D( acc, dimensions[ 0 ], dimensions[ 1 ], in ); + writeOutput2D( out, dimensions[ 0 ], dimensions[ 1 ], acc ); + } else + { + downsampleBlock1D( acc, dimensions[ 0 ], in ); + writeOutput1D( out, dimensions[ 0 ], acc ); + } + } + + private void clearAccumulator() + { + Arrays.fill( accumulator, 0, accumulator.length, 0 ); + } + + private void downsampleBlock3D( + final RandomAccess< DoubleType > acc, + final int asx, // size of accumulator image + final int asy, + final int asz, + final RandomAccess< T > in ) + { + final int d = 2; + final int bsz = downsamplingFactors[ d ]; + in.move( bsz / 2, d ); + for ( int az = 0; az < asz; ++az ) + { + downsampleBlock2D( acc, asx, asy, in ); + in.move( bsz, d ); + acc.fwd( d ); + } + in.move( -bsz * asz - bsz / 2, d ); + acc.move( -asz, d ); + } + + private void downsampleBlock2D( + final RandomAccess< DoubleType > acc, + final int asx, // size of accumulator image + final int asy, + final RandomAccess< T > in ) + { + final int d = 1; + final int bsy = downsamplingFactors[ d ]; + in.move( bsy / 2, d ); + for ( int ay = 0; ay < asy; ++ay ) + { + downsampleBlock1D( acc, asx, in ); + in.move( bsy, d ); + acc.fwd( d ); + } + in.move( -bsy * asy - bsy / 2, d ); + acc.move( -asy, d ); + } + + private void downsampleBlock1D( + final RandomAccess< DoubleType > acc, + final int asx, // size of output image + final RandomAccess< T > in ) + { + final int d = 0; + final int bsx = downsamplingFactors[ d ]; + in.move( bsx / 2, d ); + for ( int ax = 0; ax < asx; ++ax ) + { + acc.get().set( in.get().getRealDouble() ); + in.move( bsx, d ); + acc.fwd( d ); + } + in.move( -bsx * asx - bsx / 2, d ); + acc.move( -asx, d ); + } + + private void writeOutput3D( + final Cursor< T > out, // must be flat iteration order + final int asx, // size of accumulator image + final int asy, + final int asz, + final RandomAccess< DoubleType > acc ) + { + for ( int z = 0; z < asz; ++z ) + { + writeOutput2D( out, asx, asy, acc ); + acc.fwd( 2 ); + } + acc.move( -asz, 2 ); + } + + private void writeOutput2D( + final Cursor< T > out, // must be flat iteration order + final int asx, // size of output image + final int asy, + final RandomAccess< DoubleType > acc ) + { + for ( int y = 0; y < asy; ++y ) + { + writeOutput1D( out, asx, acc ); + acc.fwd( 1 ); + } + acc.move( -asy, 1 ); + } + + private void writeOutput1D( + final Cursor< T > out, // must be flat iteration order + final int asx, // size of output (resp accumulator) image + final RandomAccess< DoubleType > acc ) + { + for ( int x = 0; x < asx; ++x ) + { + out.next().setReal( acc.get().get() ); + acc.fwd( 0 ); + } + acc.move( -asx, 0 ); + } + } + + public static class ModeDownsampler< T extends RealType< T > > implements DownsampleBlock< T > + { + private final int n; + + private final int[] downsamplingFactors; + + private final TLongLongHashMapRandomAccess acc; + + public ModeDownsampler( + final int[] blockDimensions, + final int[] downsamplingFactors ) + { + n = blockDimensions.length; + if ( n < 1 || n > 3 ) + throw new IllegalArgumentException(); + + this.downsamplingFactors = downsamplingFactors; + + final int[] dims = new int[ n ]; + Arrays.setAll( dims, d -> blockDimensions[ d ] ); + + acc = new TLongLongHashMapRandomAccess( dims ); + } + + @Override + public void downsampleBlock( + final RandomAccess< T > in, + final Cursor< T > out, // must be flat iteration order + final int[] dimensions ) + { + clearAccumulator(); + + if ( n == 3 ) + { + downsampleBlock3D( acc, dimensions[ 0 ], dimensions[ 1 ], dimensions[ 2 ], in ); + writeOutput3D( out, dimensions[ 0 ], dimensions[ 1 ], dimensions[ 2 ], acc ); + } else if ( n == 2 ) + { + downsampleBlock2D( acc, dimensions[ 0 ], dimensions[ 1 ], in ); + writeOutput2D( out, dimensions[ 0 ], dimensions[ 1 ], acc ); + } else + { + downsampleBlock1D( acc, dimensions[ 0 ], in ); + writeOutput1D( out, dimensions[ 0 ], acc ); + } + } + + private void clearAccumulator() + { + acc.init(); + } + + private void downsampleBlock3D( + final TLongLongHashMapRandomAccess acc, + final int asx, // size of output (resp accumulator) image + final int asy, + final int asz, + final RandomAccess< T > in ) + { + final int bsz = downsamplingFactors[ 2 ]; + final int sz = asz * bsz; + for ( int z = 0, bz = 0; z < sz; ++z ) + { + downsampleBlock2D( acc, asx, asy, in ); + in.fwd( 2 ); + if ( ++bz == bsz ) + { + bz = 0; + acc.fwd( 2 ); + } + } + in.move( -sz, 2 ); + acc.move( -asz, 2 ); + } + + private void downsampleBlock2D( + final TLongLongHashMapRandomAccess acc, + final int asx, // size of output (resp accumulator) image + final int asy, + final RandomAccess< T > in ) + { + final int bsy = downsamplingFactors[ 1 ]; + final int sy = asy * bsy; + for ( int y = 0, by = 0; y < sy; ++y ) + { + downsampleBlock1D( acc, asx, in ); + in.fwd( 1 ); + if ( ++by == bsy ) + { + by = 0; + acc.fwd( 1 ); + } + } + in.move( -sy, 1 ); + acc.move( -asy, 1 ); + } + + private void downsampleBlock1D( + final TLongLongHashMapRandomAccess acc, + final int asx, // size of output (resp accumulator) image + final RandomAccess< T > in ) + { + final int bsx = downsamplingFactors[ 0 ]; + final int sx = asx * bsx; + for ( int x = 0, bx = 0; x < sx; ++x ) + { + final long value = (long) in.get().getRealDouble(); + final TLongLongHashMap map = acc.get(); + final long newCount = map.get( value ) + 1; + map.put( value, newCount ); + + in.fwd( 0 ); + if ( ++bx == bsx ) + { + bx = 0; + acc.fwd( 0 ); + } + } + in.move( -sx, 0 ); + acc.move( -asx, 0 ); + } + + private void writeOutput3D( + final Cursor< T > out, // must be flat iteration order + final int asx, // size of output (resp accumulator) image + final int asy, + final int asz, + final TLongLongHashMapRandomAccess acc ) + { + for ( int z = 0; z < asz; ++z ) + { + writeOutput2D( out, asx, asy, acc ); + acc.fwd( 2 ); + } + acc.move( -asz, 2 ); + } + + private void writeOutput2D( + final Cursor< T > out, // must be flat iteration order + final int asx, // size of output (resp accumulator) image + final int asy, + final TLongLongHashMapRandomAccess acc ) + { + for ( int y = 0; y < asy; ++y ) + { + writeOutput1D( out, asx, acc ); + acc.fwd( 1 ); + } + acc.move( -asy, 1 ); + } + + private void writeOutput1D( + final Cursor< T > out, // must be flat iteration order + final int asx, // size of output (resp accumulator) image + final TLongLongHashMapRandomAccess acc ) + { + for ( int x = 0; x < asx; ++x ) + { + long label = getLabel( acc ); + out.next().setReal( label ); + acc.fwd( 0 ); + } + acc.move( -asx, 0 ); + } + + private long getLabel( TLongLongHashMapRandomAccess acc ) + { + final TLongLongIterator iterator = acc.get().iterator(); + long maxCount = 0; + long label = 0; + while ( iterator.hasNext() ) + { + iterator.advance(); + if ( iterator.value() > maxCount ) + { + maxCount = iterator.value(); + label = iterator.key(); + } + } + return label; + } + } + + public static class TLongLongHashMapRandomAccess extends AbstractLocalizableInt implements RandomAccess< TLongLongHashMap > + { + private TLongLongHashMap[][][] maps; + private final int[] dims; + + public TLongLongHashMapRandomAccess( int[] dims ) + { + super( dims.length ); + + this.dims = dims; + init(); + } + + public void init() + { + if( dims.length == 1 ) + maps = new TLongLongHashMap[ dims[ 0 ] ][ 1 ][ 1 ]; + else if ( dims.length == 2 ) + maps = new TLongLongHashMap[ dims[ 0 ] ][ dims[ 1 ] ][ 1 ]; + else if ( dims.length == 3 ) + maps = new TLongLongHashMap[ dims[ 0 ] ][ dims[ 1 ] ][ dims[ 2 ] ]; + else + throw new UnsupportedOperationException( "The number of dimensions must be <= 3" ); + + for ( int x = 0; x < dims[ 0 ]; x++ ) + for ( int y = 0; y < dims[ 1 ]; y++ ) + for ( int z = 0; z < dims[ 2 ]; z++ ) + maps[ x ][ y ][ z ] = new TLongLongHashMap(); + } + + @Override + public RandomAccess< TLongLongHashMap > copyRandomAccess() + { + throw new UnsupportedOperationException( ); + } + + @Override + public void fwd( int d ) + { + position[ d ]++; + } + + @Override + public void bck( int d ) + { + position[ d ]--; + } + + @Override + public void move( int distance, int d ) + { + position[ d ] += distance; + } + + @Override + public void move( long distance, int d ) + { + position[ d ] += distance; + } + + @Override + public void move( Localizable distance ) + { + throw new UnsupportedOperationException( ); + } + + @Override + public void move( int[] distance ) + { + throw new UnsupportedOperationException( ); + } + + @Override + public void move( long[] distance ) + { + throw new UnsupportedOperationException( ); + } + + @Override + public void setPosition( Localizable position ) + { + throw new UnsupportedOperationException( ); + } + + @Override + public void setPosition( int[] position ) + { + throw new UnsupportedOperationException( ); + } + + @Override + public void setPosition( long[] position ) + { + throw new UnsupportedOperationException( ); + } + + @Override + public void setPosition( int position, int d ) + { + throw new UnsupportedOperationException( ); + } + + @Override + public void setPosition( long position, int d ) + { + throw new UnsupportedOperationException( ); + } + + @Override + public TLongLongHashMap get() + { + return maps[ position[ 0 ] ][ position[ 1 ] ][ position[ 2 ] ]; + } + + @Override + public Sampler< TLongLongHashMap > copy() + { + throw new UnsupportedOperationException( ); + } + } } + + diff --git a/src/main/java/bdv/export/ExportScalePyramid.java b/src/main/java/bdv/export/ExportScalePyramid.java index 7e3a601b..a7da2b97 100644 --- a/src/main/java/bdv/export/ExportScalePyramid.java +++ b/src/main/java/bdv/export/ExportScalePyramid.java @@ -227,6 +227,7 @@ public static < T extends RealType< T > & NativeType< T >, D > void writeScalePy final RandomAccessibleInterval< T > img, final T type, final ExportMipmapInfo mipmapInfo, + final DownsampleBlock.DownsamplingMethod downsamplingMethod, final DatasetIO< D, T > io, final ExecutorService executorService, final int numThreads, @@ -362,7 +363,7 @@ public static < T extends RealType< T > & NativeType< T >, D > void writeScalePy final Class< ? extends RealType > kl1 = type.getClass(); final Class< ? extends RandomAccess > kl2 = in.getClass(); final CopyBlock< T > copyBlock = fullResolution ? CopyBlock.create( n, kl1, kl2 ) : null; - final DownsampleBlock< T > downsampleBlock = fullResolution ? null : DownsampleBlock.create( cellDimensions, factor, kl1, kl2 ); + final DownsampleBlock< T > downsampleBlock = fullResolution ? null : DownsampleBlock.create( cellDimensions, factor, downsamplingMethod, kl1, kl2 ); for ( int i = nextCellInPlane.getAndIncrement(); i < numBlocksPerPlane; i = nextCellInPlane.getAndIncrement() ) { diff --git a/src/main/java/bdv/export/WriteSequenceToHdf5.java b/src/main/java/bdv/export/WriteSequenceToHdf5.java index 591f8a4c..bd350872 100644 --- a/src/main/java/bdv/export/WriteSequenceToHdf5.java +++ b/src/main/java/bdv/export/WriteSequenceToHdf5.java @@ -133,6 +133,7 @@ public class WriteSequenceToHdf5 public static void writeHdf5File( final AbstractSequenceDescription< ?, ?, ? > seq, final Map< Integer, ExportMipmapInfo > perSetupMipmapInfo, + final DownsampleBlock.DownsamplingMethod downsamplingMethod, final boolean deflate, final File hdf5File, final LoopbackHeuristic loopbackHeuristic, @@ -149,13 +150,13 @@ public static void writeHdf5File( setupIdSequenceToPartition.put( setup.getId(), setup.getId() ); final Partition partition = new Partition( hdf5File.getPath(), timepointIdSequenceToPartition, setupIdSequenceToPartition ); - writeHdf5PartitionFile( seq, perSetupMipmapInfo, deflate, partition, loopbackHeuristic, afterEachPlane, numCellCreatorThreads, progressWriter ); + writeHdf5PartitionFile( seq, perSetupMipmapInfo, downsamplingMethod, deflate, partition, loopbackHeuristic, afterEachPlane, numCellCreatorThreads, progressWriter ); } /** * Create a hdf5 file containing image data from all views and all * timepoints in a chunked, mipmaped representation. This is the same as - * {@link WriteSequenceToHdf5#writeHdf5File(AbstractSequenceDescription, Map, boolean, File, LoopbackHeuristic, AfterEachPlane, int, ProgressWriter)} + * {@link WriteSequenceToHdf5#writeHdf5File(AbstractSequenceDescription, Map, DownsampleBlock.DownsamplingMethod, boolean, File, LoopbackHeuristic, AfterEachPlane, int, ProgressWriter)} * except that only one set of supsampling factors and and subdivision * blocksizes is given, which is used for all {@link BasicViewSetup views}. * @@ -195,6 +196,7 @@ public static void writeHdf5File( final AbstractSequenceDescription< ?, ?, ? > seq, final int[][] resolutions, final int[][] subdivisions, + final DownsampleBlock.DownsamplingMethod downsamplingMethod, final boolean deflate, final File hdf5File, final LoopbackHeuristic loopbackHeuristic, @@ -206,7 +208,7 @@ public static void writeHdf5File( final ExportMipmapInfo mipmapInfo = new ExportMipmapInfo( resolutions, subdivisions ); for ( final BasicViewSetup setup : seq.getViewSetupsOrdered() ) perSetupMipmapInfo.put( setup.getId(), mipmapInfo ); - writeHdf5File( seq, perSetupMipmapInfo, deflate, hdf5File, loopbackHeuristic, afterEachPlane, numCellCreatorThreads, progressWriter ); + writeHdf5File( seq, perSetupMipmapInfo, downsamplingMethod, deflate, hdf5File, loopbackHeuristic, afterEachPlane, numCellCreatorThreads, progressWriter ); } /** @@ -245,7 +247,7 @@ public static void writeHdf5PartitionLinkFile( final AbstractSequenceDescription * * Note that this method only writes the master file containing links. The * individual partitions need to be written with - * {@link #writeHdf5PartitionFile(AbstractSequenceDescription, Map, boolean, Partition, LoopbackHeuristic, AfterEachPlane, int, ProgressWriter)}. + * {@link #writeHdf5PartitionFile(AbstractSequenceDescription, Map, bdv.export.DownsampleBlock.DownsamplingMethod, boolean, Partition, LoopbackHeuristic, AfterEachPlane, int, ProgressWriter)}. * * @param seq * description of the sequence to be stored as hdf5. (The @@ -354,6 +356,7 @@ public static void writeHdf5PartitionLinkFile( final AbstractSequenceDescription public static void writeHdf5PartitionFile( final AbstractSequenceDescription< ?, ?, ? > seq, final Map< Integer, ExportMipmapInfo > perSetupMipmapInfo, + final DownsampleBlock.DownsamplingMethod downsamplingMethod, final boolean deflate, final Partition partition, final LoopbackHeuristic loopbackHeuristic, @@ -449,7 +452,7 @@ public static void writeHdf5PartitionFile( final ProgressWriter subProgressWriter = new SubTaskProgressWriter( progressWriter, startCompletionRatio, endCompletionRatio ); writeViewToHdf5PartitionFile( - img, timepointIdPartition, setupIdPartition, mipmapInfo, false, + img, timepointIdPartition, setupIdPartition, mipmapInfo, false, downsamplingMethod, deflate, writerQueue, executorService, numCellCreatorThreads, loopbackHeuristic, afterEachPlane, subProgressWriter ); } } @@ -515,6 +518,7 @@ public static void writeViewToHdf5PartitionFile( final int setupIdPartition, final ExportMipmapInfo mipmapInfo, final boolean writeMipmapInfo, + final DownsampleBlock.DownsamplingMethod downsamplingMethod, final boolean deflate, final LoopbackHeuristic loopbackHeuristic, final AfterEachPlane afterEachPlane, @@ -532,7 +536,7 @@ public static void writeViewToHdf5PartitionFile( try { // write the image - writeViewToHdf5PartitionFile( img, timepointIdPartition, setupIdPartition, mipmapInfo, writeMipmapInfo, deflate, writerQueue, executorService, numCellCreatorThreads, loopbackHeuristic, afterEachPlane, progressWriter ); + writeViewToHdf5PartitionFile( img, timepointIdPartition, setupIdPartition, mipmapInfo, writeMipmapInfo, downsamplingMethod, deflate, writerQueue, executorService, numCellCreatorThreads, loopbackHeuristic, afterEachPlane, progressWriter ); } finally { @@ -661,6 +665,7 @@ public static void writeViewToHdf5PartitionFile( final int setupIdPartition, final ExportMipmapInfo mipmapInfo, final boolean writeMipmapInfo, + final DownsampleBlock.DownsamplingMethod downsamplingMethod, final boolean deflate, final IHDF5Access writerQueue, final ExecutorService executorService, // TODO @@ -689,6 +694,7 @@ public static void writeViewToHdf5PartitionFile( img, new UnsignedShortType(), mipmapInfo, + downsamplingMethod, io, executorService, numThreads, diff --git a/src/main/java/bdv/export/n5/WriteSequenceToN5.java b/src/main/java/bdv/export/n5/WriteSequenceToN5.java index d5cd0dfc..4c5a8dc0 100644 --- a/src/main/java/bdv/export/n5/WriteSequenceToN5.java +++ b/src/main/java/bdv/export/n5/WriteSequenceToN5.java @@ -28,11 +28,7 @@ */ package bdv.export.n5; -import bdv.export.ExportMipmapInfo; -import bdv.export.ExportScalePyramid; -import bdv.export.ProgressWriter; -import bdv.export.ProgressWriterNull; -import bdv.export.SubTaskProgressWriter; +import bdv.export.*; import bdv.export.ExportScalePyramid.AfterEachPlane; import bdv.export.ExportScalePyramid.LoopbackHeuristic; import bdv.img.cache.SimpleCacheArrayLoader; @@ -253,7 +249,7 @@ static < T extends RealType< T > & NativeType< T > > void writeScalePyramid( final T type = setupImgLoader.getImageType(); final N5DatasetIO< T > io = new N5DatasetIO<>( n5, compression, setupId, timepointId, type ); ExportScalePyramid.writeScalePyramid( - img, type, mipmapInfo, io, + img, type, mipmapInfo, DownsampleBlock.DownsamplingMethod.Average, io, executorService, numThreads, loopbackHeuristic, afterEachPlane, progressWriter ); } diff --git a/src/main/java/bdv/tools/crop/CropDialog.java b/src/main/java/bdv/tools/crop/CropDialog.java index cce6641e..b764f86b 100644 --- a/src/main/java/bdv/tools/crop/CropDialog.java +++ b/src/main/java/bdv/tools/crop/CropDialog.java @@ -28,6 +28,7 @@ */ package bdv.tools.crop; +import bdv.export.DownsampleBlock; import bdv.viewer.SourceAndConverter; import bdv.viewer.ViewerState; import java.awt.BorderLayout; @@ -389,7 +390,7 @@ public void cropGlobal( final int minTimepointIndex, final int maxTimepointIndex } final int numThreads = Math.max( 1, Runtime.getRuntime().availableProcessors() - 2 ); - WriteSequenceToHdf5.writeHdf5File( seq, perSetupMipmapInfo, true, hdf5File, null, null, numThreads, null ); + WriteSequenceToHdf5.writeHdf5File( seq, perSetupMipmapInfo, DownsampleBlock.DownsamplingMethod.Average, true, hdf5File, null, null, numThreads, null ); // Build ViewRegistrations with adjusted transforms. final ArrayList< ViewRegistration > registrations = new ArrayList<>();