diff --git a/src/main/java/cz/it4i/qcmp/DataCompressor.java b/src/main/java/cz/it4i/qcmp/DataCompressor.java
index 6061522ccd47345eeeed4760d3b80e9f8c9030f8..fa30b58a88c2804d6319e062401ceb87c8d0f882 100644
--- a/src/main/java/cz/it4i/qcmp/DataCompressor.java
+++ b/src/main/java/cz/it4i/qcmp/DataCompressor.java
@@ -2,6 +2,7 @@ package cz.it4i.qcmp;
import cz.it4i.qcmp.benchmark.CompressionBenchmark;
import cz.it4i.qcmp.cache.QuantizationCacheManager;
+import cz.it4i.qcmp.cache.QvcFileReader;
import cz.it4i.qcmp.cli.CliConstants;
import cz.it4i.qcmp.cli.CompressionOptionsCLIParser;
import cz.it4i.qcmp.cli.CustomFunctionBase;
@@ -9,6 +10,7 @@ import cz.it4i.qcmp.cli.functions.DebugFunction;
import cz.it4i.qcmp.compression.ImageCompressor;
import cz.it4i.qcmp.compression.ImageDecompressor;
import cz.it4i.qcmp.fileformat.FileExtensions;
+import cz.it4i.qcmp.fileformat.IQvcFile;
import org.apache.commons.cli.*;
import java.io.IOException;
@@ -36,24 +38,24 @@ public class DataCompressor {
return;
}
- final CompressionOptionsCLIParser compressionOptionsCLIParsed = new CompressionOptionsCLIParser(cmd);
+ final CompressionOptionsCLIParser parsedOptions = new CompressionOptionsCLIParser(cmd);
// NOTE(Moravec): From this point we need to dispose of possible existing SCIFIO context.
- if (compressionOptionsCLIParsed.parseError()) {
- System.err.println(compressionOptionsCLIParsed.getParseError());
+ if (parsedOptions.parseError()) {
+ System.err.println(parsedOptions.getParseError());
ScifioWrapper.dispose();
return;
}
- if (compressionOptionsCLIParsed.isVerbose()) {
- System.out.println(compressionOptionsCLIParsed.report());
+ if (parsedOptions.isVerbose()) {
+ System.out.println(parsedOptions.report());
}
- switch (compressionOptionsCLIParsed.getMethod()) {
+ switch (parsedOptions.getMethod()) {
case Compress: {
final String label =
- compressionOptionsCLIParsed.getQuantizationType().toString() + " " + compressionOptionsCLIParsed.getQuantizationVector().toString();
+ parsedOptions.getQuantizationType().toString() + " " + parsedOptions.getQuantizationVector().toString();
// final Stopwatch stopwatch = Stopwatch.startNew();
- final ImageCompressor compressor = new ImageCompressor(compressionOptionsCLIParsed);
+ final ImageCompressor compressor = new ImageCompressor(parsedOptions);
if (!compressor.compress()) {
System.err.println("Errors occurred during compression.");
}
@@ -66,7 +68,7 @@ public class DataCompressor {
break;
case Decompress: {
// final Stopwatch stopwatch = Stopwatch.startNew();
- final ImageDecompressor decompressor = new ImageDecompressor(compressionOptionsCLIParsed);
+ final ImageDecompressor decompressor = new ImageDecompressor(parsedOptions);
if (!decompressor.decompressToFile()) {
System.err.println("Errors occurred during decompression.");
}
@@ -78,11 +80,11 @@ public class DataCompressor {
break;
case Benchmark: {
- CompressionBenchmark.runBenchmark(compressionOptionsCLIParsed);
+ CompressionBenchmark.runBenchmark(parsedOptions);
}
break;
case TrainCodebook: {
- final ImageCompressor compressor = new ImageCompressor(compressionOptionsCLIParsed);
+ final ImageCompressor compressor = new ImageCompressor(parsedOptions);
if (!compressor.trainAndSaveCodebook()) {
System.err.println("Errors occurred during training/saving of codebook.");
}
@@ -94,7 +96,7 @@ public class DataCompressor {
// final CustomFunctionBase customFunction = new MeasurePlaneErrorFunction(parsedCliOptions);
// final CustomFunctionBase customFunction = new EntropyCalculation(compressionOptionsCLIParsed);
// final CustomFunctionBase cf = new CalculateDifference(compressionOptionsCLIParsed);
- final CustomFunctionBase cf = new DebugFunction(compressionOptionsCLIParsed);
+ final CustomFunctionBase cf = new DebugFunction(parsedOptions);
if (!cf.run()) {
System.err.println("Errors occurred during custom function.");
}
@@ -106,11 +108,11 @@ public class DataCompressor {
}
break;
case InspectFile: {
- if (compressionOptionsCLIParsed.getInputDataInfo().getFilePath().endsWith(FileExtensions.CACHE_FILE_EXT)) {
- QuantizationCacheManager.inspectCacheFile(compressionOptionsCLIParsed.getInputDataInfo().getFilePath(),
- compressionOptionsCLIParsed.isVerbose());
+ if (parsedOptions.getInputDataInfo().getFilePath().endsWith(FileExtensions.CACHE_FILE_EXT)) {
+ QuantizationCacheManager.inspectCacheFile(parsedOptions.getInputDataInfo().getFilePath(),
+ parsedOptions.isVerbose());
} else {
- final ImageDecompressor decompressor = new ImageDecompressor(compressionOptionsCLIParsed);
+ final ImageDecompressor decompressor = new ImageDecompressor(parsedOptions);
try {
System.out.println(decompressor.inspectCompressedFile());
} catch (final IOException e) {
@@ -121,7 +123,41 @@ public class DataCompressor {
}
}
break;
+ case Convert: {
+ final boolean inPlace = parsedOptions.getOutputFilePath() == null;
+ // TODO(Moravec): Maybe replace with generic reader which can determine file type based on magic value and not an extension.
+ if (parsedOptions.getInputDataInfo().getFilePath().endsWith(FileExtensions.CACHE_FILE_EXT)) {
+ IQvcFile cacheFile = null;
+ try {
+ cacheFile = QvcFileReader.readCacheFile(parsedOptions.getInputDataInfo().getFilePath());
+ } catch (final IOException e) {
+ System.err.println("Unable to read QVC file. Error: " + e.getMessage());
+ exitApplication(1);
+ }
+ try {
+ assert (cacheFile != null);
+ cacheFile.convertToNewerVersion(inPlace, parsedOptions.getInputDataInfo().getFilePath(),
+ parsedOptions.getOutputFilePath());
+ } catch (final IOException e) {
+ System.err.println("Unable to convert specified QVC file. Error: " + e.getMessage());
+ exitApplication(1);
+ }
+
+ if (parsedOptions.isVerbose()) {
+ System.err.println("Qvc file is converted.");
+ }
+
+ } else {
+ System.err.println("Qcmp file conversion isn't supported yet");
+ }
+ }
+ break;
}
ScifioWrapper.dispose();
}
+
+ private static void exitApplication(final int exitCode) {
+ ScifioWrapper.dispose();
+ System.exit(exitCode);
+ }
}
diff --git a/src/main/java/cz/it4i/qcmp/cli/CliConstants.java b/src/main/java/cz/it4i/qcmp/cli/CliConstants.java
index 9d327490e1e96c86c6a84302cbaed951835cf983..02a9f91b48666badc5ad5c9c871537b44ba3ac74 100644
--- a/src/main/java/cz/it4i/qcmp/cli/CliConstants.java
+++ b/src/main/java/cz/it4i/qcmp/cli/CliConstants.java
@@ -30,6 +30,9 @@ public class CliConstants {
public static final String CUSTOM_FUNCTION_SHORT = "cf";
public static final String CUSTOM_FUNCTION_LONG = "custom-function";
+ public static final String CONVERT_SHORT = "conv";
+ public static final String CONVERT_LONG = "convert";
+
public static final String BITS_SHORT = "b";
public static final String BITS_LONG = "bits";
@@ -72,6 +75,10 @@ public class CliConstants {
CliConstants.INSPECT_LONG,
false,
"Inspect the compressed file"));
+ methodGroup.addOption(new Option(CliConstants.CONVERT_SHORT,
+ CliConstants.CONVERT_LONG,
+ false,
+ "Convert input file to new version of custom file format"));
methodGroup.addOption(new Option(CliConstants.BENCHMARK_SHORT,
CliConstants.BENCHMARK_LONG,
diff --git a/src/main/java/cz/it4i/qcmp/cli/CompressionOptionsCLIParser.java b/src/main/java/cz/it4i/qcmp/cli/CompressionOptionsCLIParser.java
index 6cf18049d6e2b1934870eb9b4a781aded9019b85..c30fb4d5b807ddca0b0bfb184cbaeb532161a211 100644
--- a/src/main/java/cz/it4i/qcmp/cli/CompressionOptionsCLIParser.java
+++ b/src/main/java/cz/it4i/qcmp/cli/CompressionOptionsCLIParser.java
@@ -390,6 +390,8 @@ public class CompressionOptionsCLIParser extends CompressionOptions implements C
method = ProgramMethod.InspectFile;
} else if (cmd.hasOption(CliConstants.CUSTOM_FUNCTION_LONG)) {
method = ProgramMethod.CustomFunction;
+ } else if (cmd.hasOption(CliConstants.CONVERT_LONG)) {
+ method = ProgramMethod.Convert;
} else {
parseErrorOccurred = true;
errorBuilder.append("No program method was matched\n");
@@ -412,31 +414,7 @@ public class CompressionOptionsCLIParser extends CompressionOptions implements C
public String report() {
final StringBuilder sb = new StringBuilder();
- sb.append("Method: ");
- switch (method) {
- case Compress:
- sb.append("Compress\n");
- break;
- case Decompress:
- sb.append("Decompress\n");
- break;
- case Benchmark:
- sb.append("Benchmark\n");
- break;
- case TrainCodebook:
- sb.append("TrainCodebook\n");
- break;
- case PrintHelp:
- sb.append("PrintHelp\n");
- break;
- case CustomFunction:
- sb.append("CustomFunction\n");
- break;
- case InspectFile:
- sb.append("InspectFile\n");
- break;
- }
-
+ sb.append("Method: ").append(method).append('\n');
if (hasQuantizationType(method)) {
sb.append("Quantization type: ");
@@ -470,7 +448,6 @@ public class CompressionOptionsCLIParser extends CompressionOptions implements C
}
if (hasQuantizationType(method)) {
-
sb.append("Input image dims: ").append(getInputDataInfo().getDimensions().toString()).append('\n');
}
if (getInputDataInfo().isPlaneIndexSet()) {
diff --git a/src/main/java/cz/it4i/qcmp/cli/ProgramMethod.java b/src/main/java/cz/it4i/qcmp/cli/ProgramMethod.java
index 73d3abdd417bb37671f4984550b452703172cc4a..fd83e49716ad6c74361a64fb645c906c94d8706c 100644
--- a/src/main/java/cz/it4i/qcmp/cli/ProgramMethod.java
+++ b/src/main/java/cz/it4i/qcmp/cli/ProgramMethod.java
@@ -7,5 +7,6 @@ public enum ProgramMethod {
TrainCodebook,
PrintHelp,
CustomFunction,
- InspectFile
+ InspectFile,
+ Convert
}
diff --git a/src/main/java/cz/it4i/qcmp/fileformat/IQvcHeader.java b/src/main/java/cz/it4i/qcmp/fileformat/IQvcHeader.java
index b1a752f690a7a1b05ec7c3e245229a859a2d23db..fae999d092e365ac77588ae488fafd6472dcbff0 100644
--- a/src/main/java/cz/it4i/qcmp/fileformat/IQvcHeader.java
+++ b/src/main/java/cz/it4i/qcmp/fileformat/IQvcHeader.java
@@ -10,4 +10,6 @@ public interface IQvcHeader extends IFileHeader {
int getCodebookSize();
V3i getVectorDim();
+
+ String getTrainFileName();
}
diff --git a/src/main/java/cz/it4i/qcmp/fileformat/QvcHeaderV1.java b/src/main/java/cz/it4i/qcmp/fileformat/QvcHeaderV1.java
index 4d0027b60e1c71827a70156fffe6d293bc20ad4b..34399f17e90e6259dd646ffaa6f2dd3b57e6b157 100644
--- a/src/main/java/cz/it4i/qcmp/fileformat/QvcHeaderV1.java
+++ b/src/main/java/cz/it4i/qcmp/fileformat/QvcHeaderV1.java
@@ -155,18 +155,22 @@ public class QvcHeaderV1 implements IQvcHeader {
this.trainFileNameSize = this.trainFileName.length();
}
+ @Override
public QuantizationType getQuantizationType() {
return quantizationType;
}
+ @Override
public int getCodebookSize() {
return codebookSize;
}
+ @Override
public int getBitsPerCodebookIndex() {
return (int) Utils.log2(codebookSize);
}
+ @Override
public String getTrainFileName() {
return trainFileName;
}
@@ -183,6 +187,7 @@ public class QvcHeaderV1 implements IQvcHeader {
return vectorSizeZ;
}
+ @Override
public V3i getVectorDim() {
return new V3i(vectorSizeX, vectorSizeY, vectorSizeZ);
}
diff --git a/src/main/java/cz/it4i/qcmp/fileformat/SqQvcFile.java b/src/main/java/cz/it4i/qcmp/fileformat/SqQvcFile.java
index df75deac894302e717ad27588a8eaf81acec90e1..d90ec8946c93c562884d7d71af5a8e3b17692354 100644
--- a/src/main/java/cz/it4i/qcmp/fileformat/SqQvcFile.java
+++ b/src/main/java/cz/it4i/qcmp/fileformat/SqQvcFile.java
@@ -1,5 +1,6 @@
package cz.it4i.qcmp.fileformat;
+import cz.it4i.qcmp.cache.QvcFileWriter;
import cz.it4i.qcmp.huffman.HuffmanNode;
import cz.it4i.qcmp.huffman.HuffmanTreeBuilder;
import cz.it4i.qcmp.io.InBitStream;
@@ -88,22 +89,18 @@ public class SqQvcFile implements IQvcFile {
codebook = new SQCodebook(centroids, huffmanRoot);
}
- private void convertQvcFromV1ToV2(final String outputFilePath) {
-
- }
@Override
- public void convertToNewerVersion(final boolean inPlace, final String inputPath, final String outputPath) {
- final int headerVersion = header.getHeaderVersion();
+ public void convertToNewerVersion(final boolean inPlace, final String inputPath, final String outputPath) throws IOException {
if (!inPlace && (outputPath == null || outputPath.isEmpty())) {
System.err.println("InPlace conversion wasn't specified nor the output file path.");
return;
}
- if (headerVersion == 1) {
- convertQvcFromV1ToV2(inPlace ? inputPath : outputPath);
- } else {
- System.err.printf("Version %d is already the newest version of QVC file.\n", headerVersion);
+ if (header.getHeaderVersion() == 2) {
+ System.err.print("Version 2 is already the newest version of QVC file.\n");
+ return;
}
+ QvcFileWriter.writeSqCacheFile(inPlace ? inputPath : outputPath, header.getTrainFileName(), codebook);
}
@Override
diff --git a/src/main/java/cz/it4i/qcmp/fileformat/VqQvcFile.java b/src/main/java/cz/it4i/qcmp/fileformat/VqQvcFile.java
index 83dcc6af614a66072aa453af63c6d659a06b37ca..b7ad419c6853c93a09051841fe7826be0ddfd7b3 100644
--- a/src/main/java/cz/it4i/qcmp/fileformat/VqQvcFile.java
+++ b/src/main/java/cz/it4i/qcmp/fileformat/VqQvcFile.java
@@ -1,5 +1,6 @@
package cz.it4i.qcmp.fileformat;
+import cz.it4i.qcmp.cache.QvcFileWriter;
import cz.it4i.qcmp.huffman.HuffmanNode;
import cz.it4i.qcmp.huffman.HuffmanTreeBuilder;
import cz.it4i.qcmp.io.InBitStream;
@@ -97,8 +98,16 @@ public class VqQvcFile implements IQvcFile {
}
@Override
- public void convertToNewerVersion(final boolean inPlace, final String inputPath, final String outputPath) {
- assert false : "NOT IMPLEMENTED YET";
+ public void convertToNewerVersion(final boolean inPlace, final String inputPath, final String outputPath) throws IOException {
+ if (!inPlace && (outputPath == null || outputPath.isEmpty())) {
+ System.err.println("InPlace conversion wasn't specified nor the output file path.");
+ return;
+ }
+ if (header.getHeaderVersion() == 2) {
+ System.err.print("Version 2 is already the newest version of QVC file.\n");
+ return;
+ }
+ QvcFileWriter.writeVqCacheFile(inPlace ? inputPath : outputPath, header.getTrainFileName(), codebook);
}
@Override
@@ -111,7 +120,5 @@ public class VqQvcFile implements IQvcFile {
}
builder.append("\n- - - - - - - - - - - - - - - - - - - - - - - - -\n");
}
-
-
}
}