diff --git a/src/main/java/azgracompress/compression/CompressorDecompressorBase.java b/src/main/java/azgracompress/compression/CompressorDecompressorBase.java
index e91e4ff0a2dde7065d2887dd161a5c464d0b4f27..9b16a04b3c9689a1bc28f7aabadca395fba08372 100644
--- a/src/main/java/azgracompress/compression/CompressorDecompressorBase.java
+++ b/src/main/java/azgracompress/compression/CompressorDecompressorBase.java
@@ -6,9 +6,11 @@ public abstract class CompressorDecompressorBase {
public static final String EXTENSTION = ".QCMP";
protected final ParsedCliOptions options;
+ protected final int codebookSize;
public CompressorDecompressorBase(ParsedCliOptions options) {
this.options = options;
+ this.codebookSize = (int) Math.pow(2, this.options.getBitsPerPixel());
}
protected int[] getPlaneIndicesForCompression() {
diff --git a/src/main/java/azgracompress/compression/ImageCompressor.java b/src/main/java/azgracompress/compression/ImageCompressor.java
index cea032642f4eb9a275615c679d12184ad56a99cf..9f0ed92889886b34ca612f49e23fd08a3be5ba59 100644
--- a/src/main/java/azgracompress/compression/ImageCompressor.java
+++ b/src/main/java/azgracompress/compression/ImageCompressor.java
@@ -1,15 +1,12 @@
package azgracompress.compression;
import azgracompress.cli.ParsedCliOptions;
-import azgracompress.U16;
import azgracompress.data.Chunk2D;
import azgracompress.data.ImageU16;
import azgracompress.data.V2i;
import azgracompress.fileformat.QCMPFileHeader;
import azgracompress.io.OutBitStream;
import azgracompress.io.RawDataIO;
-import azgracompress.quantization.scalar.LloydMaxU16ScalarQuantization;
-import azgracompress.quantization.scalar.ScalarQuantizer;
import azgracompress.quantization.vector.CodebookEntry;
import azgracompress.quantization.vector.LBGResult;
import azgracompress.quantization.vector.LBGVectorQuantizer;
@@ -43,9 +40,11 @@ public class ImageCompressor extends CompressorDecompressorBase {
boolean compressionResult = true;
switch (options.getQuantizationType()) {
- case Scalar:
- compressUsingScalarQuantization(dataOutputStream);
- break;
+ case Scalar: {
+ SQImageCompressor compressor = new SQImageCompressor(options);
+ compressor.compress(dataOutputStream);
+ }
+ break;
case Vector1D:
case Vector2D:
compressUsingVectorQuantization(dataOutputStream);
@@ -62,14 +61,6 @@ public class ImageCompressor extends CompressorDecompressorBase {
fos.close();
}
-
- private ScalarQuantizer getScalarQuantizerFromPlane(final ImageU16 plane) {
-
- LloydMaxU16ScalarQuantization lloydMax = new LloydMaxU16ScalarQuantization(plane.getData(), codebookSize);
- lloydMax.train(false);
- return new ScalarQuantizer(U16.Min, U16.Max, lloydMax.getCentroids());
- }
-
private int[][] getPlaneVectors(final ImageU16 plane) {
final V2i qVector = options.getVectorDimension();
@@ -153,14 +144,6 @@ public class ImageCompressor extends CompressorDecompressorBase {
return header;
}
- private void writeCodebookToOutputStream(final ScalarQuantizer quantizer,
- DataOutputStream compressStream) throws IOException {
- final int[] centroids = quantizer.getCentroids();
- for (final int quantizationValue : centroids) {
- compressStream.writeShort(quantizationValue);
- }
- }
-
private void writeCodebookToOutputStream(final VectorQuantizer quantizer,
DataOutputStream compressStream) throws IOException {
final CodebookEntry[] codebook = quantizer.getCodebook();
@@ -171,44 +154,4 @@ public class ImageCompressor extends CompressorDecompressorBase {
}
}
}
-
-
- private void compressUsingScalarQuantization(DataOutputStream compressStream) throws Exception {
- ScalarQuantizer quantizer = null;
- if (options.hasReferencePlaneIndex()) {
- final ImageU16 referencePlane = RawDataIO.loadImageU16(options.getInputFile(),
- options.getImageDimension(),
- options.getReferencePlaneIndex());
-
- Log("Creating codebook from reference plane...");
- quantizer = getScalarQuantizerFromPlane(referencePlane);
- writeCodebookToOutputStream(quantizer, compressStream);
- Log("Wrote reference codebook.");
- }
-
- final int[] planeIndices = getPlaneIndicesForCompression();
-
- for (final int planeIndex : planeIndices) {
- Log(String.format("Loading plane %d...", planeIndex));
- final ImageU16 plane = RawDataIO.loadImageU16(options.getInputFile(),
- options.getImageDimension(),
- planeIndex);
-
- if (!options.hasReferencePlaneIndex()) {
- Log("Creating plane codebook...");
- quantizer = getScalarQuantizerFromPlane(plane);
- writeCodebookToOutputStream(quantizer, compressStream);
- Log("Wrote plane codebook.");
- }
-
- assert (quantizer != null);
-
- Log("Writing quantization indices...");
- final int[] indices = quantizer.quantizeIntoIndices(plane.getData());
- OutBitStream outBitStream = new OutBitStream(compressStream, options.getBitsPerPixel(), 2048);
- outBitStream.write(indices);
- outBitStream.flush();
- Log(String.format("Finished processing of plane %d", planeIndex));
- }
- }
}
diff --git a/src/main/java/azgracompress/compression/SQImageCompressor.java b/src/main/java/azgracompress/compression/SQImageCompressor.java
new file mode 100644
index 0000000000000000000000000000000000000000..fd5a59e61f7b8def46d732f32ff438929c09011d
--- /dev/null
+++ b/src/main/java/azgracompress/compression/SQImageCompressor.java
@@ -0,0 +1,92 @@
+package azgracompress.compression;
+
+import azgracompress.U16;
+import azgracompress.cli.ParsedCliOptions;
+import azgracompress.data.ImageU16;
+import azgracompress.io.OutBitStream;
+import azgracompress.io.RawDataIO;
+import azgracompress.quantization.scalar.LloydMaxU16ScalarQuantization;
+import azgracompress.quantization.scalar.ScalarQuantizer;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class SQImageCompressor extends CompressorDecompressorBase {
+
+ public SQImageCompressor(ParsedCliOptions options) {
+ super(options);
+
+ }
+
+ /**
+ * Train Lloyd-Max scalar quantizer from plane data.
+ *
+ * @param planeData Plane data from which quantizer will be trained.
+ * @return Trained scalar quantizer.
+ */
+ private ScalarQuantizer trainScalarQuantizerFromData(final short[] planeData) {
+ LloydMaxU16ScalarQuantization lloydMax = new LloydMaxU16ScalarQuantization(planeData, codebookSize);
+ lloydMax.train(false);
+ return new ScalarQuantizer(U16.Min, U16.Max, lloydMax.getCentroids());
+ }
+
+ /**
+ * Writes the scalar quantizer to the compressed stream.
+ *
+ * @param quantizer Quantizer used for compression of the image.
+ * @param compressStream Compressed data stream.
+ * @throws IOException when writing to the stream fails.
+ */
+ private void writeCodebookToOutputStream(final ScalarQuantizer quantizer,
+ DataOutputStream compressStream) throws IOException {
+ final int[] centroids = quantizer.getCentroids();
+ for (final int quantizationValue : centroids) {
+ compressStream.writeShort(quantizationValue);
+ }
+ }
+
+ /**
+ * Compress the image file specified by parsed CLI options using scalar quantization..
+ *
+ * @param compressStream Stream to which compressed data will be written.
+ * @throws Exception When compress process fails.
+ */
+ public void compress(DataOutputStream compressStream) throws Exception {
+ ScalarQuantizer quantizer = null;
+ if (options.hasReferencePlaneIndex()) {
+ final ImageU16 referencePlane = RawDataIO.loadImageU16(options.getInputFile(),
+ options.getImageDimension(),
+ options.getReferencePlaneIndex());
+
+ Log("Creating codebook from reference plane...");
+ quantizer = trainScalarQuantizerFromData(referencePlane.getData());
+ writeCodebookToOutputStream(quantizer, compressStream);
+ Log("Wrote reference codebook.");
+ }
+
+ final int[] planeIndices = getPlaneIndicesForCompression();
+
+ for (final int planeIndex : planeIndices) {
+ Log(String.format("Loading plane %d...", planeIndex));
+ final ImageU16 plane = RawDataIO.loadImageU16(options.getInputFile(),
+ options.getImageDimension(),
+ planeIndex);
+
+ if (!options.hasReferencePlaneIndex()) {
+ Log("Creating plane codebook...");
+ quantizer = trainScalarQuantizerFromData(plane.getData());
+ writeCodebookToOutputStream(quantizer, compressStream);
+ Log("Wrote plane codebook.");
+ }
+
+ assert (quantizer != null);
+
+ Log("Writing quantization indices...");
+ final int[] indices = quantizer.quantizeIntoIndices(plane.getData());
+ OutBitStream outBitStream = new OutBitStream(compressStream, options.getBitsPerPixel(), 2048);
+ outBitStream.write(indices);
+ outBitStream.flush();
+ Log(String.format("Finished processing of plane %d", planeIndex));
+ }
+ }
+}
diff --git a/src/main/java/azgracompress/compression/VQImageCompressor.java b/src/main/java/azgracompress/compression/VQImageCompressor.java
new file mode 100644
index 0000000000000000000000000000000000000000..cfb69b8ea0072a5f59d5b66288a9a91dda5713c8
--- /dev/null
+++ b/src/main/java/azgracompress/compression/VQImageCompressor.java
@@ -0,0 +1,4 @@
+package azgracompress.compression;
+
+public class VQImageCompressor {
+}