package ij.plugin; import ij.*; import ij.process.*; import ij.gui.*; /** * This plugin implements the Image/Stacks/Tools/Make Substack command. * What it does is extracts selected images from a stack to make a new substack. * It takes three types of inputs: a range of images (e.g. 2-14), a range of images * with an increment (e.g. 2-14-3), or a list of images (e.g. 7,9,25,27,34,132). * It then copies those images from the active stack to a new stack in the order * of listing or range. * * @author Anthony Padua * @author Daniel Barboriak, MD * @author Neuroradiology * @author Duke University Medical Center * * @author Ved P. Sharma, Ph.D. * @author Anatomy and Structural Biology * @author Albert Einstein College of Medicine * */ public class SubstackMaker implements PlugIn { private static boolean delete = false; public void run(String arg) { ImagePlus imp = IJ.getImage(); if (imp.isHyperStack() || imp.isComposite()) { IJ.error("Make Substack", "This command does not currently work with hyperstacks."); return; } String userInput = showDialog(); if (userInput==null) return; ImagePlus imp2 = makeSubstack(imp, userInput); if (imp2!=null) imp2.show(); } public ImagePlus makeSubstack(ImagePlus imp, String userInput) { String stackTitle = "Substack ("+userInput+")"; if (stackTitle.length()>25) { int idxA = stackTitle.indexOf(",",18); int idxB = stackTitle.lastIndexOf(","); if(idxA>=1 && idxB>=1){ String strA = stackTitle.substring(0,idxA); String strB = stackTitle.substring(idxB+1); stackTitle = strA + ", ... " + strB; } } ImagePlus imp2 = null; try { int idx1 = userInput.indexOf("-"); if (idx1>=1) { // input displayed in range String rngStart = userInput.substring(0, idx1); String rngEnd = userInput.substring(idx1+1); Integer obj = new Integer(rngStart); int first = obj.intValue(); int inc = 1; int idx2 = rngEnd.indexOf("-"); if (idx2>=1) { String rngEndAndInc = rngEnd; rngEnd = rngEndAndInc.substring(0, idx2); String rngInc = rngEndAndInc.substring(idx2+1); obj = new Integer(rngInc); inc = obj.intValue(); } obj = new Integer(rngEnd); int last = obj.intValue(); imp2 = stackRange(imp, first, last, inc, stackTitle); } else { int count = 1; // count # of slices to extract for (int j=0; j<userInput.length(); j++) { char ch = Character.toLowerCase(userInput.charAt(j)); if (ch==',') {count += 1;} } int[] numList = new int[count]; for(int i=0; i<count; i++) { int idx2 = userInput.indexOf(","); if(idx2>0) { String num = userInput.substring(0,idx2); Integer obj = new Integer(num); numList[i] = obj.intValue(); userInput = userInput.substring(idx2+1); } else{ String num = userInput; Integer obj = new Integer(num); numList[i] = obj.intValue(); } } imp2 = stackList(imp, count, numList, stackTitle); } } catch (Exception e) { IJ.error("Substack Maker", "Invalid input string: \n \n \""+userInput+"\""); } return imp2; } String showDialog() { GenericDialog gd = new GenericDialog("Substack Maker"); gd.setInsets(10,45,0); gd.addMessage("Enter a range (e.g. 2-14), a range with increment\n(e.g. 1-100-2) or a list (e.g. 7,9,25,27)"); gd.addStringField("Slices:", "", 40); gd.addCheckbox("Delete slices from original stack", delete); gd.showDialog(); if (gd.wasCanceled()) return null; else { delete = gd.getNextBoolean(); return gd.getNextString(); } } // extract specific slices ImagePlus stackList(ImagePlus imp, int count, int[] numList, String stackTitle) throws Exception { ImageStack stack = imp.getStack(); ImageStack stack2 = null; Roi roi = imp.getRoi(); for (int i=0, j=0; i<count; i++) { int currSlice = numList[i]-j; ImageProcessor ip2 = stack.getProcessor(currSlice); ip2.setRoi(roi); ip2 = ip2.crop(); if (stack2==null) stack2 = new ImageStack(ip2.getWidth(), ip2.getHeight()); stack2.addSlice(stack.getSliceLabel(currSlice), ip2); if (delete) { stack.deleteSlice(currSlice); j++; } } if (delete) { imp.setStack(stack); // next three lines for updating the scroll bar ImageWindow win = imp.getWindow(); StackWindow swin = (StackWindow) win; swin.updateSliceSelector(); } ImagePlus impSubstack = imp.createImagePlus(); impSubstack.setStack(stackTitle, stack2); impSubstack.setCalibration(imp.getCalibration()); return impSubstack; } // extract range of slices ImagePlus stackRange(ImagePlus imp, int first, int last, int inc, String title) throws Exception { ImageStack stack = imp.getStack(); ImageStack stack2 = null; Roi roi = imp.getRoi(); for (int i= first, j=0; i<= last; i+=inc) { //IJ.log(first+" "+last+" "+inc+" "+i); int currSlice = i-j; ImageProcessor ip2 = stack.getProcessor(currSlice); ip2.setRoi(roi); ip2 = ip2.crop(); if (stack2==null) stack2 = new ImageStack(ip2.getWidth(), ip2.getHeight()); stack2.addSlice(stack.getSliceLabel(currSlice), ip2); if (delete) { stack.deleteSlice(currSlice); j++; } } if (delete) { imp.setStack(stack); // next three lines for updating the scroll bar ImageWindow win = imp.getWindow(); StackWindow swin = (StackWindow) win; swin.updateSliceSelector(); } ImagePlus substack = imp.createImagePlus(); substack.setStack(title, stack2); substack.setCalibration(imp.getCalibration()); return substack; } }