/*--- formatted by Jindent 2.1, (www.c-lab.de/~jindent) ---*/

/*
 * JIGL--Java Imaging and Graphics Library
 * Copyright (C)1999 Brigham Young University
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 * A copy of the GNU Library General Public Licence is contained in
 * /jigl/licence.txt
 */


/**
 * This Canvas provides  a way to display images in a frame
 * Currently supports:  Jigl images, Java images (.gif, .jpg, .jpeg),
 * and PPM images (.ppm, .pgm, .pbm).
 * @version 1.3, Modifikation der urspruenglichen jigl Paketstruktur durch Jens Martin
 * @see jigl.gui.ImageCanvas
 */

package jm.jigl; // Modifizierte Paketstruktur [JM]
import jm.jigl.*;

// import jigl.*;


import java.awt.*;
import java.io.*;
import java.awt.image.*;
import java.util.*;

// import java.awt.Rectangle.*;
// import jigl.image.*;


/**
 * ImageCanvas is a class made to facilitate the displaying of a JIGL image
 */
public class ImageCanvas extends Canvas {


	/**
	 * used to wait until the image loads before continuing
	 */
	MediaTracker							m_tracker = null;


	/**
	 * Java image
	 */
	protected java.awt.Image	image;


	/**
	 * JIGL image
	 */
	protected jm.jigl.Image		jimage;


	/**
	 * Upper x corner of the selection box
	 */
	public int								mouseux = 0;


	/**
	 * Upper y corner of the selection box
	 */
	public int								mouseuy = 0;


	/**
	 * Lower x corner of the selection box
	 */
	public int								mouselx = 0;


	/**
	 * Lower y corner of the selection box
	 */
	public int								mousely = 0;


	/**
	 * Used as a toggle on the ImageCanvas
	 */
	public boolean						mouse_clicked = false;


	/**
	 * Used as a toggle on the ImageCanvas
	 */
	public boolean						box_draw = true;
	private boolean						db = true;


	/**
	 * Creates an empty ImageCanvas
	 */
	public ImageCanvas() {
		super();
	}


	/**
	 * Creates an ImageCanvas from a file
	 * @param fname filename
	 */
	public ImageCanvas(String fname) throws FileExtensionNotSupportedException, BadImageException, IllegalPBMFormatException, InterruptedException, ImageNotSupportedException, FileNotFoundException, IOException {
		super();
		image = getImageFromFile(fname);
	}


	/**
	 * Creates an ImageCanvas from a GrayImage
	 * @param img GrayImage
	 */
	public ImageCanvas(GrayImage img) throws BadImageException {
		super();
		image = getJavaImage(img);
		jimage = img;

	}


	/**
	 * Creates an ImageCanvas from a RealGrayImage
	 * @param img RealGrayImage
	 */
	public ImageCanvas(RealGrayImage img) throws BadImageException {
		super();
		image = getJavaImage(img);
		jimage = img;

	}



	/**
	 * Creates an ImageCanvas from a ComplexImage
	 * @param img CpmplexImage
	 */
	public ImageCanvas(ComplexImage img) throws BadImageException {
		super();
		image = getJavaImage(img);
		jimage = img;

	}


	/**
	 * Creates an ImageCanvas from a JIGL Image
	 * @param img JIGL Image
	 */
	public ImageCanvas(jm.jigl.Image img) throws BadImageException {
		super();
		image = getJavaImage(img);
		jimage = img;

	}


	/**
	 * Sets the drawing of the Region of Interest box to true or false
	 * @param value sets the drawing of an xor box to true or false
	 */
	public void setDrawBox(boolean value) {
		db = value;
	}


	/**
	 * Sets the JIGL image to <i>img</i> and Java Image to null
	 */
	public void setImage(java.awt.Image img) {
		image = img;
		jimage = null;
	}


	/**
	 * Sets the JIGL Image and Java Image to <i>img</i>
	 */
	public void setImage(jm.jigl.Image img) throws BadImageException {
		image = getJavaImage(img);
		jimage = img;
	}


	/**
	 * Returns the JIGL image
	 */
	public jm.jigl.Image getImage() {
		return jimage;
	}


	/**
	 * Returns the Java image
	 */
	public java.awt.Image getJavaImage() {
		return image;
	}


	/**
	 * Returns an instance of Graphics that, when modified, modifies the Java image
	 */
	public Graphics setOffScreen() {
		java.awt.Image	tempImage;
		Graphics				g;

		tempImage = image;
		image = this.createImage(image.getWidth(this), image.getHeight(this));
		g = image.getGraphics();
		g.drawImage(tempImage, 0, 0, this);

		return g;


	}


	/**
	 * Returns an instance of Graphics that, when modified, modifies the Java image
	 * @param xfactor zoom of x axis
	 * @param yfactor zoom of y axis
	 */
	public Graphics setOffScreen(double xfactor, double yfactor) {
		java.awt.Image	tempImage;
		Graphics				g;

		tempImage = image;
		image = this.createImage((int) (image.getWidth(this) * xfactor), (int) (image.getHeight(this) * yfactor));

		g = image.getGraphics();

		g.drawImage(tempImage, 0, 00, (int) (tempImage.getWidth(this) * xfactor), (int) (tempImage.getHeight(this) * yfactor), this);


		return g;


	}


	/**
	 * Overrides Component.setVisible(boolean)
	 */
	public void setVisible(boolean b) {
		setSize(imWidth(), imHeight());
		super.setVisible(b);

	}


	/**
	 * Returns the image height
	 */
	public int imHeight() {
		return image.getHeight(this);
	}


	/**
	 * Returns the image width
	 */
	public int imWidth() {
		return image.getWidth(this);
	}


	/**
	 * Takes a jigl image as input, converts it to a java
	 * image, and returns the java image.
	 * @param img the JIGL image
	 */
	public java.awt.Image getJavaImage(jm.jigl.Image img) throws BadImageException, RuntimeException {

		int							w = 0;
		int							h = 0;
		java.awt.Image	jimg = null;



		short						max = Short.MIN_VALUE;
		short						min = Short.MAX_VALUE;

		if (img instanceof GrayImage) {
			GrayImage im = (GrayImage) img;

			w = im.X();
			h = im.Y();
			jimg = createImage(im.getJavaImage());
		} else if (img instanceof RealGrayImage) {
			RealGrayImage im = (RealGrayImage) img;

			w = im.X();
			h = im.Y();
			jimg = createImage(im.getJavaImage());
		} else if (img instanceof ComplexImage) {
			ComplexImage	im = (ComplexImage) img;

			w = im.X();
			h = im.Y();
			jimg = createImage(im.getJavaImage());
		} else {
			throw new BadImageException();
		}


		w += 0;
		h += 0;

		if (w > getSize().width) {
			setSize(w, h);
		}
		if (h > getSize().height) {
			setSize(w, h);
		}

		return jimg;
	}


	/**
	 * Gets a JIGL image from a file.
	 * This currently supports Java files (.gif, .jpg),
	 * and PPM files (.ppm, .pgm, .pbm).  The file extension must be one of the above, or it won't
	 * look at it.
	 * @param fname filename
	 */
	public java.awt.Image getImageFromFile(String fname) throws FileExtensionNotSupportedException, BadImageException, IllegalPBMFormatException, InterruptedException, ImageNotSupportedException, IOException, FileNotFoundException {

		java.awt.Image	img = null;

		// setLayout(new FlowLayout());    // NEED to specify a layout manager!!

		if (fname.endsWith(".gif") || fname.endsWith(".jpg") || fname.endsWith(".jpeg")) {

			// do Java file load
			Toolkit toolkit = Toolkit.getDefaultToolkit();

			img = toolkit.getImage(fname);
			m_tracker = new MediaTracker(this);
			m_tracker.addImage(img, 0);
			try {
				m_tracker.waitForAll();
			} catch (InterruptedException e) {
				System.out.println("Interrupted image load.");
			}

			jimage = null;
			return img;
		} else if (fname.endsWith(".ppm") || fname.endsWith(".pgm") || fname.endsWith(".pbm")) {

			// do a Jigl load

			ImageInputStream	is = new ImageInputStream(fname);

			jimage = is.read();
			return getJavaImage(jimage);
		}

		return img;		// shouldn't get here if all goes well
	}


	/**
	 * Repaints the ImageCanvas (including the selection box).  If drawBox is set to true
	 * then it will also draw the region of interest.
	 * @g Graphics
	 */
	public void update(Graphics g) {
		g.drawImage(image, 0, 0, this);
		g.setXORMode(Color.white);
		if (db == true) {
			g.drawLine(this.mouseux, this.mouseuy, this.mouselx, this.mouseuy);
			g.drawLine(this.mouseux, this.mousely, this.mouselx, this.mousely);
			g.drawLine(this.mouseux, this.mouseuy, this.mouseux, this.mousely);
			g.drawLine(this.mouselx, this.mouseuy, this.mouselx, this.mousely);
		}
	}


	/**
	 * Overrides the repaint method for smoother redraw
	 */

	// public void repaint() {
	// update(this.getGraphics());

	// }


	/**
	 * Overrides the paint method for smoother redraw
	 */
	public void paint(Graphics g) {
		update(g);
	}

}


/*--- formatting done in "My Own Convention" style on 08-08-2000 ---*/

