// "Stack Blaster" // // Stack Blaster performs image calculations allowing a second image // image to be "superimposed" upon a background image. The second // image may be superimposed anywhere on the background image by // selecting entering values for Initial Horizontal Displacement and Initial // Vertical Displacement (cooresponding to the placement of the top left // corner of the second image). The second image may be superimposed with // a linear trajectory through the slices of the stack by entering values // for Slice Horizontal increment and Slice Vertical increment. This can be // used to simulate animation effects. If "Apply Overlay as Modulus?" is // checked, the second image will be repeated multiple times through the // background image. For example if there are 256 slices in the background // image and 16 in the second image, the second image will be repeated // 16 times. Stack Blaster also works with Virtual stacks (a new image // will be created with the same dimensions of the background image. macro "Stack Blaster" { var ImagePasteModes=newArray("Transparent-zero","Transparent-white","Copy","Blend","Difference","AND","OR","XOR", "Add","Subtract","Multiply","Divide","Min","Max" ); var ImageOverlayPositions=newArray("X-Y Position","Top-Left","Top-Center","Top-Right" ,"Center-Left","Center", "Center-Right","Bottom-Left","Bottom-Center","Bottom-Right"); setBatchMode(true); ImageArray= LoadAllImages(2,true); size= ImageArray.length; AnimationFPS=16; UseModulus=false; //------------------------------------------------------- //DEFAULT Properties title = "Blasted"; XDisplacement=0; YDisplacement=0; ZXincrement=0; ZYincrement=0; //------------------------------------------------------- Dialog.create ("Stack Blaster"); Dialog.addChoice("Background Image", ImageArray, ImageArray[0]); Dialog.addChoice("Overlay Image", ImageArray, ImageArray[1]); //------------------------------------------------------- Dialog.addChoice("Paste Mode", ImagePasteModes, ImagePasteModes[2]); //Default Copy Dialog.addChoice("Image Overlay Position", ImageOverlayPositions, ImageOverlayPositions[5]); //Default Center Dialog.addNumber("Initial Horizontal Displacement (pixels)", XDisplacement); Dialog.addNumber("Initial Vertical Displacement (pixels)", YDisplacement); Dialog.addNumber("Slice Horizontal increment (pixels)", ZXincrement); Dialog.addNumber("Slice Vertical increment (pixels)", ZYincrement); Dialog.addString("Image Title", title); Dialog.addCheckbox("Apply Overlay as Modulus?", UseModulus); Dialog.addCheckbox("Create New Window", false); Dialog.addCheckbox("Run Animation", true); Dialog.addNumber("Animation Frames per second", AnimationFPS); //------------------------------------------------------- Dialog.show(); //------------------------------------------------------- BackgroundImage=Dialog.getChoice(); OverlayImage=Dialog.getChoice(); PasteMode=Dialog.getChoice(); OverlayPosition = Dialog.getChoice(); XDisplacement=Dialog.getNumber(); YDisplacement=Dialog.getNumber(); ZXincrement=Dialog.getNumber(); ZYincrement=Dialog.getNumber(); NewImageTitle=Dialog.getString(); UseModulus=Dialog.getCheckbox(); CreateNewWindow=Dialog.getCheckbox(); RunAnimation=Dialog.getCheckbox(); AnimationFPS=Dialog.getNumber(); CacheCurrentPasteMode=getCurrentPasteMode(); setPasteMode(PasteMode); NewImageID=runStackBlaster (BackgroundImage, OverlayImage, UseModulus , OverlayPosition, XDisplacement, YDisplacement, ZXincrement, ZYincrement, NewImageTitle, CreateNewWindow); setBatchMode("exit and display"); updateDisplay(); setPasteMode(CacheCurrentPasteMode); selectImage(NewImageID); if (RunAnimation==true) { run("Animation Options...", "speed="+ AnimationFPS + " first=1 last="+ nSlices +" start");} //------------------------------------------------------- //------------------------------------------------------- function LoadAllImages (minImageCount, blnSorted) { arrIndex=0; for (i=1; i<=nImages; i++) { selectImage(i); if (isValidToInclude(getTitle() ) ) arrIndex= arrIndex + 1; } if (arrIndex< minImageCount) exit ("Fewer than " + minImageCount + " images are open"); //------------------------------- ImageArray=newArray(arrIndex+1); arrIndex=-1; for (i=1; i<=nImages; i++) { selectImage(i); if (isValidToInclude(getTitle() ) ) { arrIndex= arrIndex + 1; ImageArray[arrIndex]=getTitle() ; } } if (blnSorted==true) { ImageArray[arrIndex+1]="zzzzzzzz"; ImageArray=Array.sort(ImageArray); } ImageArray[arrIndex+1]="-NONE-"; return ImageArray; } //------------------------------------------------------- //------------------------------------------------------- function isValidToInclude (title) { if (title=="CP") return false; if (title=="Memory") return false; return true; } //------------------------------------------------------- //------------------------------------------------------- function getCurrentPasteMode () { numGCPM= call("ij.gui.Roi.getCurrentPasteMode") ; if (numGCPM== "0") return "Copy" ; if (numGCPM== "2") return "Transparent-white"; if (numGCPM== "3") return "Add"; if (numGCPM== "4") return "Subtract"; if (numGCPM== "5") return "Multiply"; if (numGCPM== "6") return "Divide"; if (numGCPM== "7") return "Blend"; if (numGCPM== "8") return "Difference"; if (numGCPM== "9") return "AND"; if (numGCPM== "10") return "OR"; if (numGCPM== "11") return "XOR"; if (numGCPM== "12") return "Min"; if (numGCPM== "13") return "Max"; if (numGCPM== "14") return "Transparent-zero"; } //------------------------------------------------------- //------------------------------------------------------- function runStackBlaster (BackgroundImage, OverlayImage, UseModulus , OverlayPosition, XDisplacement, YDisplacement, ZXincrement, ZYincrement, NewImageTitle, CreateNewWindow) { //------------------------------------------------------- //------------------------------------------------------- selectWindow(BackgroundImage); nBKGSlices= nSlices; wBKG= getWidth; hBKG= getHeight; if (is("Virtual Stack")==true) CreateNewWindow==true ; if (CreateNewWindow==true) { run("Duplicate...", "title="+ NewImageTitle + " duplicate range=1-" + nBKGSlices); } ImageBKG=getImageID(); selectWindow(OverlayImage); ImageOVL=getImageID(); wOVL=getWidth; hOVL=getHeight; nOVL= nSlices; //--------------------- xCenterOrigen = (wBKG-wOVL)/2; yCenterOrigen = (hBKG-hOVL)/2; xRightOrigen= (wBKG-wOVL); yBottomOrigen= (hBKG-hOVL); nUsableSlices=minOf(nBKGSlices, nOVL); if (UseModulus==true ) nUsableSlices=maxOf(nBKGSlices, nOVL); // Calculate X and Y Origens if (OverlayPosition=="Top-Left") {XDisplacement=0; YDisplacement=0;} if (OverlayPosition=="Top-Center") {XDisplacement= xCenterOrigen; YDisplacement=0;} if (OverlayPosition=="Top-Right") {XDisplacement= xRightOrigen; YDisplacement=0;} if (OverlayPosition=="Center-Left") {XDisplacement=0; YDisplacement= yCenterOrigen;} if (OverlayPosition=="Center") {XDisplacement= xCenterOrigen; YDisplacement= yCenterOrigen;} if (OverlayPosition=="Center-Right") {XDisplacement= xRightOrigen; YDisplacement= yCenterOrigen;} if (OverlayPosition=="Bottom-Left") {XDisplacement=0; YDisplacement= yBottomOrigen;} if (OverlayPosition=="Bottom-Center") {XDisplacement =xCenterOrigen; YDisplacement= yBottomOrigen;} if (OverlayPosition=="Bottom-Right") {XDisplacement= xRightOrigen; YDisplacement= yBottomOrigen;} for (slice =1; slice <= nUsableSlices; slice++) { XOrigen=XDisplacement + slice * ZXincrement ; YOrigen=YDisplacement + slice * ZYincrement ; OVLslice= slice; if (UseModulus==true ) {OVLslice=(slice + nOVL ) % nOVL ; if (OVLslice ==0) OVLslice = nOVL; } selectImage(ImageOVL); setSlice(OVLslice); run("Copy"); selectImage(ImageBKG); setSlice(slice); makeRectangle(XOrigen, YOrigen, wOVL, hOVL); run ("Paste"); showStatus("Iteration " + slice + " of " + nUsableSlices ); showProgress((slice)/nUsableSlices); } selectImage(ImageBKG); setSlice(1); run("Select None"); return ImageBKG; } }