import ij.IJ;

import ij.ImagePlus;

import ij.ImageStack;

import ij.io.OpenDialog;

import ij.plugin.PlugIn;

import ij.measure.Calibration;

import java.io.*;



public class RawAsciiReader_ implements PlugIn {



	public void run(String arg) {

		OpenDialog od = new OpenDialog("Open Raw Ascii...", arg);

		String dir = od.getDirectory();

		String name = od.getFileName();

		if (name==null)

			return;



		String result = openRawAscii(dir, name);



		if (result != null)

			IJ.error(result);

	}



	abstract class PixelReader {

		ImageStack stack;

		int w, h, i, j;



		PixelReader(int width, int height) {

			w = width;

			h = height;

			i = j = 0;

			stack = new ImageStack(w, h);

		}



		abstract void initSlice();

		abstract void setCurrentPixel(double value);

		abstract void addSlice();



		void add(double value) {

			if (i == 0 && j == 0)

				initSlice();

			setCurrentPixel(value);

			i++;

			if (i >= w) {

				i = 0;

				j++;

				if (j >= h) {

					addSlice();

					j = 0;

				}

			}

		}

	}



	class UnsignedCharReader extends PixelReader {

		byte[] slice;



		UnsignedCharReader(int width, int height) {

			super(width, height);

		}



		void initSlice() {

			slice = new byte[w * h];

		}



		void setCurrentPixel(double value) {

			slice[i + j * w] = (byte)(int)value;

		}



		void addSlice() {

			stack.addSlice("", slice);

		}

	}



	StreamTokenizer tokenizer;

	String nextToken() throws IOException {

		if (tokenizer.nextToken() == StreamTokenizer.TT_EOF)

			throw new RuntimeException("Early end of file!");

		if (tokenizer.ttype == StreamTokenizer.TT_NUMBER)

			tokenizer.sval = Double.toString(tokenizer.nval);

		return tokenizer.sval;

	}



	double nextDouble() throws IOException {

		if (tokenizer.nextToken() == StreamTokenizer.TT_EOF)

			throw new RuntimeException("Early end of file!");

		return tokenizer.nval;

	}



	int nextInt() throws IOException {

		return (int)Math.round(nextDouble());

	}



	String openRawAscii(String dir, String name) {

		IJ.showStatus("Opening: " + dir + name);

		try {

			if (dir == null || dir.equals(""))

				dir = "./";



			File file = new File(dir, name);

			FileReader reader = new FileReader(file);

			tokenizer = new StreamTokenizer(reader);



			if (!nextToken().equals("ascii"))

				return "Not an ASCII stack";

			if (nextDouble() != 3)

				return "Not an ASCII stack";



			String pixelFormat = nextToken();

			int w = nextInt();

			int h = nextInt();

			int d = nextInt();

			double minX = nextDouble();

			double maxX = nextDouble();

			double minY = nextDouble();

			double maxY = nextDouble();

			double minZ = nextDouble();

			double maxZ = nextDouble();



			PixelReader pixelReader = null;

			if (pixelFormat.equals("uc"))

				pixelReader = new UnsignedCharReader(w, h);

			else

				return "Unknown pixel format: " + pixelFormat;



			for (int i = 0; i < w * h * d; i++)

				pixelReader.add(nextDouble());



			ImageStack stack = pixelReader.stack;

			ImagePlus image = new ImagePlus(name, stack);

			Calibration cal = new Calibration();

			cal.xOrigin = minX;

			cal.yOrigin = minY;

			cal.zOrigin = minZ;

			cal.pixelWidth = (maxX - minX) / w;

			cal.pixelHeight = (maxY - minY) / h;

			cal.pixelDepth = (maxZ - minZ) / d;

			image.setCalibration(cal);

			image.show();

		} catch (IOException e) {

			throw new RuntimeException(e);

		}

		return null;

	}

}