
ij.plugin.BatchProcessor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ij Show documentation
Show all versions of ij Show documentation
ImageJ is an open source Java image processing program inspired by NIH Image for the Macintosh.
package ij.plugin;
import ij.*;
import ij.process.*;
import ij.gui.*;
import ij.util.Tools;
import ij.util.StringSorter;
import ij.io.*;
import ij.macro.Interpreter;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.Vector;
/** This plugin implements the File/Batch/Macro and File/Batch/Virtual Stack commands. */
public class BatchProcessor implements PlugIn, ActionListener, ItemListener, Runnable {
private static final String MACRO_FILE_NAME = "BatchMacro.ijm";
private static final String[] formats = {"TIFF", "8-bit TIFF", "JPEG", "GIF", "PNG", "PGM", "BMP", "FITS", "Text Image", "ZIP", "Raw"};
private static String format = Prefs.get("batch.format", formats[0]);
private static final String[] code = {
"[Select from list]",
"Add Border",
"Convert to RGB",
"Crop",
"Gaussian Blur",
"Invert",
"Label",
"Timestamp",
"Max Dimension",
"Measure",
"Print Index and Title",
"Resize",
"Scale",
"Show File Info",
"Unsharp Mask",
};
private static final String help = ""
+"Process>Batch>Virtual Stack
"
+""
+"This command runs macro code on each image in a virtual stack.
"
+"The processed images are saved in the Output folder,
"
+"in the specified Format, allowing them to be opened as a
"
+"virtual stack. Make sure the Output folder is empty
"
+"before clicking on Process.
"
+"
"
+"In the macro code, the 'i' (slice index) and 'n' (stack size) variables
"
+"are predefined. Call setOption('SaveBatchOutput',false) to
"
+"prevent the image currently being processed from being saved,
"
+"effectively removing it from the output virtual stack.
"
+"";
private String macro = "";
private int testImage;
private Button input, output, open, save, test;
private TextField inputDir, outputDir;
private GenericDialog gd;
private Thread thread;
private ImagePlus virtualStack;
private ImagePlus outputImage;
private boolean errorDisplayed;
private String filter;
private static boolean saveOutput = true;
public void run(String arg) {
if (arg.equals("stack")) {
virtualStack = IJ.getImage();
if (virtualStack.getStackSize()==1) {
error("This command requires a stack or virtual stack.");
return;
}
}
String macroPath = IJ.getDirectory("macros")+MACRO_FILE_NAME;
macro = IJ.openAsString(macroPath);
if (macro==null || macro.startsWith("Error: ")) {
IJ.showStatus(macro.substring(7) + ": "+macroPath);
macro = "";
}
if (!showDialog()) return;
String inputPath = null;
if (virtualStack==null) {
inputPath = inputDir.getText();
if (inputPath.equals("")) {
error("Please choose an input folder");
return;
}
inputPath = addSeparator(inputPath);
File f1 = new File(inputPath);
if (!f1.exists() || !f1.isDirectory()) {
error("Input does not exist or is not a folder\n \n"+inputPath);
return;
}
}
String outputPath = outputDir.getText();
outputPath = addSeparator(outputPath);
File f2 = new File(outputPath);
if (!outputPath.equals("") && (!f2.exists() || !f2.isDirectory())) {
error("Output does not exist or is not a folder\n \n"+outputPath);
return;
}
if (macro.equals("")) {
error("There is no macro code in the text area");
return;
}
ImageJ ij = IJ.getInstance();
if (ij!=null) ij.getProgressBar().setBatchMode(true);
IJ.resetEscape();
if (virtualStack!=null)
processVirtualStack(outputPath);
else
processFolder(inputPath, outputPath);
IJ.showProgress(1,1);
if (virtualStack==null)
Prefs.set("batch.input", inputDir.getText());
Prefs.set("batch.output", outputDir.getText());
Prefs.set("batch.format", format);
macro = gd.getTextArea1().getText();
if (!macro.equals(""))
IJ.saveString(macro, IJ.getDirectory("macros")+MACRO_FILE_NAME);
}
boolean showDialog() {
validateFormat();
gd = GUI.newNonBlockingDialog("Batch Process");
addPanels(gd);
gd.setInsets(15, 0, 5);
gd.addChoice("Output_format:", formats, format);
gd.setInsets(0, 0, 5);
gd.addChoice("Add macro code:", code, code[0]);
if (virtualStack==null)
gd.addStringField("File name contains:", "", 10);
gd.setInsets(15, 10, 0);
Dimension screen = IJ.getScreenSize();
gd.addTextAreas(macro, null, screen.width<=600?10:15, 60);
addButtons(gd);
gd.setOKLabel("Process");
Vector choices = gd.getChoices();
Choice choice = (Choice)choices.elementAt(1);
if (virtualStack!=null)
gd.addHelp(help);
choice.addItemListener(this);
gd.showDialog();
format = gd.getNextChoice();
if (virtualStack==null)
filter = gd.getNextString();
macro = gd.getNextText();
return !gd.wasCanceled();
}
void processVirtualStack(String outputPath) {
ImageStack stack = virtualStack.getStack();
int n = stack.size();
int index = 0;
for (int i=1; i<=n; i++) {
if (IJ.escapePressed()) break;
IJ.showProgress(i, n);
ImageProcessor ip = stack.getProcessor(i);
if (ip==null) return;
ImagePlus imp = new ImagePlus(i+"/"+stack.size(), ip);
if (!macro.equals("")) {
if (!runMacro("i="+(index++)+";"+"n="+stack.size()+";"+macro, imp))
break;
}
if (saveOutput && !outputPath.equals("")) {
if (format.equals("8-bit TIFF") || format.equals("GIF")) {
if (imp.getBitDepth()==24)
IJ.run(imp, "8-bit Color", "number=256");
else
IJ.run(imp, "8-bit", "");
}
IJ.saveAs(imp, format, outputPath+pad(i));
}
saveOutput = true;
imp.close();
}
if (outputPath!=null && !outputPath.equals(""))
IJ.run("Image Sequence...", "open=[" + outputPath + "]"+" use");
}
String pad(int n) {
String str = ""+n;
while (str.length()<5)
str = "0" + str;
return str;
}
void processFolder(String inputPath, String outputPath) {
String[] list = (new File(inputPath)).list();
list = FolderOpener.getFilteredList(list, filter, "Batch Processor");
if (list==null)
return;
StringSorter.sort(list);
int index = 0;
int startingCount = WindowManager.getImageCount();
for (int i=0; istartingCount)
imp = WindowManager.getCurrentImage();
if (imp==null)
imp = Opener.openUsingBioFormats(path);
if (imp==null) {
IJ.log("openImage() and openUsingBioFormats() returned null: "+path);
continue;
}
if (!macro.equals("")) {
outputImage = null;
if (!runMacro("i="+(index++)+";"+macro, imp))
break;
}
if (saveOutput && !outputPath.equals("")) {
if (format.equals("8-bit TIFF") || format.equals("GIF")) {
if (imp.getBitDepth()==24)
IJ.run(imp, "8-bit Color", "number=256");
else
IJ.run(imp, "8-bit", "");
}
if (outputImage!=null && outputImage!=imp)
IJ.saveAs(outputImage, format, outputPath+list[i]);
else
IJ.saveAs(imp, format, outputPath+list[i]);
}
saveOutput = true;
imp.close();
}
}
private boolean runMacro(String macro, ImagePlus imp) {
WindowManager.setTempCurrentImage(imp);
Interpreter interp = new Interpreter();
try {
outputImage = interp.runBatchMacro(macro, imp);
} catch(Throwable e) {
interp.abortMacro();
String msg = e.getMessage();
if (!(e instanceof RuntimeException && msg!=null && e.getMessage().equals(Macro.MACRO_CANCELED)))
IJ.handleException(e);
return false;
} finally {
WindowManager.setTempCurrentImage(null);
}
return true;
}
String addSeparator(String path) {
if (path.equals("")) return path;
if (!(path.endsWith("/")||path.endsWith("\\")))
path = path + File.separator;
return path;
}
void validateFormat() {
boolean validFormat = false;
for (int i=0; i 0)
sb.append(b,0, n);
macro = sb.toString();
}
catch (IOException e) {
return null;
}
return macro;
}
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
if (source==input) {
String path = IJ.getDirectory("Input Folder");
if (path==null) return;
inputDir.setText(path);
} else if (source==output) {
String path = IJ.getDirectory("Output Folder");
if (path==null) return;
outputDir.setText(path);
} else if (source==test) {
thread = new Thread(this, "BatchTest");
thread.setPriority(Math.max(thread.getPriority()-2, Thread.MIN_PRIORITY));
thread.start();
} else if (source==open)
open();
else if (source==save)
save();
}
void open() {
String text = IJ.openAsString("");
if (text==null) return;
if (text.startsWith("Error: "))
error(text.substring(7));
else {
if (text.length()>30000)
error("File is too large");
else
gd.getTextArea1().setText(text);
}
}
void save() {
macro = gd.getTextArea1().getText();
if (!macro.equals(""))
IJ.saveString(macro, "");
}
void error(String msg) {
IJ.error("Batch Processor", msg);
}
public void run() {
TextArea ta = gd.getTextArea1();
//ta.selectAll();
String macro = ta.getText();
if (macro.equals("")) {
error("There is no macro code in the text area");
return;
}
ImagePlus imp = null;
IJ.redirectErrorMessages(true);
if (virtualStack!=null)
imp = getVirtualStackImage();
else
imp = getFolderImage();
IJ.redirectErrorMessages(false);
if (imp==null) {
if (!errorDisplayed)
IJ.log("IJ.openImage() returned null");
return;
}
runMacro("i=0;"+macro, imp);
Point loc = new Point(10, 30);
if (testImage!=0) {
ImagePlus imp2 = WindowManager.getImage(testImage);
if (imp2!=null) {
ImageWindow win = imp2.getWindow();
if (win!=null) loc = win.getLocation();
imp2.changes=false;
imp2.close();
}
}
imp.show();
ImageWindow iw = imp.getWindow();
if (iw!=null) iw.setLocation(loc);
testImage = imp.getID();
}
ImagePlus getVirtualStackImage() {
ImagePlus imp = virtualStack.createImagePlus();
imp.setProcessor("", virtualStack.getProcessor().duplicate());
return imp;
}
ImagePlus getFolderImage() {
String inputPath = inputDir.getText();
inputPath = addSeparator(inputPath);
File f1 = new File(inputPath);
if (!f1.exists() || !f1.isDirectory()) {
error("Input does not exist or is not a folder\n \n"+inputPath);
errorDisplayed = true;
return null;
}
String[] list = (new File(inputPath)).list();
String name = list[0];
if (name.startsWith(".")&&list.length>1) name = list[1];
String path = inputPath + name;
setDirAndName(path);
return IJ.openImage(path);
}
void setDirAndName(String path) {
File f = new File(path);
OpenDialog.setLastDirectory(f.getParent()+File.separator);
OpenDialog.setLastName(f.getName());
}
public static void saveOutput(boolean b) {
saveOutput = b;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy