diff --git a/pom.xml b/pom.xml
index d1e4815..1f5d5e1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,18 +1,19 @@
-
+
4.0.0
a2geek.apple2
apple2-image-encoder
- 4.4.0-FINAL
+ 5.0.0-SNAPSHOT
Apple II Image Encoder
A utility that got out of hand and became an application to move modern images to the Apple II platform.
-
+
1.8
1.8
- 2.4.3
+ 3.0.0
4.12
+ 1.14
@@ -22,6 +23,23 @@
${junit.version}
test
+
+ org.apache.commons
+ commons-compress
+ ${commons-compress.version}
+
+
+ org.brotli
+ dec
+ 0.1.2
+ true
+
+
+ org.tukaani
+ xz
+ 1.6
+ true
+
@@ -52,4 +70,5 @@
-
\ No newline at end of file
+
+
\ No newline at end of file
diff --git a/src/main/java/a2geek/apple2/image/encoder/encode/A2EncoderFactory.java b/src/main/java/a2geek/apple2/image/encoder/encode/A2EncoderFactory.java
new file mode 100644
index 0000000..24ec285
--- /dev/null
+++ b/src/main/java/a2geek/apple2/image/encoder/encode/A2EncoderFactory.java
@@ -0,0 +1,27 @@
+package a2geek.apple2.image.encoder.encode;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.compress.compressors.CompressorStreamFactory;
+
+public abstract class A2EncoderFactory {
+ public static List getEncoders() {
+ List list = new ArrayList<>();
+ list.add(new RleEncoder());
+ list.add(new VariableRleEncoder());
+ list.add(new PackBitsEncoder());
+ list.add(new BitPack1());
+ list.add(new BitPack2());
+ list.add(new BitPack3());
+ list.add(new GZipEncoder());
+ list.add(new ZipEncoder());
+ // From Apache Commons
+ for (String outputProvider : CompressorStreamFactory.findAvailableCompressorOutputStreamProviders().keySet()) {
+ // PACK200 does nothing for some reason, so just ignoring it
+ if (CompressorStreamFactory.PACK200.equals(outputProvider)) continue;
+ list.add(new CommonsCodecEncoder(outputProvider));
+ }
+ return list;
+ }
+}
diff --git a/src/main/java/a2geek/apple2/image/encoder/encode/CommonsCodecEncoder.java b/src/main/java/a2geek/apple2/image/encoder/encode/CommonsCodecEncoder.java
new file mode 100644
index 0000000..f8e97f8
--- /dev/null
+++ b/src/main/java/a2geek/apple2/image/encoder/encode/CommonsCodecEncoder.java
@@ -0,0 +1,48 @@
+package a2geek.apple2.image.encoder.encode;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import org.apache.commons.compress.compressors.CompressorException;
+import org.apache.commons.compress.compressors.CompressorOutputStream;
+import org.apache.commons.compress.compressors.CompressorStreamFactory;
+import org.apache.commons.compress.compressors.CompressorStreamProvider;
+
+import a2geek.apple2.image.encoder.A2Image;
+import a2geek.apple2.image.encoder.ui.ImageEncoderApp;
+
+public class CommonsCodecEncoder extends A2Encoder {
+ private CompressorStreamProvider provider = new CompressorStreamFactory();
+ private String name;
+ private String title;
+
+ public CommonsCodecEncoder(String name) {
+ this(name, name.toUpperCase());
+ }
+ public CommonsCodecEncoder(String name, String title) {
+ this.name = name;
+ this.title = title;
+ }
+
+ @Override
+ public void encode(A2Image a2image, int maxSize) {
+ try {
+ reset(maxSize);
+ ByteArrayOutputStream ba = new ByteArrayOutputStream();
+ CompressorOutputStream out = provider.createCompressorOutputStream(name, ba);
+ out.write(a2image.getBytes());
+ out.close();
+ for (byte b : ba.toByteArray()) {
+ addByte(b);
+ }
+ } catch (CompressorException | IOException ex) {
+ ImageEncoderApp.showErrorDialog("Apache Commons '" + name + "' compress", ex);
+ }
+ }
+
+ @Override
+ public String getTitle() {
+ return title;
+ }
+
+}
diff --git a/src/main/java/a2geek/apple2/image/encoder/ui/EncoderTableModel.java b/src/main/java/a2geek/apple2/image/encoder/ui/EncoderTableModel.java
index b630807..9cb1ee5 100644
--- a/src/main/java/a2geek/apple2/image/encoder/ui/EncoderTableModel.java
+++ b/src/main/java/a2geek/apple2/image/encoder/ui/EncoderTableModel.java
@@ -7,14 +7,7 @@ import javax.swing.table.AbstractTableModel;
import a2geek.apple2.image.encoder.A2Image;
import a2geek.apple2.image.encoder.encode.A2Encoder;
-import a2geek.apple2.image.encoder.encode.BitPack1;
-import a2geek.apple2.image.encoder.encode.BitPack2;
-import a2geek.apple2.image.encoder.encode.BitPack3;
-import a2geek.apple2.image.encoder.encode.GZipEncoder;
-import a2geek.apple2.image.encoder.encode.PackBitsEncoder;
-import a2geek.apple2.image.encoder.encode.RleEncoder;
-import a2geek.apple2.image.encoder.encode.VariableRleEncoder;
-import a2geek.apple2.image.encoder.encode.ZipEncoder;
+import a2geek.apple2.image.encoder.encode.A2EncoderFactory;
import a2geek.apple2.image.encoder.util.ProgressListener;
/**
@@ -25,7 +18,7 @@ import a2geek.apple2.image.encoder.util.ProgressListener;
*/
@SuppressWarnings("serial")
public class EncoderTableModel extends AbstractTableModel {
- private List encoders = new ArrayList();
+ private final List results = new ArrayList<>();
private byte[] data = null;
private String[] headers = new String[] { "Type", "Original", "Compressed", "%" };
/**
@@ -33,30 +26,18 @@ public class EncoderTableModel extends AbstractTableModel {
*/
public EncoderTableModel(A2Image image, int maxSize, ProgressListener listener) {
this.data = image.getBytes();
-
- Class[] encoderClasses = new Class[] {
- RleEncoder.class,
- VariableRleEncoder.class,
- PackBitsEncoder.class,
- BitPack1.class,
- BitPack2.class,
- BitPack3.class,
- GZipEncoder.class,
- ZipEncoder.class
- };
+
int count = 0;
- for (Class encoderClass : encoderClasses) {
- if (listener != null && listener.isCancelled()) return;
- A2Encoder a2encoder = null;
+ int size = A2EncoderFactory.getEncoders().size();
+ for (A2Encoder encoder : A2EncoderFactory.getEncoders()) {
try {
- a2encoder = (A2Encoder)encoderClass.newInstance();
+ if (listener != null && listener.isCancelled()) return;
count++;
- if (listener != null) listener.update(count, encoderClasses.length, a2encoder.getTitle());
- a2encoder.encode(image, maxSize);
- encoders.add(a2encoder);
+ if (listener != null) listener.update(count, size, encoder.getTitle());
+ encoder.encode(image, maxSize);
+ results.add(encoder);
} catch (Throwable t) {
- // FIXME ignore errors...
- //ImageEncoderApp.showErrorDialog(a2encoder.getTitle(), t);
+ // Ignoring these as some are expected to throw errors if boundaries are missed
}
}
}
@@ -70,7 +51,7 @@ public class EncoderTableModel extends AbstractTableModel {
* Answer with the number of rows.
*/
public int getRowCount() {
- return encoders.size();
+ return results.size();
}
/**
* Answer with the number of columns.
@@ -84,13 +65,13 @@ public class EncoderTableModel extends AbstractTableModel {
public Object getValueAt(int rowIndex, int columnIndex) {
switch (columnIndex) {
case 0:
- return encoders.get(rowIndex).getTitle();
+ return results.get(rowIndex).getTitle();
case 1:
return data.length;
case 2:
- return encoders.get(rowIndex).getSize();
+ return results.get(rowIndex).getSize();
case 3:
- return (encoders.get(rowIndex).getSize() * 100) / data.length;
+ return (results.get(rowIndex).getSize() * 100) / data.length;
default:
return "Unknown";
}
@@ -116,6 +97,6 @@ public class EncoderTableModel extends AbstractTableModel {
* Answer with the specific A2Encoder.
*/
public A2Encoder getSelectedEncoder(int rowIndex) {
- return encoders.get(rowIndex);
+ return results.get(rowIndex);
}
}