apple2-image-encoder/src/main/java/a2geek/apple2/image/encoder/ui/ImageEncoderApp.java

305 lines
12 KiB
Java

package a2geek.apple2.image.encoder.ui;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.util.prefs.Preferences;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import com.sun.from.TableSorter;
import a2geek.apple2.image.encoder.A2Image;
import a2geek.apple2.image.encoder.encode.A2Encoder;
import a2geek.apple2.image.encoder.util.DefaultSwingProgressListener;
import a2geek.apple2.image.encoder.util.ProgressListener;
public class ImageEncoderApp {
private static final String WORKING_DIRECTORY = "WorkingDirectory";
private static final String MAXIMUM_COMPRESSED_SIZE = "MaximumCompressedSize";
private static ImageEncoderFrame appFrame;
private static ImageFileFilter openFilter;
private static ImageFileFilter saveFilter;
private static BufferedImage originalImage;
private static A2Image a2image;
private static ListSelectionListener listSelectionListener = null;
private static Preferences prefs = null;
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Throwable ignored) {
}
prefs = Preferences.userRoot().node("/a2geek/apple2/ImageEncoderApp");
openFilter = new ImageFileFilter(ImageIO.getReaderFormatNames());
saveFilter = new ImageFileFilter(ImageIO.getWriterFormatNames());
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
appFrame = new ImageEncoderFrame();
appFrame.getOriginalImageScrollPane().setTransferHandler(new DropHandler());
appFrame.getMaxSizeTextField().setText(prefs.get(MAXIMUM_COMPRESSED_SIZE, "8192"));
appFrame.setVisible(true);
}
});
}
public static void loadImage() {
JFileChooser chooser = new JFileChooser(getWorkingDirectory());
chooser.setFileFilter(openFilter);
chooser.setDialogTitle("Choose an image to convert");
int action = chooser.showOpenDialog(appFrame);
if (action == JFileChooser.APPROVE_OPTION) {
try {
File file = chooser.getSelectedFile();
setWorkingDirectory(file);
loadImage(file);
} catch (Throwable t) {
showErrorDialog("loading an image", t);
}
}
}
public static void loadImage(File file) throws IOException {
originalImage = ImageIO.read(file);
ImageIcon imageIcon = new ImageIcon(originalImage);
JScrollPane pane = appFrame.getOriginalImageScrollPane();
JLabel imageIconLabel = new JLabel();
imageIconLabel.setHorizontalAlignment(JLabel.CENTER);
imageIconLabel.setVerticalAlignment(JLabel.CENTER);
imageIconLabel.setVerticalTextPosition(JLabel.CENTER);
imageIconLabel.setHorizontalTextPosition(JLabel.CENTER);
imageIconLabel.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createLoweredBevelBorder(),
BorderFactory.createEmptyBorder(5,5,5,5)));
imageIconLabel.setIcon(imageIcon);
pane.setViewportView(imageIconLabel);
enableConvertButton();
disableSaveConvertedImageButton();
resetImageScrollPane();
resetCompressionTable();
StringBuffer buf = new StringBuffer();
buf.append("This image is ");
buf.append(originalImage.getWidth());
buf.append("x");
buf.append(originalImage.getHeight());
buf.append(".");
appFrame.originalInfoLabel.setText(buf.toString());
}
public static void showErrorDialog(String operation, Throwable t) {
StringBuffer buf = new StringBuffer();
buf.append("An error occurred while ");
buf.append(operation);
buf.append(". The Java exception message reported is '");
buf.append(t.getLocalizedMessage());
buf.append("' for exception '");
buf.append(t.getClass().getName());
buf.append("'.");
JOptionPane.showMessageDialog(appFrame, buf.toString(), "An error occurred!", JOptionPane.ERROR_MESSAGE);
}
public static String getAboutText() {
StringBuffer buf = new StringBuffer();
buf.append("\n");
buf.append("Apple II Image Encoder\n");
buf.append("Copyright (c) 2005\n");
buf.append("\n");
buf.append("The image encoder stems from trying to convert a 'modern' 16 million color image into a ");
buf.append("IIgs super hires 320x200 color. As usual, the story quickly turned complicated since the ");
buf.append("IIgs color palette isn't one set of 256 colors but 16 palettes of 16 colors. The image ");
buf.append("tools can generate a beautiful 256 color image or a fairly good 16 color image. However, ");
buf.append("I wanted something that could take care of the IIgs palette.\n");
buf.append("\n");
buf.append("From there, I started getting carried away...");
return buf.toString();
}
public static void convertImage() {
final ProgressListener listener = new DefaultSwingProgressListener(appFrame,
"Converting image - please wait...", "Starting up");
Thread thread = new Thread() {
public void run() {
GraphicsModeComboBoxModel model = (GraphicsModeComboBoxModel)appFrame.getGraphicModeComboBox().getModel();
Class imageClass = model.getSelectedClass();
boolean keepAspectRatio = appFrame.getKeepAspectRatioCheckBox().isSelected();
try {
Constructor constructor = imageClass.getDeclaredConstructor(
new Class[] { BufferedImage.class, boolean.class, ProgressListener.class });
a2image = (A2Image)constructor.newInstance(new Object[] { originalImage, keepAspectRatio, listener });
if (listener.isCancelled()) {
a2image = null;
return;
}
} catch (Throwable t) {
showErrorDialog("Unable to create graphics mode handler.", t);
return;
}
BufferedImage displayImage = a2image.getImage();
if (displayImage.getWidth() < 320) {
displayImage = new BufferedImage(a2image.getWidth()*5, a2image.getHeight()*5,
BufferedImage.TYPE_INT_RGB);
Graphics g = displayImage.getGraphics();
g.drawImage(a2image.getImage(), 0, 0, displayImage.getWidth(), displayImage.getHeight(), null);
g.dispose();
}
ImageIcon imageIcon = new ImageIcon(displayImage);
JScrollPane pane = appFrame.getConvertedImageScrollPane();
JLabel imageIconLabel = new JLabel();
imageIconLabel.setHorizontalAlignment(JLabel.CENTER);
imageIconLabel.setVerticalAlignment(JLabel.CENTER);
imageIconLabel.setVerticalTextPosition(JLabel.CENTER);
imageIconLabel.setHorizontalTextPosition(JLabel.CENTER);
imageIconLabel.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createLoweredBevelBorder(),
BorderFactory.createEmptyBorder(5,5,5,5)));
imageIconLabel.setIcon(imageIcon);
pane.setViewportView(imageIconLabel);
enableSaveConvertedImageButton();
enableCompressButton();
resetCompressionTable();
}
};
thread.setPriority(Thread.NORM_PRIORITY);
thread.start();
}
public static void saveImage() {
JFileChooser chooser = new JFileChooser(getWorkingDirectory());
chooser.setFileFilter(saveFilter);
chooser.setDialogTitle("Choose where to save your image");
int action = chooser.showSaveDialog(appFrame);
if (action == JFileChooser.APPROVE_OPTION) {
try {
File file = chooser.getSelectedFile();
setWorkingDirectory(file);
FileOutputStream output = new FileOutputStream(file);
output.write(a2image.getBytes());
output.close();
} catch (Throwable t) {
showErrorDialog("saving an image", t);
}
}
}
public static void compressAll() {
final ProgressListener listener = new DefaultSwingProgressListener(appFrame,
"Please wait - compressing images...", "Initializing.");
Thread thread = new Thread() {
public void run() {
try {
int maxSize = Integer.parseInt(appFrame.getMaxSizeTextField().getText());
prefs.putInt(MAXIMUM_COMPRESSED_SIZE, maxSize);
JTable table = appFrame.getCompressionTable();
EncoderTableModel model = new EncoderTableModel(a2image, maxSize, listener);
TableSorter sorter = new TableSorter(model);
table.setModel(sorter);
DefaultTableCellRenderer renderer = new EncoderTableCellRenderer(model, maxSize);
table.setDefaultRenderer(String.class, renderer);
table.setDefaultRenderer(Integer.class, renderer);
sorter.setTableHeader(table.getTableHeader());
ListSelectionModel listSelectionModel = table.getSelectionModel();
listSelectionModel.removeListSelectionListener(getListSelectionListener());
listSelectionModel.addListSelectionListener(getListSelectionListener());
} catch (Throwable t) {
showErrorDialog("compressing", t);
}
}
};
thread.setPriority(Thread.NORM_PRIORITY);
thread.run();
}
private static ListSelectionListener getListSelectionListener() {
if (listSelectionListener == null) {
listSelectionListener = new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
if (e.getValueIsAdjusting()) return; //Ignore extra messages.
ListSelectionModel lsm = (ListSelectionModel)e.getSource();
appFrame.getSaveEncodedImageButton().setEnabled(!lsm.isSelectionEmpty());
}
};
}
return listSelectionListener;
}
public static void saveEncodedImage() {
JFileChooser chooser = new JFileChooser(getWorkingDirectory());
chooser.setDialogTitle("Choose where to save your data");
int action = chooser.showSaveDialog(appFrame);
if (action == JFileChooser.APPROVE_OPTION) {
try {
File file = chooser.getSelectedFile();
setWorkingDirectory(file);
TableSorter sorter = (TableSorter)appFrame.getCompressionTable().getModel();
EncoderTableModel model = (EncoderTableModel)sorter.getTableModel();
A2Encoder encoder = model.getSelectedEncoder(appFrame.getCompressionTable().getSelectedRow());
FileOutputStream output = new FileOutputStream(file);
output.write(encoder.getData(), 0, encoder.getSize());
output.close();
} catch (Throwable t) {
showErrorDialog("saving an image", t);
}
}
}
public static void enableConvertButton() {
appFrame.getConvertButton().setEnabled(true);
}
public static void disableConvertButton() {
appFrame.getConvertButton().setEnabled(false);
}
public static void enableSaveConvertedImageButton() {
appFrame.getSaveConvertedImageButton().setEnabled(true);
}
public static void disableSaveConvertedImageButton() {
appFrame.getSaveConvertedImageButton().setEnabled(false);
}
public static void resetImageScrollPane() {
appFrame.getConvertedImageScrollPane().setViewportView(appFrame.noImageConvertedLabel);
}
public static void resetCompressionTable() {
appFrame.getCompressionTable().setModel(new DefaultTableModel()); // empty it out
}
public static void enableCompressButton() {
appFrame.getCompressButton().setEnabled(true);
}
public static void disableCompressButton() {
appFrame.getCompressButton().setEnabled(false);
}
private static String getWorkingDirectory() {
return prefs.get(WORKING_DIRECTORY, null);
}
private static void setWorkingDirectory(File file) {
prefs.put(WORKING_DIRECTORY, file.getParentFile() == null ?
null : file.getParentFile().getAbsolutePath());
}
}