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;
     }