/* import statements for PsuedoProcessorTest */

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;

import ij.io.FileInfo;
import ij.io.ImageReader;
import ij.io.TiffDecoder;
import ij.process.ImageProcessor;

/* import statements for custom ColorProcessor (see below) */

import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Image;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DirectColorModel; //simple constructor to get ColorModel
import java.awt.image.IndexColorModel;
import java.awt.image.SampleModel;
import java.awt.image.WritableRaster;
import java.lang.IllegalArgumentException;

import javax.swing.DebugGraphics; //simple constructor to get a Graphics

import ij.gui.ProgressBar;
import ij.process.FloatProcessor;
//import ij.process.ImageProcessor; //imported above...

/*
  Try to create a ColorProcessor without tossing up a GUI.
  Adapted from FileOpener.
*/

public class PseudoProcessorTest {

    public static void main(String[] args) {
        TiffDecoder td = new TiffDecoder(args[1], args[3]);
        FileInfo[] fi = null;
        ImageProcessor ip = null;
        int width;
        int height;
        try {
            fi = td.getTiffInfo();
        } catch(IOException ioe) {
            System.out.println("sucka");
            ioe.printStackTrace();
        }
        if(fi != null) {
            ImageReader reader = new ImageReader(fi[0]);
            width = fi[0].width;
            height = fi[0].height;
            InputStream is = null;
            try {
                is = createInputStream(fi[0]);
            } catch(IOException ioe) {
                System.out.println("pringles can");
                ioe.printStackTrace();
            }
            if(is != null) {
                Object pixels = reader.readPixels(is);
                if(pixels != null) {
                /*
                  no GUI upto this point. Comment out the lines below
                  and there's no problem. Leave them uncommented, and
                  the program will create a GUI, even though the class
                  definition below presumably doesn't instantiate any
                  AWT components... see the ColorProcessor class definition 
                  below.
                */
                    ip = new ColorProcessor(
                        width, height, ((int[])pixels));
                }
            }
        }
    }

    static InputStream createInputStream(FileInfo fi) throws IOException {
		InputStream is = null;
		if (fi.inputStream!=null)
			is = fi.inputStream;
		else {
			if (fi.directory.length()>0 
                && !fi.directory.endsWith("/"))
				fi.directory += "/";
		    File f = new File(fi.directory + fi.fileName);
		    if (f==null || f.isDirectory() || !validateFileInfo(f, fi))
		    	is = null;
		    else
				is = new FileInputStream(f);
		}
		return is;
	}

	static boolean validateFileInfo(File f, FileInfo fi) {
		long offset = fi.longOffset>0?fi.longOffset:fi.offset;
		long length = 0;
		if (fi.width<=0 || fi.height<0) {
		   System.out.println("Width or height <= 0.");
		   return false;
		}
		if (offset>=0 && offset<1000)
			 return true;
		if (offset<0) {
		   System.out.println("Offset is negative.");
		   return false;
		}
		if (fi.fileType==FileInfo.BITMAP 
            || fi.compression!=FileInfo.COMPRESSION_NONE)
			return true;
		length = f.length();
		long size = fi.width*fi.height*fi.getBytesPerPixel();
		size = fi.nImages>1?size:size/4;
		if (fi.height==1) size = 0; 
		if (offset+size>length) {
		   System.out.println("Offset + image size > file length.");
		   return false;
		}
		return true;
	}
}


/**
    THIS IS NOT A REAL COLOR PROCESSOR. IT DOESN'T DO ANYTHING. The point of 
    this class is to try to create a sub-class of ImageProcessor that doesn't 
    create a GUI.

    Bare essentials to implement a non-functional sub-class of ImageProcessor.
    Also overwrites all ImageProcessor methods in a attempt to prevent the
    class from instantiating any AWT components.
    
    Most methods are empty. Those that return something almost certainly
    do not give you what you want...

    NOT INTENDED FOR ANY USE.
*/
class ColorProcessor extends ImageProcessor {
	
	public ColorProcessor() {}
	/* 
	   Constructors don't instantiate anything. They don't even call a method 
	   and yet instantiating this class creates a GUI...
    */
	public ColorProcessor(int a, int b, int[] c) {}
	
	//ImageProcessor's abstract methods
	public void setColor(Color color) {}
	public void setValue(double value) {}
	public void setBackgroundValue(double value) {}
	public double getMin() {return 0.0;}
	public double getMax() {return 0.0;}
	public void flipVertical() {}
	public void fill(ImageProcessor mask) {}
	public Object getPixels() {return new Object();}
	public Object getPixelsCopy() {return new Object();}
	public int get(int index) {return 1;}
	public float getf(int index) {return (float)0.0;}
	public void setPixels(Object pixels) {}
	public Image createImage() {return (Image) new BufferedImage(1670, 890, BufferedImage.TYPE_BYTE_GRAY);}
	public void snapshot() {}
	public void reset() {}
	public void reset(ImageProcessor mask) {}
	public void setSnapshotPixels(Object pixels) {}
	public Object getSnapshotPixels() {return new Object();}
	public void filter(int type) {}
	public void medianFilter() {}
	public ImageProcessor crop() {return (ImageProcessor) new ColorProcessor();}
	public void threshold(int level) {}
	public ImageProcessor duplicate() {return (ImageProcessor) new ColorProcessor();}
	public void erode() {}
	public void dilate() {}


	public void setMinAndMax(double min, double max) {}
	public int getPixel(int x, int y) {return 1;}
	public int get(int x, int y) {return 1;}
	public void set(int x, int y, int value) {}
	public void set(int index, int value) {}
	public float getf(int x, int y) {return (float)0.0;}
	public void setf(int x, int y, float value) {}
	public void setf(int index, float value) {}
	public double getInterpolatedPixel(double x, double y) {return 0.0;}
	public void putPixel(int x, int y, int value) {}
	public float getPixelValue(int x, int y) {return (float)0.0;}
	public void putPixelValue(int x, int y, double value) {}
	public void drawPixel(int x, int y) {}
	public void copyBits(ImageProcessor ip, int xloc, int yloc, int mode) {}
	public ImageProcessor createProcessor(int width, int height) {return (ImageProcessor) new ColorProcessor();}
	public void scale(double xScale, double yScale) {}
	public ImageProcessor resize(int dstWidth, int dstHeight) {return (ImageProcessor) new ColorProcessor();}
	public FloatProcessor toFloat(int channelNumber, FloatProcessor fp) {return new FloatProcessor(1,1, new int[4]);}
	public void setPixels(int channelNumber, FloatProcessor fp) {}

	public void applyTable(int[] lut) {}
	public void convolve3x3(int[] kernel) {}
	public void noise(double range) {}
	public int[] getHistogram() {return new int[4];}
	public void convolve(float[] kernel, int kernelWidth, int kernelHeight) {}

  	public void rotate(double angle) {}

    //overwrite ImageProcessor's methods as well...

	private static double rWeight=1d/3d, gWeight=1d/3d,	bWeight=1d/3d; 
	protected void showProgress(double percentDone) {}
	protected void hideProgress() {}
	public int getWidth() {return 1;}
	public int getHeight() {return 1;}
	public ColorModel getColorModel() {return (ColorModel)new DirectColorModel(1,1,1,1);}
	public ColorModel getCurrentColorModel() {return (ColorModel)new DirectColorModel(1,1,1,1);}
	public void setColorModel(ColorModel cm) {}
	protected void makeDefaultColorModel() {}
	public void invertLut() {}
	public int getBestIndex(Color c) {return 1;}
	public boolean isInvertedLut() {return true;}
	public boolean isColorLut() {return true;}
	public void setColor(int value) {}
	public void resetMinAndMax() {}
	public void resetThreshold() {}
	public double getMinThreshold() {return 0.0;}
	public double getMaxThreshold() {return 0.0;}
	public int getLutUpdateMode() {return 1;}
	public void resetBinaryThreshold() {}
	public void setRoi(Rectangle roi) {}
	public void setRoi(Polygon roi) {}
	public void resetRoi() {}
	public Rectangle getRoi() {return new Rectangle();}
	public void setMask(ImageProcessor mask) {}
	public ImageProcessor getMask() {return (ImageProcessor) new ColorProcessor();}
	public void setProgressBar(ProgressBar pb) {}
	public void setInterpolate(boolean interpolate) {}
	public boolean getInterpolate() {return true;}
	public boolean isKillable() {return true;}
	public void setLineWidth(int width) {}
	public void drawPolygon(Polygon p) {}
	public void fillPolygon(Polygon p) {}
	private void setupFontMetrics() {}
	public void drawString(String s) {}
	public void setJustification(int justification) {}
	public void setFont(Font font) {}
	public void setAntialiasedText(boolean antialiasedText) {}
	public int getStringWidth(String s) {return 1;}
	public FontMetrics getFontMetrics() {return (new DebugGraphics()).getFontMetrics();}
	public void smooth() {}
	public void sharpen() {}
	public void findEdges() {}
	public void flipHorizontal() {}
	public ImageProcessor rotateRight() {return (ImageProcessor) new ColorProcessor();}
	public ImageProcessor rotateLeft() {return (ImageProcessor) new ColorProcessor();}
	public String toString() {return "duh";}
	public void fill() {}
	public void setHistogramSize(int size) {}
	public int getHistogramSize() {return 1;}
	public double getHistogramMin() {return 0.0;}
	public double getHistogramMax() {return 0.0;}
	public int getPixelCount() {return 1;}
	public void invert() {}
	public void add(int value) {}
	public void add(double value) {}
	public void multiply(double value) {}
	public void and(int value) {}
	public void or(int value) {}
	public void xor(int value) {}
	public void gamma(double value) {}
	public void log() {}
	public void exp() {}
	public void sqr() {}
	public void sqrt() {}
	public void abs() {}
	public void min(double value) {}
	public void max(double value) {}
	public ImageProcessor resize(int dstWidth) {return (ImageProcessor) new ColorProcessor();}
	public void setLutAnimation(boolean lutAnimation) {}
	void resetPixels(Object pixels) {}
	public ImageProcessor convertToByte(boolean doScaling) {return (ImageProcessor) new ColorProcessor();}
	public ImageProcessor convertToShort(boolean doScaling) {return (ImageProcessor) new ColorProcessor();}
	public ImageProcessor convertToFloat() {return (ImageProcessor) new ColorProcessor();}
	public ImageProcessor convertToRGB() {return (ImageProcessor) new ColorProcessor();}
	public void autoThreshold() {}
	public int getAutoThreshold() {return 1;}
	public void setClipRect(Rectangle clipRect) {}
	protected String maskSizeError(ImageProcessor mask) {return "duh";}
	protected SampleModel getIndexSampleModel() {
        IndexColorModel icm = getDefaultColorModel();
        WritableRaster wr = icm.createCompatibleWritableRaster(1, 1);
        sampleModel = wr.getSampleModel();
        return sampleModel.createCompatibleSampleModel(1670, 890);
	}
	public IndexColorModel getDefaultColorModel() {
        byte[] r = new byte[256];
        byte[] g = new byte[256];
        byte[] b = new byte[256];
        for(int i=0; i<256; i++) {
            r[i]=(byte)i;
            g[i]=(byte)i;
            b[i]=(byte)i;
        }
        return new IndexColorModel(8, 256, r, g, b);
	}
	public void setSnapshotCopyMode(boolean b) {}
	public int getNChannels() {return 1;}
	public double minValue() {return 0.0;}
	public double maxValue() {return 0.0;}
	void updateLutBytes() {}

}