diff --git a/README.md b/README.md
index fa8b0d8024208b3bfc19bd249af868c3c29e851f..bf49431a6d48dfbe18393205df04363c2a3e6114 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,7 @@ usage: azgracompress.DataCompressor [options] input
-h,--help Print help
-i,--inspect Inspect the compressed file
-o,--output <arg> Custom output file
- -rp,--reference-plane <arg> Reference plane index
+ -mp,--middle-plane Use middle plane for codebook training.
-sq,--scalar-quantization Use scalar quantization.
-tcb,--train-codebook Train codebook and save learned
codebook to cache file.
@@ -39,9 +39,9 @@ usage: azgracompress.DataCompressor [options] input
- QT is required
- Set the bits per pixel using `-b` or `--bits` and integer value from 1 to 8. Codebook size is equal to (*2^bits*).
- Normally the codebook is created for each image plane separately, if one wants to use general codebook for all planes, these are the options:
- - Set the reference plane index using `-rp` or `--reference-plane`. Reference plane is used to create codebook for all planes.
+ - Set the middle plane index using `-mp` or `--middle-plane`. Middle plane is used to create codebook for all planes.
- Set the cache folder by `cbc` or `--codebook-cache`, quantizer will look for cached codebook of given file and codebook size.
-- For input file info seee Input File section
+- For input file info see Input File section
### Decompress
- Use with `-d` or `--decompress`
@@ -50,7 +50,7 @@ usage: azgracompress.DataCompressor [options] input
### Inspect
- Use with `-i` or `--inspect`
-- Inspect the compressed file. Read compressed file header are write the informations from that header.
+- Inspect the compressed file. Read compressed file header are write the information from that header.
### Train codebook
- Use with `-tcb` or `--train-codebook`
diff --git a/src/main/java/azgracompress/benchmark/BenchmarkBase.java b/src/main/java/azgracompress/benchmark/BenchmarkBase.java
index 3a2e4378bfd767d24702f646266665136321d1d6..18aad38e617da1e8fa0cd6474cf350977437d300 100644
--- a/src/main/java/azgracompress/benchmark/BenchmarkBase.java
+++ b/src/main/java/azgracompress/benchmark/BenchmarkBase.java
@@ -23,8 +23,7 @@ abstract class BenchmarkBase {
protected final int[] planes;
protected final V3i rawImageDims;
- protected final boolean hasReferencePlane;
- protected final int referencePlaneIndex;
+ protected final boolean useMiddlePlane;
protected final int codebookSize;
protected final boolean hasCacheFolder;
protected final String cacheFolder;
@@ -41,8 +40,7 @@ abstract class BenchmarkBase {
this.planes = planes;
this.rawImageDims = rawImageDims;
- hasReferencePlane = false;
- referencePlaneIndex = -1;
+ useMiddlePlane = false;
codebookSize = 256;
hasCacheFolder = false;
@@ -56,8 +54,7 @@ abstract class BenchmarkBase {
this.inputFile = options.getInputFile();
this.outputDirectory = options.getOutputFile();
this.rawImageDims = options.getImageDimension();
- this.hasReferencePlane = options.hasReferencePlaneIndex();
- this.referencePlaneIndex = options.getReferencePlaneIndex();
+ this.useMiddlePlane = options.shouldUseMiddlePlane();
this.codebookSize = (int) Math.pow(2, options.getBitsPerPixel());
if (options.hasPlaneIndexSet()) {
@@ -81,7 +78,7 @@ abstract class BenchmarkBase {
hasCacheFolder = options.hasCodebookCacheFolder();
cacheFolder = options.getCodebookCacheFolder();
- hasGeneralQuantizer = hasReferencePlane || hasCacheFolder;
+ hasGeneralQuantizer = useMiddlePlane || hasCacheFolder;
workerCount = options.getWorkerCount();
}
diff --git a/src/main/java/azgracompress/benchmark/ScalarQuantizationBenchmark.java b/src/main/java/azgracompress/benchmark/ScalarQuantizationBenchmark.java
index 4cf0060343b8ce622f47b1c0e190fc685087d7c0..051ee8e3aa6b4ccc6180b629dbb5c5e1739a654d 100644
--- a/src/main/java/azgracompress/benchmark/ScalarQuantizationBenchmark.java
+++ b/src/main/java/azgracompress/benchmark/ScalarQuantizationBenchmark.java
@@ -49,19 +49,20 @@ public class ScalarQuantizationBenchmark extends BenchmarkBase {
return;
}
System.out.println("Created quantizer from cache");
- } else if (hasReferencePlane) {
- final int[] refPlaneData = loadPlaneData(referencePlaneIndex);
- if (refPlaneData.length == 0) {
- System.err.println("Failed to load reference plane data.");
+ } else if (useMiddlePlane) {
+ final int middlePlaneIndex = rawImageDims.getZ() / 2;
+ final int[] middlePlaneData = loadPlaneData(middlePlaneIndex);
+ if (middlePlaneData.length == 0) {
+ System.err.println("Failed to load middle plane data.");
return;
}
if (useDiffEvolution) {
assert (false) : "DE is depracated";
quantizer = null;
} else {
- quantizer = trainLloydMaxQuantizer(refPlaneData, codebookSize);
+ quantizer = trainLloydMaxQuantizer(middlePlaneData, codebookSize);
}
- System.out.println("Created reference quantizer.");
+ System.out.println("Created quantizer from middle plane.");
}
for (final int planeIndex : planes) {
diff --git a/src/main/java/azgracompress/benchmark/VectorQuantizationBenchmark.java b/src/main/java/azgracompress/benchmark/VectorQuantizationBenchmark.java
index 7c01f3c2bb3e24007b3f7fe04235fd4926723d50..5224d38e73a5e5e0a8766477945cb9cb7ced53c8 100644
--- a/src/main/java/azgracompress/benchmark/VectorQuantizationBenchmark.java
+++ b/src/main/java/azgracompress/benchmark/VectorQuantizationBenchmark.java
@@ -76,19 +76,20 @@ public class VectorQuantizationBenchmark extends BenchmarkBase {
return;
}
System.out.println("Created quantizer from cache");
- } else if (hasReferencePlane) {
- final ImageU16 plane = loadPlane(referencePlaneIndex);
+ } else if (useMiddlePlane) {
+ final int middlePlaneIndex = rawImageDims.getZ() / 2;
+ final ImageU16 middlePlane = loadPlane(middlePlaneIndex);
- if (plane == null) {
- System.err.println("Failed to load reference plane data.");
+ if (middlePlane == null) {
+ System.err.println("Failed to load middle plane data.");
return;
}
- final int[][] refPlaneData = getPlaneVectors(plane, qVector);
+ final int[][] refPlaneData = getPlaneVectors(middlePlane, qVector);
LBGVectorQuantizer vqInitializer = new LBGVectorQuantizer(refPlaneData, codebookSize, workerCount);
final LBGResult vqResult = vqInitializer.findOptimalCodebook();
quantizer = new VectorQuantizer(vqResult.getCodebook());
- System.out.println("Created reference quantizer.");
+ System.out.println("Created quantizer from middle plane.");
}
for (final int planeIndex : planes) {
diff --git a/src/main/java/azgracompress/cli/CliConstants.java b/src/main/java/azgracompress/cli/CliConstants.java
index 4044e30f61f953ef81506d54202a700a6c70b958..aa5dd83adeb0a67bc37ae3e1ea69a4c6a6c7c1f0 100644
--- a/src/main/java/azgracompress/cli/CliConstants.java
+++ b/src/main/java/azgracompress/cli/CliConstants.java
@@ -51,8 +51,8 @@ public class CliConstants {
public static final String VECTOR_QUANTIZATION_SHORT = "vq";
public static final String VECTOR_QUANTIZATION_LONG = "vector-quantization";
- public static final String REFERENCE_PLANE_SHORT = "rp";
- public static final String REFERENCE_PLANE_LONG = "reference-plane";
+ public static final String USE_MIDDLE_PLANE_SHORT = "md";
+ public static final String USE_MIDDLE_PLANE_LONG = "middle-plane";
@NotNull
public static Options getOptions() {
@@ -105,10 +105,10 @@ public class CliConstants {
options.addOptionGroup(compressionMethodGroup);
options.addOption(CliConstants.BITS_SHORT, CliConstants.BITS_LONG, true, "Bit count per pixel [Default 8]");
- options.addOption(CliConstants.REFERENCE_PLANE_SHORT,
- CliConstants.REFERENCE_PLANE_LONG,
- true,
- "Reference plane index");
+ options.addOption(CliConstants.USE_MIDDLE_PLANE_SHORT,
+ CliConstants.USE_MIDDLE_PLANE_LONG,
+ false,
+ "Use middle plane for codebook creation");
options.addOption(new Option(CliConstants.VERBOSE_SHORT,
CliConstants.VERBOSE_LONG,
diff --git a/src/main/java/azgracompress/cli/ParsedCliOptions.java b/src/main/java/azgracompress/cli/ParsedCliOptions.java
index eb4add1e4b6b0181cab6a27c0b3a668ee8041f76..b43ce7fbb62d81730656560092d7fd255ca21cb6 100644
--- a/src/main/java/azgracompress/cli/ParsedCliOptions.java
+++ b/src/main/java/azgracompress/cli/ParsedCliOptions.java
@@ -27,8 +27,7 @@ public class ParsedCliOptions {
private boolean planeIndexSet = false;
private int planeIndex;
- private boolean refPlaneIndexSet = false;
- private int referencePlaneIndex = -1;
+ private boolean useMiddlePlane = false;
private boolean verbose;
@@ -93,7 +92,7 @@ public class ParsedCliOptions {
parseBitsPerPixel(cmd, errorBuilder);
- parseReferencePlaneIndex(cmd, errorBuilder);
+ useMiddlePlane = cmd.hasOption(CliConstants.USE_MIDDLE_PLANE_LONG);
final String[] fileInfo = cmd.getArgs();
parseInputFilePart(errorBuilder, fileInfo);
@@ -219,23 +218,6 @@ public class ParsedCliOptions {
}
- private void parseReferencePlaneIndex(CommandLine cmd, StringBuilder errorBuilder) {
- if (cmd.hasOption(CliConstants.REFERENCE_PLANE_LONG)) {
- final String rpString = cmd.getOptionValue(CliConstants.REFERENCE_PLANE_LONG);
- final ParseResult<Integer> parseResult = tryParseInt(rpString);
- if (parseResult.isSuccess()) {
- referencePlaneIndex = parseResult.getValue();
- refPlaneIndexSet = true;
- } else {
- errorOccurred = true;
- errorBuilder.append("Failed to parse reference plane index").append('\n');
- errorBuilder.append(parseResult.getErrorMessage()).append('\n');
- }
- } else {
- refPlaneIndexSet = false;
- }
- }
-
private void parseBitsPerPixel(CommandLine cmd, StringBuilder errorBuilder) {
if (cmd.hasOption(CliConstants.BITS_LONG)) {
final String bitsString = cmd.getOptionValue(CliConstants.BITS_LONG);
@@ -375,16 +357,12 @@ public class ParsedCliOptions {
return planeIndex;
}
- public int getReferencePlaneIndex() {
- return referencePlaneIndex;
- }
-
public boolean isVerbose() {
return verbose;
}
- public boolean hasReferencePlaneIndex() {
- return refPlaneIndexSet;
+ public boolean shouldUseMiddlePlane() {
+ return useMiddlePlane;
}
public boolean hasPlaneIndexSet() {
@@ -482,8 +460,8 @@ public class ParsedCliOptions {
if (planeIndexSet) {
sb.append("PlaneIndex: ").append(planeIndex).append('\n');
}
- if (refPlaneIndexSet) {
- sb.append("ReferencePlaneIndex: ").append(referencePlaneIndex).append('\n');
+ if (useMiddlePlane) {
+ sb.append("Use middle plane for codebook training\n");
}
if (planeRangeSet) {
sb.append("FromPlaneIndex: ").append(fromPlaneIndex).append('\n');
diff --git a/src/main/java/azgracompress/cli/functions/MeasurePlaneErrorFunction.java b/src/main/java/azgracompress/cli/functions/MeasurePlaneErrorFunction.java
index b48c91f314c121d702fd55f23f430d119d234322..cdc809747db281d71d29ba667c271752fc479a2d 100644
--- a/src/main/java/azgracompress/cli/functions/MeasurePlaneErrorFunction.java
+++ b/src/main/java/azgracompress/cli/functions/MeasurePlaneErrorFunction.java
@@ -122,9 +122,6 @@ public class MeasurePlaneErrorFunction extends CustomFunctionBase {
final int workerCount = 8;
final V3i dims = new V3i(1041, 996, 946);
final int planePixelCount = dims.getX() * dims.getY();
- // ImageU16 compressedPlane = null;
- // ImageU16 originalPlane = null;
- // ImageU16 differencePlane = null;
PlaneError[] planeErrors = new PlaneError[dims.getZ()];
diff --git a/src/main/java/azgracompress/compression/CompressorDecompressorBase.java b/src/main/java/azgracompress/compression/CompressorDecompressorBase.java
index f80ba046a1d3d4e808df6329c78c7be4dac271b5..4519b12c88a86b47c1ef37de3a1cceb0d4c5b215 100644
--- a/src/main/java/azgracompress/compression/CompressorDecompressorBase.java
+++ b/src/main/java/azgracompress/compression/CompressorDecompressorBase.java
@@ -70,4 +70,12 @@ public abstract class CompressorDecompressorBase {
System.err.println(message);
}
}
+
+ /**
+ * Get index of the middle plane.
+ * @return Index of the middle plane.
+ */
+ protected int getMiddlePlaneIndex() {
+ return (options.getImageDimension().getZ() / 2);
+ }
}
diff --git a/src/main/java/azgracompress/compression/ImageCompressor.java b/src/main/java/azgracompress/compression/ImageCompressor.java
index 75ed35d8171b8e4a442aa4cd1bff784223736dcd..701725eb1fd07e0fef4d146272f9714ce4b05d88 100644
--- a/src/main/java/azgracompress/compression/ImageCompressor.java
+++ b/src/main/java/azgracompress/compression/ImageCompressor.java
@@ -128,8 +128,8 @@ public class ImageCompressor extends CompressorDecompressorBase {
header.setQuantizationType(options.getQuantizationType());
header.setBitsPerPixel((byte) options.getBitsPerPixel());
- // Codebook per plane is used only if reference plane isn't set nor is the cache folder.
- final boolean oneCodebook = options.hasReferencePlaneIndex() || options.hasCodebookCacheFolder();
+ // Codebook per plane is used only if middle plane isn't set nor is the cache folder.
+ final boolean oneCodebook = options.shouldUseMiddlePlane() || options.hasCodebookCacheFolder();
header.setCodebookPerPlane(!oneCodebook);
header.setImageSizeX(options.getImageDimension().getX());
diff --git a/src/main/java/azgracompress/compression/SQImageCompressor.java b/src/main/java/azgracompress/compression/SQImageCompressor.java
index 82d8eb88cf307811dfca1270eefac7782901d441..20bb0a222da8d20b0601ed840a924ecf82d78cde 100644
--- a/src/main/java/azgracompress/compression/SQImageCompressor.java
+++ b/src/main/java/azgracompress/compression/SQImageCompressor.java
@@ -90,9 +90,7 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm
*/
public long[] compress(DataOutputStream compressStream) throws ImageCompressionException {
Stopwatch stopwatch = new Stopwatch();
-
- final boolean hasGeneralQuantizer = options.hasCodebookCacheFolder() || options.hasReferencePlaneIndex();
-
+ final boolean hasGeneralQuantizer = options.hasCodebookCacheFolder() || options.shouldUseMiddlePlane();
ScalarQuantizer quantizer = null;
Huffman huffman = null;
final int[] huffmanSymbols = createHuffmanSymbols();
@@ -102,27 +100,27 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm
quantizer = loadQuantizerFromCache();
Log("Cached quantizer created.");
writeCodebookToOutputStream(quantizer, compressStream);
- } else if (options.hasReferencePlaneIndex()) {
- // TODO(Moravec): Reference plane will be deprecated in favor of 'middle' plane.
+ } else if (options.shouldUseMiddlePlane()) {
stopwatch.restart();
- ImageU16 referencePlane = null;
+ ImageU16 middlePlane = null;
+ final int middlePlaneIndex = getMiddlePlaneIndex();
try {
- referencePlane = RawDataIO.loadImageU16(options.getInputFile(),
- options.getImageDimension(),
- options.getReferencePlaneIndex());
+ middlePlane = RawDataIO.loadImageU16(options.getInputFile(),
+ options.getImageDimension(),
+ getMiddlePlaneIndex());
// TODO(Moravec): Create huffman.
} catch (Exception ex) {
- throw new ImageCompressionException("Unable to load reference plane data.", ex);
+ throw new ImageCompressionException("Unable to load plane data.", ex);
}
- Log(String.format("Training scalar quantizer from reference plane %d.", options.getReferencePlaneIndex()));
- quantizer = trainScalarQuantizerFromData(referencePlane.getData());
+ Log(String.format("Training scalar quantizer from middle plane %d.", middlePlaneIndex));
+ quantizer = trainScalarQuantizerFromData(middlePlane.getData());
stopwatch.stop();
writeCodebookToOutputStream(quantizer, compressStream);
- Log("Reference codebook created in: " + stopwatch.getElapsedTimeString());
+ Log("Middle plane codebook created in: " + stopwatch.getElapsedTimeString());
}
final int[] planeIndices = getPlaneIndicesForCompression();
@@ -157,19 +155,19 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm
Log("Compressing plane...");
final int[] indices = quantizer.quantizeIntoIndices(plane.getData(), 1);
-// ////////////////////////
-// for (int i = 0; i < indices.length; i++) {
-// final boolean[] huffmanCode = huffman.getCode(indices[i]);
-// HuffmanNode currentHuffmanNode = huffman.getRoot();
-// boolean bit;
-// int index = 0;
-// while (!currentHuffmanNode.isLeaf()) {
-// bit = huffmanCode[index++];
-// currentHuffmanNode = currentHuffmanNode.traverse(bit);
-// }
-// assert (indices[i] == currentHuffmanNode.getSymbol());
-// }
-// ////////////////////////////////
+ // ////////////////////////
+ // for (int i = 0; i < indices.length; i++) {
+ // final boolean[] huffmanCode = huffman.getCode(indices[i]);
+ // HuffmanNode currentHuffmanNode = huffman.getRoot();
+ // boolean bit;
+ // int index = 0;
+ // while (!currentHuffmanNode.isLeaf()) {
+ // bit = huffmanCode[index++];
+ // currentHuffmanNode = currentHuffmanNode.traverse(bit);
+ // }
+ // assert (indices[i] == currentHuffmanNode.getSymbol());
+ // }
+ // ////////////////////////////////
try (OutBitStream outBitStream = new OutBitStream(compressStream, options.getBitsPerPixel(), 2048)) {
@@ -199,7 +197,7 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm
options.getImageDimension(),
options.getPlaneIndex()).getData();
} catch (IOException e) {
- throw new ImageCompressionException("Failed to load reference image data.", e);
+ throw new ImageCompressionException("Failed to load plane data.", e);
}
} else if (options.hasPlaneRangeSet()) {
Log("Loading plane range data.");
diff --git a/src/main/java/azgracompress/compression/SQImageDecompressor.java b/src/main/java/azgracompress/compression/SQImageDecompressor.java
index 75eb8e2925960f3d1b65acd2671ad14eb1de147d..5d71d0da92c46310a6f608f0fb9e7e3c5b04c0e5 100644
--- a/src/main/java/azgracompress/compression/SQImageDecompressor.java
+++ b/src/main/java/azgracompress/compression/SQImageDecompressor.java
@@ -78,9 +78,9 @@ public class SQImageDecompressor extends CompressorDecompressorBase implements I
Huffman huffman = null;
if (!header.isCodebookPerPlane()) {
// There is only one codebook.
- Log("Loading reference codebook...");
huffman = null;
// TODO(Moravec): Handle loading of Huffman.
+ Log("Loading codebook from cache...");
//quantizationValues = readScalarQuantizationValues(compressedStream, codebookSize);
}
diff --git a/src/main/java/azgracompress/compression/VQImageCompressor.java b/src/main/java/azgracompress/compression/VQImageCompressor.java
index 29413055f6933f39765df19ca311d16cf5f05cc5..8bf557a8e91994dc6df339e78b7d15a09ef7e359 100644
--- a/src/main/java/azgracompress/compression/VQImageCompressor.java
+++ b/src/main/java/azgracompress/compression/VQImageCompressor.java
@@ -88,7 +88,7 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
public long[] compress(DataOutputStream compressStream) throws ImageCompressionException {
long[] planeDataSizes = new long[options.getImageDimension().getZ()];
Stopwatch stopwatch = new Stopwatch();
- final boolean hasGeneralQuantizer = options.hasCodebookCacheFolder() || options.hasReferencePlaneIndex();
+ final boolean hasGeneralQuantizer = options.hasCodebookCacheFolder() || options.shouldUseMiddlePlane();
VectorQuantizer quantizer = null;
if (options.hasCodebookCacheFolder()) {
@@ -96,24 +96,25 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
quantizer = loadQuantizerFromCache();
Log("Cached quantizer created.");
writeQuantizerToCompressStream(quantizer, compressStream);
- } else if (options.hasReferencePlaneIndex()) {
+ } else if (options.shouldUseMiddlePlane()) {
stopwatch.restart();
- ImageU16 referencePlane = null;
+ final int middlePlaneIndex = getMiddlePlaneIndex();
+ ImageU16 middlePlane = null;
try {
- referencePlane = RawDataIO.loadImageU16(options.getInputFile(),
+ middlePlane = RawDataIO.loadImageU16(options.getInputFile(),
options.getImageDimension(),
- options.getReferencePlaneIndex());
+ middlePlaneIndex);
} catch (Exception ex) {
- throw new ImageCompressionException("Unable to load reference plane data.", ex);
+ throw new ImageCompressionException("Unable to load plane data.", ex);
}
- Log(String.format("Training vector quantizer from reference plane %d.", options.getReferencePlaneIndex()));
- final int[][] refPlaneVectors = referencePlane.toQuantizationVectors(options.getVectorDimension());
+ Log(String.format("Training vector quantizer from middle plane %d.", middlePlaneIndex));
+ final int[][] refPlaneVectors = middlePlane.toQuantizationVectors(options.getVectorDimension());
quantizer = trainVectorQuantizerFromPlaneVectors(refPlaneVectors);
writeQuantizerToCompressStream(quantizer, compressStream);
stopwatch.stop();
- Log("Reference codebook created in: " + stopwatch.getElapsedTimeString());
+ Log("Middle plane codebook created in: " + stopwatch.getElapsedTimeString());
}
final int[] planeIndices = getPlaneIndicesForCompression();
@@ -184,7 +185,7 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
try {
trainData = loadPlaneQuantizationVectors(options.getPlaneIndex());
} catch (IOException e) {
- throw new ImageCompressionException("Failed to load reference image data.", e);
+ throw new ImageCompressionException("Failed to load plane data.", e);
}
} else {
Log(options.hasPlaneRangeSet() ? "VQ: Loading plane range data." : "VQ: Loading all planes data.");
diff --git a/src/main/java/azgracompress/compression/VQImageDecompressor.java b/src/main/java/azgracompress/compression/VQImageDecompressor.java
index 7e4324330b8c0154ea9478ff886fc8fff7575bf2..5045688502d048a0c1c993d40ecb98433143f13e 100644
--- a/src/main/java/azgracompress/compression/VQImageDecompressor.java
+++ b/src/main/java/azgracompress/compression/VQImageDecompressor.java
@@ -102,7 +102,7 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I
int[][] quantizationVectors = null;
if (!header.isCodebookPerPlane()) {
// There is only one codebook.
- Log("Loading reference codebook...");
+ Log("Loading codebook from cache...");
quantizationVectors = readCodebookVectors(compressedStream, codebookSize, vectorSize);
}