package edu.mbl.jif.imagej;
//import edu.mbl.jif.imaging.ImgInfoDumper;
import ij.ImagePlus;
import ij.ImageStack;
import ij.measure.Calibration;
import ij.process.ByteProcessor;
import ij.process.ColorProcessor;
import ij.process.FloatProcessor;
import ij.process.ImageProcessor;
import ij.process.ImageStatistics;
import ij.process.ShortProcessor;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferDouble;
import java.awt.image.DataBufferFloat;
import java.awt.image.DataBufferInt;
import java.awt.image.DataBufferShort;
import java.awt.image.DataBufferUShort;
import java.awt.image.IndexColorModel;
import java.awt.image.RenderedImage;
import java.awt.image.SampleModel;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import javax.swing.SwingUtilities;
import org.dart.imagej.IJClient;
import org.dart.imagej.IJClientFactory;
public class IJTools {
public static void main(String[] args) {
// //copyFiles();
// setWorkingDir("");
//
// invokeImageJ();
}
private static void setWorkingDir(String dir) {
String workDir = System.getProperty("user.dir");
System.out.println("WorkDir=" + workDir);
//System.setProperty("user.dir", dir);
}
public static void copyFiles() {
String from = "";
String to = "";
try {
copyFile(from, to, true);
} catch (IOException ex) {
ex.printStackTrace();
}
}
// === Open ImageJ =========================================================
public static void invokeImageJ() {
dispatchToEDT(new Runnable() {
public void run() {
openImageJ();
}
});
}
public static void openImageJ() {
IJClient ijClient = IJClientFactory.getIJClient(false);
// ImageJ ij = IJ.getInstance();
// if ((ij == null) || ((ij != null) && !ij.isShowing())) {
// if (IJ.isMacOSX()) {
// System.setProperty("com.apple.mrj.application.growbox.intrudes", "true");
// ij = new ImageJ(null);
// System.setProperty("com.apple.mrj.application.growbox.intrudes", "false");
// } else {
// ij = new ImageJ(null);
// }
// }
// if (ij != null) {
// ij.setVisible(true);
// }
}
public static void dispatchToEDT(Runnable runnable) {
if (!SwingUtilities.isEventDispatchThread()) {
try {
SwingUtilities.invokeAndWait(runnable);
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
runnable.run();
}
}
// Make ImageJ stack from array of BufferedImages
public static ImagePlus makeStack(String name, BufferedImage[] rImage) {
ImagePlus imp = null;
if (name == null) {
name = "None";
}
if (rImage.length >= 1) {
ImageStack stack = new ImageStack(rImage[0].getWidth(), rImage[0].getHeight());
for (int i = 0; i < (rImage.length); i++) {
DataBuffer dBuff = rImage[i].getData().getDataBuffer();
ColorModel cm = rImage[i].getColorModel();
try {
ImageProcessor ip = createProcessor(rImage[i].getWidth(),
rImage[i].getHeight(), dBuff, cm);
stack.addSlice(String.valueOf(i - 1), ip);
} catch (Exception ex) {
ex.printStackTrace();
}
//stack.addSlice();
}
if (stack == null) {
return null;
}
if (stack.getSize() == 0) {
return null;
}
imp = new ImagePlus(name, stack);
} else { // single image
imp = new ImagePlus(name, (Image) rImage[0]);
}
imp.show();
// setResolution(fi, imp);
return imp;
}
// Make ImageJ stack from array of RenderedImages
public static ImagePlus makeStack(String name, RenderedImage[] rImage) {
Object pixels = null;
ImagePlus imp = null;
if (name == null) {
name = "None";
}
if (rImage.length > 1) {
ImageStack stack = new ImageStack(rImage[0].getWidth(), rImage[0].getHeight());
for (int i = 0; i < (rImage.length); i++) {
DataBuffer dBuff = rImage[i].getData().getDataBuffer();
ColorModel cm = rImage[i].getColorModel();
try {
ImageProcessor ip = createProcessor(rImage[i].getWidth(),
rImage[i].getHeight(), dBuff, cm);
stack.addSlice(String.valueOf(i - 1), ip);
} catch (Exception ex) {
ex.printStackTrace();
}
//stack.addSlice();
}
if (stack == null) {
return null;
}
if (stack.getSize() == 0) {
return null;
}
imp = new ImagePlus(name, stack);
} else { // single image
imp = new ImagePlus(name, (Image) rImage[0]);
}
imp.show();
// setResolution(fi, imp);
return imp;
}
//
//---------------------------------------------------------------------
public static ImagePlus makeImagePlus(String name, java.awt.Image awtImage) {
ImagePlus iPlus = new ImagePlus(name, awtImage);
ByteProcessor ip = (ByteProcessor) iPlus.getProcessor();
return iPlus;
// ImagePlus createBtyeImage(title, w, h, slices, fill)
}
//
//---------------------------------------------------------------------------
public static double[] getLinePixels(String name, java.awt.Image awtImage, Rectangle roi) {
ImagePlus iPlus = new ImagePlus(name, awtImage);
ByteProcessor ip = (ByteProcessor) iPlus.getProcessor();
return ip.getLine((double) roi.getX(), (double) (roi.getX() + roi.getWidth()),
(double) roi.getY(), (double) (roi.getY() + roi.getHeight()));
}
//===========================================================================
/**
* Create an ImageProcessor object from a DataBuffer.
*
* @param w Image width.
* @param h Image height.
* @param buffer Data buffer.
* @param cm Color model.
* @return Image processor object.
* @exception Exception If data buffer is in unknown format.
* From ijImageIO
*/
public static ImageProcessor createProcessor(int w, int h, DataBuffer buffer, ColorModel cm)
throws Exception {
if (buffer.getOffset() != 0) {
throw new Exception("Expecting BufferData with no offset.");
}
switch (buffer.getDataType()) {
case DataBuffer.TYPE_BYTE:
return new ByteProcessor(w, h, ((DataBufferByte) buffer).getData(), cm);
case DataBuffer.TYPE_USHORT:
return new ShortProcessor(w, h, ((DataBufferUShort) buffer).getData(), cm);
case DataBuffer.TYPE_SHORT:
short[] pixels = ((DataBufferShort) buffer).getData();
for (int i = 0; i < pixels.length; ++i) {
pixels[i] = (short) (pixels[i] + 32768);
}
return new ShortProcessor(w, h, pixels, cm);
case DataBuffer.TYPE_INT:
return new FloatProcessor(w, h, ((DataBufferInt) buffer).getData());
case DataBuffer.TYPE_FLOAT: {
DataBufferFloat dbFloat = (DataBufferFloat) buffer;
return new FloatProcessor(w, h, dbFloat.getData(), cm);
}
case DataBuffer.TYPE_DOUBLE:
return new FloatProcessor(w, h, ((DataBufferDouble) buffer).getData());
case DataBuffer.TYPE_UNDEFINED:
throw new Exception("Pixel type is undefined.");
default:
throw new Exception("Unrecognized DataBuffer data type");
}
}
//===========================================================================
public static ImagePlus[] makeImagePlusArray(BufferedImage[] imageArray, String title)
throws Exception {
// Get number of sub images
int nbPages = imageArray.length;
if (nbPages < 1) {
throw new Exception("Image decoding problem. " +
"Image file has less then 1 page. Nothing to decode.");
}
// Iterate through pages
ArrayList imageList = new ArrayList();
for (int i = 0; i < nbPages; ++i) {
imageList.add(create(imageArray[i].getRaster(), null, "Something"));
}
ImagePlus[] images = (ImagePlus[]) imageList.toArray(new ImagePlus[imageList.size()]);
if (nbPages == 1) {
// Do not use page numbers in image name
images[0].setTitle(title);
} else {
// Attempt to combine images into a single stack.
ImagePlus im = combineImages(images);
if (im != null) {
im.setTitle(title);
images = new ImagePlus[1];
images[0] = im;
}
}
return images;
}
/**
* Attempt to combine images into a single stack. Images can be combined into
* a stack if all of them are single slice images of the same type and
* dimensions.
* @param images Array of images.
* @return Input images combined into a stack. Return null if images
* cannot be combined.
*/
public static ImagePlus combineImages(ImagePlus[] images) {
if ((images == null) || (images.length <= 1)) {
return null;
}
if (images[0].getStackSize() != 1) {
return null;
}
int fileType = images[0].getFileInfo().fileType;
int w = images[0].getWidth();
int h = images[0].getHeight();
ImageStack stack = images[0].getStack();
for (int i = 1; i < images.length; ++i) {
ImagePlus im = images[i];
if (im.getStackSize() != 1) {
return null;
}
if ((fileType == im.getFileInfo().fileType) && (w == im.getWidth()) &&
(h == im.getHeight())) {
stack.addSlice(null, im.getProcessor().getPixels());
} else {
return null;
}
}
images[0].setStack(images[0].getTitle(), stack);
return images[0];
}
/**
* Create instance of ImagePlus from WritableRaster r and ColorModel cm.
*
* @param r Raster containing pixel data.
* @param cm Image color model (can be null).
* @return ImagePlus object created from WritableRaster r and
* ColorModel cm
* @exception Exception when enable to create ImagePlus.
*/
public static ImagePlus create(WritableRaster r, ColorModel cm, String title)
throws Exception {
DataBuffer db = r.getDataBuffer();
int numBanks = db.getNumBanks();
if ((numBanks > 1) && (cm == null)) {
throw new Exception("Don't know what to do with image with no " +
"color model and multiple banks.");
}
SampleModel sm = r.getSampleModel();
int dbType = db.getDataType();
if ((numBanks > 1) || (sm.getNumBands() > 1)) {
// If image has multiple banks or multiple color components, assume that it
// is a color image and relay on AWT for proper decoding.
BufferedImage bi = new BufferedImage(cm, r, false, null);
return new ImagePlus(null, new ColorProcessor((Image) bi));
} else if (sm.getSampleSize(0) < 8) {
// Temporary fix for less then 8 bit images
BufferedImage bi = new BufferedImage(cm, r, false, null);
return new ImagePlus(null, new ByteProcessor((Image) bi));
} else {
if (!(cm instanceof IndexColorModel)) {
// Image/J (as of version 1.26r) can not properly deal with non color
// images and ColorModel that is not an instance of IndexedColorModel.
cm = null;
}
ImageProcessor ip = createProcessor(r.getWidth(), r.getHeight(), r.getDataBuffer(), cm);
ImagePlus im = new ImagePlus(title, ip);
// Add calibration function for 'short' pixels
if (db.getDataType() == DataBuffer.TYPE_SHORT) {
Calibration cal = new Calibration(im);
double[] coeff = new double[2];
coeff[0] = -32768.0;
coeff[1] = 1.0;
cal.setFunction(Calibration.STRAIGHT_LINE, coeff, "gray value");
im.setCalibration(cal);
} else if (cm == null) {
Calibration cal = im.getCalibration();
im.setCalibration(null);
ImageStatistics stats = im.getStatistics();
im.setCalibration(cal);
ip.setMinAndMax(stats.min, stats.max);
im.updateImage();
}
return im;
}
}
public static void test() {
/** @todo test with short and float */
// BufferedImage bi = edu.mbl.jif.imaging.ImageFactoryGrayScale.testImageByte();
// System.out.println(ImgInfoDumper.dump(bi));
// ImagePlus iPlus = new ImagePlus("NewImagePlus", bi); // makes an RGB
// iPlus.show();
// try {
// ImagePlus iPlus2 = create(bi.getRaster(), bi.getColorModel(), "create");
// iPlus2.show();
// } catch (Exception ex) {
// ex.printStackTrace();
// }
// int n = 6;
// BufferedImage[] biArray = new BufferedImage[n];
// for (int i = 0; i < n; i++) {
// biArray[i] = edu.mbl.jif.imaging.ImageFactoryGrayScale.testImageByte();
// }
// ImagePlus[] iPlusArray = new ImagePlus[n];
// for (int i = 0; i < n; i++) {
// try {
// iPlusArray[i] = create(biArray[i].getRaster(), biArray[i].getColorModel(),
// "slice " + String.valueOf(i));
// iPlusArray[i].show();
// } catch (Exception ex) {
// ex.printStackTrace();
// }
// }
//
// // Combine the images into a stack
// ImagePlus iPlusStack = combineImages(iPlusArray);
// iPlusStack.show();
}
// --------------------------- Copy File -------------------------------------
/**
* Copies a file to another location/file
* Returns true if file copied or
* false if not (possibly the file existed and 'overwrite' was not set).
*/
public static boolean copyFile(String fromName, String toName, boolean overwrite)
throws IOException {
if (fromName == null) {
throw new IOException("source filename is null!");
}
if (toName == null) {
throw new IOException("destination filename is null!");
}
File fromFile = new File(fromName);
File toFile = new File(toName);
return (copyFile(fromFile, toFile, overwrite));
}
/**
* Copies a file to another location/file
* Returns true if file copied or
* false if not (possibly the file existed and 'overwrite' was not set).
*/
public static boolean copyFile(File fromFile, File toFile, boolean overwrite)
throws IOException {
final int IO_BUF_SIZE = 1024 * 32;
if (fromFile == null) {
throw new IOException("source file is null!");
}
if (toFile == null) {
throw new IOException("destination file is null!");
}
// make sure that source file exists
if (!fromFile.exists()) {
throw new IOException("no such source file: " + fromFile.getAbsoluteFile());
}
if (!fromFile.isFile()) {
throw new IOException("can't copy directory: " + fromFile.getAbsoluteFile());
}
if (!fromFile.canRead()) {
throw new IOException("source file is unreadable: " + fromFile.getAbsoluteFile());
}
if (toFile.isDirectory()) {
toFile = new File(toFile, fromFile.getName());
}
if (toFile.exists()) {
if (!toFile.canWrite()) {
throw new IOException("destination file is unwriteable: " +
toFile.getAbsoluteFile());
}
// check if we should overwrite it
if (!overwrite) {
return (false);
}
} else {
// if the file dosn't exist, check if the directory exists and is
// writeable. If getParent() returns null, then the directory is the
// current dir. so look up the user.dir system property to find out
// what that is.
String parent = toFile.getParent(); // the destination dir
if (parent == null) { // if none use the current dir
parent = System.getProperty("user.dir");
}
File dir = new File(parent); // convert it to a file
if (!dir.exists()) {
throw new IOException("destination directory doesn't exist: " + parent);
}
if (dir.isFile()) {
throw new IOException("destination is not a directory: " + parent);
}
if (!dir.canWrite()) {
throw new IOException("destination directory is unwritable: " + parent);
}
}
// if we've gotten this far then everything is ok
// so we copy the file one buffer of bytes at a time
FileInputStream from = null; // Stream to read from source
FileOutputStream to = null; // Stream to write to destination
try {
from = new FileInputStream(fromFile); // Create input stream
to = new FileOutputStream(toFile); // Create output stream
byte[] buffer = new byte[IO_BUF_SIZE]; // to hold file data
int bytesRead;
// read a chunk of bytes into the buffer then write them out
// looping until we reach the EOF (when read() returns -1)
// Note the combination of assignment and comparison in this
// while loop. This is a common I/O programming idiom.
while ((bytesRead = from.read(buffer)) != -1) { // read until EOF
to.write(buffer, 0, bytesRead); // write
}
} catch (IOException e) {
throw (e);
} finally {
if (from != null) {
try {
from.close();
} catch (IOException ignored) {
}
}
if (to != null) {
try {
to.close();
} catch (IOException ignored) {
}
}
}
return (true);
}
}