import ij.plugin.*; import ij.*; import ij.gui.*; import ij.process.*; import java.util.*; /** iMorph2 iMorph is a plug-in for (trans)morphing one image to another. Description: Given two images, it generates a series of images (in ImageStack format) to gradually transform one image into the other image. It gives you a choice of morphing back, so that it can be played in loop. Limitations: Only works with RGB images that have identical size (i.e. dimension) probably don't handle transparency very well. current version only implements linear morphing and random morphing., could be useful for web page animations Random morphing works only with Java 2 Other Remarks: Initial development with iMac(233Hz, Rev. A. MacOS 9.0.4 MRJ 2.2.4 ) using iText editor (2.2.1 English release) Current development with Linux JDK 1.3.1 using emacs editor suggestions, criticism, optimization, modification welcome. More morphing operations will be done, but cannot promise when. @author Hajime Hirase (hirase@axon.rutgers.edu) Center for Molecular and Behavioral Neuroscience Rutgers University, Newark, NJ 07102 @version 0.6.0 (8/1/2001) (modified from ImageCalculator plug-in) */ public class iMorph2_ implements PlugIn { // the interface is a modified copy of ImageCalculator Plug-in // nothing special has been done, aside from checking image kind (stack,RGB) // and size. It calls doOperation to do actual morphing. private static int operator; private static String title1 = ""; private static String title2 = ""; private static boolean iMorphBack = false; private static int nFrame=10; public void run(String arg) { int nValidImage=0; int[] wList = WindowManager.getIDList(); if (wList==null) { IJ.error("No windows are open."); return; } IJ.register(iMorph2_.class); String[] operators = {"Linear","Random"}; // first, count how many valid images there are .. (could have used Vector instead) //for (int i=0; i1;i--) { iMorphedPlus.getStack().addSlice("",iMorphedPlus.getStack().getProcessor(i)); } } iMorphedPlus.show(); } void iMLinear(ImagePlus imp) { // linear morphing int n = imp.getStackSize(); int size = imp.getWidth() * imp.getHeight(); int fromPixels[] = (int []) imp.getStack().getProcessor(1).getPixels(); int toPixels[] = (int []) imp.getStack().getProcessor(n).getPixels(); int tmpPixels[]; int fRed,fGre,fBlu; int tRed,tGre,tBlu; int mRed,mGre,mBlu; for (int i=2;i>16; fGre = (fromPixels[j]&0xff00)>>8; fBlu = fromPixels[j]&0xff; tRed = (toPixels[j]&0xff0000)>>16; tGre = (toPixels[j]&0xff00)>>8; tBlu = toPixels[j]&0xff; mRed = (int)(fRed + ((float)tRed-fRed)/(n-1)*(i-1)); mGre = (int)(fGre + ((float)tGre-fGre)/(n-1)*(i-1)); mBlu = (int)(fBlu + ((float)tBlu-fBlu)/(n-1)*(i-1)); tmpPixels[j] = mRed<<16|mGre<<8|mBlu; } } } // random morphing // creating random indicies is very inefficient. future // version will create random numbers in double, sort the array // and pick the sorted indicies. void iMRandom(ImagePlus imp) { int n = imp.getStackSize(); int size = imp.getWidth()*imp.getHeight(); int masking[] = new int[size]; int nMorphPixel = size/n-1; int randIndex; int [] tmppixels; int [] topixels; ImageProcessor fromImg = imp.getStack().getProcessor(1); ImageProcessor toImg =imp.getStack().getProcessor(n); int [][] pixels = new int[n+1][]; for (int i=1;i<=n;i++) { pixels[i] = (int[])imp.getStack().getProcessor(i).getPixels(); } IJ.showProgress((double)0.0); // create random permutation int totalMorphPixel = (n-2)*nMorphPixel; RandPerm rndPrm = new RandPerm(size); for (int i=2;i((PairNum)pairnum).value) result = 1; else if (value<((PairNum)pairnum).value) result = -1; else result = 0; return result; } } // this is the class to create random permutation // the constructor takes care of class RandPerm { private Vector randdata; public RandPerm(int n) { Random rndGen = new Random(); randdata = new Vector(n); for (int i=0;i