I don't really remember how this works anymore. Documentation is unlikely to occur. Here's the code though. It did work.
Align_Stack.java:
import ij.*; import ij.plugin.filter.PlugInFilter; import ij.plugin.*; import ij.process.*; import ij.gui.*; import java.awt.event.*; import java.io.*; import java.awt.Color; /** * This plugin implements the KeyListener interface and listens * for key events generated by the current image. */ public class Align_Stack implements PlugIn, KeyListener { ImagePlus img; ImageProcessor flatProcessor; ImagePlus flatImg; ImageStack stack; String fileName; int[] flatdisplacementX; int[] flatdisplacementY; int[] flatrotation; int depth; int currentSlice; int stepSize; void reConstruct() { flatProcessor.multiply(0); for(int z = 1; z<=depth; z++){ ImageProcessor tempIp = stack.getProcessor(z).duplicate(); if (z == currentSlice) { tempIp.multiply(.5); } else if (Math.abs(z-currentSlice)<3){ tempIp.multiply(.1); } else { tempIp.multiply(.1/(depth-5)); } flatProcessor.copyBits(tempIp,flatdisplacementX[z],flatdisplacementY[z],Blitter.ADD); } flatImg.updateAndDraw(); IJ.log("Slice: "+currentSlice); } void loadData() { try { if (!( new File(fileName).exists() )) {IJ.error("No input file");return;} BufferedReader br = new BufferedReader(new FileReader(fileName)); for(int i=1;i<=depth;i++) { String[] line = br.readLine().split(","); flatdisplacementX[i]= new Integer(line[0]).intValue(); flatdisplacementY[i]= new Integer(line[1]).intValue(); flatrotation[i]= new Integer(line[2]).intValue(); stack.getProcessor(i).insert(img.getStack().getProcessor(i),0,0); stack.getProcessor(i).rotate(flatrotation[i]); } br.close(); reConstruct(); return; } catch (IOException e) { IJ.showMessage("FileIO Error On Load: ", ""+e); return; } } void saveData() { try { new File(fileName).delete(); PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(fileName))); for(int i=1;i<=depth;i++) { pw.print(flatdisplacementX[i]+","+flatdisplacementY[i]+","+flatrotation[i]+"\n"); } pw.flush(); pw.close(); } catch (IOException e) { IJ.showMessage("FileIO Error On Write: ", ""+e); return; } } public void run(String arg) { img = WindowManager.getCurrentImage(); ImageWindow win = img.getWindow(); ImageCanvas canvas = win.getCanvas(); canvas.addKeyListener(this); IJ.write(img.toString()); //fileName = "/Users/peter/Pictures/registerdata"; fileName = img.getOriginalFileInfo().directory+img.getOriginalFileInfo().fileName+".stackAlignData"; depth = img.getStackSize(); stack = new ImageStack(img.getWidth(),img.getHeight()); for (int i = 1;i<=depth;i++) { stack.addSlice(null,img.getStack().getProcessor(i).duplicate()); stack.getProcessor(i).invertLut(); } flatdisplacementX = new int[depth+1]; flatdisplacementY = new int[depth+1]; flatrotation = new int[depth+1]; flatProcessor = img.getStack().getProcessor(1).duplicate(); currentSlice = 1; flatImg = new ImagePlus("Projection", flatProcessor); ImageCanvas flatCanvas = new ImageCanvas(flatImg); reConstruct(); new ImageWindow(flatImg, flatCanvas); } public void keyPressed(KeyEvent e) { int keyCode = e.getKeyCode(); char keyChar = e.getKeyChar(); int flags = e.getModifiers(); IJ.log("keyCode=" + keyCode + " (" + KeyEvent.getKeyText(keyCode) + ") keyChar=\"" + keyChar + "\" (" + (int)keyChar + ") " + KeyEvent.getKeyModifiersText(flags)); if(keyCode==34 && currentSlice < img.getStackSize()) { currentSlice = currentSlice+1; reConstruct(); } if(keyCode==33 && currentSlice>1) { currentSlice = currentSlice-1; reConstruct(); } if ((flags & KeyEvent.SHIFT_MASK) != 0) { stepSize = 10; } else { stepSize = 1; } if(keyCode==39) { flatdisplacementX[currentSlice] = flatdisplacementX[currentSlice] + stepSize; reConstruct(); } if(keyCode==37) { flatdisplacementX[currentSlice] = flatdisplacementX[currentSlice] - stepSize; reConstruct(); } if(keyCode==40) { flatdisplacementY[currentSlice] = flatdisplacementY[currentSlice] + stepSize; reConstruct(); } if(keyCode==38) { flatdisplacementY[currentSlice] = flatdisplacementY[currentSlice] - stepSize; reConstruct(); } if(keyCode==107) { flatrotation[currentSlice] = flatrotation[currentSlice] + stepSize/10; stack.getProcessor(currentSlice).insert(img.getStack().getProcessor(currentSlice),0,0); stack.getProcessor(currentSlice).setValue(0); stack.getProcessor(currentSlice).rotate(flatrotation[currentSlice]); reConstruct(); } if(keyCode==109) { flatrotation[currentSlice] = flatrotation[currentSlice] - stepSize/10; stack.getProcessor(currentSlice).insert(img.getStack().getProcessor(currentSlice),0,0); stack.getProcessor(currentSlice).setValue(0); stack.getProcessor(currentSlice).rotate(flatrotation[currentSlice]); reConstruct(); } if(keyCode==10) { ImageStack newStack = new ImageStack(img.getWidth(),img.getHeight(),img.getStack().getColorModel()); for( int z = 1; z <=depth; z++){ IJ.write("Stanrting :"+z); ImageProcessor tempProcessor = img.getStack().getProcessor(z).duplicate(); tempProcessor.invertLut(); tempProcessor.rotate(flatrotation[z]); newStack.addSlice(img.getStack().getSliceLabel(z), tempProcessor.createProcessor(img.getWidth(),img.getHeight())); //lousy initialize newStack.getProcessor(z).copyBits(tempProcessor,flatdisplacementX[z],flatdisplacementY[z],Blitter.ADD); newStack.getProcessor(z).invertLut(); } ImagePlus newImg = new ImagePlus( ); newImg.setStack("Aligned_stack",newStack); ImageCanvas newCanvas = new ImageCanvas(newImg); new ImageWindow(newImg, newCanvas); IJ.write("Step4"); } if(keyCode==76) { loadData(); } if(keyCode==106) { saveData(); } if(keyCode==86) { IJ.write("##### View Results #####"); for(int i=1;i<=depth;i++){ IJ.write("Slice "+i+": "+flatdisplacementX[i]+","+flatdisplacementY[i]+","+flatrotation[i]); } IJ.write("########################"); IJ.write(" "); IJ.write(" "); } } public void keyReleased(KeyEvent e) {} public void keyTyped(KeyEvent e) {} /** Returns the current list of modifier keys. */ public String modifiers(int flags) { String s = " [ "; if (flags == 0) return ""; if ((flags & KeyEvent.SHIFT_MASK) != 0) s += "Shift "; if ((flags & KeyEvent.CTRL_MASK) != 0) s += "Control "; if ((flags & KeyEvent.META_MASK) != 0) s += "Meta "; if ((flags & KeyEvent.ALT_MASK) != 0) s += "Alt "; s += "] "; return s; } }
Align_Colors.java:
import ij.*; import ij.plugin.filter.PlugInFilter; import ij.plugin.*; import ij.process.*; import ij.gui.*; import java.awt.event.*; import java.io.*; /** * This plugin implements the KeyListener interface and listens * for key events generated by the current image. */ public class Align_Colors implements PlugIn, KeyListener { ImagePlus img; ImageStack originalStack; String fileName; int[][] displacementX; int[][] displacementY; int[][] rotation; int depth,w,h; int currentColor; //0-red 1-green 2-blue int stepSize; void loadData() { try { if (!( new File(fileName).exists() )) {IJ.error("No input file");return;} int startColor = currentColor; BufferedReader br = new BufferedReader(new FileReader(fileName)); for(int i=1;i<=depth;i++) { img.setSlice(i); for(int c=0;c<3;c++){ String[] line = br.readLine().split(","); displacementX[i][c]= new Integer(line[0]).intValue(); displacementY[i][c]= new Integer(line[1]).intValue(); rotation[i][c]= new Integer(line[2]).intValue(); currentColor=c; refreshView(); } } br.close(); currentColor = startColor; return; } catch (IOException e) { IJ.showMessage("FileIO Error On Load: ", ""+e); return; } } void saveData() { try { new File(fileName).delete(); PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(fileName))); for(int i=1;i<=depth;i++) { for(int c=0;c<3;c++){ pw.print(displacementX[i][c]+","+displacementY[i][c]+","+rotation[i][c]+"\n"); } } pw.flush(); pw.close(); } catch (IOException e) { IJ.showMessage("FileIO Error On Write: ", ""+e); return; } } void refreshView() { int currentSlice = img.getCurrentSlice(); byte[][] cbytes = new byte[3][w*h]; byte[][] obytes = new byte[3][w*h]; ((ColorProcessor)(img.getStack().getProcessor(currentSlice))).getRGB(cbytes[0],cbytes[1],cbytes[2]); ((ColorProcessor)(originalStack.getProcessor(currentSlice))).getRGB(obytes[0],obytes[1],obytes[2]); ByteProcessor tempProcessor = new ByteProcessor(w,h,obytes[currentColor],null); tempProcessor.invertLut(); tempProcessor.rotate(rotation[currentSlice][currentColor]); ByteProcessor tempProcessor2 = new ByteProcessor(w,h); tempProcessor2.insert(tempProcessor,displacementX[currentSlice][currentColor],displacementY[currentSlice][currentColor]); cbytes[currentColor]=(byte[])tempProcessor2.getPixels(); ((ColorProcessor)(img.getStack().getProcessor(currentSlice))).setRGB(cbytes[0],cbytes[1],cbytes[2]); img.updateAndDraw(); } public void run(String arg) { img = WindowManager.getCurrentImage(); ImageWindow win = img.getWindow(); ImageCanvas canvas = win.getCanvas(); canvas.addKeyListener(this); fileName = img.getOriginalFileInfo().directory+img.getOriginalFileInfo().fileName+".colorAlignData"; depth = img.getStackSize(); w = img.getWidth(); h = img.getHeight(); originalStack = new ImageStack(w,h); for (int i = 1;i<=depth;i++) { IJ.showProgress((i-1)/depth); originalStack.addSlice(null,img.getStack().getProcessor(i).duplicate()); } displacementX = new int[depth+1][3]; displacementY = new int[depth+1][3]; rotation = new int[depth+1][3]; } public void keyPressed(KeyEvent e) { int keyCode = e.getKeyCode(); char keyChar = e.getKeyChar(); int flags = e.getModifiers(); IJ.log("keyCode=" + keyCode + " (" + KeyEvent.getKeyText(keyCode) + ") keyChar=\"" + keyChar + "\" (" + (int)keyChar + ") " + KeyEvent.getKeyModifiersText(flags)); int currentSlice = img.getCurrentSlice(); if ((flags & KeyEvent.SHIFT_MASK) != 0) { stepSize = 10; } else { stepSize = 1; } if(keyCode==39) { displacementX[currentSlice][currentColor] = displacementX[currentSlice][currentColor] + stepSize; refreshView(); } if(keyCode==37) { displacementX[currentSlice][currentColor] = displacementX[currentSlice][currentColor] - stepSize; refreshView(); } if(keyCode==40) { displacementY[currentSlice][currentColor] = displacementY[currentSlice][currentColor] + stepSize; refreshView(); } if(keyCode==38) { displacementY[currentSlice][currentColor] = displacementY[currentSlice][currentColor] - stepSize; refreshView(); } if(keyCode==107) { rotation[currentSlice][currentColor] = rotation[currentSlice][currentColor] + stepSize/10; refreshView(); } if(keyCode==109) { rotation[currentSlice][currentColor] = rotation[currentSlice][currentColor] - stepSize/10; refreshView(); } if(keyCode==76) { loadData(); } if(keyCode==106) { saveData(); } if(keyCode==82) { currentColor=0; } if(keyCode==71) { currentColor=1; } if(keyCode==66) { currentColor=2; } if(keyCode==86) { IJ.write("##### View Results #####"); for(int i=1;i<=depth;i++){ for(int c=0;c<3;c++){ IJ.write(displacementX[i][c]+","+displacementY[i][c]+","+rotation[i][c]); } } IJ.write("########################"); IJ.write(" "); IJ.write(" "); } } public void keyReleased(KeyEvent e) {} public void keyTyped(KeyEvent e) {} /** Returns the current list of modifier keys. */ public String modifiers(int flags) { String s = " [ "; if (flags == 0) return ""; if ((flags & KeyEvent.SHIFT_MASK) != 0) s += "Shift "; if ((flags & KeyEvent.CTRL_MASK) != 0) s += "Control "; if ((flags & KeyEvent.META_MASK) != 0) s += "Meta "; if ((flags & KeyEvent.ALT_MASK) != 0) s += "Alt "; s += "] "; return s; } }