/* * @(#)/Volume.java 1.7 96/03/31 by Andrew Barclay abb@nuccard.eushc.org * * Copyright (c) 1995 Andrew B. Barclay All Rights Reserved. */ import java.applet.Applet ; import java.awt.Dimension ; import java.awt.Image ; import java.awt.Point ; import java.awt.image.FilteredImageSource ; import java.awt.image.ImageConsumer ; import java.awt.image.ImageObserver ; import java.awt.image.ImageProducer ; import java.util.Enumeration ; import java.util.Vector ; import XSliceVolumeFilter ; import YSliceVolumeFilter ; import ZSliceVolumeFilter ; /** * A volume composed of 2D slices across the z-axis. * * @see SliceVolumeFilter * * @version 1.7 96/03/31 * @author Andrew Barclay */ public class Volume extends Object implements ImageObserver { Image src ; int srcwidth ; int srcheight ; int dimensions[] ; double voxelsize[] ; Point srcSlices[] ; static char axissym[] = { 'x', 'y', 'z' } ; Vector slicefilters = new Vector() ; boolean loaderror = false ; boolean debug = false ; /** * Construct a Volume * @param src source image slices arranged in a 2D grid * @param dimensions[] the dimensions of the volume * @param voxelsize[] the voxel size (arbitrary units) */ public Volume( Image src, int dimensions[], double voxelsize[] ) { this.src = src ; this.dimensions = dimensions ; if( voxelsize == null ) { this.voxelsize = new double[3] ; this.voxelsize[0] = this.voxelsize[1] = this.voxelsize[2] = 1.0 ; } else { this.voxelsize = voxelsize ; } initialize() ; } public Volume( Image src, int dimensions[] ) { this( src, dimensions, null ) ; } void initialize() { dbg( "Volume: getting src width and height" ) ; try { Dimension dim = getImageDimensions( src ) ; srcwidth = dim.width ; srcheight = dim.height ; } catch (Exception e) { perror( "Volume.initialize: Image load error." ) ; } dbg( "width="+srcwidth+" height="+srcheight ) ; // Now we've got the info we need to make up the srcSlices[]. srcSlices = new Point[dimensions[2]] ; int xstart = 0 ; int rowstride = dimensions[1] ; int colstride = dimensions[0] ; int x = xstart ; int y = 0 ; for( int z = 0 ; z < dimensions[2] ; z++ ) { srcSlices[z] = new Point( x, y ) ; x += colstride ; if( x >= srcwidth ) { x = xstart ; y += rowstride ; } } dbg( "finished with Volume.initialize()" ) ; } Image Slice( Applet comp, double pos, int axis ) { switch( axis ) { case 0: return XSlice( comp, pos ) ; case 1: return YSlice( comp, pos ) ; case 2: return ZSlice( comp, pos ) ; } return null ; } Image XSlice( Applet comp, double pos ) { dbg( "Volume.XSlice( comp, double )" ) ; XSliceVolumeFilter svf = new XSliceVolumeFilter( srcSlices, dimensions[0], dimensions[1], pos/voxelsize[0], dimensions[2], dimensions[1] ) ; slicefilters.addElement( svf ) ; return comp.createImage( new FilteredImageSource( src.getSource(), svf ) ) ; } Image YSlice( Applet comp, double pos ) { dbg( "Volume.YSlice( comp, double )" ) ; YSliceVolumeFilter svf = new YSliceVolumeFilter( srcSlices, dimensions[0], dimensions[1], pos/voxelsize[1], dimensions[0], dimensions[2] ) ; slicefilters.addElement( svf ) ; return comp.createImage( new FilteredImageSource( src.getSource(), svf ) ) ; } Image ZSlice( Applet comp, double pos ) { dbg( "Volume.ZSlice( comp, double )" ) ; ZSliceVolumeFilter svf = new ZSliceVolumeFilter( srcSlices, dimensions[0], dimensions[1], pos/voxelsize[2], dimensions[0], dimensions[1] ) ; slicefilters.addElement( svf ) ; return comp.createImage( new FilteredImageSource( src.getSource(), svf ) ) ; } /* * The lengths I go to in order to stop an image load... * and it still doesn't work -- how do you find all the * consumers and stop the download? */ public void StopConsuming() { ImageProducer ip = src.getSource() ; Enumeration en = slicefilters.elements() ; for( ; en.hasMoreElements() ; ) { SliceVolumeFilter svf = (SliceVolumeFilter)en.nextElement() ; if( ip.isConsumer( svf ) ) { dbg( "Volume.StopConsuming(): removing consumer" ) ; ip.removeConsumer( svf ) ; } } } /** * Lifted from Animator.java: * Get the dimensions of an image. * @return the image's dimensions. */ synchronized Dimension getImageDimensions( Image img ) { int width ; int height ; dbg( "Volume.getImageDimensions() img="+img ) ; // Get the width of the image. while ((width = img.getWidth(this)) < 0) { try { dbg( "waiting on width..." ) ; wait(100); } catch (InterruptedException e) { } if (loaderror) { perror( "Volume.getImageDimensions: got a load error 1" ) ; } } // Get the height of the image. while ((height = img.getHeight(this)) < 0) { try { dbg( "waiting on height..." ) ; wait(100); } catch (InterruptedException e) { } if (loaderror) { perror( "Volume.getImageDimensions: got a load error 2" ) ; } } return new Dimension( width, height ) ; } public synchronized boolean imageUpdate( Image img, int infoflags, int x, int y, int w, int h ) { //dbg( "Volume.imageUpdate() infoflags="+infoflags ) ; if( img != src ) { return false ; } if ((infoflags & WIDTH) != 0) { dbg( "Volume: Got src width = " + w ) ; } if ((infoflags & HEIGHT) != 0) { dbg( "Volume: Got src height = " + h ) ; } if ((infoflags & (FRAMEBITS | ALLBITS)) != 0) { dbg( "Volume: Finished loading volume." ) ; } else if ((infoflags & SOMEBITS) != 0) { dbg( "Volume: Got some bits, x=" + x + " y=" + y ) ; } if( (infoflags & ERROR) != 0 ) { dbg( "Volume: Load error" ) ; loaderror = true ; } return true ; } void perror( String s ) { System.err.println( s ) ; } void dbg( String s ) { if( debug ) { System.out.println( s ) ; } } }