diff --git a/src/main/java/bdv/BigDataViewer.java b/src/main/java/bdv/BigDataViewer.java index efa9b082bb4f8ff53c6fc5ce4a13c38593406415..f047881d75f5f2ff6dbf476c805f83c01aa31cc0 100644 --- a/src/main/java/bdv/BigDataViewer.java +++ b/src/main/java/bdv/BigDataViewer.java @@ -382,8 +382,10 @@ public class BigDataViewer // final String fn = "/Users/pietzsch/desktop/data/catmaid-confocal.xml"; // final String fn = "/home/saalfeld/openconnectome-bock11-neariso.xml"; // final String fn = "/home/saalfeld/catmaid-confocal.xml"; +// final String fn = "/home/saalfeld/catmaid-second-set-tem.xml"; + final String fn = "/home/saalfeld/catmaid-l1.xml"; // final String fn = "/home/saalfeld/trakem2-test.xml"; - final String fn = "/home/saalfeld/trakem2-fly-test.xml"; +// final String fn = "/home/saalfeld/trakem2-fly-test.xml"; // final String fn = "/Users/pietzsch/desktop/data/BDV130418A325/BDV130418A325_NoTempReg.xml"; // final String fn = "/Users/pietzsch/Desktop/data/valia2/valia.xml"; // final String fn = "/Users/pietzsch/workspace/data/fast fly/111010_weber/combined.xml"; diff --git a/src/main/java/bdv/img/catmaid/CatmaidImageLoader.java b/src/main/java/bdv/img/catmaid/CatmaidImageLoader.java index eeaac44bb89c5264198fde11c421199fb6333f46..3fd3ccad0310c5882e9d76ae7dbc613f7630c813 100644 --- a/src/main/java/bdv/img/catmaid/CatmaidImageLoader.java +++ b/src/main/java/bdv/img/catmaid/CatmaidImageLoader.java @@ -23,31 +23,23 @@ import bdv.img.cache.VolatileImgCells.CellCache; public class CatmaidImageLoader extends AbstractViewerImgLoader< ARGBType, VolatileARGBType > { - private long width; + private String urlFormat; + private long width; private long height; - private long depth; - private double resXY; - - private double resZ; - - private String urlFormat; - private int tileWidth; - private int tileHeight; private int numScales; private double[][] mipmapResolutions; - private AffineTransform3D[] mipmapTransforms; - private long[][] imageDimensions; - - private int[][] blockDimensions; + + private double zScale; + private int[] zScales; private VolatileGlobalCellCache< VolatileIntArray > cache; @@ -63,8 +55,10 @@ public class CatmaidImageLoader extends AbstractViewerImgLoader< ARGBType, Volat height = Long.parseLong( elem.getChildText( "height" ) ); depth = Long.parseLong( elem.getChildText( "depth" ) ); - resXY = Double.parseDouble( elem.getChildText( "resXY" ) ); - resZ = Double.parseDouble( elem.getChildText( "resZ" ) ); + final double resXY = Double.parseDouble( elem.getChildText( "resXY" ) ); + final double resZ = Double.parseDouble( elem.getChildText( "resZ" ) ); + + zScale = resZ / resXY; urlFormat = elem.getChildText( "urlFormat" ); @@ -79,25 +73,34 @@ public class CatmaidImageLoader extends AbstractViewerImgLoader< ARGBType, Volat mipmapResolutions = new double[ numScales ][]; imageDimensions = new long[ numScales ][]; - blockDimensions = new int[ numScales ][]; mipmapTransforms = new AffineTransform3D[ numScales ]; + zScales = new int[ numScales ]; for ( int l = 0; l < numScales; ++l ) { - mipmapResolutions[ l ] = new double[] { 1 << l, 1 << l, 1 }; - imageDimensions[ l ] = new long[] { width >> l, height >> l, depth }; - blockDimensions[ l ] = new int[] { tileWidth, tileHeight, 1 }; + final int sixy = 1 << l; + int siz = Math.max( 1, ( int )Math.round( sixy / zScale ) ); + + mipmapResolutions[ l ] = new double[] { sixy, sixy, siz }; + imageDimensions[ l ] = new long[] { width >> l, height >> l, depth / siz }; + zScales[ l ] = siz; final AffineTransform3D mipmapTransform = new AffineTransform3D(); - mipmapTransform.set( mipmapResolutions[ l ][ 0 ], 0, 0 ); - mipmapTransform.set( mipmapResolutions[ l ][ 1 ], 1, 1 ); - mipmapTransform.set( 0.5 * ( mipmapResolutions[ l ][ 0 ] - 1 ), 0, 3 ); - mipmapTransform.set( 0.5 * ( mipmapResolutions[ l ][ 0 ] - 1 ), 1, 3 ); + + mipmapTransform.set( sixy, 0, 0 ); + mipmapTransform.set( sixy, 1, 1 ); + mipmapTransform.set( zScale * siz, 2, 2 ); + + mipmapTransform.set( 0.5 * ( sixy - 1 ), 0, 3 ); + mipmapTransform.set( 0.5 * ( sixy - 1 ), 1, 3 ); + mipmapTransform.set( 0.5 * ( zScale * siz - 1 ), 2, 3 ); + mipmapTransforms[ l ] = mipmapTransform; } final int[] maxLevels = new int[] { numScales - 1 }; + cache = new VolatileGlobalCellCache< VolatileIntArray >( - new CatmaidVolatileIntArrayLoader( urlFormat, tileWidth, tileHeight ), 1, 1, numScales, maxLevels, 10 ); + new CatmaidVolatileIntArrayLoader( urlFormat, tileWidth, tileHeight, zScales ), 1, 1, numScales, maxLevels, 10 ); } final static public int getNumScales( long width, long height, final long tileWidth, final long tileHeight ) @@ -148,7 +151,7 @@ public class CatmaidImageLoader extends AbstractViewerImgLoader< ARGBType, Volat protected < T extends NativeType< T > > CellImg< T, VolatileIntArray, VolatileCell< VolatileIntArray > > prepareCachedImage( final View view, final int level, final LoadingStrategy loadingStrategy ) { final long[] dimensions = imageDimensions[ level ]; - final int[] cellDimensions = blockDimensions[ level ]; + final int[] cellDimensions = new int[]{ tileWidth, tileHeight, 1 }; final CellCache< VolatileIntArray > c = cache.new VolatileCellCache( view.getTimepointIndex(), view.getSetupIndex(), level, loadingStrategy ); final VolatileImgCells< VolatileIntArray > cells = new VolatileImgCells< VolatileIntArray >( c, 1, dimensions, cellDimensions ); diff --git a/src/main/java/bdv/img/catmaid/CatmaidVolatileIntArrayLoader.java b/src/main/java/bdv/img/catmaid/CatmaidVolatileIntArrayLoader.java index 762693a9db71ccad96e39508fdb3d3c29ac4608d..797570d70708a1ffa11a7d54e2ad229fa3780076 100644 --- a/src/main/java/bdv/img/catmaid/CatmaidVolatileIntArrayLoader.java +++ b/src/main/java/bdv/img/catmaid/CatmaidVolatileIntArrayLoader.java @@ -14,11 +14,12 @@ public class CatmaidVolatileIntArrayLoader implements CacheArrayLoader< Volatile { private VolatileIntArray theEmptyArray; - private final String urlFormat; + final private String urlFormat; - private final int tileWidth; - - private final int tileHeight; + final private int tileWidth; + final private int tileHeight; + + final private int[] zScales; /** * <p>Create a {@link CacheArrayLoader} for a CATMAID source. Tiles are @@ -50,12 +51,13 @@ public class CatmaidVolatileIntArrayLoader implements CacheArrayLoader< Volatile * @param tileWidth * @param tileHeight */ - public CatmaidVolatileIntArrayLoader( final String urlFormat, final int tileWidth, final int tileHeight ) + public CatmaidVolatileIntArrayLoader( final String urlFormat, final int tileWidth, final int tileHeight, final int[] zScales ) { theEmptyArray = new VolatileIntArray( tileWidth * tileHeight, false ); this.urlFormat = urlFormat; this.tileWidth = tileWidth; this.tileHeight = tileHeight; + this.zScales = zScales; } @Override @@ -72,37 +74,76 @@ public class CatmaidVolatileIntArrayLoader implements CacheArrayLoader< Volatile final int[] dimensions, final long[] min ) throws InterruptedException { - final int c = ( int ) min[ 0 ] / tileWidth; - final int r = ( int ) min[ 1 ] / tileHeight; + final int col = ( int ) min[ 0 ] / tileWidth; + final int row = ( int ) min[ 1 ] / tileHeight; final double scale = 1.0 / Math.pow(2.0, level); - final String urlString = String.format( urlFormat, level, scale, min[ 0 ], min[ 1 ], min[ 2 ], tileWidth, tileHeight, r, c ); - final int w = dimensions[ 0 ]; final int h = dimensions[ 1 ]; final int[] data = new int[ w * h ]; try { - final URL url = new URL( urlString ); -// final Image image = toolkit.createImage( url ); - final BufferedImage jpg = ImageIO.read( url ); - - /* This gymnastic is necessary to get reproducible gray - * values, just opening a JPG or PNG, even when saved by - * ImageIO, and grabbing its pixels results in gray values - * with a non-matching gamma transfer function, I cannot tell - * why... */ - final BufferedImage image = new BufferedImage( w, h, BufferedImage.TYPE_INT_RGB ); - image.createGraphics().drawImage( jpg, 0, 0, null ); - final PixelGrabber pg = new PixelGrabber( image, 0, 0, w, h, data, 0, w ); - pg.grabPixels(); + if ( zScales[ level ] > 1 ) + { + final long[] rs = new long[ data.length ], gs = new long[ data.length ], bs = new long[ data.length ]; + + for ( int z = ( int )min[ 2 ] * zScales[ level ], dz = 0; dz < zScales[ level ]; ++dz ) + { + final String urlString = String.format( urlFormat, level, scale, min[ 0 ], min[ 1 ], z + dz, tileWidth, tileHeight, row, col ); + + final URL url = new URL( urlString ); + final BufferedImage jpg = ImageIO.read( url ); + + /* This gymnastic is necessary to get reproducible gray + * values, just opening a JPG or PNG, even when saved by + * ImageIO, and grabbing its pixels results in gray values + * with a non-matching gamma transfer function, I cannot tell + * why... */ + final BufferedImage image = new BufferedImage( w, h, BufferedImage.TYPE_INT_RGB ); + image.createGraphics().drawImage( jpg, 0, 0, null ); + final PixelGrabber pg = new PixelGrabber( image, 0, 0, w, h, data, 0, w ); + pg.grabPixels(); + for ( int i = 0; i < data.length; ++i ) + { + rs[ i ] += ( data[ i ] >> 16 ) & 0xff; + gs[ i ] += ( data[ i ] >> 8 ) & 0xff; + bs[ i ] += data[ i ] & 0xff; + } + } + for ( int i = 0; i < data.length; ++i ) + { + final int r = ( int )( rs[ i ] / zScales[ level ] ); + final int g = ( int )( gs[ i ] / zScales[ level ] ); + final int b = ( int )( bs[ i ] / zScales[ level ] ); + + data[ i ] = ( ( ( ( r << 8 ) | g ) << 8 ) | b ) | 0xff000000; + } + } + else + { + final String urlString = String.format( urlFormat, level, scale, min[ 0 ], min[ 1 ], min[ 2 ], tileWidth, tileHeight, row, col ); + + final URL url = new URL( urlString ); + // final Image image = toolkit.createImage( url ); + final BufferedImage jpg = ImageIO.read( url ); + + /* This gymnastic is necessary to get reproducible gray + * values, just opening a JPG or PNG, even when saved by + * ImageIO, and grabbing its pixels results in gray values + * with a non-matching gamma transfer function, I cannot tell + * why... */ + final BufferedImage image = new BufferedImage( w, h, BufferedImage.TYPE_INT_RGB ); + image.createGraphics().drawImage( jpg, 0, 0, null ); + final PixelGrabber pg = new PixelGrabber( image, 0, 0, w, h, data, 0, w ); + pg.grabPixels(); + } // System.out.println( "success loading r=" + entry.key.r + " c=" + entry.key.c + " url(" + urlString + ")" ); } catch (final IOException e) { - System.out.println( "failed loading r=" + r + " c=" + c + " url(" + urlString + ")" ); + System.out.println( "failed loading r=" + row + " c=" + col ); } catch (final InterruptedException e) { diff --git a/src/main/java/bdv/img/openconnectome/OpenConnectomeImageLoader.java b/src/main/java/bdv/img/openconnectome/OpenConnectomeImageLoader.java index 83f8f8b02f879f7848e68ea6c7a754ffbbf36817..67914bdda9662c368894be6737446f9591cbf32a 100644 --- a/src/main/java/bdv/img/openconnectome/OpenConnectomeImageLoader.java +++ b/src/main/java/bdv/img/openconnectome/OpenConnectomeImageLoader.java @@ -91,7 +91,9 @@ public class OpenConnectomeImageLoader implements ViewerImgLoader< UnsignedByteT throws JsonSyntaxException, JsonIOException, IOException { final Gson gson = new Gson(); - final URL url = new URL( baseUrl + "/" + token + "/info/" ); + final String urlString = baseUrl + "/" + token + "/info/"; + System.out.println( "Attempting to open " + urlString ); + final URL url = new URL( urlString ); return gson.fromJson( new InputStreamReader( url.openStream() ), OpenConnectomeTokenInfo.class ); } diff --git a/src/main/java/bdv/img/trakem2/TrakEM2ImageLoader.java b/src/main/java/bdv/img/trakem2/TrakEM2ImageLoader.java index bc3978fe1ab429659ba6ca751d1cdcfdc298c3e7..71971a932f3ad292baff4faedcdd98ae4a65575b 100644 --- a/src/main/java/bdv/img/trakem2/TrakEM2ImageLoader.java +++ b/src/main/java/bdv/img/trakem2/TrakEM2ImageLoader.java @@ -38,10 +38,10 @@ public class TrakEM2ImageLoader extends AbstractViewerImgLoader< ARGBType, Volat private int height; private int depth; - private double zScale; - private int tileWidth; private int tileHeight; + + private double zScale; private int numScales; @@ -51,7 +51,7 @@ public class TrakEM2ImageLoader extends AbstractViewerImgLoader< ARGBType, Volat private long[][] imageDimensions; - private int[][] blockDimensions; + private int[] zScales; private VolatileGlobalCellCache< VolatileIntArray > cache; @@ -59,14 +59,14 @@ public class TrakEM2ImageLoader extends AbstractViewerImgLoader< ARGBType, Volat { super( new ARGBType(), new VolatileARGBType() ); } - - @Override - public void init( final Element elem, final File basePath ) + + public void init( final Project project, final int tileWidth, final int tileHeight, final int numScales ) { - final String projectPath = elem.getChildText( "projectPath" ); + this.project = project; + this.tileWidth = tileWidth; + this.tileHeight = tileHeight; + this.numScales = numScales; - ControlWindow.setGUIEnabled( false ); - project = Project.openFSProject( projectPath, false); loader = project.getLoader(); layerset = project.getRootLayerSet(); layerset.setSnapshotsMode(1); @@ -79,37 +79,53 @@ public class TrakEM2ImageLoader extends AbstractViewerImgLoader< ARGBType, Volat final Calibration calibration = layerset.getCalibration(); zScale = calibration.pixelDepth / calibration.pixelWidth; - tileWidth = Integer.parseInt( elem.getChildText( "tileWidth" ) ); - tileHeight = Integer.parseInt( elem.getChildText( "tileHeight" ) ); - - final String numScalesString = elem.getChildText( "numScales" ); - if ( numScalesString == null ) - numScales = getNumScales( width, height, tileWidth, tileHeight ); - else - numScales = Integer.parseInt( numScalesString ); - mipmapResolutions = new double[ numScales ][]; imageDimensions = new long[ numScales ][]; - blockDimensions = new int[ numScales ][]; mipmapTransforms = new AffineTransform3D[ numScales ]; + zScales = new int[ numScales ]; for ( int l = 0; l < numScales; ++l ) { - mipmapResolutions[ l ] = new double[] { 1 << l, 1 << l, 1 }; - imageDimensions[ l ] = new long[] { width >> l, height >> l, depth }; - blockDimensions[ l ] = new int[] { tileWidth, tileHeight, 1 }; + final int sixy = 1 << l; + int siz = Math.max( 1, ( int )Math.round( sixy / zScale ) ); + + mipmapResolutions[ l ] = new double[] { sixy, sixy, siz }; + imageDimensions[ l ] = new long[] { width >> l, height >> l, depth / siz }; + zScales[ l ] = siz; final AffineTransform3D mipmapTransform = new AffineTransform3D(); - mipmapTransform.set( mipmapResolutions[ l ][ 0 ], 0, 0 ); - mipmapTransform.set( mipmapResolutions[ l ][ 1 ], 1, 1 ); - mipmapTransform.set( zScale, 2, 2 ); - mipmapTransform.set( 0.5 * ( mipmapResolutions[ l ][ 0 ] - 1 ), 0, 3 ); - mipmapTransform.set( 0.5 * ( mipmapResolutions[ l ][ 0 ] - 1 ), 1, 3 ); + + mipmapTransform.set( sixy, 0, 0 ); + mipmapTransform.set( sixy, 1, 1 ); + mipmapTransform.set( zScale * siz, 2, 2 ); + + mipmapTransform.set( 0.5 * ( sixy - 1 ), 0, 3 ); + mipmapTransform.set( 0.5 * ( sixy - 1 ), 1, 3 ); + mipmapTransform.set( 0.5 * ( zScale * siz - 1 ), 2, 3 ); + mipmapTransforms[ l ] = mipmapTransform; } final int[] maxLevels = new int[] { numScales - 1 }; cache = new VolatileGlobalCellCache< VolatileIntArray >( - new TrakEM2VolatileIntArrayLoader( loader, layerset ), 1, 1, numScales, maxLevels, 10 ); + new TrakEM2VolatileIntArrayLoader( loader, layerset, zScales ), 1, 1, numScales, maxLevels, 10 ); + } + + @Override + public void init( final Element elem, final File basePath ) + { + final String projectPath = elem.getChildText( "projectPath" ); + final int tileWidth = Integer.parseInt( elem.getChildText( "tileWidth" ) ); + final int tileHeight = Integer.parseInt( elem.getChildText( "tileHeight" ) ); + final String numScalesString = elem.getChildText( "numScales" ); + if ( numScalesString == null ) + numScales = getNumScales( width, height, tileWidth, tileHeight ); + else + numScales = Integer.parseInt( numScalesString ); + + ControlWindow.setGUIEnabled( false ); + project = Project.openFSProject( projectPath, false); + + init( project, tileWidth, tileHeight, numScales ); } final static public int getNumScales( long width, long height, final long tileWidth, final long tileHeight ) @@ -160,7 +176,7 @@ public class TrakEM2ImageLoader extends AbstractViewerImgLoader< ARGBType, Volat protected < T extends NativeType< T > > CellImg< T, VolatileIntArray, VolatileCell< VolatileIntArray > > prepareCachedImage( final View view, final int level, final LoadingStrategy loadingStrategy ) { final long[] dimensions = imageDimensions[ level ]; - final int[] cellDimensions = blockDimensions[ level ]; + final int[] cellDimensions = new int[]{ tileWidth, tileHeight, 1 }; final CellCache< VolatileIntArray > c = cache.new VolatileCellCache( view.getTimepointIndex(), view.getSetupIndex(), level, loadingStrategy ); final VolatileImgCells< VolatileIntArray > cells = new VolatileImgCells< VolatileIntArray >( c, 1, dimensions, cellDimensions ); diff --git a/src/main/java/bdv/img/trakem2/TrakEM2VolatileIntArrayLoader.java b/src/main/java/bdv/img/trakem2/TrakEM2VolatileIntArrayLoader.java index 411596aaf6f6cf74419633fa8a82850fe2ee8ac0..7bed6f3e56fa121d205b51d62f1d770a95886a5b 100644 --- a/src/main/java/bdv/img/trakem2/TrakEM2VolatileIntArrayLoader.java +++ b/src/main/java/bdv/img/trakem2/TrakEM2VolatileIntArrayLoader.java @@ -1,8 +1,8 @@ package bdv.img.trakem2; import ij.ImagePlus; +import ini.trakem2.display.Displayable; import ini.trakem2.display.LayerSet; -import ini.trakem2.display.Patch; import ini.trakem2.persistence.Loader; import java.awt.Color; @@ -17,9 +17,11 @@ public class TrakEM2VolatileIntArrayLoader implements CacheArrayLoader< Volatile { private VolatileIntArray theEmptyArray; - private final Loader loader; + final private Loader loader; - private final LayerSet layerset; + final private LayerSet layerset; + + final private int[] zScales; /** * <p>Create a {@link CacheArrayLoader} for a TrakEM2 source. Tiles are @@ -29,11 +31,12 @@ public class TrakEM2VolatileIntArrayLoader implements CacheArrayLoader< Volatile * @param tileWidth * @param tileHeight */ - public TrakEM2VolatileIntArrayLoader( final Loader loader, final LayerSet layerset ) + public TrakEM2VolatileIntArrayLoader( final Loader loader, final LayerSet layerset, final int[] zScales ) { theEmptyArray = new VolatileIntArray(1, false ); this.loader = loader; this.layerset = layerset; + this.zScales = zScales; } @Override @@ -52,23 +55,62 @@ public class TrakEM2VolatileIntArrayLoader implements CacheArrayLoader< Volatile { final int iScale = 1 << level; final double scale = 1.0 / iScale; - final Rectangle box = new Rectangle( ( int )( min[ 0 ] * iScale ), ( int )( min[ 1 ] * iScale ), dimensions[ 0 ] * iScale, dimensions[ 1 ] * iScale ); + final int w = dimensions[ 0 ] * iScale; + final int h = dimensions[ 1 ] * iScale; + final Rectangle box = new Rectangle( ( int )( min[ 0 ] * iScale ), ( int )( min[ 1 ] * iScale ), w, h ); final int[] data = new int[ dimensions[ 0 ] * dimensions[ 1 ] ]; try { - final Image image = loader.getFlatAWTImage( - layerset.getLayer( ( int )min[ 2 ] ), - box, - scale, - 0xffffffff, - ImagePlus.COLOR_RGB, - Patch.class, - null, - true, - new Color( 0x00000000, true ) ); - final PixelGrabber pg = new PixelGrabber( image, 0, 0, dimensions[ 0 ], dimensions[ 1 ], data, 0, dimensions[ 0 ] ); - pg.grabPixels(); + if ( zScales[ level ] > 1 ) + { + final long[] rs = new long[ data.length ], gs = new long[ data.length ], bs = new long[ data.length ]; + + for ( int z = ( int )min[ 2 ] * zScales[ level ], dz = 0; dz < zScales[ level ]; ++dz ) + { + final Image image = loader.getFlatAWTImage( + layerset.getLayer( z + dz ), + box, + scale, + 0xffffffff, + ImagePlus.COLOR_RGB, + Displayable.class, + null, + true, + new Color( 0x00000000, true ) ); + final PixelGrabber pg = new PixelGrabber( image, 0, 0, dimensions[ 0 ], dimensions[ 1 ], data, 0, dimensions[ 0 ] ); + pg.grabPixels(); + for ( int i = 0; i < data.length; ++i ) + { + rs[ i ] += ( data[ i ] >> 16 ) & 0xff; + gs[ i ] += ( data[ i ] >> 8 ) & 0xff; + bs[ i ] += data[ i ] & 0xff; + } + } + for ( int i = 0; i < data.length; ++i ) + { + final int r = ( int )( rs[ i ] / zScales[ level ] ); + final int g = ( int )( gs[ i ] / zScales[ level ] ); + final int b = ( int )( bs[ i ] / zScales[ level ] ); + + data[ i ] = ( ( ( ( r << 8 ) | g ) << 8 ) | b ) | 0xff000000; + } + } + else + { + final Image image = loader.getFlatAWTImage( + layerset.getLayer( ( int )min[ 2 ] ), + box, + scale, + 0xffffffff, + ImagePlus.COLOR_RGB, + Displayable.class, + null, + true, + new Color( 0x00000000, true ) ); + final PixelGrabber pg = new PixelGrabber( image, 0, 0, dimensions[ 0 ], dimensions[ 1 ], data, 0, dimensions[ 0 ] ); + pg.grabPixels(); + } // System.out.println( "success loading r=" + entry.key.r + " c=" + entry.key.c + " url(" + urlString + ")" );