|
StackWindow |
|
package ij.gui;
import ij.*;
import ij.measure.Calibration;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
/** This class is an extended ImageWindow used to display image stacks. */
public class StackWindow extends ImageWindow implements Runnable, AdjustmentListener, ActionListener, MouseWheelListener {
protected Scrollbar channelSelector, sliceSelector, frameSelector;
protected Thread thread;
protected volatile boolean done;
protected volatile int slice;
boolean hyperStack;
int nChannels=1, nSlices=1, nFrames=1;
int c=1, z=1, t=1;
public StackWindow(ImagePlus imp) {
this(imp, null);
}
public StackWindow(ImagePlus imp, ImageCanvas ic) {
super(imp, ic);
// add slice selection slider
ImageStack s = imp.getStack();
int stackSize = s.getSize();
nSlices = stackSize;
hyperStack = imp.getOpenAsHyperStack();
imp.setOpenAsHyperStack(false);
int[] dim = imp.getDimensions();
int nDimensions = 2+(dim[2]>1?1:0)+(dim[3]>1?1:0)+(dim[4]>1?1:0);
if (nDimensions<=3 && dim[2]!=nSlices) hyperStack = false;
if (hyperStack) {
nChannels = dim[2];
nSlices = dim[3];
nFrames = dim[4];
}
//IJ.log("StackWindow: "+hyperStack+" "+nChannels+" "+nSlices+" "+nFrames);
if (nSlices==stackSize) hyperStack = false;
if (nChannels*nSlices*nFrames!=stackSize) hyperStack = false;
addMouseWheelListener(this);
ImageJ ij = IJ.getInstance();
if (nChannels>1) {
channelSelector = new Scrollbar(Scrollbar.HORIZONTAL, 1, 1, 1, nChannels+1);
Panel panel = new Panel(new BorderLayout(2, 0));
//panel.add(new Label("c"), BorderLayout.WEST);
//panel.add(channelSelector, BorderLayout.CENTER);
add(channelSelector);
if (ij!=null) channelSelector.addKeyListener(ij);
channelSelector.addAdjustmentListener(this);
channelSelector.setFocusable(false); // prevents scroll bar from blinking on Windows
channelSelector.setUnitIncrement(1);
channelSelector.setBlockIncrement(1);
}
if (nSlices>1) {
sliceSelector = new Scrollbar(Scrollbar.HORIZONTAL, 1, 1, 1, nSlices+1);
add(sliceSelector);
if (ij!=null) sliceSelector.addKeyListener(ij);
sliceSelector.addAdjustmentListener(this);
sliceSelector.setFocusable(false);
int blockIncrement = nSlices/10;
if (blockIncrement<1) blockIncrement = 1;
sliceSelector.setUnitIncrement(1);
sliceSelector.setBlockIncrement(blockIncrement);
}
if (nFrames>1) {
frameSelector = new Scrollbar(Scrollbar.HORIZONTAL, 1, 1, 1, nFrames+1);
add(frameSelector);
if (ij!=null) frameSelector.addKeyListener(ij);
frameSelector.addAdjustmentListener(this);
frameSelector.setFocusable(false);
int blockIncrement = nFrames/10;
if (blockIncrement<1) blockIncrement = 1;
frameSelector.setUnitIncrement(1);
frameSelector.setBlockIncrement(blockIncrement);
}
if (sliceSelector==null && this.getClass().getName().indexOf("Image5D")!=-1)
sliceSelector = new Scrollbar(); // prevents Image5D from crashing
//IJ.log(nChannels+" "+nSlices+" "+nFrames);
pack();
ic = imp.getCanvas();
if (ic!=null) ic.setMaxBounds();
show();
int previousSlice = imp.getCurrentSlice();
if (previousSlice>1 && previousSlice<=stackSize)
imp.setSlice(previousSlice);
else
imp.setSlice(1);
thread = new Thread(this, "SliceSelector");
thread.start();
}
public synchronized void adjustmentValueChanged(AdjustmentEvent e) {
if (!running2) {
//slice = sliceSelector.getValue();
if (e.getSource()==channelSelector)
c = channelSelector.getValue();
else if (e.getSource()==sliceSelector)
z = sliceSelector.getValue();
else if (e.getSource()==frameSelector)
t = frameSelector.getValue();
updatePosition();
notify();
}
}
void updatePosition() {
slice = (t-1)*nChannels*nSlices + (z-1)*nChannels + c;
imp.updatePosition(c, z, t);
}
public void actionPerformed(ActionEvent e) {
}
public void mouseWheelMoved(MouseWheelEvent event) {
synchronized(this) {
int rotation = event.getWheelRotation();
if (hyperStack) {
if (rotation>0)
IJ.runPlugIn("ij.plugin.Animator", "next");
else if (rotation<0)
IJ.runPlugIn("ij.plugin.Animator", "previous");
} else {
int slice = imp.getCurrentSlice() + rotation;
if (slice<1)
slice = 1;
else if (slice>imp.getStack().getSize())
slice = imp.getStack().getSize();
imp.setSlice(slice);
}
}
}
public boolean close() {
if (!super.close())
return false;
synchronized(this) {
done = true;
notify();
}
return true;
}
/** Displays the specified slice and updates the stack scrollbar. */
public void showSlice(int index) {
if (index>=1 && index<=imp.getStackSize())
imp.setSlice(index);
}
/** Updates the stack scrollbar. */
public void updateSliceSelector() {
if (hyperStack) return;
int stackSize = imp.getStackSize();
int max = sliceSelector.getMaximum();
if (max!=(stackSize+1))
sliceSelector.setMaximum(stackSize+1);
sliceSelector.setValue(imp.getCurrentSlice());
}
public void run() {
while (!done) {
synchronized(this) {
try {wait();}
catch(InterruptedException e) {}
}
if (done) return;
if (slice>0) {
int s = slice;
slice = 0;
if (s!=imp.getCurrentSlice())
imp.setSlice(s);
}
}
}
public String createSubtitle() {
String subtitle = super.createSubtitle();
if (!hyperStack) return subtitle;
String s="";
int[] dim = imp.getDimensions();
int channels=dim[2], slices=dim[3], frames=dim[4];
if (channels>1) {
s += "c:"+imp.getChannel()+"/"+channels;
if (slices>1||frames>1) s += " ";
}
if (slices>1) {
s += "z:"+imp.getSlice()+"/"+slices;
if (frames>1) s += " ";
}
if (frames>1)
s += "t:"+imp.getFrame()+"/"+frames;
if (running2) return s;
int index = subtitle.indexOf(";");
if (index!=-1) {
int index2 = subtitle.indexOf("(");
if (index2>=0 && index2<index && subtitle.length()>index2+4 && !subtitle.substring(index2+1, index2+4).equals("ch:")) {
index = index2;
s = s + " ";
}
subtitle = subtitle.substring(index, subtitle.length());
} else
subtitle = "";
return s + subtitle;
}
public boolean isHyperStack() {
return hyperStack;
}
public void setPosition(int channel, int slice, int frame) {
if (channelSelector!=null && channel!=c) {
c = channel;
channelSelector.setValue(channel);
}
if (sliceSelector!=null && slice!=z) {
z = slice;
sliceSelector.setValue(slice);
}
if (frameSelector!=null && frame!=t) {
t = frame;
frameSelector.setValue(frame);
}
updatePosition();
if (this.slice>0) {
int s = this.slice;
this.slice = 0;
if (s!=imp.getCurrentSlice())
imp.setSlice(s);
}
}
public boolean validDimensions() {
int c = imp.getNChannels();
int z = imp.getNSlices();
int t = imp.getNFrames();
if (c!=nChannels||z!=nSlices||t!=nFrames||c*z*t!=imp.getStackSize())
return false;
else
return true;
}
}
|
StackWindow |
|