305 lines
12 KiB
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());
|
|
}
|
|
}
|