package cx.prutser.sudoku.capture;
import com.jhlabs.image.PerspectiveFilter;
import com.jhlabs.image.TransformFilter;
import cx.prutser.sudoku.ocr.GraphicalSolver;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.net.URL;
/**
* @author Erik van Zijst
*/
public class SnapshotDialog extends JFrame {
// image taken from http://www.ajaxload.info
private static final String ANIMATION_FILE = "wait1.gif";
private static final long SEARCH_TIMEOUT = 5000L;
public SnapshotDialog(Image image, final GraphicalSolver solver) {
setTitle("Snapshot");
final JPanel glass = createAnimationOverlay();
final BufferedImage bi = CaptureUtils.createBufferedImage(image, BufferedImage.TYPE_INT_RGB);
final int width = bi.getWidth();
final int height = bi.getHeight();
final ApertureImage apertureImage = new ApertureImage(bi);
final JButton button = new JButton("Solve");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Solve!");
glass.setVisible(true);
apertureImage.setFixed(true);
button.setEnabled(false);
Thread t = new Thread(new Runnable() {
public void run() {
java.util.List<Point> corners = apertureImage.getCorners();
PerspectiveFilter filter = new PerspectiveFilter();
filter.quadToUnitSquare(
(float)(corners.get(0).getX() / width), (float)(corners.get(0).getY() / height),
(float)(corners.get(1).getX() / width), (float)(corners.get(1).getY() / height),
(float)(corners.get(2).getX() / width), (float)(corners.get(2).getY() / height),
(float)(corners.get(3).getX() / width), (float)(corners.get(3).getY() / height));
filter.setClip(true);
filter.setInterpolation(TransformFilter.BILINEAR);
BufferedImage corrected = new BufferedImage(bi.getWidth(null), bi.getHeight(null), BufferedImage.TYPE_INT_RGB);
filter.filter(bi, corrected);
final int newSize = Math.min(bi.getWidth(), bi.getHeight());
final BufferedImage target = CaptureUtils.createBufferedImage(
corrected.getScaledInstance(newSize, newSize, Image.SCALE_SMOOTH),
BufferedImage.TYPE_INT_RGB);
// write stretched image to the screen:
SwingUtilities.invokeLater(new Runnable() {
public void run() {
apertureImage.setImage(target);
}
});
final BufferedImage solution = solver.solve(target, SEARCH_TIMEOUT);
// write solution to the screen:
SwingUtilities.invokeLater(new Runnable() {
public void run() {
apertureImage.setImage(solution);
glass.setVisible(false);
}
});
}
}, "SolverThread");
t.setDaemon(true);
t.start();
}
});
GridBagLayout layout = new GridBagLayout();
GridBagConstraints c = new GridBagConstraints();
setLayout(layout);
c.fill = GridBagConstraints.NONE;
c.gridwidth = GridBagConstraints.REMAINDER;
layout.setConstraints(apertureImage, c);
add(apertureImage);
c.fill = GridBagConstraints.HORIZONTAL;
layout.setConstraints(button, c);
add(button);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
setVisible(false);
dispose();
}
});
pack();
setResizable(false);
setVisible(true);
}
private JPanel createAnimationOverlay() {
final JPanel glass = (JPanel)getGlassPane();
glass.setLayout(new GridBagLayout());
final URL iconUrl = getClass().getResource("/" + ANIMATION_FILE);
if (iconUrl == null) {
System.err.println("Animation file " + ANIMATION_FILE + " not found on classpath.");
} else {
ImageIcon ii = new ImageIcon(iconUrl);
JLabel label = new JLabel("Solving...", ii, JLabel.CENTER);
Font font = label.getFont().deriveFont(Font.BOLD, 20);
label.setFont(font);
label.setVerticalTextPosition(JLabel.BOTTOM);
label.setHorizontalTextPosition(JLabel.CENTER);
glass.add(label);
}
return glass;
}
}