summaryrefslogtreecommitdiff
path: root/java
diff options
context:
space:
mode:
authorpjain <pjain@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1997-04-07 17:25:19 +0000
committerpjain <pjain@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1997-04-07 17:25:19 +0000
commit40e0a419db16f5c42865615794fdcf5d76329726 (patch)
treef82d40848859e8127c3fed0acf8e34ffc2a25b0f /java
parenteeaf6aba2867bb8f49248688fba8e12dec1f09c7 (diff)
downloadATCD-40e0a419db16f5c42865615794fdcf5d76329726.tar.gz
Added the Image Processing framework to CVS
Diffstat (limited to 'java')
-rw-r--r--java/ImageProcessing/framework/BaseButton.java229
-rw-r--r--java/ImageProcessing/framework/DialogManager.java174
-rw-r--r--java/ImageProcessing/framework/DialogType.java9
-rw-r--r--java/ImageProcessing/framework/FileBrowser.java177
-rw-r--r--java/ImageProcessing/framework/FilePanel.java147
-rw-r--r--java/ImageProcessing/framework/FilterTest.java62
-rw-r--r--java/ImageProcessing/framework/Hierarchy.java333
-rw-r--r--java/ImageProcessing/framework/Icon.java70
-rw-r--r--java/ImageProcessing/framework/ImageApp.java278
-rw-r--r--java/ImageProcessing/framework/ImageCanvas.java146
-rw-r--r--java/ImageProcessing/framework/ImageFilterFactory.java47
-rw-r--r--java/ImageProcessing/framework/ImageProcessor.java111
-rw-r--r--java/ImageProcessing/framework/ListFiles.java161
-rw-r--r--java/ImageProcessing/framework/Options.java25
-rw-r--r--java/ImageProcessing/framework/Separator.java90
-rw-r--r--java/ImageProcessing/framework/StatusDisplay.java23
-rw-r--r--java/ImageProcessing/framework/URLFrame.java106
17 files changed, 2188 insertions, 0 deletions
diff --git a/java/ImageProcessing/framework/BaseButton.java b/java/ImageProcessing/framework/BaseButton.java
new file mode 100644
index 00000000000..f8208d2ed13
--- /dev/null
+++ b/java/ImageProcessing/framework/BaseButton.java
@@ -0,0 +1,229 @@
+package imaging.framework;
+
+import java.awt.*;
+import imaging.filters.*;
+
+public class BaseButton extends Panel
+{
+ public BaseButton (String title, String description, ImageApp parent)
+ {
+ this.setLayout (new BorderLayout ());
+ this.button_ = new Button (title);
+ this.add ("Center", this.button_);
+ this.resize (100, 100);
+ this.description_ = description;
+ this.parent_ = parent;
+ }
+
+ public boolean mouseEnter(Event evt, int x, int y)
+ {
+ this.parent_.displayStatus (this.description_);
+ return true;
+ }
+
+ public boolean mouseExit(Event evt, int x, int y)
+ {
+ this.parent_.displayStatus ("");
+ return true;
+ }
+
+ protected ImageApp parent_;
+ private String description_;
+ private Button button_;
+}
+
+class URLDialogButton extends BaseButton
+{
+ public URLDialogButton (String title, String desc, ImageApp parent)
+ {
+ super (title, desc, parent);
+ this.openURLFrame_ = new URLFrame ("Open URL", this.parent_);
+ }
+
+ public boolean action (Event e, Object arg)
+ {
+ this.openURLFrame_.show ();
+ return true;
+ }
+ private URLFrame openURLFrame_;
+}
+
+class SaveButton extends BaseButton
+{
+ public SaveButton (String title, String desc, ImageApp parent)
+ {
+ super (title, desc, parent);
+ }
+
+ public boolean action (Event e, Object arg)
+ {
+ this.parent_.saveFile ();
+ return true;
+ }
+}
+
+class ReloadButton extends BaseButton
+{
+ public ReloadButton (String title, String desc, ImageApp parent)
+ {
+ super (title, desc, parent);
+ }
+
+ public boolean action (Event e, Object arg)
+ {
+ this.parent_.reloadFilters ();
+ return true;
+ }
+}
+
+class ApplyButton extends BaseButton
+{
+ public ApplyButton (String title, String desc, ImageApp parent)
+ {
+ super (title, desc, parent);
+ }
+
+ public boolean action (Event e, Object arg)
+ {
+ this.parent_.apply ();
+ return true;
+ }
+}
+
+class ResetButton extends BaseButton
+{
+ public ResetButton (String title, String desc, ImageApp parent)
+ {
+ super (title, desc, parent);
+ }
+
+ public boolean action (Event e, Object arg)
+ {
+ this.parent_.resetImage ();
+ return true;
+ }
+}
+
+class ZoomInButton extends BaseButton
+{
+ public ZoomInButton (String title, String desc, ImageApp parent)
+ {
+ super (title, desc, parent);
+ }
+
+ public boolean action (Event e, Object arg)
+ {
+ this.parent_.zoomFactor (1.6);
+ return true;
+ }
+}
+
+class ZoomOutButton extends BaseButton
+{
+ public ZoomOutButton (String title, String desc, ImageApp parent)
+ {
+ super (title, desc, parent);
+ }
+
+ public boolean action (Event e, Object arg)
+ {
+ this.parent_.zoomFactor (0.625);
+ return true;
+ }
+}
+
+
+class AboutButton extends BaseButton
+{
+ public AboutButton (String title, String desc, ImageApp parent)
+ {
+ super (title, desc, parent);
+ }
+
+ public boolean action (Event e, Object arg)
+ {
+ DialogManager.popDialog (DialogType.ABOUT, null);
+ return true;
+ }
+}
+
+class HelpButton extends BaseButton
+{
+ public HelpButton (String title, String desc, ImageApp parent)
+ {
+ super (title, desc, parent);
+ }
+
+ public boolean action (Event e, Object arg)
+ {
+ System.out.println ("Help selected");
+ return true;
+ }
+}
+
+class ChoicePanel extends Panel
+{
+ public ChoicePanel (String desc, ImageApp parent)
+ {
+ this.description_ = desc;
+ this.parent_ = parent;
+
+ this.loadFilters ();
+ // Set the layout of the Choice Panel. Note that the Choice Panel
+ // holds the choice button of filters.
+ this.setLayout (new FlowLayout ());
+ this.resize (150, 100);
+ }
+
+ public void choice (Choice choice)
+ {
+ this.choice_ = choice;
+ }
+
+ public Choice choice ()
+ {
+ return this.choice_;
+ }
+
+ public void loadFilters ()
+ {
+ // First remove all components of the panel including the
+ // choices of filters
+ this.removeAll ();
+
+ // Now create new choices
+ this.choice_ = this.parent_.getFilters ();
+
+ // Add the choices to our choice panel
+ this.add (this.choice_);
+ }
+
+ public boolean mouseEnter(Event evt, int x, int y)
+ {
+ MedFilter filter = null;
+ String displayString = null;
+ String filterName = this.choice_.getSelectedItem ();
+
+ if (filterName.compareTo ("None") == 0)
+ displayString = "No filter selected";
+ else
+ {
+ filter = (MedFilter) this.parent_.getFilter (filterName);
+ displayString = filter.info ();
+ }
+ this.parent_.displayStatus (displayString);
+ // this.parent_.displayStatus (this.description_);
+ return true;
+ }
+
+ public boolean mouseExit(Event evt, int x, int y)
+ {
+ this.parent_.displayStatus ("");
+ return true;
+ }
+
+ private Choice choice_;
+ private ImageApp parent_;
+ String description_;
+}
+
diff --git a/java/ImageProcessing/framework/DialogManager.java b/java/ImageProcessing/framework/DialogManager.java
new file mode 100644
index 00000000000..2a169675e0b
--- /dev/null
+++ b/java/ImageProcessing/framework/DialogManager.java
@@ -0,0 +1,174 @@
+package imaging.framework;
+
+import java.awt.*;
+import java.awt.image.*;
+
+class DialogManager
+{
+ public static void popDialog (int type, String message)
+ {
+ Frame frame = null;
+
+ switch (type)
+ {
+ case DialogType.ABOUT:
+ frame = new AboutFrame ();
+ break;
+ case DialogType.MALFORMED_URL:
+ case DialogType.URL_NOT_FOUND:
+ frame = new MessageFrame ("Error", message);
+ break;
+ case DialogType.NOT_YET_IMPLEMENTED:
+ frame = new MessageFrame ("", message);
+ break;
+ }
+ Dimension d = Toolkit.getDefaultToolkit ().getScreenSize ();
+ frame.move ((d.width - frame.size ().width)/2,
+ (d.height - frame.size ().height)/2);
+ /* frame.reshape ((d.width - frame.size ().width)/2,
+ (d.height - frame.size ().height)/2,
+ frame.size ().width,
+ frame.size ());
+ */
+ frame.show ();
+ }
+}
+
+class MessageFrame extends Frame
+{
+ public MessageFrame (String title, String message)
+ {
+ super (title);
+
+ this.resize (250,100);
+ this.setLayout (new BorderLayout ());
+
+ this.text_ = new TextField (message);
+ this.text_.setEditable (false);
+
+ Panel okButtonPanel = new Panel ();
+ okButtonPanel.add (this.okButton_);
+ okButtonPanel.resize (100, 100);
+
+ this.add ("Center", this.text_);
+ this.add ("South", okButtonPanel);
+ }
+
+ public boolean handleEvent (Event evt)
+ {
+ if (evt.id == Event.WINDOW_DESTROY)
+ {
+ this.dispose ();
+ return true;
+ }
+ return super.handleEvent (evt);
+ }
+
+ // Handle all action events
+ public boolean action (Event e, Object arg)
+ {
+ if (e.target instanceof Button)
+ {
+ if (e.target == this.okButton_)
+ {
+ this.dispose ();
+ }
+ return true;
+ }
+ else
+ return false;
+ }
+
+ private Button okButton_ = new Button (" ok ");
+ private TextField text_ = null;
+}
+
+class AboutFrame extends Frame
+{
+ public AboutFrame ()
+ {
+ super ("About");
+ this.setText ();
+
+ this.resize (500,700);
+ this.setLayout (new BorderLayout ());
+
+ Panel okButtonPanel = new Panel ();
+ okButtonPanel.add (this.okButton_);
+
+ this.add ("South", okButtonPanel);
+ }
+
+ public void paint (Graphics g)
+ {
+ g.clearRect (0, 0, this.size ().width, this.size ().height);
+ g.setFont (new Font ("TimesRoman", Font.PLAIN, 18));
+ this.setBackground (Color.white);
+ int x = 20;
+ int y = 100;
+
+ for (int i = 0; i < AboutFrame.MAXROWS; i++)
+ {
+ g.drawString(this.text_[i], x, y);
+ y += g.getFont ().getSize () + 5;
+ }
+ }
+
+ // Handle window destroy events
+ public boolean handleEvent (Event evt)
+ {
+ if (evt.id == Event.WINDOW_DESTROY)
+ {
+ this.dispose ();
+ return true;
+ }
+ return super.handleEvent (evt);
+ }
+
+ // Handle all action events
+ public boolean action (Event e, Object arg)
+ {
+ if (e.target instanceof Button)
+ {
+ if (e.target == this.okButton_)
+ {
+ this.dispose ();
+ }
+ return true;
+ }
+ else
+ return false;
+ }
+
+ private void setText ()
+ {
+ text_[0] = "This is a prototype of a large scale distributed medical";
+ text_[1] = "imaging system. It has been developed using Java, in";
+ text_[2] = "particular, several components of Java ACE.";
+ text_[3] = "";
+ text_[4] = "The prototype allows images to be downloaded across the";
+ text_[5] = "network. It then provides several filters that can be";
+ text_[6] = "used to do image processing. The image filters are";
+ text_[7] = "configured into the system dynamically using the Service";
+ text_[8] = "Configurator pattern. In the current implementation, the";
+ text_[9] = "filters are specified via a configuration file located at";
+ text_[10] = "server. The file can be modified at runtime to add";
+ text_[11] = "additional filters or to remove some filters. This allows";
+ text_[12] = "filters to be configured and reconfigured dynamically.";
+ text_[13] = "";
+ text_[14] = "Currently, images can not be uploaded. This is mainly due";
+ text_[15] = "to security restrictions imposed by current servers. Our";
+ text_[16] = "goal is to use the prototpe in conjunction with JAWS, an";
+ text_[17] = "adaptive web server we are currently developing in which we";
+ text_[18] = "plan to provide support for image uploading.";
+ text_[19] = "";
+ text_[20] = "For more information about this prototype, please contact";
+ text_[21] = "Prashant Jain (pjain@cs.wustl.edu).";
+ }
+
+ private final static int MAXROWS = 22;
+ private Button okButton_ = new Button (" ok ");
+ private TextArea textArea_ = null;
+ private String [] text_ = new String [AboutFrame.MAXROWS];
+}
+
diff --git a/java/ImageProcessing/framework/DialogType.java b/java/ImageProcessing/framework/DialogType.java
new file mode 100644
index 00000000000..33652d227f8
--- /dev/null
+++ b/java/ImageProcessing/framework/DialogType.java
@@ -0,0 +1,9 @@
+package imaging.framework;
+
+public class DialogType
+{
+ public static final int ABOUT = 0;
+ public static final int MALFORMED_URL = 1;
+ public static final int URL_NOT_FOUND = 2;
+ public static final int NOT_YET_IMPLEMENTED = 10;
+}
diff --git a/java/ImageProcessing/framework/FileBrowser.java b/java/ImageProcessing/framework/FileBrowser.java
new file mode 100644
index 00000000000..776bf9d7ded
--- /dev/null
+++ b/java/ImageProcessing/framework/FileBrowser.java
@@ -0,0 +1,177 @@
+package imaging.framework;
+
+import java.awt.*;
+import java.awt.image.*;
+import gjt.Separator;
+import java.net.*;
+import java.applet.*;
+//import gjt.ComponentScroller;
+
+class FileNode extends Hierarchy
+{
+ public FileNode (String name,
+ Icon icon,
+ boolean root,
+ ImageApp app)
+ {
+ super (name, icon, root);
+ this.app_ = app;
+ }
+
+ public FileNode (String name,
+ Icon icon,
+ ListFiles list,
+ ImageApp app)
+ {
+ super (name, icon);
+ this.list_ = list;
+ this.app_ = app;
+ }
+
+ public ImageApp app ()
+ {
+ return this.app_;
+ }
+
+ public void handleEvent ()
+ {
+ String s = null;
+ String pString = "";
+ Hierarchy p = this.getHierarchyParent ();
+
+ while (p != null)
+ {
+ pString = p.getName () + pString;
+ p = p.getHierarchyParent ();
+ }
+
+ if (pString.endsWith ("/"))
+ s = "http://" + pString + this.getName ();
+ else
+ s = "http://" + pString + "/" + this.getName ();
+
+ System.out.println ("Opening: " + s);
+
+ // If list is null, then it is a file, else it is a directory and
+ // use list to get the rest of the directory.
+ if (this.list_ == null)
+ this.app_.openURL (s); // It is a file
+ else
+ this.list_.listFiles (s, this); // It is a directory.
+ }
+
+ private ListFiles list_ = null;
+ private ImageApp app_ = null;
+}
+
+class BrowserPanel extends Panel
+{
+ public BrowserPanel (ImageApp parent)
+ {
+ this.resize (300, 300);
+ this.parent_ = parent;
+ this.setLayout (new BorderLayout ());
+ }
+
+ public int initialize (String url, ListFiles list)
+ {
+ String directory = null;
+ int index = -1;
+
+ String pString = list.stripProtocolHeader (url);
+ if (!pString.endsWith ("/"))
+ pString = pString + "/";
+
+ try
+ {
+ Icon dirIcon = new Icon (this.parent_.getCodeBase () + "file03.gif", (Applet) this.parent_);
+ System.out.println (this.parent_.getCodeBase () + "file03.gif");
+ this.root_ = new FileNode (pString,
+ dirIcon, true, this.parent_);
+ }
+ catch (MalformedURLException e)
+ {
+ }
+
+ int count = list.listFiles (url, this.root_);
+ // System.out.println ("Count: " + count);
+ if (count > 0)
+ this.add ("Center", this.root_);
+ return count;
+ // this.scroller_ = new HierarchyScroller (this.root_);
+ // this.add ("East", this.scroller_);
+ // this.scroller_.setComponent (this.root_);
+ }
+
+ public boolean handleEvent (Event evt)
+ {
+ if (evt.target == this.scroller_)
+ {
+ repaint ();
+ return true;
+ }
+ return super.handleEvent (evt);
+ }
+
+ private FileNode root_ = null;
+ private ImageApp parent_;
+ private HierarchyScroller scroller_;
+}
+
+class FileBrowser extends Frame
+{
+ public FileBrowser (String title, ImageApp parent)
+ {
+ super (title);
+ this.resize (300, 300);
+ this.browser_ = new BrowserPanel (parent);
+ this.setLayout (new BorderLayout ());
+
+ this.cancelButton_ = new Button (" cancel ");
+ Panel buttonPanel = new Panel ();
+ buttonPanel.add (this.cancelButton_);
+ buttonPanel.resize (100, 100);
+
+ Panel southPanel = new Panel ();
+ southPanel.setLayout (new BorderLayout ());
+ southPanel.add ("North", new Separator ());
+ southPanel.add ("South", buttonPanel);
+ this.add ("South", southPanel);
+ this.add ("Center", this.browser_);
+ }
+
+ public int initialize (String url, ListFiles list)
+ {
+ return this.browser_.initialize (url, list);
+ }
+
+ // Handle window destroy events
+ public boolean handleEvent (Event evt)
+ {
+ if (evt.id == Event.WINDOW_DESTROY)
+ {
+ this.dispose ();
+ return true;
+ }
+ return super.handleEvent (evt);
+ }
+
+ // Handle all action events
+ public boolean action (Event e, Object arg)
+ {
+ if (e.target instanceof Button)
+ {
+ if (e.target == this.cancelButton_)
+ {
+ this.dispose ();
+ }
+ validate ();
+ return true;
+ }
+ else
+ return false;
+ }
+
+ private Button cancelButton_;;
+ private BrowserPanel browser_;
+}
diff --git a/java/ImageProcessing/framework/FilePanel.java b/java/ImageProcessing/framework/FilePanel.java
new file mode 100644
index 00000000000..0f233eda8ff
--- /dev/null
+++ b/java/ImageProcessing/framework/FilePanel.java
@@ -0,0 +1,147 @@
+package imaging.framework;
+
+import java.awt.*;
+
+// Create a panel for all the buttons
+class FilePanel extends Panel
+{
+ FilePanel (ImageApp parent)
+ {
+ this.parent_ = parent;
+
+ this.setLayout (new GridLayout (2, 1));
+
+ // First create all the buttons
+ this.URLDialogButton_ = new URLDialogButton ("Open URL", "Download an image", this.parent_);
+ this.saveButton_ = new SaveButton ("Save", "Upload an image", this.parent_);
+
+ // Place the created buttons in the panel
+ this.add (this.URLDialogButton_);
+ this.add (this.saveButton_);
+
+ // Disable the save button for now
+ this.saveButton_.disable ();
+ this.resize (400, 400);
+ }
+
+ // All the created buttons
+ private URLDialogButton URLDialogButton_;
+ private SaveButton saveButton_;
+
+ private ImageApp parent_;
+}
+
+// Create a panel for all the buttons
+class ResetPanel extends Panel
+{
+ ResetPanel (ImageApp parent)
+ {
+ this.parent_ = parent;
+
+ this.setLayout (new GridLayout (2, 1));
+
+ // First create all the buttons
+ this.reloadButton_ = new ReloadButton ("Reload Filters", "Reload all filters", this.parent_);
+ this.resetButton_ = new ResetButton ("Reset", "Reset the image", this.parent_);
+
+
+ // Place the created buttons in the panel
+ this.add (this.resetButton_);
+ this.add (this.reloadButton_);
+
+ this.resize (400, 400);
+ }
+
+ // All the created buttons
+ private ReloadButton reloadButton_;
+ private ResetButton resetButton_;
+
+ private ImageApp parent_;
+}
+
+
+class ZoomPanel extends Panel
+{
+ ZoomPanel (ImageApp parent)
+ {
+ this.parent_ = parent;
+
+ this.setLayout (new GridLayout (2, 1));
+
+ // First create the two zoom buttons
+ this.zoomInButton_ = new ZoomInButton ("<< Zoom in", "Zoom into the image", this.parent_);
+ this.zoomOutButton_ = new ZoomOutButton ("Zoom out >>", "Zoom out of the image", this.parent_);
+
+ // Now add the buttons to the panel
+ this.add (this.zoomInButton_);
+ this.add (this.zoomOutButton_);
+
+ this.resize (100, 100);
+ }
+
+ private ZoomInButton zoomInButton_;
+ private ZoomOutButton zoomOutButton_;
+
+ private ImageApp parent_;
+}
+
+
+class FilterPanel extends Panel
+{
+ FilterPanel (ImageApp parent)
+ {
+ this.parent_ = parent;
+
+ this.setLayout (new GridLayout (2, 1));
+ this.applyButton_ = new ApplyButton ("Apply", "Apply the selected filter", this.parent_);
+
+ // Set the layout of the Choice Panel. Note that the Choice Panel
+ // holds the choice button of filters.
+ this.choicePanel_ = new ChoicePanel ("Select filter", this.parent_);
+
+ this.add (this.applyButton_);
+ this.add (this.choicePanel_);
+ this.resize (200,200);
+ }
+
+ public Choice choice ()
+ {
+ return this.choicePanel_.choice ();
+ }
+
+ public void loadFilters ()
+ {
+ this.choicePanel_.loadFilters ();
+ }
+
+ private ChoicePanel choicePanel_;
+ private ApplyButton applyButton_;
+ private ImageApp parent_;
+}
+
+class HelpPanel extends Panel
+{
+ HelpPanel (ImageApp parent)
+ {
+ this.parent_ = parent;
+
+ this.setLayout (new GridLayout (2, 1));
+
+ this.aboutButton_ = new AboutButton ("About", "About the applet", this.parent_);
+ this.helpButton_ = new HelpButton ("Help", "Help on how to use the applet", this.parent_);
+
+ // Now add the buttons to the panel
+ this.add (this.aboutButton_);
+ this.add (this.helpButton_);
+
+ // Disable the Help button for now
+ this.helpButton_.disable ();
+
+ this.resize (100, 100);
+ }
+
+ private AboutButton aboutButton_;
+ private HelpButton helpButton_;
+
+ private ImageApp parent_;
+}
diff --git a/java/ImageProcessing/framework/FilterTest.java b/java/ImageProcessing/framework/FilterTest.java
new file mode 100644
index 00000000000..b1e33482be9
--- /dev/null
+++ b/java/ImageProcessing/framework/FilterTest.java
@@ -0,0 +1,62 @@
+package imaging.framework;
+
+import java.awt.*;
+import java.awt.image.*;
+import imaging.filters.Timer;
+
+public class FilterTest
+{
+ public static void main(String[] args)
+ {
+ Timer timer = new Timer();
+ ImageProcessor ip = new ImageProcessor();
+ ImageFilterFactory iff = new ImageFilterFactory();
+ Frame frame = new Frame("Rotate Example");
+ Toolkit tk = Toolkit.getDefaultToolkit();
+ Dimension d = tk.getScreenSize();
+ Image old_image = tk.getImage("myphoto.gif"), image;
+ int image_x, image_y, x = 50, y = 50;
+ Graphics g;
+
+ frame.reshape(d.width/4, d.height/8, d.width/2, 3*d.height/4);
+ frame.show();
+ g = frame.getGraphics();
+ d = frame.size();
+
+ MediaTracker tracker = new MediaTracker(frame);
+ tracker.addImage(old_image, 0);
+ try { tracker.waitForID(0); } catch(InterruptedException excp) {}
+ g.drawImage(old_image, x, y, frame);
+ x += old_image.getWidth(frame) + 50;
+
+ timer.start();
+ image = ip.processImage(old_image, iff.createMeanImageFilter(), frame);
+ timer.stop();
+ System.out.println(timer);
+ g.drawImage(image, x, y, frame);
+ x += old_image.getWidth(frame) + 50;
+
+ timer.start();
+ image = ip.processImage(old_image, iff.createSobelFilter(), frame);
+ timer.stop();
+ System.out.println(timer);
+ g.drawImage(image, x, y, frame);
+ x = 50;
+ y += old_image.getHeight(frame) + 50;
+
+ timer.start();
+ image = ip.processImage(old_image, iff.createEmbossFilter(), frame);
+ timer.stop();
+ System.out.println(timer);
+ g.drawImage(image, x, y, frame);
+ x += old_image.getWidth(frame) + 50;
+
+ image = ip.processImage(old_image, iff.createSharpenFilter(), frame);
+ g.drawImage(image, x, y, frame);
+ x = 50;
+ y += old_image.getHeight(frame) + 50;
+
+ image = ip.processImage(old_image, iff.createRotateImageFilter(), frame);
+ g.drawImage(image, x, y, frame);
+ }
+}
diff --git a/java/ImageProcessing/framework/Hierarchy.java b/java/ImageProcessing/framework/Hierarchy.java
new file mode 100644
index 00000000000..b24ea53b6e3
--- /dev/null
+++ b/java/ImageProcessing/framework/Hierarchy.java
@@ -0,0 +1,333 @@
+package imaging.framework;
+
+import java.awt.*;
+import java.util.Vector;
+
+public class Hierarchy extends Canvas
+{
+ // Attributes
+ private String name_;
+ private Hierarchy root_;
+ private Hierarchy parent_;
+ private Icon icon_ = null;
+
+ // State
+ private boolean collapsed_ = true;
+ private boolean deadend_ = true;
+ private Vector contained_ = new Vector();
+ private Rectangle self_;
+ private Rectangle scope_;
+
+ // Constants
+ private Color COLOR = Color.black;
+ private Font FONT = new Font("Dialog", Font.BOLD, 12);
+ private static int TRI_HEIGHT = 8;
+ private int SPACE = 15;
+
+ static Hierarchy last_lit_ = null;
+
+ public Hierarchy(String name, boolean root)
+ {
+ name_ = name;
+
+ if (root)
+ {
+ deadend_ = false;
+ root_ = this;
+ parent_ = null;
+ }
+ }
+
+ public Hierarchy(String name, Icon icon, boolean root)
+ {
+ this(name, root);
+ icon_ = icon;
+ }
+
+ public Hierarchy(String name)
+ {
+ this(name, false);
+ }
+
+ public Hierarchy(String name, Icon icon)
+ {
+ this(name, icon, false);
+ }
+
+ public void setExpandable(boolean expandable)
+ {
+ deadend_ = ! expandable;
+ }
+
+ public void setCollapsed(boolean collapsed)
+ {
+ collapsed_ = collapsed;
+ }
+
+ public void addEntry(Hierarchy entry)
+ {
+ deadend_ = false;
+ entry.parent_ = this;
+ entry.root_ = root_;
+ entry.FONT = FONT;
+ entry.COLOR = COLOR;
+ entry.SPACE = SPACE;
+
+ contained_.addElement(entry);
+ }
+
+ public boolean removeEntry(String name)
+ {
+ if (contained_.size() == 1)
+ deadend_ = true;
+
+ return contained_.removeElement(name);
+ }
+
+ public String getName()
+ {
+ return name_;
+ }
+
+ public void setName(String name)
+ {
+ name_ = name;
+ }
+
+ public Hierarchy getHierarchyParent()
+ {
+ return parent_;
+ }
+
+ public void setFont(Font font)
+ {
+ FONT = font;
+ }
+
+ public void setColor(Color color)
+ {
+ COLOR = color;
+ }
+
+ public void setSpace(int space)
+ {
+ SPACE = space;
+ }
+
+ public void handleEvent() {}
+
+ public boolean mouseDown(Event evt, int x, int y)
+ {
+ Hierarchy value = mouseInside(x, y);
+
+ if (value != null)
+ {
+ if (! value.deadend_)
+ {
+ if (x < value.self_.x + TRI_HEIGHT + SPACE)
+ {
+ value.collapsed_ = ! value.collapsed_;
+ if (value.contained_.isEmpty())
+ value.handleEvent();
+ repaint();
+ }
+ }
+ else
+ {
+ if (value.contained_.isEmpty())
+ value.handleEvent();
+ }
+ }
+
+ return false;
+ }
+
+ public boolean mouseMove(Event evt, int x, int y)
+ {
+ Hierarchy value = mouseInside(x, y);
+
+ if ((value != last_lit_) && (last_lit_ != null))
+ last_lit_.highlight(getGraphics(), false);
+
+ if (value != null && value.deadend_)
+ value.highlight(getGraphics(), true);
+
+ last_lit_ = value;
+
+ return false;
+ }
+
+
+ public void paint(Graphics g)
+ {
+ drawLevel(g, SPACE, SPACE);
+ }
+
+ private Point drawLevel(Graphics g, int x, int y)
+ {
+ g.setFont(FONT);
+ FontMetrics font_metrics = g.getFontMetrics();
+ int string_height = font_metrics.getHeight();
+ int string_width = font_metrics.stringWidth(name_);
+ int entry_height = string_height;
+ int entry_width = string_width + 2*SPACE + TRI_HEIGHT;
+ int total_height, total_width, initial_x = x, initial_y = y;
+ int indent = SPACE + TRI_HEIGHT/2;
+ int temp_x = x;
+ Point place_marker;
+ Hierarchy entry;
+
+ if (icon_ != null)
+ {
+ entry_height = Math.max(string_height, icon_.iconSize().height);
+ entry_width += icon_.iconSize().width;
+ indent += icon_.iconSize().width/2;
+ if (! deadend_)
+ drawShape(g, x, y + (entry_height - TRI_HEIGHT)/2, deadend_, collapsed_);
+ }
+ else
+ drawShape(g, x, y + (entry_height - TRI_HEIGHT)/2, deadend_, collapsed_);
+
+ self_ = new Rectangle(initial_x, initial_y, entry_width, entry_height);
+
+ temp_x += TRI_HEIGHT + SPACE;
+
+ if (icon_ != null)
+ {
+ icon_.drawIcon(g, temp_x, y, root_);
+ temp_x += SPACE + icon_.iconSize().width;
+ }
+
+ g.setColor(COLOR);
+
+ g.drawString(name_, temp_x, y + (entry_height + string_height)/2);
+
+ total_width = entry_width;
+ y += entry_height + SPACE;
+
+ if (! (deadend_ || collapsed_))
+ {
+ x += indent;
+ for (int i = 0; i < contained_.size(); i++)
+ {
+ entry = (Hierarchy)contained_.elementAt(i);
+ place_marker = entry.drawLevel(g, x, y);
+ total_width = Math.max(total_width, entry.self_.width + indent);
+ x = place_marker.x;
+ y = place_marker.y;
+ }
+ x -= indent;
+ }
+
+ total_height = y - initial_y;
+ scope_ = new Rectangle(initial_x, initial_y, total_width, total_height);
+
+ return new Point(x, y);
+ }
+
+ private Hierarchy mouseInside(int x, int y)
+ {
+ Hierarchy entry;
+ Hierarchy return_value = null;
+
+ if (self_.inside(x, y))
+ {
+ return_value = this;
+ }
+ else
+ {
+ if (scope_.inside(x, y) && (! collapsed_))
+ {
+ for (int i = 0; i < contained_.size(); i++)
+ {
+ entry = (Hierarchy)contained_.elementAt(i);
+ if ((return_value = entry.mouseInside(x, y)) != null)
+ break;
+ }
+ }
+ else
+ return_value = null;
+ }
+
+ return return_value;
+ }
+
+ private void highlight(Graphics g, boolean lit)
+ {
+ g.setFont(FONT);
+ FontMetrics fm = g.getFontMetrics();
+ int string_height = fm.getHeight();
+ int x = self_.x + SPACE + TRI_HEIGHT;
+ int y = self_.y;
+
+ if (icon_ != null)
+ x += icon_.iconSize().width + SPACE;
+
+ if (lit)
+ g.setColor(Color.magenta);
+ else
+ g.setColor(COLOR);
+
+ g.drawString(name_, x, y + (self_.height + string_height)/2);
+ }
+
+
+ private static void drawShape(Graphics g, int x, int y, boolean dead_end, boolean collapsed)
+ {
+ int xpoints[] = new int[3];
+ int ypoints[] = new int[3];
+
+ xpoints[0] = x;
+ ypoints[0] = y;
+
+ if (dead_end)
+ {
+ g.fillOval(x, y, TRI_HEIGHT, TRI_HEIGHT);
+ }
+ else
+ {
+ // Draw a small collapsed triangle: |>
+ if (collapsed)
+ {
+ xpoints[1] = x;
+ xpoints[2] = x + TRI_HEIGHT;
+ ypoints[1] = y + TRI_HEIGHT;
+ ypoints[2] = y + TRI_HEIGHT/2;
+ g.fillPolygon(xpoints, ypoints, 3);
+ }
+ //Draw a small uncollapsed triangle
+ else
+ {
+ xpoints[1] = x + TRI_HEIGHT;
+ xpoints[2] = x + TRI_HEIGHT/2;
+ ypoints[1] = y;
+ ypoints[2] = y + TRI_HEIGHT;
+ g.fillPolygon(xpoints, ypoints, 3);
+ }
+ }
+ }
+
+ private static void drawVertHashedLine(Graphics g, int x, int y1, int y2, int hashsize)
+ {
+ for (int ytemp = y1; ytemp < y2; ytemp += hashsize*3)
+ {
+ if (y2 - hashsize < ytemp)
+ g.drawLine(x, ytemp, x, y2);
+ else
+ g.drawLine(x, ytemp, x, ytemp + hashsize);
+ }
+ }
+
+ private static void drawHoroHashedLine(Graphics g, int y, int x1, int x2, Color color, int hashsize)
+ {
+ for (int xtemp = x1; xtemp < x2; xtemp += hashsize*3)
+ {
+ if (x2 - hashsize < xtemp)
+ g.drawLine(xtemp, y, x1, y);
+ else
+ g.drawLine(xtemp, y, xtemp + hashsize, y);
+ }
+ }
+}
+
+
diff --git a/java/ImageProcessing/framework/Icon.java b/java/ImageProcessing/framework/Icon.java
new file mode 100644
index 00000000000..eed91ed55c7
--- /dev/null
+++ b/java/ImageProcessing/framework/Icon.java
@@ -0,0 +1,70 @@
+package imaging.framework;
+
+import java.awt.*;
+import java.applet.*;
+import java.net.*;
+
+public class Icon
+{
+ protected Image icon_;
+ protected Dimension iconSize_;
+
+ Icon()
+ {
+ super();
+ }
+
+ Icon(String file_name, Component comp)
+ {
+ this.icon_ = Toolkit.getDefaultToolkit().getImage(file_name);
+ this.loadImage(comp);
+ }
+
+ Icon(Image icon_image, Component comp)
+ {
+ this.icon_ = icon_image;
+ this.loadImage(comp);
+ }
+
+ Icon(String url, Applet applet) throws MalformedURLException
+ {
+ this.icon_ = applet.getImage(new URL(url));
+ loadImage(applet);
+ }
+
+ public void drawIcon(Graphics g, int x, int y, Component comp)
+ {
+ g.drawImage(this.icon_, x, y, comp);
+ }
+
+ private void loadImage(Component comp)
+ {
+ try
+ {
+ MediaTracker tracker = new MediaTracker(comp);
+ tracker.addImage(this.icon_, 0);
+ tracker.waitForID(0);
+
+ this.iconSize_ = new Dimension(this.icon_.getWidth(comp), this.icon_.getHeight(comp));
+ }
+ catch (InterruptedException excp)
+ {
+ System.err.println("Icon::getIcon image failed to load");
+ }
+ }
+
+ public Dimension iconSize()
+ {
+ return this.iconSize_;
+ }
+
+ public Image getIconImage()
+ {
+ return this.icon_;
+ }
+
+}
+
+
+
+
diff --git a/java/ImageProcessing/framework/ImageApp.java b/java/ImageProcessing/framework/ImageApp.java
new file mode 100644
index 00000000000..fc0b6550148
--- /dev/null
+++ b/java/ImageProcessing/framework/ImageApp.java
@@ -0,0 +1,278 @@
+package imaging.framework;
+
+import java.util.*;
+import java.awt.*;
+import java.net.*;
+import java.io.*;
+import java.awt.image.*;
+import java.applet.*;
+import gjt.Separator;
+import imaging.filters.Timer;
+
+public class ImageApp extends Applet
+{
+ public void init ()
+ {
+ // Use BorderLayout for our applet frame
+ this.setLayout (new BorderLayout ());
+
+ // Now load all the filters specified in the config file
+ // this.loadFilters ();
+ this.setupButtonPanel ();
+ this.add ("Center", this.imageCanvas_);
+ }
+
+ private void setupButtonPanel ()
+ {
+ Panel southPanel = new Panel ();
+ southPanel.setLayout (new BorderLayout ());
+
+ Panel buttonPanel = new Panel ();
+ buttonPanel.setLayout (new GridLayout (1, 5));
+
+ this.statusDisplay_ = new StatusDisplay ();
+ // Create a panel for all the buttons
+ this.filePanel_ = new FilePanel (this);
+ this.resetPanel_ = new ResetPanel (this);
+ this.zoomPanel_ = new ZoomPanel (this);
+ this.filterPanel_ = new FilterPanel (this);
+ this.helpPanel_ = new HelpPanel (this);
+
+ buttonPanel.add (this.filePanel_);
+ buttonPanel.add (this.resetPanel_);
+ buttonPanel.add (this.zoomPanel_);
+ buttonPanel.add (this.filterPanel_);
+ buttonPanel.add (this.helpPanel_);
+
+ southPanel.add ("North", new Separator ());
+ southPanel.add ("Center", buttonPanel);
+ southPanel.add ("South", this.statusDisplay_);
+
+ southPanel.resize (400, 400);
+
+ // Now add all these components to the main frame
+ this.add ("South", southPanel);
+ this.add ("North", new Panel ()); // Empty panel (for aesthetics)
+ // this.add ("East", new Panel ()); // Empty panel (for aesthetics)
+ // this.add ("West", new Panel ()); // Empty panel (for aesthetics)
+ }
+
+ public void displayStatus (String s)
+ {
+ this.statusDisplay_.setText (s);
+ }
+
+ // Handle all action events
+ public void zoomFactor (double zoomFactor)
+ {
+ this.imageCanvas_.zoomFactor (zoomFactor);
+ }
+
+ public void reloadFilters ()
+ {
+ this.filterPanel_.loadFilters ();
+ repaint ();
+ }
+
+ public ImageFilter getFilter (String s)
+ {
+ return (ImageFilter) this.filterTable_.get (s);
+ }
+
+ public void apply ()
+ {
+ ImageFilter filter = this.getFilter (this.filterPanel_.choice ().getSelectedItem ());
+ if (filter != null)
+ {
+ Util.getFrame (this).setCursor (Frame.WAIT_CURSOR);
+ this.imageCanvas_.applyFilter (filter);
+ Util.getFrame (this).setCursor (Frame.DEFAULT_CURSOR);
+ }
+ }
+
+ public void resetImage ()
+ {
+ this.imageCanvas_.applyFilter (null);
+ }
+
+ public void openURL (String url)
+ {
+ if (url == null)
+ {
+ DialogManager.popDialog (DialogType.MALFORMED_URL,
+ "Error: Malformed URL");
+ return;
+ }
+ Image image;
+ try
+ {
+ if (url.compareTo ("pj") == 0) // This is just for debugging...
+ image = getImage (new URL ("http://www.cs/~pjain/myphoto.gif"));
+ else
+ image = getImage (new URL (url));
+ }
+ catch (MalformedURLException e)
+ {
+ DialogManager.popDialog (DialogType.MALFORMED_URL,
+ "Error: Malformed URL");
+ return;
+ }
+
+ if (image != null)
+ this.imageCanvas_.setImage (image);
+ else
+ DialogManager.popDialog (DialogType.URL_NOT_FOUND,
+ "Error: URL not found");
+ }
+
+ public void saveFile ()
+ {
+ DialogManager.popDialog (DialogType.NOT_YET_IMPLEMENTED,
+ "Save File: Not yet implemented ");
+ }
+
+ public Choice getFilters ()
+ {
+ Choice choice = new Choice ();
+
+ // Add the default choice first
+ choice.addItem ("None");
+
+ // Now do the file processing -- to determine which filters need
+ // to be loaded.
+
+ // Check if the filename has been previously specified and
+ // if not then check if the user has specified the name of the
+ // config file
+ if (this.configFile_ == null)
+ this.configFile_ = getParameter ("configFile");
+ if (this.configFile_ == null)
+ this.configFile_ = "http://www.cs.wustl.edu/~pjain/java/ImageProcessing/framework/filter.conf";
+
+ if (this.filterContext_ == null)
+ this.filterContext_ = getParameter ("filterContext");
+ if (this.filterContext_ == null)
+ this.filterContext_ = "http://www.cs.wustl.edu/~pjain/java/ImageProcessing/";
+
+ URL url;
+ String configInfo= null;
+ try
+ {
+ System.out.println ("Configuration File: " + this.configFile_);
+ // Create a new URL
+ url = new URL (this.configFile_);
+
+ // Get the input stream and pipe it to a DataInputStream
+ DataInputStream iStream = new DataInputStream (url.openStream ());
+
+ // Create a buffer to hold all the data we get
+ StringBuffer tempBuf = new StringBuffer ();
+ // Keep reading the data until we are done
+ String tempString = iStream.readLine ();
+ while (tempString != null)
+ {
+ tempBuf.append (tempString);
+ tempBuf.append (" ");
+ tempString = iStream.readLine ();
+ }
+ configInfo = tempBuf.toString ();
+ }
+ catch (MalformedURLException e)
+ {
+ System.err.println (e);
+ }
+ catch (IOException e)
+ {
+ System.err.println (e);
+ }
+
+ if (configInfo != null)
+ {
+ try
+ {
+ StringTokenizer tokens = new StringTokenizer (configInfo);
+ String fullFilterName = null;
+ String filterName = null;
+ // Now parse the string, picking up filter names. Use these
+ // names to load the actual filters as well add new choices to
+ // the filter choices.
+ while (tokens.hasMoreTokens ())
+ {
+ // Get the next token
+ fullFilterName = tokens.nextToken ();
+ filterName = this.extractFilterName (fullFilterName);
+
+ // URL filter = new URL (this.filterContext_ + fullFilterName + ".class");
+ System.out.println ("Loading: " + fullFilterName);
+ // Load the filter class
+ Class c = Class.forName (fullFilterName);
+ // Class c = this.filterRepository_.load (filter);
+
+ // Add the filter to the Filter Repository
+ this.filterTable_.put (filterName,
+ (ImageFilter) c.newInstance ());
+
+ // Add filter name to the list of filter choices
+ choice.addItem (filterName);
+ }
+ }
+ catch (ClassNotFoundException e)
+ {
+ System.err.println ("Filter not found: " + e);
+ return null;
+ }
+ catch (IllegalAccessException e)
+ {
+ System.err.println ("Filter not found: " + e);
+ return null;
+ }
+ catch (InstantiationException e)
+ {
+ System.err.println ("Filter not found: " + e);
+ return null;
+ }
+ }
+ return choice;
+ }
+
+ // Extract the short filter name from the full filter name. For
+ // example, this method returns "EmbossFilter" if it is given the
+ // string "imaging/filters/EmbossFilter"
+ private String extractFilterName (String s)
+ {
+ String filterName = null;
+ StringTokenizer tokens = new StringTokenizer (s, ".");
+ while (tokens.hasMoreTokens ())
+ filterName = tokens.nextToken ();
+ return filterName;
+ }
+
+ private Panel centerPanel_ = new Panel ();
+ private String configFile_ = null;
+ private String filterContext_ = null;
+ private Choice choice_ = null;
+ private ImageCanvas imageCanvas_ = new ImageCanvas ();
+ private FilePanel filePanel_;
+ private ResetPanel resetPanel_;
+ private ZoomPanel zoomPanel_;
+ private FilterPanel filterPanel_;
+ private HelpPanel helpPanel_;
+
+ private StatusDisplay statusDisplay_;
+
+ // Now create all the buttons
+ private Button URLDialogButton_ = new Button ("Open URL");
+ private Button saveButton_ = new Button ("Save");
+ private Button reloadButton_ = new Button ("Reload Filters");
+ private Button applyButton_ = new Button ("Apply");
+ private Button resetButton_ = new Button ("Reset");
+ private Button aboutButton_ = new Button ("About");
+
+ private Button zoomInButton_ = new Button ("<< Zoom in");
+ private Button zoomOutButton_ = new Button ("Zoom out >>");
+
+
+ private Hashtable filterTable_ = new Hashtable ();
+ private ImageFilterFactory iff_ = new ImageFilterFactory ();
+ // private FilterRepository filterRepository_ = new FilterRepository ();
+}
diff --git a/java/ImageProcessing/framework/ImageCanvas.java b/java/ImageProcessing/framework/ImageCanvas.java
new file mode 100644
index 00000000000..f05f50c72e4
--- /dev/null
+++ b/java/ImageProcessing/framework/ImageCanvas.java
@@ -0,0 +1,146 @@
+package imaging.framework;
+
+import java.awt.*;
+import java.awt.image.*;
+
+class ImageCanvas extends Canvas
+{
+ public static final double MAX_ZOOM = 4.0;
+ public static final double MIN_ZOOM = 0.5;
+
+ public void setImage (Image image)
+ {
+ if (image != null)
+ {
+ this.image_ = image;
+ this.originalImage_ = this.image_;
+
+ // Load the image
+ this.tracker_.addImage(this.image_, 0);
+ try { this.tracker_.waitForID(0); } catch(InterruptedException excp) {}
+
+ this.x_ = (this.size ().width - this.image_.getWidth (this))/2;
+ this.y_ = (this.size ().height - this.image_.getHeight (this))/2;
+ this.original_x_ = this.x_;
+ this.original_y_ = this.y_;
+ repaint ();
+ }
+ }
+
+ public void paint (Graphics g)
+ {
+ this.setBackground (Color.white);
+ if (this.image_ != null)
+ g.drawImage(this.image_,
+ this.x_, this.y_,
+ (int) (this.image_.getWidth (this) * this.zoom_),
+ (int) (this.image_.getHeight (this) * this.zoom_),
+ this);
+ }
+
+ public void applyFilter (ImageFilter filter)
+ {
+ if (this.image_ != null)
+ {
+ Image temp;
+ if (filter == null)
+ {
+ temp = this.originalImage_;
+ this.x_ = this.original_x_;
+ this.y_ = this.original_y_;
+ this.zoom_ = 1.0;
+ }
+ else
+ temp = this.ip_.processImage(this.image_, filter, this);
+
+ this.tracker_.addImage(temp, 0);
+ try { this.tracker_.waitForID(0); } catch(InterruptedException excp) {}
+
+ this.image_ = temp;
+
+ // Originally I needed to flush the pixel data for the image to be
+ // drawn properly. When running the applet in appletviewer, the
+ // image used to jump around, but running in a browser seems to be
+ // ok.
+ //this.image_.flush();
+ repaint ();
+ }
+ }
+
+ public void zoomFactor (double zoom)
+ {
+ this.zoom_ *= zoom;
+ if (this.zoom_ > ImageCanvas.MAX_ZOOM)
+ this.zoom_ = ImageCanvas.MAX_ZOOM;
+ else if (this.zoom_ < ImageCanvas.MIN_ZOOM)
+ this.zoom_ = ImageCanvas.MIN_ZOOM;
+
+ repaint ();
+ }
+
+ public boolean mouseDown (Event evt, int x, int y)
+ {
+ if (inBounds (x, y))
+ {
+ this.selected_ = true;
+ this.last_x_ = x;
+ this.last_y_ = y;
+ }
+ return true;
+ }
+
+ public boolean mouseUp (Event evt, int x, int y)
+ {
+ this.selected_ = false;
+ return true;
+ }
+
+ public boolean mouseDrag (Event evt, int x, int y)
+ {
+ if (this.selected_)
+ {
+ this.x_ = x - (this.last_x_ - this.x_);
+ this.y_ = y - (this.last_y_ - this.y_);
+ this.last_x_ = x;
+ this.last_y_ = y;
+ repaint ();
+ }
+ return true;
+ }
+
+ public boolean mouseMove (Event evt, int x, int y)
+ {
+ if (this.image_ != null && inBounds (x, y))
+ Util.getFrame (this).setCursor (Frame.HAND_CURSOR);
+ else
+ Util.getFrame (this).setCursor (Frame.DEFAULT_CURSOR);
+ return true;
+ }
+
+ public boolean mouseExit (Event evt, int x, int y)
+ {
+ Util.getFrame (this).setCursor (Frame.DEFAULT_CURSOR);
+ return true;
+ }
+
+ // Check if mouse is within the bounds of the image
+ private boolean inBounds (int x, int y)
+ {
+ return (x >= this.x_) &&
+ (y >= this.y_) &&
+ (x <= (this.x_ + this.zoom_ * this.image_.getWidth (this))) &&
+ (y <= (this.y_ + this.zoom_ * this.image_.getHeight (this)));
+ }
+
+ private MediaTracker tracker_ = new MediaTracker(this);
+ private Image image_, originalImage_;
+ private int x_ = 0, y_ = 0;
+ private int original_x_ = 0, original_y_ = 0;
+ private int width_ = 0, height_ = 0;
+ private ImageProcessor ip_ = new ImageProcessor ();
+ private boolean selected_ = false;
+ private int last_x_ = 0, last_y_ = 0;
+ private double zoom_ = 1.0;
+
+}
+
diff --git a/java/ImageProcessing/framework/ImageFilterFactory.java b/java/ImageProcessing/framework/ImageFilterFactory.java
new file mode 100644
index 00000000000..e854a41904f
--- /dev/null
+++ b/java/ImageProcessing/framework/ImageFilterFactory.java
@@ -0,0 +1,47 @@
+package imaging.framework;
+
+import java.awt.image.*;
+import imaging.filters.*;
+
+public class ImageFilterFactory
+{
+ public ImageFilterFactory()
+ {
+ }
+
+ public RotateFilter createRotateFilter()
+ {
+ return new RotateFilter(Math.PI/3);
+ }
+
+ public MeanFilter createMeanFilter()
+ {
+ return new MeanFilter();
+ }
+
+ public EmbossFilter createEmbossFilter()
+ {
+ return new EmbossFilter();
+ }
+
+ public SobelFilter createSobelFilter()
+ {
+ return new SobelFilter();
+ }
+
+ public SharpenFilter createSharpenFilter()
+ {
+ return new SharpenFilter();
+ }
+
+ public DarkenFilter createDarkenFilter()
+ {
+ return new DarkenFilter(50);
+ }
+
+ public DissolveFilter createDissolveFilter()
+ {
+ return new DissolveFilter(85);
+ }
+
+}
diff --git a/java/ImageProcessing/framework/ImageProcessor.java b/java/ImageProcessing/framework/ImageProcessor.java
new file mode 100644
index 00000000000..422298d508f
--- /dev/null
+++ b/java/ImageProcessing/framework/ImageProcessor.java
@@ -0,0 +1,111 @@
+package imaging.framework;
+
+import java.awt.*;
+import java.awt.image.*;
+import java.util.Vector;
+
+public class ImageProcessor
+{
+ private Vector pipeline_ = new Vector();
+
+
+ public ImageProcessor()
+ {
+ }
+
+ public void addFilter(String filter_name, ImageFilter filter)
+ {
+ pipeline_.addElement(new FilterNode(filter_name, filter));
+ }
+
+ public boolean removeFilter(String name)
+ {
+ FilterNode filter_node;
+
+ for (int i = 0; i < pipeline_.size(); i++)
+ {
+ filter_node = (FilterNode)pipeline_.elementAt(i);
+ if (name.equals(filter_node.getName()))
+ {
+ pipeline_.removeElementAt(i);
+ pipeline_.trimToSize();
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public Image processImage(Image image, ImageFilter filter, Component component)
+ {
+ Image old_image = image, new_image = old_image;
+ MediaTracker tracker = new MediaTracker(component);
+
+ try
+ {
+ new_image = component.createImage(new FilteredImageSource(old_image.getSource(), filter));
+ tracker.addImage(new_image, 0);
+ tracker.waitForID(0);
+ }
+ catch(InterruptedException excp)
+ {
+ System.out.println("ImageProcessor::processImage Image failed to load.");
+ System.out.println(excp);
+ return null;
+ }
+
+ return new_image;
+ }
+
+ public Image processImage(Image image, Component component)
+ {
+ Image old_image = image, new_image = null;
+ ImageFilter image_filter;
+ FilterNode filter_node;
+ MediaTracker tracker = new MediaTracker(component);
+
+ try
+ {
+ for (int i = 0; i < pipeline_.size(); i++)
+ {
+ filter_node = (FilterNode) pipeline_.elementAt(i);
+ image_filter = filter_node.getFilter();
+ new_image = component.createImage(new FilteredImageSource(old_image.getSource(), image_filter));
+ old_image = new_image;
+ tracker.addImage(new_image, 0);
+ tracker.waitForID(0);
+ }
+ }
+ catch(InterruptedException excp)
+ {
+ System.out.println("ImageProcessor::processImage Image failed to load.");
+ System.out.println(excp);
+ return null;
+ }
+
+ return new_image;
+ }
+}
+
+
+class FilterNode
+{
+ private String name_;
+ private ImageFilter filter_;
+
+ FilterNode(String name, ImageFilter filter)
+ {
+ name_ = name;
+ filter_ = filter;
+ }
+
+ String getName()
+ {
+ return name_;
+ }
+
+ ImageFilter getFilter()
+ {
+ return filter_;
+ }
+}
diff --git a/java/ImageProcessing/framework/ListFiles.java b/java/ImageProcessing/framework/ListFiles.java
new file mode 100644
index 00000000000..fb409ab148d
--- /dev/null
+++ b/java/ImageProcessing/framework/ListFiles.java
@@ -0,0 +1,161 @@
+package imaging.framework;
+
+import java.net.*;
+import java.io.*;
+import java.applet.*;
+
+public class ListFiles
+{
+ public ListFiles ()
+ {
+ }
+
+ public ListFiles (FileBrowser browser, Applet parent)
+ {
+ this.browser_ = browser;
+ try
+ {
+ this.fileIcon_ = new Icon (parent.getCodeBase () + "doc01.gif", parent);
+ this.dirIcon_ = new Icon (parent.getCodeBase () + "file03.gif", parent);
+ }
+ catch (MalformedURLException e)
+ {
+ }
+ }
+
+ public String stripProtocolHeader (String url)
+ {
+ if (url.startsWith ("http://"))
+ {
+ return url.substring (7);
+ }
+ else
+ return url;
+ }
+
+ public int listFiles (String url, FileNode fileNode)
+ {
+ String s = this.stripProtocolHeader (url);
+ String hostname = s;
+ String directory = null;
+ int index = -1;
+
+ if ((index = s.indexOf ("/")) != -1)
+ {
+ hostname = s.substring (0, index);
+ directory = s.substring (index);
+ }
+ return this.listFiles (hostname, directory, fileNode);
+ }
+
+ public int listFiles (String url, String directory, FileNode fileNode)
+ {
+ boolean validDirectory = false;
+ int count = 0;
+ String hostname = this.stripProtocolHeader (url);
+ this.url_ = url;
+ this.directory_ = directory;
+ try
+ {
+ Socket sock = new Socket (hostname, 80);
+ PrintStream out = new PrintStream (sock.getOutputStream ());
+ DataInputStream in = new DataInputStream (sock.getInputStream ());
+ System.out.println ("Connected to: " + hostname);
+
+ String request = null;
+ if (directory.endsWith ("/"))
+ request = "GET " + directory + "\n\n";
+ else
+ request = "GET " + directory + "/\n\n";
+
+ System.out.println ("Sending request: " + request);
+
+ // Send the request
+ out.println (request);
+
+ String reply = null;
+ // Receive the reply
+
+ // Read all the data in a loop. Search for "Parent Directory"
+ // to verify that this indeed is a directory. If we encounter
+ // the string "<HTML>" then assume that this is an HTML page
+ // and therefore the directory contained "index.html"
+ while ((reply = in.readLine ()) != null)
+ {
+ if (validDirectory)
+ this.parse (reply, fileNode);
+ else
+ {
+ // Take a guess at the type of data we get back
+ if (reply.indexOf ("Parent Directory") != -1)
+ validDirectory = true;
+ else if ((reply.toUpperCase ().indexOf ("<HTML>") != -1) ||
+ (reply.toUpperCase ().indexOf ("<P>") != -1) ||
+ (reply.toUpperCase ().indexOf ("<TABLE") != -1))
+ return 0;
+ }
+ }
+ }
+ catch (MalformedURLException e)
+ {
+ System.err.println (e);
+ }
+ catch (IOException e)
+ {
+ System.err.println (e);
+ }
+ if (validDirectory == false)
+ return -1;
+ return 1;
+ }
+
+ private int parse (String s, FileNode fileNode)
+ {
+ int i= -1;
+ int j = -1;
+ int startIndex = -1;
+ int endIndex = -1;
+ boolean isFile = true;
+ String name = null;
+
+ if ((i = s.indexOf ("HREF=")) != -1)
+ startIndex = i + 6;
+ else
+ return -1;
+
+ if ((j = s.indexOf (">", i)) != -1)
+ endIndex = j - 1;
+ else
+ return -1;
+
+ // Check if this is a directory
+ if (s.charAt (endIndex - 1) == '/')
+ isFile = false;
+
+ if (endIndex >= startIndex)
+ {
+ name = s.substring (startIndex, endIndex);
+ if (browser_ != null)
+ {
+ // System.out.println (name);
+ if (isFile)
+ fileNode.addEntry (new FileNode (name, this.fileIcon_, null,
+ fileNode.app ()));
+ else
+ {
+ FileNode f = new FileNode (name, this.dirIcon_, this,
+ fileNode.app ());
+ fileNode.addEntry (f);
+ f.setExpandable (true);
+ }
+ }
+ }
+ return 0;
+ }
+
+ private FileBrowser browser_ = null;
+ private String url_ = null;
+ private String directory_ = null;
+ private Icon fileIcon_;
+ private Icon dirIcon_;
+}
diff --git a/java/ImageProcessing/framework/Options.java b/java/ImageProcessing/framework/Options.java
new file mode 100644
index 00000000000..edbe90ba904
--- /dev/null
+++ b/java/ImageProcessing/framework/Options.java
@@ -0,0 +1,25 @@
+package imaging.framework;
+
+import java.awt.*;
+
+class Options
+{
+ // Set GridBagConstraints
+ public static void constrain (Container container, Component component,
+ int gridx, int gridy,
+ int gridwidth, int gridheight,
+ int fill, int anchor)
+ {
+ GridBagConstraints c = new GridBagConstraints ();
+ GridBagLayout gbl = (GridBagLayout) container.getLayout ();
+
+ c.gridx = gridx;
+ c.gridy = gridy;
+ c.gridwidth = gridwidth;
+ c.gridheight = gridheight;
+ c.fill = fill;
+ c.anchor = anchor;
+ gbl.setConstraints (component, c);
+ container.add (component);
+ }
+}
diff --git a/java/ImageProcessing/framework/Separator.java b/java/ImageProcessing/framework/Separator.java
new file mode 100644
index 00000000000..6bd610e1ad9
--- /dev/null
+++ b/java/ImageProcessing/framework/Separator.java
@@ -0,0 +1,90 @@
+package gjt;
+
+import java.awt.*;
+
+/**
+ * A separator that is drawn either vertically or horizontally
+ * depending upon how it is laid out. Can be drawn either
+ * etched-in or etched-out, with varying thicknesses. Both
+ * thickness and etching are settable at construction time
+ * only.<p>
+ *
+ * Default thickness is 2 pixels and default etching is
+ * Etching.IN. Note that thicknesses greater than 4 loose the
+ * etching effect.<p>
+ *
+ * @version 1.0, Apr 1 1996
+ * @author David Geary
+ * @see Etching
+ * @see gjt.test.SeparatorTest
+ */
+public class Separator extends Canvas {
+ static private Etching _defaultEtching = Etching.IN;
+ static private int _defaultThickness = 2;
+
+ private Etching etching;
+ private int thickness;
+
+ public Separator() {
+ this(_defaultThickness, _defaultEtching);
+ }
+ public Separator(int thickness) {
+ this(thickness, _defaultEtching);
+ }
+ public Separator(Etching etching) {
+ this(_defaultThickness, etching);
+ }
+ public Separator(int thickness, Etching etching) {
+ this.etching = etching;
+ this.thickness = thickness;
+ resize(thickness, thickness);
+ }
+ public Dimension minimumSize() {
+ return preferredSize();
+ }
+ public Dimension preferredSize() {
+ return new Dimension(thickness, thickness);
+ }
+ public void paint(Graphics g) {
+ Dimension size = size();
+ Color brighter = getBackground().brighter().brighter();
+ Color darker = getBackground().darker().darker();
+
+ if(etching == Etching.IN) {
+ if(size.width > size.height)
+ paintHorizontal(g, size, darker, brighter);
+ else
+ paintVertical(g, size, darker, brighter);
+ }
+ else {
+ if(size.width > size.height)
+ paintHorizontal(g, size, brighter, darker);
+ else
+ paintVertical(g, size, brighter, darker);
+ }
+ }
+ public String paramString() {
+ Dimension size = size();
+ Orientation orient = size.width > size.height ?
+ Orientation.HORIZONTAL :
+ Orientation.VERTICAL;
+ return super.paramString() + "thickness=" +
+ thickness + "," + etching + "," + orient;
+ }
+ private void paintHorizontal(Graphics g, Dimension size,
+ Color top, Color bottom) {
+ g.setColor(top);
+ g.fillRect(0, (size.height/2) - (thickness/2),
+ size.width, thickness/2);
+ g.setColor(bottom);
+ g.fillRect(0, size.height/2, size.width, thickness/2);
+ }
+ private void paintVertical(Graphics g, Dimension size,
+ Color left, Color right) {
+ g.setColor(left);
+ g.fillRect((size.width/2) - (thickness/2),
+ 0, thickness/2, size.height);
+ g.setColor(right);
+ g.fillRect(size.width/2, 0, thickness/2, size.height);
+ }
+}
diff --git a/java/ImageProcessing/framework/StatusDisplay.java b/java/ImageProcessing/framework/StatusDisplay.java
new file mode 100644
index 00000000000..e20e9b8384d
--- /dev/null
+++ b/java/ImageProcessing/framework/StatusDisplay.java
@@ -0,0 +1,23 @@
+package imaging.framework;
+
+import java.awt.*;
+import gjt.Separator;
+
+class StatusDisplay extends Panel
+{
+ public StatusDisplay ()
+ {
+ this.setLayout (new BorderLayout ());
+ this.textField_.setEditable (false);
+ this.add ("North", new Separator ());
+ this.add ("Center", this.textField_);
+ this.add ("South", new Separator ());
+ }
+
+ public void setText (String s)
+ {
+ this.textField_.setText (s);
+ }
+
+ private TextField textField_ = new TextField ();
+}
diff --git a/java/ImageProcessing/framework/URLFrame.java b/java/ImageProcessing/framework/URLFrame.java
new file mode 100644
index 00000000000..d9cdca04a5c
--- /dev/null
+++ b/java/ImageProcessing/framework/URLFrame.java
@@ -0,0 +1,106 @@
+package imaging.framework;
+
+import java.awt.*;
+import java.awt.image.*;
+import java.net.*;
+import java.io.*;
+import gjt.ComponentScroller;
+
+class URLFrame extends Frame
+{
+ public URLFrame (String title, ImageApp parent)
+ {
+ super (title);
+
+ this.parent_ = parent;
+ this.resize (500,130);
+ this.setLayout (new BorderLayout ());
+
+ Panel textPanel = new Panel ();
+ textPanel.setLayout (new BorderLayout ());
+ textPanel.add ("North", new Label ("Image Location:"));
+ textPanel.add ("Center", this.openURLText_);
+
+ Panel buttonPanel = new Panel ();
+ buttonPanel.setLayout (new FlowLayout (FlowLayout.CENTER));
+ buttonPanel.add (this.browseButton_);
+ buttonPanel.add (this.loadButton_);
+ buttonPanel.add (this.clearButton_);
+ buttonPanel.add (this.cancelButton_);
+
+ this.add ("North", textPanel);
+ this.add ("South", buttonPanel);
+ this.loadButton_.nextFocus ();
+ }
+
+ private int browseFiles ()
+ {
+ String pString = this.openURLText_.getText ();
+ if (pString.compareTo ("ru") == 0)
+ pString = "http://www.cs/~pjain/java";
+
+ fileBrowser_ = new FileBrowser ("Browse", this.parent_);
+ // this.scroller_ = new ComponentScroller (fileBrowser_);
+ ListFiles list = new ListFiles (this.fileBrowser_, this.parent_);
+ return this.fileBrowser_.initialize (pString, list);
+ }
+
+ // Handle all action events
+ public boolean action (Event e, Object arg)
+ {
+ if (e.target instanceof Button)
+ {
+ if (e.target == this.loadButton_)
+ {
+ this.parent_.openURL (this.openURLText_.getText ());
+ this.dispose ();
+ }
+ else if (e.target == this.clearButton_)
+ {
+ this.openURLText_.setText (new String ());
+ this.openURLText_.requestFocus ();
+ }
+ else if (e.target == this.cancelButton_)
+ this.dispose ();
+ else if (e.target == this.browseButton_)
+ {
+ this.dispose ();
+ ListFiles list = new ListFiles ();
+ switch (this.browseFiles ())
+ {
+ case 1:
+ this.fileBrowser_.show ();
+ break;
+ case 0:
+ DialogManager.popDialog (DialogType.MALFORMED_URL,
+ "Error: Directory contains index.html");
+ break;
+ default:
+ DialogManager.popDialog (DialogType.MALFORMED_URL,
+ "Error: Malformed URL");
+ break;
+ }
+ }
+
+ validate ();
+ return true;
+ }
+ else
+ return false;
+ }
+
+ // Create the Open URL Frame and also the buttons which appear in
+ // it
+ private Button browseButton_ = new Button ("Browse");
+ private Button loadButton_ = new Button ("Load");
+ private Button clearButton_ = new Button ("Clear");
+ private Button cancelButton_ = new Button ("Cancel");
+
+ private TextField openURLText_ = new TextField (40);
+
+ private FileBrowser fileBrowser_ = null;
+ private ImageApp parent_;
+ private ComponentScroller scroller_;
+
+}
+