package iiuf.jai; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionAdapter; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.JFrame; import javax.swing.JPanel; /** (c) 1999, IIUF<p> Projection Profile @author $Author: hassan $ @version $Revision: 1.1 $ */ public class ProjectionProfile { /** Profile direction. */ public final static int VERTICAL = 0; public final static int HORIZONTAL = 1; /** Original projection profile. */ protected int[] profile; /** Construct a projection profile. */ public ProjectionProfile(int[] profile) { this.profile = profile; } /** Get the profile size. */ public int size() { return profile.length; } /** Get a copy of the original profile. */ public int[] getArray() { return profile; } /** Smooth the profile. */ public void smooth() { for (int i = 0; i < size()-1; i++) { profile[i] = (profile[i]+profile[i+1])/2; } } /** Calculate the derivative of the profile. */ public void derive() { for (int i = 0; i < size()-1; i++) { profile[i] = profile[i+1]-profile[i]; } profile[size()-1] = 0; } /** Tries to find the ascent between start and end, from top to bottom. Ascent: max(dy) for positive dy's */ public int findAscent(int start, int end) { int peak_i = 0; int peak_diff = 0; for (int i = start; i < end-1; i++) { int d = profile[i+1] - profile[i]; if (d > peak_diff) { peak_diff = d; peak_i = i; } } return peak_i; } /** Tries to find the ascent in the upper half of the word. */ public int findAscent() { return findAscent(0, profile.length/2); } /** Tries to find the base line between start and end, from bottom to top. Baseline: max(dy) for negative dy's */ public int findBaseline(int start, int end) { int peak_i = 0; int peak_diff = 0; if (start < end) { int tmp = start; start = end; end = tmp; } for (int i = start; i > end; --i) { int d = profile[i-1] - profile[i]; if (d > peak_diff) { peak_diff = d; peak_i = i; } } return peak_i; } public int findBaseline() { return findBaseline(profile.length/2, profile.length-1); } /** Returns the position of the maximum between start and end. */ public int getMax(int start, int end) { int max_i = 0; int max_val = 0; for (int i = start; i < end-1; i++) { if (profile[i] > max_val) { max_i = i; max_val = profile[i]; } } return max_i; } /** Creates a visual representation of this profile. */ public JPanel getVerticalPanel() { return new ProfilePanel(VERTICAL); } public JPanel getHorizontalPanel() { return new ProfilePanel(HORIZONTAL); } /** Paints the profile in a certain direction and at a certain position. @param g The current graphics context @param direction VERTICAL or HORIZONTAL @param x Position @param y Pposition */ public void paint(Graphics2D g, int direction, int x, int y) { for (int i = 0; i < size(); i++) { if (direction == VERTICAL) { g.drawLine(x, y+i, x+profile[i], y+i); } else { g.drawLine(x+i, y, x+i, y+profile[i]); } } } /** A class used to display projection profiles. */ private class ProfilePanel extends JPanel { protected int direction; public ProfilePanel(int direction) { this.direction = direction; int maxval = profile[getMax(0, ProjectionProfile.this.size())]; if (direction == ProjectionProfile.VERTICAL) { setMinimumSize(new Dimension(maxval, ProjectionProfile.this.size())); setPreferredSize(new Dimension(maxval, ProjectionProfile.this.size())); } else { setMinimumSize(new Dimension(ProjectionProfile.this.size(), maxval)); setPreferredSize(new Dimension(ProjectionProfile.this.size(), maxval)); } } protected void paintComponent(Graphics g) { Graphics2D g2 = (Graphics2D) g; Dimension size = getSize(null); g2.setColor(getBackground()); g2.fillRect(0, 0, size.width, size.height); g2.setColor(Color.black); ProjectionProfile.this.paint(g2, direction, 0, 0); } } }