diff --git a/src/main/java/cz/it4i/qcmp/DataCompressor.java b/src/main/java/cz/it4i/qcmp/DataCompressor.java
index 0c0de09f5cc9796aab1de49da55a59803c3b2e8f..b87be17f263e1b5b73221bef29a27b72b7d42503 100644
--- a/src/main/java/cz/it4i/qcmp/DataCompressor.java
+++ b/src/main/java/cz/it4i/qcmp/DataCompressor.java
@@ -7,10 +7,11 @@ import cz.it4i.qcmp.cli.CustomFunctionBase;
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 cz.it4i.qcmp.io.FileTypeInspector;
import cz.it4i.qcmp.io.QuantizationCacheManager;
import cz.it4i.qcmp.io.QvcFileReader;
+import cz.it4i.qcmp.utilities.ColorConsole;
import org.apache.commons.cli.*;
import java.io.IOException;
@@ -108,47 +109,69 @@ public class DataCompressor {
}
break;
case InspectFile: {
- if (parsedOptions.getInputDataInfo().getFilePath().endsWith(FileExtensions.CACHE_FILE_EXT)) {
- QuantizationCacheManager.inspectCacheFile(parsedOptions.getInputDataInfo().getFilePath(),
- parsedOptions.isVerbose());
- } else {
- final ImageDecompressor decompressor = new ImageDecompressor(parsedOptions);
- try {
- System.out.println(decompressor.inspectCompressedFile());
- } catch (final IOException e) {
- System.err.println("Errors occurred during inspecting file.");
- System.err.println(e.getMessage());
- e.printStackTrace();
+ final FileTypeInspector.FileType fileType = FileTypeInspector.inspectFile(parsedOptions.getInputDataInfo().getFilePath());
+ switch (fileType) {
+ case Qcmp: {
+ final ImageDecompressor decompressor = new ImageDecompressor(parsedOptions);
+ try {
+ System.out.println(decompressor.inspectCompressedFile());
+ } catch (final IOException e) {
+ System.err.println("Errors occurred during inspecting file.");
+ System.err.println(e.getMessage());
+ e.printStackTrace();
+ }
}
+ break;
+ case Qvc: {
+ QuantizationCacheManager.inspectCacheFile(parsedOptions.getInputDataInfo().getFilePath(),
+ parsedOptions.isVerbose());
+ }
+ break;
+ case InvalidPath:
+ exitWithInvalidFilePath();
+ break;
+ case Unknown:
+ exitWithUnknownFile();
+ break;
}
}
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);
+ final FileTypeInspector.FileType fileType = FileTypeInspector.inspectFile(parsedOptions.getInputDataInfo().getFilePath());
+ switch (fileType) {
+ case Qcmp: {
+ System.err.println("Qcmp file conversion isn't supported yet");
}
+ break;
+ case Qvc: {
+ 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);
+ }
+ final boolean inPlace = parsedOptions.getOutputFilePath() == null;
+ 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.");
+ if (parsedOptions.isVerbose()) {
+ System.err.println("Qvc file is converted.");
+ }
}
-
- } else {
- System.err.println("Qcmp file conversion isn't supported yet");
+ break;
+ case InvalidPath:
+ exitWithInvalidFilePath();
+ break;
+ case Unknown:
+ exitWithUnknownFile();
+ break;
}
}
break;
@@ -156,6 +179,21 @@ public class DataCompressor {
ScifioWrapper.dispose();
}
+ private static void exitWithUnknownFile() {
+ ColorConsole.fprintf(ColorConsole.Target.stderr,
+ ColorConsole.Color.Red,
+ "Provided file is of unknown type. Only QCMP and QVC files are supported.\n");
+
+ exitApplication(1);
+ }
+
+ private static void exitWithInvalidFilePath() {
+ ColorConsole.fprintf(ColorConsole.Target.stderr,
+ ColorConsole.Color.Red,
+ "File specified by provided path doesn't exist.\n");
+ exitApplication(1);
+ }
+
private static void exitApplication(final int exitCode) {
ScifioWrapper.dispose();
System.exit(exitCode);
diff --git a/src/main/java/cz/it4i/qcmp/fileformat/QCMPFileHeader.java b/src/main/java/cz/it4i/qcmp/fileformat/QCMPFileHeader.java
index e9522b44fc23b32eaf463623c295d3d17289936c..e720b0d51452c01b75166bc1b73d97ff6087e99a 100644
--- a/src/main/java/cz/it4i/qcmp/fileformat/QCMPFileHeader.java
+++ b/src/main/java/cz/it4i/qcmp/fileformat/QCMPFileHeader.java
@@ -15,7 +15,7 @@ public class QCMPFileHeader implements IFileHeader, Cloneable {
//region Constants
private static final int VERSION = 1;
private static final int BASE_QCMP_HEADER_SIZE = 23;
- private static final String MAGIC_VALUE = "QCMPFILE";
+ public static final String MAGIC_VALUE = "QCMPFILE";
//endregion
//region Header fields
diff --git a/src/main/java/cz/it4i/qcmp/io/FileTypeInspector.java b/src/main/java/cz/it4i/qcmp/io/FileTypeInspector.java
new file mode 100644
index 0000000000000000000000000000000000000000..14a99bd4f0c4cf0aac015d831dcd01847d42bfce
--- /dev/null
+++ b/src/main/java/cz/it4i/qcmp/io/FileTypeInspector.java
@@ -0,0 +1,64 @@
+package cz.it4i.qcmp.io;
+
+import cz.it4i.qcmp.fileformat.QCMPFileHeader;
+import cz.it4i.qcmp.fileformat.QvcHeaderV1;
+import cz.it4i.qcmp.fileformat.QvcHeaderV2;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+public class FileTypeInspector {
+ public enum FileType {
+ /**
+ * Compressed image hyperstack.
+ */
+ Qcmp,
+ /**
+ * Codebook cache file.
+ */
+ Qvc,
+ /**
+ * Invalid file path.
+ */
+ InvalidPath,
+ /**
+ * No known magic value was matched.
+ */
+ Unknown
+ }
+
+ /**
+ * Inspect file specified by path and return its type.
+ *
+ * @param filePath Path to the file.
+ * @return File type.
+ */
+ public static FileType inspectFile(final String filePath) {
+ // QCMPFileHeader.MAGIC_VALUE // 8 bytes
+ // QvcHeaderV1.MAGIC_VALUE // 9 bytes
+ // QvcHeaderV2.MAGIC_VALUE // 9 bytes
+ try (final FileInputStream stream = new FileInputStream(filePath)) {
+ final byte[] buf1 = new byte[QCMPFileHeader.MAGIC_VALUE.length()];
+ RawDataIO.readFullBuffer(stream, buf1);
+ if (new String(buf1).equals(QCMPFileHeader.MAGIC_VALUE)) {
+ return FileType.Qcmp;
+ }
+
+ final byte[] buf2 = new byte[QvcHeaderV1.MAGIC_VALUE.length()];
+ System.arraycopy(buf1, 0, buf2, 0, buf1.length);
+ final int read = stream.read(buf2, buf1.length, 1);
+ if (read != 1)
+ return FileType.Unknown;
+
+ final String magicValue = new String(buf2);
+ if (magicValue.equals(QvcHeaderV1.MAGIC_VALUE) || magicValue.equals(QvcHeaderV2.MAGIC_VALUE))
+ return FileType.Qvc;
+ } catch (final FileNotFoundException e) {
+ return FileType.InvalidPath;
+ } catch (final IOException e) {
+ return FileType.Unknown;
+ }
+ return FileType.Unknown;
+ }
+}
diff --git a/src/main/java/cz/it4i/qcmp/utilities/ColorConsole.java b/src/main/java/cz/it4i/qcmp/utilities/ColorConsole.java
index d41b65963ff2109a08d0f4dd32f9b1115ffd2ec6..a3625f1f8c00710ab45b41a3a0bebd74b9ec4048 100644
--- a/src/main/java/cz/it4i/qcmp/utilities/ColorConsole.java
+++ b/src/main/java/cz/it4i/qcmp/utilities/ColorConsole.java
@@ -48,10 +48,10 @@ public final class ColorConsole {
switch (target) {
case stdout:
- System.out.println(getColor(color) + string + ANSI_RESET);
+ System.out.print(getColor(color) + string + ANSI_RESET);
break;
case stderr:
- System.err.println(getColor(color) + string + ANSI_RESET);
+ System.err.print(getColor(color) + string + ANSI_RESET);
break;
}
}