import ij.*;
import ij.process.*;
import ij.plugin.*;
import ij.io.*;
import java.io.*;

// Plugin to handle file types which are not implemented 
// directly in ImageJ through io.Opener
// nb since there is no _ in the name it will not appear in Plugins menu
// -----
// Can be user modified so that your own specialised file types
// can be opened through File ... Open
// OR by drag and drop onto the ImageJ main panel
// OR by double clicking in the MacOS 9/X Finder
// -----
// Go to the point marked MODIFY HERE and modify to 
// recognise and load your own file type
// I have implemented two file types as examples:
// 	Biorad PIC and Gatan DM3
// -----
// Gregory Jefferis - 030629
// jefferis@stanford.edu

public class HandleExtraFileTypes extends ImagePlus implements PlugIn {
	static final int IMAGE_OPENED=-1;
	static final int PLUGIN_NOT_FOUND=-1;
	
	// Called from io/Opener.java
	public void run(String path) {
		//IJ.log("HandleExtraFileTypes: "+path);
		if (IJ.versionLessThan("1.30u"))
			return;
		File theFile=new File(path);
		String directory = theFile.getParent();
		String fileName = theFile.getName();
		if (directory==null) return;
		
		// Try and recognise file type and load the file if recognised
		ImagePlus imp=openImage(directory,fileName);
		if (imp==null) {			
			// failed to load file or plugin has opened and displayed it
			IJ.showStatus("");
			return;  // failed to load file or plugin has opened and displayed it
		}
		ImageStack stack=imp.getStack();
		// Set the stack of this HandleExtraFileTypes object
		// to that attached to the ImagePlus object returned by openImage()
		setStack(fileName,stack);
		// Copy over the calibration info since it doesn't come with the ImageProcessor
		setCalibration(imp.getCalibration());
		// Also copy the Show Info field over if it exists
		if (imp.getProperty("Info")!=null)
			setProperty("Info",imp.getProperty("Info"));
	}  

	private ImagePlus openImage(String directory, String name) {
		ImagePlus imp;

		// Set out file name and path
		if (directory.length()>0 && !directory.endsWith(Prefs.separator))
			directory += Prefs.separator;
		String path = directory+name;

		// set up a stream to read in 132 bytes from the file header
		// These can be checked for "magic" values which are diagnostic
		// of some image types
		InputStream is;
		byte[] buf = new byte[132];
		try {
			is = new FileInputStream(path);
			is.read(buf, 0, 132);
			is.close();
		} catch (IOException e) {
			// Couldn't open the file for reading
			return null;
		}
		name = name.toLowerCase();

		// OK now we get to the interesting bit 
			
		// GJ: added Biorad PIC confocal file handler
		// Note that the Biorad_Reader plugin extends the ImagePlus class,
		// which is why the IJ.runPlugIn() call below returns an ImagePlus object.
		// ------------------------------------------
		// These make 12345 if you read them as the right kind of short
		// and should have this value in every Biorad PIC file
		if(buf[54]==57 && buf[55]==48) {
			// Ok we've identified the file type 
			// Now load it using the relevant plugin
			imp = (ImagePlus)IJ.runPlugIn("Biorad_Reader", path);
			if (imp==null) width = PLUGIN_NOT_FOUND;
			if (imp!=null&&imp.getWidth()==0) imp = null;
			return imp;
		}
		
		// GJ: added Gatan Digital Micrograph DM3 handler
		// Note that the DM3_Reader plugin extends the ImagePlus class,
		// which is why the IJ.runPlugIn() call below returns an ImagePlus object.
		// ----------------------------------------------
		// Check if the file ends in .DM3 or .dm3
		if (name.endsWith(".dm3")) {
			// These make an int value of 3 which is the DM3 version number
			if(buf[0]==0 && buf[1]==0 && buf[2]==0 && buf[3]==3) {
				// Ok we've identified the file type - now load it
				imp = (ImagePlus)IJ.runPlugIn("DM3_Reader", path);
				if (imp==null) width = PLUGIN_NOT_FOUND;
				if (imp!=null&&imp.getWidth()==0) imp = null;
				return imp;
			}
		}

		// Added Analyze format (.img/.hdr) handler
		// Note that the Analyze_Reader plugin opens and displays the
		// image and does not implement the ImagePlus class.
		if (name.endsWith(".img") || name.endsWith(".hdr")) {
			// Open Analyze image and display it
			IJ.runPlugIn("Analyze_Reader", path);
			// Set flag so Opener.openImage() does not display error
			width = IMAGE_OPENED; 
			return null; 
		}

		// IPLab file handler
		// Little-endian IPLab files start with "iiii"
		if (buf[0]==105&& buf[1]==105&&buf[2]==105&&buf[3]==105) {
			imp = (ImagePlus)IJ.runPlugIn("IPLab_Reader", path);
			if (imp==null) width = PLUGIN_NOT_FOUND;
			if (imp!=null&&imp.getWidth()==0) imp = null;
			return imp;
		}

		// ****************** MODIFY HERE ******************
		// Do what ever you have to do to recognise your own file type
		// and then call appropriate plugin 
		// using the above as models 
		// eg:
		
		/* 
		// A. Dent: Added XYZ handler
		// ----------------------------------------------
		// Check if the file ends in .XYZ or .xyz
		if (name.toUpperCase().endsWith(".XYZ")) {
			// Bytes 0 and 1 must equal 42 for this file type
			if(buf[0]==42 && buf[1]==42) {
				// Ok we've identified the file type - now load it
				imp = (ImagePlus)IJ.runPlugIn("XYZ_Reader", path);
				if (imp==null) width = PLUGIN_NOT_FOUND;
				if (imp!=null&&imp.getWidth()==0) imp = null;
				return imp;
			}
		}
		*/
		
		// If we got this far we didn't recognise the file type
		return null;
	}

}
