diff --git a/src/main/java/azgracompress/benchmark/Benchmark.java b/src/main/java/azgracompress/benchmark/Benchmark.java new file mode 100644 index 0000000000000000000000000000000000000000..a54814f627d1730ca9df953cab279036128349d6 --- /dev/null +++ b/src/main/java/azgracompress/benchmark/Benchmark.java @@ -0,0 +1,108 @@ +package azgracompress.benchmark; + +import azgracompress.U16; +import azgracompress.cli.ParsedCliOptions; +import azgracompress.compression.ImageCompressor; +import azgracompress.compression.ImageDecompressor; +import azgracompress.data.ImageU16; +import azgracompress.io.RawDataIO; +import azgracompress.utilities.Utils; + +import java.io.File; +import java.io.IOException; + +public class Benchmark extends BenchmarkBase { + + + protected Benchmark(ParsedCliOptions options) { + super(options); + } + + @Override + public void startBenchmark() { + + ParsedCliOptions compressOps; + ParsedCliOptions decompressOps; + try { + compressOps = (ParsedCliOptions) options.clone(); + decompressOps = (ParsedCliOptions) options.clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + return; + } + + boolean dirCreated = new File(options.getOutputFile()).mkdirs(); + //"%d_cb%d.raw.qcmp" + final String qcmpFilePath = getFileNamePathIntoOutDir(String.format(COMPRESSED_FILE_TEMPLATE, + options.getPlaneIndex(), + codebookSize)); + compressOps.setOutputFile(qcmpFilePath); + ImageCompressor compressor = new ImageCompressor(compressOps); + if (!compressor.compress()) { + System.err.println("Errors occurred during compression."); + return; + } + + decompressOps.setInputFile(qcmpFilePath); + + + final String decompressedFile = getFileNamePathIntoOutDir(String.format(QUANTIZED_FILE_TEMPLATE, + options.getPlaneIndex(), + codebookSize)); + + decompressOps.setOutputFile(decompressedFile); + ImageDecompressor decompressor = new ImageDecompressor(decompressOps); + if (!decompressor.decompress()) { + System.err.println("Errors occurred during decompression."); + } + + final int[] originalData; + try { + originalData = RawDataIO.loadImageU16(options.getInputFile(), + options.getImageDimension(), + options.getPlaneIndex()).getData(); + } catch (IOException e) { + e.printStackTrace(); + return; + } + final int[] quantizedData; + try { + quantizedData = RawDataIO.loadImageU16(decompressedFile, + options.getImageDimension().toV2i().toV3i(), 0).getData(); + } catch (IOException e) { + e.printStackTrace(); + return; + } + + final int[] diffArray = Utils.getDifference(originalData, quantizedData); + final double mse = Utils.calculateMse(diffArray); + final double PSNR = Utils.calculatePsnr(mse, U16.Max); + System.out.println(String.format("MSE: %.4f\tPSNR: %.4f(dB)", mse, PSNR)); + + final int[] absDifferenceData = Utils.asAbsoluteValues(diffArray); + + final String diffFilePath = getFileNamePathIntoOutDir(String.format(DIFFERENCE_FILE_TEMPLATE, + options.getPlaneIndex(), + codebookSize)); + + final String absDiffFilePath = getFileNamePathIntoOutDir(String.format(ABSOLUTE_DIFFERENCE_FILE_TEMPLATE, + options.getPlaneIndex(), + codebookSize)); + + ImageU16 img = new ImageU16(rawImageDims.getX(), + rawImageDims.getY(), + absDifferenceData); + try { + // NOTE(Moravec): Use little endian so that gnuplot can read the array. + RawDataIO.writeImageU16(absDiffFilePath, img, true); + System.out.println("Saved absolute difference to: " + absDiffFilePath); + + RawDataIO.writeDataI32(diffFilePath, diffArray, true); + System.out.println("Saved difference to: " + absDiffFilePath); + } catch (Exception e) { + e.printStackTrace(); + System.err.println("Failed to save difference."); + return; + } + } +} diff --git a/src/main/java/azgracompress/benchmark/BenchmarkBase.java b/src/main/java/azgracompress/benchmark/BenchmarkBase.java index 1d159e2360e85c366b1f6a07dd43f1376a1cb4ba..b2777a94e82a2230874aa2bfb6d7583ca9a03fe4 100644 --- a/src/main/java/azgracompress/benchmark/BenchmarkBase.java +++ b/src/main/java/azgracompress/benchmark/BenchmarkBase.java @@ -14,6 +14,7 @@ import java.io.OutputStreamWriter; abstract class BenchmarkBase { + protected final static String COMPRESSED_FILE_TEMPLATE = "%d_cb%d.raw.qcmp"; protected final static String QUANTIZED_FILE_TEMPLATE = "%d_cb%d.raw"; protected final static String DIFFERENCE_FILE_TEMPLATE = "%d_cb%d.data"; protected final static String ABSOLUTE_DIFFERENCE_FILE_TEMPLATE = "%d_cb%d_abs.data"; @@ -33,26 +34,10 @@ abstract class BenchmarkBase { protected final int workerCount; - protected BenchmarkBase(final String inputFile, - final String outputDirectory, - final int[] planes, - final V3i rawImageDims) { - this.inputFile = inputFile; - this.outputDirectory = outputDirectory; - this.planes = planes; - this.rawImageDims = rawImageDims; - - useMiddlePlane = false; - codebookSize = 256; - - hasCacheFolder = false; - cacheFolder = null; - hasGeneralQuantizer = false; - - workerCount = 1; - } + protected final ParsedCliOptions options; protected BenchmarkBase(final ParsedCliOptions options) { + this.options = options; this.inputFile = options.getInputFile(); this.outputDirectory = options.getOutputFile(); this.rawImageDims = options.getImageDimension(); @@ -152,12 +137,10 @@ abstract class BenchmarkBase { * @param absDiffFile File storing u16 absolute difference values. * @return True if both files were saved successfully. */ - protected boolean saveDifference(final int[] originalData, - final int[] transformedData, + protected boolean saveDifference(final int[] differenceData, final String diffFile, final String absDiffFile) { - final int[] differenceData = Utils.getDifference(originalData, transformedData); final int[] absDifferenceData = Utils.asAbsoluteValues(differenceData); final String diffFilePath = getFileNamePathIntoOutDir(diffFile); final String absDiffFilePath = getFileNamePathIntoOutDir(absDiffFile); diff --git a/src/main/java/azgracompress/benchmark/CompressionBenchmark.java b/src/main/java/azgracompress/benchmark/CompressionBenchmark.java index 83d9dc9136fcea2579784cebf262e34783e39c61..1f717686306db6c0617be70cc589bb0855c0b938 100644 --- a/src/main/java/azgracompress/benchmark/CompressionBenchmark.java +++ b/src/main/java/azgracompress/benchmark/CompressionBenchmark.java @@ -4,23 +4,25 @@ import azgracompress.cli.ParsedCliOptions; public class CompressionBenchmark { public static void runBenchmark(final ParsedCliOptions options) { - switch (options.getQuantizationType()) { - case Scalar: { - SQBenchmark sqBenchmark = new SQBenchmark(options); - sqBenchmark.startBenchmark(); - } - break; - case Vector1D: - case Vector2D: { - VQBenchmark vqBenchmark = new VQBenchmark(options); - vqBenchmark.startBenchmark(options.getVectorDimension()); - } - break; - case Vector3D: - case Invalid: { - System.err.println("Unsupported benchmark type."); - } - break; - } + Benchmark benchmark = new Benchmark(options); + benchmark.startBenchmark(); +// switch (options.getQuantizationType()) { +// case Scalar: { +// SQBenchmark sqBenchmark = new SQBenchmark(options); +// sqBenchmark.startBenchmark(); +// } +// break; +// case Vector1D: +// case Vector2D: { +// VQBenchmark vqBenchmark = new VQBenchmark(options); +// vqBenchmark.startBenchmark(options.getVectorDimension()); +// } +// break; +// case Vector3D: +// case Invalid: { +// System.err.println("Unsupported benchmark type."); +// } +// break; +// } } } diff --git a/src/main/java/azgracompress/benchmark/SQBenchmark.java b/src/main/java/azgracompress/benchmark/SQBenchmark.java index a26b41e1f883845edc23ceca5b3bc0a21f298404..4850b367805f606519d3670898b0c31058a3c1cd 100644 --- a/src/main/java/azgracompress/benchmark/SQBenchmark.java +++ b/src/main/java/azgracompress/benchmark/SQBenchmark.java @@ -79,12 +79,10 @@ public class SQBenchmark extends BenchmarkBase { final int[] quantizedData = quantizer.quantize(planeData); - { - final int[] diffArray = Utils.getDifference(planeData, quantizedData); - final double mse = Utils.calculateMse(diffArray); - final double PSNR = Utils.calculatePsnr(mse, U16.Max); - System.out.println(String.format("MSE: %.4f\tPSNR: %.4f(dB)", mse, PSNR)); - } + final int[] diffArray = Utils.getDifference(planeData, quantizedData); + final double mse = Utils.calculateMse(diffArray); + final double PSNR = Utils.calculatePsnr(mse, U16.Max); + System.out.println(String.format("MSE: %.4f\tPSNR: %.4f(dB)", mse, PSNR)); if (!saveQuantizedPlaneData(quantizedData, quantizedFile)) { @@ -92,7 +90,7 @@ public class SQBenchmark extends BenchmarkBase { return; } - saveDifference(planeData, quantizedData, diffFile, absoluteDiffFile); + saveDifference(diffArray, diffFile, absoluteDiffFile); } } diff --git a/src/main/java/azgracompress/benchmark/VQBenchmark.java b/src/main/java/azgracompress/benchmark/VQBenchmark.java index 565bc98bfdb5560536ae36b612c512d5abeabb9c..463a90878cf3a472e8f98a436d8e7d6d9321d4a1 100644 --- a/src/main/java/azgracompress/benchmark/VQBenchmark.java +++ b/src/main/java/azgracompress/benchmark/VQBenchmark.java @@ -16,10 +16,6 @@ public class VQBenchmark extends BenchmarkBase { final static V2i DEFAULT_QVECTOR = new V2i(3, 3); - public VQBenchmark(String inputFile, String outputDirectory, int[] planes, V3i rawImageDims) { - super(inputFile, outputDirectory, planes, rawImageDims); - } - public VQBenchmark(final ParsedCliOptions options) { super(options); } @@ -120,20 +116,18 @@ public class VQBenchmark extends BenchmarkBase { final ImageU16 quantizedImage = reconstructImageFromQuantizedVectors(plane, quantizedData, qVector); - { - final int[] diffArray = Utils.getDifference(plane.getData(), quantizedImage.getData()); - final double mse = Utils.calculateMse(diffArray); - final double PSNR = Utils.calculatePsnr(mse, U16.Max); - System.out.println(String.format("MSE: %.4f\tPSNR: %.4f(dB)", mse, PSNR)); - } + final int[] diffArray = Utils.getDifference(plane.getData(), quantizedImage.getData()); + final double mse = Utils.calculateMse(diffArray); + final double PSNR = Utils.calculatePsnr(mse, U16.Max); + System.out.println(String.format("MSE: %.4f\tPSNR: %.4f(dB)", mse, PSNR)); if (!saveQuantizedPlaneData(quantizedImage.getData(), quantizedFile)) { System.err.println("Failed to save quantized plane."); return; } - saveDifference(plane.getData(), quantizedImage.getData(), diffFile, absoluteDiffFile); + saveDifference(diffArray, diffFile, absoluteDiffFile); } } } diff --git a/src/main/java/azgracompress/cli/ParsedCliOptions.java b/src/main/java/azgracompress/cli/ParsedCliOptions.java index b43ce7fbb62d81730656560092d7fd255ca21cb6..eb78338020e59dc9a25e2fe6dfc30c8062c2aef2 100644 --- a/src/main/java/azgracompress/cli/ParsedCliOptions.java +++ b/src/main/java/azgracompress/cli/ParsedCliOptions.java @@ -9,7 +9,7 @@ import org.apache.commons.cli.CommandLine; import java.io.File; import java.nio.file.Paths; -public class ParsedCliOptions { +public class ParsedCliOptions implements Cloneable { private static final int DEFAULT_BITS_PER_PIXEL = 8; @@ -488,4 +488,27 @@ public class ParsedCliOptions { return imageDimension.getZ(); } } + + /** + * Change te output file path. + * + * @param outputFile Output file path. + */ + public void setOutputFile(final String outputFile) { + this.outputFile = outputFile; + } + + /** + * Change te input file path. + * + * @param inputFile Input file path. + */ + public void setInputFile(final String inputFile) { + this.inputFile = inputFile; + } + + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } } diff --git a/src/main/java/azgracompress/compression/CompressorDecompressorBase.java b/src/main/java/azgracompress/compression/CompressorDecompressorBase.java index 50416a8d6ef467d947fd61f17a4fc22d932abbd1..996173e91348e023372e459ff743b9f64fb7ac49 100644 --- a/src/main/java/azgracompress/compression/CompressorDecompressorBase.java +++ b/src/main/java/azgracompress/compression/CompressorDecompressorBase.java @@ -6,8 +6,6 @@ import azgracompress.huffman.Huffman; import azgracompress.io.OutBitStream; import java.io.DataOutputStream; -import java.util.Iterator; -import java.util.Map; public abstract class CompressorDecompressorBase { public static final int LONG_BYTES = 8; @@ -33,18 +31,18 @@ public abstract class CompressorDecompressorBase { Huffman huffman = new Huffman(symbols, frequencies); huffman.buildHuffmanTree(); - if (options.isVerbose()) { - StringBuilder sb = new StringBuilder(); - sb.append("Huffman symbols and their probabilities:\n"); - - Iterator<Map.Entry<Integer, Double>> it = huffman.getSymbolProbabilityMap().entrySet().iterator(); - while (it.hasNext()) { - final Map.Entry<Integer, Double> pair = (Map.Entry<Integer, Double>) it.next(); - - sb.append(String.format("%d: %.10f\n", pair.getKey(), pair.getValue())); - } - System.out.println(sb.toString()); - } +// if (options.isVerbose()) { +// StringBuilder sb = new StringBuilder(); +// sb.append("Huffman symbols and their probabilities:\n"); +// +// Iterator<Map.Entry<Integer, Double>> it = huffman.getSymbolProbabilityMap().entrySet().iterator(); +// while (it.hasNext()) { +// final Map.Entry<Integer, Double> pair = (Map.Entry<Integer, Double>) it.next(); +// +// sb.append(String.format("%d: %.10f\n", pair.getKey(), pair.getValue())); +// } +// System.out.println(sb.toString()); +// } return huffman; }