/*
* ImageProcessorOJ.java
*
* manages linked images in the project window, such as adding, deleting, and updating properties of linked images
*
*/
package oj.processor;
import ij.IJ;
import ij.ImagePlus;
import ij.WindowManager;
import ij.gui.GenericDialog;
import ij.gui.ImageCanvas;
import ij.gui.ImageLayout;
import ij.gui.ImageWindow;
import ij.gui.StackWindow;
import ij.io.FileInfo;
import ij.io.FileOpener;
import ij.io.Opener;
import ij.measure.Calibration;
import java.awt.Frame;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import oj.OJ;
import oj.util.UtilsOJ;
import oj.project.ImageOJ;
import oj.graphics.CustomCanvasOJ;
import oj.gui.MenuManagerOJ;
import oj.gui.MouseEventManagerOJ;
import oj.processor.events.CellChangedListenerOJ;
import oj.processor.events.ImageChangedEventOJ;
import oj.processor.events.ImageChangedListener2OJ;
import oj.processor.events.YtemChangedListenerOJ;
import oj.processor.events.YtemDefChangedListenerOJ;
import oj.project.ImagesOJ;
import oj.util.ImageJAccessOJ;
import oj.util.ImageWindowUtilsOJ;
import oj.util.TiffFileInfoOJ;
public class ImageProcessorOJ implements ImageChangedListener2OJ, DropTargetListener {
private Hashtable openedImages = new Hashtable();//ImageOJ <-> Name
public ImageProcessorOJ() {
OJ.getEventProcessor().addImageChangedListener(this);
}
public void closeImage(String name) {
ImageWindow imgw = getOpenLinkedImageWindow(name);
if (imgw != null) {
imgw.close();
removeFromOpenedImages(name);
}
}
/* not used, does not work*/
private String resolveAlias(String dir, String fName) {
File f = new File(dir, fName);
String fullpath = f.getPath();
File f2 = new File(fullpath);
try {
String path = f2.getCanonicalPath();
return path;
} catch (IOException e) {
return "An error occured while resolving alias";
}
}
public void openImage(String imageName) {
//check for the file in the project directory
ImageOJ imageOJ = OJ.getData().getImages().getImageByName(imageName);
if (imageOJ != null) {
if (!isInProjectDir(imageOJ.getFilename())) {
String msg = "The selected image \n\"" + imageName + "\" \nwas not found in the project directory.";//8.7.2009
if (ij.IJ.isMacro()) {
ImageJAccessOJ.InterpreterAccess.interpError(msg);
return;
} else {
GenericDialog gd = new GenericDialog("Linked Images");
gd.addMessage(msg);
if (ij.IJ.isMacintosh()) {
gd.setOKLabel("Bring Project Folder to Front");
} else if (ij.IJ.isWindows()) {
gd.setOKLabel("Bring Project Folder to Front");
} else {
ij.IJ.error(msg);
}
gd.showDialog();
if (!gd.wasCanceled()) {
UtilsOJ.showInFinderOrExplorer();
}
}
return;
}
if (!checkForOpenOJ(imageName)) {
ImagePlus imp = checkForOpenIJ(imageName);
if (imp == null) {
String dir = OJ.getData().getDirectory();
String fName = imageOJ.getFilename();
//String resolvedPath = resolveAlias(dir, fName);
//dir = new Opener().getDir(resolvedPath);
//fName = new Opener().getName(resolvedPath);
imp = new Opener().openImage(dir, fName);
}
Calibration cal = imp.getCalibration();//10.7.2009
if (cal.pixelHeight == 1 && cal.pixelWidth == 1) {
if ((imageOJ.getVoxelSizeX() != 1 || imageOJ.getVoxelSizeY() != 1)) {
cal.pixelWidth = imageOJ.getVoxelSizeX();
cal.pixelHeight = imageOJ.getVoxelSizeY();
cal.setUnit(imageOJ.getVoxelUnitX());
imp.setCalibration(cal);
} else {
imageOJ.setVoxelSizeX(cal.pixelWidth);
imageOJ.setVoxelSizeY(cal.pixelHeight);
}
}
ImageJAccessOJ.ImagePlusAccess.notifyImagePlusOpened(imp);
MenuManagerOJ.getInstance().imageOpened(imageName);
} else {
getOpenLinkedImageWindow(imageName).setExtendedState(Frame.NORMAL);
getOpenLinkedImageWindow(imageName).toFront();
}
} else {
IJ.showMessage("The selected image \"" + imageName + "\" doe not exist.");
}
}
/**
* the function links an image already opened in the ImageJ
* @param imp the image opened by the ImageJ
*/
public void addImage(ImagePlus imp) {
if (imp != null) {
//check for the file in the project directory
String fileName = imp.getTitle();
String imageName = fileName;
if (!isInProjectDir(fileName)) {
IJ.showMessage("Error: Image \"" + imageName + "\" is not saved in the project directory.");
return;
}
//check if the image is already linked
boolean showChangeMessage = true;
if (isLinked(imageName)) {
IJ.showMessage("Image \"" + imageName + "\" is already linked.");
if (!checkForOpenOJ(imageName)) {
applyImageGraphics(imp, OJ.getData().getImages().getImageByName(imageName), showChangeMessage);
MenuManagerOJ.getInstance().imageOpened(imageName);
} else {
/*ImageManagerOJ.getInstance().*/ getOpenLinkedImageWindow(imageName).setExtendedState(Frame.NORMAL);
/*ImageManagerOJ.getInstance().*/ getOpenLinkedImageWindow(imageName).toFront();
}
return;
} else {
ImageOJ imj = OJ.getData().getImages().getImageByName(imageName);
if (imj == null) {
imp.setTitle(fileName);
imj =
new ImageOJ(imageName, /*fileName,*/ imp.getID());//27.8.2010
updateImageProperties(OJ.getData().getDirectory(), imj);
OJ.getData().getImages().addImage(imj);
}
applyImageGraphics(imp, imj, showChangeMessage);
MenuManagerOJ.getInstance().imageOpened(imageName);
}
}
}
/**
* Links all images in the projct folder. Does not go into subfoldeers, and
* does not link .zip, .mov or .avi
*/
public void linkAllImages() {
File projectDirectory = new File(OJ.getData().getDirectory());
File[] files = projectDirectory.listFiles();
int nFiles = files.length;
for (int jj = 0; jj
< nFiles; jj++) {
ij.IJ.showProgress(jj, nFiles);
ij.IJ.showStatus("" + jj + "/" + nFiles);
File file = files[jj];
String name = file.getName().toLowerCase();
boolean bad = (file.isDirectory());
bad =
bad || file.isHidden();
bad =
bad || name.endsWith(".avi");
bad =
bad || name.endsWith(".mov");
bad =
bad || name.endsWith(".zip");
if (!bad) {
addImage(files[jj].getName(), false, false);
}
}
int count = OJ.getData().getImages().getImagesCount();
ij.IJ.showStatus("" + count + " images are linked");
}
/**
* the function links an image after a drag and drop action
* @param imageName the name of the image dropped on the application
*/
public void addImage(String fileName, boolean shouldOpen, boolean showAlreadyLinkedMessage) {
String imageName = fileName;
//check for the file in the project directory
boolean valid = isInProjectDir(fileName);//23.2.2010 wrong message when it is a directory
if (!valid) {
String msg = "Before linking image \n \"" + imageName + "\"\n to the project, you need to move it to the project folder.";
GenericDialog gd = new GenericDialog("Linked Images");
gd.addMessage(msg);
if (ij.IJ.isMacintosh()) {
gd.setOKLabel("Bring Project Folder to Front");
} else if (ij.IJ.isWindows()) {
gd.setOKLabel("Bring Project Folder to Front");
} else {
ij.IJ.error(msg);
}
gd.showDialog();
if (!gd.wasCanceled()) {
UtilsOJ.showInFinderOrExplorer();
}
return;
}
//check if the image is already linked
if (isLinked(imageName)) {
if (showAlreadyLinkedMessage) {
IJ.showMessage("This is already linked to the project.");
}
if (!checkForOpenOJ(imageName)) {
} else {
getOpenLinkedImageWindow(imageName).setExtendedState(Frame.NORMAL);
getOpenLinkedImageWindow(imageName).toFront();
}
return;
} else {
File file = new File(OJ.getData().getDirectory(), fileName);
ImagePlus imp = new Opener().openImage(file.getAbsolutePath());
if (imp != null) {
ImageOJ imj = OJ.getData().getImages().getImageByName(imageName);
if (imj == null) {
imp.setTitle(fileName);
int ID = imp.getID();
imj = new ImageOJ(imageName, /*fileName, */ ID);//27.8.2010
updateImageProperties(OJ.getData().getDirectory(), imj);
OJ.getData().getImages().addImage(imj);
}
if (shouldOpen) {
ImageJAccessOJ.ImagePlusAccess.notifyImagePlusOpened(imp);
MenuManagerOJ.getInstance().imageOpened(imageName);
}
}
}
}
private boolean isInProjectDir(String imageName) {
String dir = OJ.getData().getDirectory();
File file = new File(dir, imageName);
return (file.exists() && file.isFile() && !file.isHidden());
}
private boolean isLinked(String imageName) {//true if name is among linked images
return OJ.getData().getImages().getImageByName(imageName) != null;
}
private boolean checkForOpenOJ(String imageName) {//true if
return getOpenLinkedImageWindow(imageName) != null;
}
private ImagePlus checkForOpenIJ(String imageName) {
ImagePlus imp = WindowManager.getImage(imageName);
if (imp != null) {
if (imp.getOriginalFileInfo() == null) {
return null;
}
String dir = imp.getOriginalFileInfo().directory;
if (dir == null) {
return null;
}
File imageDirectory = new File(imp.getOriginalFileInfo().directory);
File projectDirectory = new File(OJ.getData().getDirectory());
if ((imp != null) && (projectDirectory.equals(imageDirectory))) {
return imp;
}
}
return null;
}
public void applyImageGraphics(ImagePlus imp, ImageOJ imOj, boolean showChangeMessage) {
if (imp == null) {
IJ.showMessage("Error", "ImageProcessorOJ.applyImageGraphics failed. The ImagePlus is null.");
return;
}
if (imOj == null) {
IJ.showMessage("Error", "ImageProcessorOJ.applyImageGraphics failed. The ImageOJ is null.");
return;
}
CustomCanvasOJ cc = new CustomCanvasOJ(imp, OJ.getData(), imOj.getName());
if ((imp.getNSlices() != imOj.getNumberOfSlices()) || (imp.getNFrames() != imOj.getNumberOfFrames()) || (imp.getNChannels() != imOj.getNumberOfChannels())) {
if (showChangeMessage) {
IJ.showMessage("There are differences in image properties (slices, frames and channels count) and project data. Project data are now adjusted");
}
int slices = imp.getNSlices();
imOj.setNumberOfSlices(slices);
int frames = imp.getNFrames();
imOj.setNumberOfFrames(frames);
int channels = imp.getNChannels();
imOj.setNumberOfChannels(channels);
}
ImageCanvas ic = imp.getCanvas();
cc.updateCanvas(ic, imp);
ImageWindow imgw = imp.getWindow();
if (imgw == null) {
if (imp.getStackSize() > 1) {
//IJ.log("creating a new StackWindow");//14.11.2008
imgw = new StackWindow(imp, cc);
} else {
imgw = new ImageWindow(imp, cc);
}
} else {
ImageWindowUtilsOJ.setImageCanvas(imgw, cc);
imgw.remove(ic);
imgw.setLayout(new ImageLayout(cc));
if (imgw instanceof StackWindow) {
imgw.add(cc, 0);
} else {
imgw.add(cc);
}
imgw.validate();
}
MouseEventManagerOJ.getInstance().replaceMouseListener(imp);
/*ImageManagerOJ.getInstance().*/ //addToOpenedImages(imgw);
imp.getWindow().getComponent(0).requestFocus();
imp.setTitle(imOj.getName());
addToOpenedImages(imgw);//13.10.2010
}
public void applyImageProperties(ImagePlus imp, ImageOJ imoj) {
//set image size
imoj.setWidth(imp.getWidth());
imoj.setHeight(imp.getHeight());
imoj.setNumberOfSlices(imp.getNSlices());
imoj.setNumberOfFrames(imp.getNFrames());
imoj.setNumberOfChannels(imp.getNChannels());
//set image calibration
String unit = imp.getCalibration().getUnit();
if (unit.equals(IJ.micronSymbol + "m")) {
unit = "um";
} else if (unit.equals("" + IJ.angstromSymbol)) {
unit = "A";
}
imoj.setVoxelUnitX(unit);
imoj.setVoxelUnitY(unit);
imoj.setVoxelUnitZ(unit);
imoj.setVoxelSizeX(imp.getCalibration().pixelWidth);
imoj.setVoxelSizeY(imp.getCalibration().pixelHeight);
imoj.setVoxelSizeZ(imp.getCalibration().pixelDepth);
//set frame settings
imoj.setFrameInterval((int) imp.getCalibration().frameInterval);
imoj.setFrameRateUnit(imp.getCalibration().getTimeUnit());
}
public static String extractImageName(
String filename) {
if (filename != null) {
int index = filename.lastIndexOf(".");
if (index > 0) {
return filename.substring(0, index);
} else {
return filename;
}
} else {
return null;
}
}
public static ImageWindow getCurrentImage() {
ImagePlus imp = IJ.getImage();
if (imp != null) {
return imp.getWindow();
} else {
return null;
}
}
public static boolean isFrontImageLinked() {
//ImagePlus imp = IJ.getImage();
ImagePlus imp = WindowManager.getCurrentImage();
if (imp == null) {
return false;
}
String title = imp.getTitle();
FileInfo fileInfo = imp.getOriginalFileInfo();
if (fileInfo == null) {
return false;
}
String dir = fileInfo.directory;
if (!oj.OJ.getData().getDirectory().equals(dir)) {
return false;
}
ImagesOJ images = OJ.getData().getImages();
int index = images.getIndexOfImage(title);
if (index == -1) {
return false;
}
return true;
}
static String getCurrentImageName() {
ImagePlus imp = IJ.getImage();
if (imp != null) {
// return ImageProcessorOJ.extractImageName(imp.getTitle());
return imp.getTitle();
} else {
return null;
}
}
public void imageChanged(ImageChangedEventOJ evt) {
if (evt.getOperation() == ImageChangedEventOJ.IMAGE_DELETED) {
closeImage(evt.getName());
}
}
public void applyImageMarkers() {
for (int i = 0; i
< OJ.getData().getImages().getImagesCount(); i++) {
ImageOJ imj = OJ.getData().getImages().getImageByIndex(i);
ImagePlus imp = checkForOpenIJ(imj.getName());
boolean showChangeMessage = true;
if (imp != null) {
applyImageGraphics(imp, imj, showChangeMessage);
}
}
}
public void updateImagesProperties() {
String dirname = OJ.getData().getDirectory();
for (int i = 0; i
< OJ.getData().getImages().getImagesCount(); i++) {
ImageOJ image = OJ.getData().getImages().getImageByIndex(i);
updateImageProperties(dirname, image);
}
}
/**
* if image is open, image properties are copied to ImageOJ.
* if image is not open and it is TIF, tiff properties are read from disk and
* copied to ImageOJ.
* otherwise nothing happens.
* Why do we need all this?
*/
public void updateImageProperties(String directory, ImageOJ image) {
ImagePlus imp = WindowManager.getImage(image.getName());
if (imp != null) {
applyImageProperties(imp, image);
OJ.getEventProcessor().fireImageChangedEvent(image.getName(), ImageChangedEventOJ.IMAGE_EDITED);
} else {//disabled 4.9.2010
String filename = image.getFilename();
File file = new File(directory, filename);
if (file.exists() && true) {//9.4.2004
TiffFileInfoOJ tiffInfoDecoder = new TiffFileInfoOJ(directory, filename);
FileInfo fileInfo = tiffInfoDecoder.getTiffFileInfo();
if (fileInfo != null) {
applyImageProperties(fileInfo, image);
OJ.getEventProcessor().fireImageChangedEvent(image.getName(), ImageChangedEventOJ.IMAGE_EDITED);
}
}
}
}
private void applyImageProperties(FileInfo fileInfo, ImageOJ image) {
//should be a static method
Properties props = new FileOpener(fileInfo).decodeDescriptionString(fileInfo);
image.setWidth(fileInfo.width);
image.setHeight(fileInfo.height);
image.setVoxelSizeX(((double) ((int) (fileInfo.pixelWidth * 1E6))) / 1E6);
image.setVoxelSizeY(((double) ((int) (fileInfo.pixelHeight * 1E6))) / 1E6);
image.setVoxelSizeZ(((double) ((int) (fileInfo.pixelDepth * 1E6))) / 1E6);
image.setVoxelUnitX((fileInfo.unit != null) ? fileInfo.unit : "");
image.setVoxelUnitY((fileInfo.unit != null) ? fileInfo.unit : "");
image.setVoxelUnitZ((fileInfo.unit != null) ? fileInfo.unit : "");
//n_3.3.2009
image.setNumberOfSlices(1);
image.setNumberOfFrames(1);
image.setNumberOfChannels(1);
if (props != null) {//n_3.3.2009
image.setNumberOfSlices(getInteger(props, "slices") == 0 ? 1 : getInteger(props, "slices"));
image.setNumberOfFrames(getInteger(props, "frames") == 0 ? 1 : getInteger(props, "frames"));
image.setNumberOfChannels(getInteger(props, "channels") == 0 ? 1 : getInteger(props, "channels"));
//set frame settings
image.setFrameInterval(getInteger(props, "finterval"));
image.setFrameRateUnit(props.getProperty("tunit", "sec"));
}
//set image type
//image.setImageType(fileInfo.fileFormat); 8.3.2010 removed
//image.setFileType(fileInfo.fileType);
image.setChanged(false);
OJ.getData().getResults().recalculate();
}
private Double getNumber(Properties props, String key) {
String s = props.getProperty(key);
if (s != null) {
try {
return Double.valueOf(s);
} catch (NumberFormatException e) {
}
}
return null;
}
private int getInteger(Properties props, String key) {
Double n = getNumber(props, key);
return n != null ? n.intValue() : 0;
}
private double getDouble(Properties props, String key) {
Double n = getNumber(props, key);
return n != null ? n.doubleValue() : 0.0;
}
private boolean getBoolean(Properties props, String key) {
String s = props.getProperty(key);
return s != null && s.equals("true") ? true : false;
}
//private static ImageManagerOJ instance;
/**
* add an image name to the list of linked images
*/
public void addToOpenedImages(ImageWindow imgw) {
//FileInfo fInfo = imgw.getImagePlus().getFileInfo();//13.10.2010
String fName = imgw.getTitle();
//fInfo.fileName;
openedImages.put(fName, imgw);
}
/**
* @return link index of current window, or -1 if it is not linked
*/
public int getCurrentImageIndex() {
ImageWindow imgw = WindowManager.getCurrentWindow();
if (imgw != null) {
ImagePlus imp = imgw.getImagePlus();
String name = imp.getTitle();
FileInfo fInfo = imp.getOriginalFileInfo();//24.10.2010
String projectDir = OJ.getData().getDirectory();
if (fInfo != null && fInfo.directory == projectDir) {//26.9.2010
ImageOJ img = OJ.getData().getImages().getImageByName(name);
if (img != null) {
for (int i = 0; i < OJ.getData().getImages().getImagesCount(); i++) {
if (OJ.getData().getImages().getImageByIndex(i).getName().equals(name)) {
return i;
}
}
}
}
}
return -1;
}
/**
* @param name
* @return linked ImageWindow with this name, or null if not found
*/
// public ImageWindow getImageWindowOld(String name) {//19.10.2010
// if (openedImages.containsKey(name)) {
// return (ImageWindow) openedImages.get(name);
// }
// return null;
// }
public ImageWindow getOpenLinkedImageWindow(String name) {
ImagePlus imp = getOpenLinkedImage(name);
if (imp != null) {
return imp.getWindow();
}
return null;
}
//get linked imp with that name, or null if it is not open
public ImagePlus getOpenLinkedImage(String name) {//test 19.10.2010
int[] openImgs = WindowManager.getIDList();
if (openImgs != null) {
for (int jj = 0; jj < openImgs.length; jj++) {
int id = openImgs[jj];
ImagePlus imp = WindowManager.getImage(id);
FileInfo fInfo = imp.getOriginalFileInfo();
String fileName = null;
if (fInfo != null) {
fileName = fInfo.fileName;
String dirName = fInfo.directory;
if (fileName == null || dirName == null) {
return null;
}
if (dirName.equals(OJ.getData().getDirectory()) && fileName.equals(name)) {
return imp;
}
}
}
}
return null;
}
//if linked image is open several times, close all except the first one
public boolean closeDuplicates(String name) {
int found = 0;
ImagePlus firstImp = null;
int[] openImgs = WindowManager.getIDList();
if (openImgs != null) {
for (int jj = 0; jj < openImgs.length; jj++) {
int id = openImgs[jj];
ImagePlus imp = WindowManager.getImage(id);
FileInfo fInfo = imp.getOriginalFileInfo();
String fileName = null;
if (fInfo != null) {
fileName = fInfo.fileName;
String dirName = fInfo.directory;
if (fileName != null && dirName != null) {
if (dirName.equals(OJ.getData().getDirectory()) && fileName.equals(name)) {
found++;
if (found == 1) {
firstImp = imp;
}
if (found > 1) {
imp.close();
firstImp.getWindow().setState(Frame.NORMAL);
}
}
}
}
}
if (found > 1) {
firstImp.getWindow().setState(Frame.NORMAL);
}
}
return found > 1;
}
public ImageWindow getImageWindow(int id) {
for (Enumeration e = openedImages.keys(); e.hasMoreElements();) {
ImageWindow imgw = (ImageWindow) openedImages.get(e.nextElement());
if (imgw.getImagePlus().getID() == id) {
return imgw;
}
}
return null;
}
/**
* removes linked image and its listeners
* @param name
*/
public void removeFromOpenedImages(String name) {
if (openedImages.containsKey(name)) {
ImageWindow imgw = (ImageWindow) openedImages.get(name);
OJ.getEventProcessor().removeYtemDefChangedListener((YtemDefChangedListenerOJ) imgw.getCanvas());
OJ.getEventProcessor().removeYtemChangedListener((YtemChangedListenerOJ) imgw.getCanvas());
OJ.getEventProcessor().removeCellChangedListener((CellChangedListenerOJ) imgw.getCanvas());
openedImages.remove(name);
}
}
/**
* repaints all open linked images
*/
public void updateOpenImages() {
for (Enumeration e = openedImages.keys(); e.hasMoreElements();) {
((ImageWindow) openedImages.get(e.nextElement())).getCanvas().repaint();
}
}
/**
* ImageDnDOJ.java
* -- documented
*
* for handling drag+drop of images into the Images panel
*/
//private static ImageDnDOJ instance = null;
public static int dropOperations = DnDConstants.ACTION_COPY;
// public static ImageDnDOJ getInstance() {
// if (instance == null) {
// instance = new ImageDnDOJ();
// }
// return instance;
// }
public void dragEnter(DropTargetDragEvent dtde) {
dtde.acceptDrag(DnDConstants.ACTION_COPY);
}
public void dragOver(DropTargetDragEvent dtde) {
}
public void dropActionChanged(DropTargetDragEvent dtde) {
}
public void dragExit(DropTargetEvent dtde) {
}
public void drop(DropTargetDropEvent dtde) {
dtde.acceptDrop(DnDConstants.ACTION_COPY | DnDConstants.ACTION_LINK);
try {
Transferable t = dtde.getTransferable();
DataFlavor[] flavors = t.getTransferDataFlavors();
if (flavors.length == 0) {
ij.IJ.showMessage("Drag&Drop ignored, -please try again");//30.9.2009
}
if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
Object data = t.getTransferData(DataFlavor.javaFileListFlavor);
Collections.sort((List) data);
Iterator iterator = ((List) data).iterator();
while (iterator.hasNext()) {
File file = (File) iterator.next();
String fName = file.getName();
if (!fName.endsWith(".zip")) {
OJ.getImageProcessor().addImage(fName, false, false);//problem as the file name is changed 17.5.2009
}
}
}
} catch (Exception e) {
dtde.dropComplete(false);
return;
}
dtde.dropComplete(true);
}
}
|