diff --git a/src/main/java/azgracompress/benchmark/BenchmarkBase.java b/src/main/java/azgracompress/benchmark/BenchmarkBase.java
index 7a6b629990a55c19176dca4f2915294f193ad701..b1983a2d3ae664fe0eac5882d8686c04d3875166 100644
--- a/src/main/java/azgracompress/benchmark/BenchmarkBase.java
+++ b/src/main/java/azgracompress/benchmark/BenchmarkBase.java
@@ -1,5 +1,6 @@
 package azgracompress.benchmark;
 
+import azgracompress.compression.CompressionOptions;
 import azgracompress.io.InputData;
 import azgracompress.cli.ParsedCliOptions;
 import azgracompress.data.ImageU16;
@@ -27,11 +28,10 @@ abstract class BenchmarkBase {
     protected final int[] planes;
     protected final V3i rawImageDims;
 
-    protected final boolean useMiddlePlane;
     protected final int codebookSize;
-    protected final boolean hasCacheFolder;
     protected final String cacheFolder;
-    protected final boolean hasGeneralQuantizer;
+
+    protected CompressionOptions.CodebookType codebookType;
 
     protected final int workerCount;
 
@@ -45,7 +45,7 @@ abstract class BenchmarkBase {
         this.outputDirectory = options.getOutputFilePath();
 
         this.rawImageDims = ifi.getDimensions();
-        this.useMiddlePlane = options.shouldUseMiddlePlane();
+        this.codebookType = options.getCodebookType();
 
         this.codebookSize = (int) Math.pow(2, options.getBitsPerCodebookIndex());
 
@@ -67,9 +67,7 @@ abstract class BenchmarkBase {
             }
         }
 
-        hasCacheFolder = options.hasCodebookCacheFolder();
         cacheFolder = options.getCodebookCacheFolder();
-        hasGeneralQuantizer = useMiddlePlane || hasCacheFolder;
         workerCount = options.getWorkerCount();
     }
 
diff --git a/src/main/java/azgracompress/benchmark/SQBenchmark.java b/src/main/java/azgracompress/benchmark/SQBenchmark.java
index 1fc7d82de080e2e5b93978fc09818cfd57f3497a..29b19bbba675b91e91b27b356aed8242ce9cbd4c 100644
--- a/src/main/java/azgracompress/benchmark/SQBenchmark.java
+++ b/src/main/java/azgracompress/benchmark/SQBenchmark.java
@@ -3,6 +3,7 @@ package azgracompress.benchmark;
 import azgracompress.U16;
 import azgracompress.cache.QuantizationCacheManager;
 import azgracompress.cli.ParsedCliOptions;
+import azgracompress.compression.CompressionOptions;
 import azgracompress.io.loader.IPlaneLoader;
 import azgracompress.io.loader.PlaneLoaderFactory;
 import azgracompress.quantization.QTrainIteration;
@@ -40,7 +41,7 @@ public class SQBenchmark extends BenchmarkBase {
         System.out.println(String.format("|CODEBOOK| = %d", codebookSize));
         ScalarQuantizer quantizer = null;
 
-        if (hasCacheFolder) {
+        if (options.getCodebookType() == CompressionOptions.CodebookType.Global) {
             System.out.println("Loading codebook from cache");
             QuantizationCacheManager cacheManager = new QuantizationCacheManager(cacheFolder);
             final SQCodebook codebook = cacheManager.loadSQCodebook(inputFile, codebookSize);
@@ -52,7 +53,7 @@ public class SQBenchmark extends BenchmarkBase {
 
             quantizer = new ScalarQuantizer(codebook);
             System.out.println("Created quantizer from cache");
-        } else if (useMiddlePlane) {
+        } else if (options.getCodebookType() == CompressionOptions.CodebookType.MiddlePlane) {
             final int middlePlaneIndex = rawImageDims.getZ() / 2;
 
             final int[] middlePlaneData;
@@ -90,7 +91,7 @@ public class SQBenchmark extends BenchmarkBase {
                     codebookSize);
             final String trainLogFile = String.format(TRAIN_FILE_TEMPLATE, planeIndex, codebookSize);
 
-            if (!hasGeneralQuantizer) {
+            if (options.getCodebookType() == CompressionOptions.CodebookType.Individual) {
                 quantizer = trainLloydMaxQuantizer(planeData, codebookSize, trainLogFile);
                 System.out.println("Created plane quantizer");
             }
diff --git a/src/main/java/azgracompress/benchmark/VQBenchmark.java b/src/main/java/azgracompress/benchmark/VQBenchmark.java
index c9095c4b4f51db17ac4550b4887e5d50911a69fb..d4847493d32ad617eae7fc2a51e6e6d842c6db4e 100644
--- a/src/main/java/azgracompress/benchmark/VQBenchmark.java
+++ b/src/main/java/azgracompress/benchmark/VQBenchmark.java
@@ -3,6 +3,7 @@ package azgracompress.benchmark;
 import azgracompress.U16;
 import azgracompress.cache.QuantizationCacheManager;
 import azgracompress.cli.ParsedCliOptions;
+import azgracompress.compression.CompressionOptions;
 import azgracompress.data.*;
 import azgracompress.io.loader.IPlaneLoader;
 import azgracompress.io.loader.PlaneLoaderFactory;
@@ -66,7 +67,7 @@ public class VQBenchmark extends BenchmarkBase {
         System.out.println(String.format("|CODEBOOK| = %d", codebookSize));
         VectorQuantizer quantizer = null;
 
-        if (hasCacheFolder) {
+        if (options.getCodebookType() == CompressionOptions.CodebookType.Global) {
             System.out.println("Loading codebook from cache");
             QuantizationCacheManager cacheManager = new QuantizationCacheManager(cacheFolder);
             final VQCodebook codebook = cacheManager.loadVQCodebook(inputFile, codebookSize, qVector.toV3i());
@@ -77,7 +78,7 @@ public class VQBenchmark extends BenchmarkBase {
             quantizer = new VectorQuantizer(codebook);
             System.out.println("Created quantizer from cache");
 
-        } else if (useMiddlePlane) {
+        } else if (options.getCodebookType() == CompressionOptions.CodebookType.MiddlePlane) {
             final int middlePlaneIndex = rawImageDims.getZ() / 2;
             final ImageU16 middlePlane;
             try {
@@ -113,7 +114,7 @@ public class VQBenchmark extends BenchmarkBase {
             final int[][] planeData = getPlaneVectors(plane, qVector);
 
 
-            if (!hasGeneralQuantizer) {
+            if (options.getCodebookType() == CompressionOptions.CodebookType.Individual) {
                 LBGVectorQuantizer vqInitializer = new LBGVectorQuantizer(planeData,
                         codebookSize,
                         workerCount,
diff --git a/src/main/java/azgracompress/cli/ParsedCliOptions.java b/src/main/java/azgracompress/cli/ParsedCliOptions.java
index 524efef8db5091494dc287546b051994ed0a7fb8..1ff3dfe5242e1d5e517ac1f376d9b412674103d1 100644
--- a/src/main/java/azgracompress/cli/ParsedCliOptions.java
+++ b/src/main/java/azgracompress/cli/ParsedCliOptions.java
@@ -120,7 +120,17 @@ public class ParsedCliOptions extends CompressionOptions implements Cloneable {
 
         parseBitsPerPixel(cmd, errorBuilder);
 
-        setUseMiddlePlane(cmd.hasOption(CliConstants.USE_MIDDLE_PLANE_LONG));
+        if (cmd.hasOption(CliConstants.USE_MIDDLE_PLANE_LONG))
+            setCodebookType(CodebookType.MiddlePlane);
+        else if (cmd.hasOption(CliConstants.CODEBOOK_CACHE_FOLDER_LONG)) {
+            final String cbc = cmd.getOptionValue(CliConstants.CODEBOOK_CACHE_FOLDER_LONG, null);
+            assert (cbc != null);
+            setCodebookType(CodebookType.Global);
+            setCodebookCacheFolder(cbc);
+        } else {
+            setCodebookType(CodebookType.Individual);
+        }
+
 
         final String[] fileInfo = cmd.getArgs();
         parseInputFilePart(errorBuilder, fileInfo);
@@ -137,7 +147,6 @@ public class ParsedCliOptions extends CompressionOptions implements Cloneable {
                 errorBuilder.append("Unable to parse worker count. Expected int got: ").append(wcString).append('\n');
             }
         }
-        setCodebookCacheFolder(cmd.getOptionValue(CliConstants.CODEBOOK_CACHE_FOLDER_LONG, null));
 
         if (!parseErrorOccurred) {
             setOutputFilePath(cmd.getOptionValue(CliConstants.OUTPUT_LONG, getDefaultOutputFilePath(((FileInputData) getInputDataInfo()).getFilePath())));
@@ -192,7 +201,7 @@ public class ParsedCliOptions extends CompressionOptions implements Cloneable {
         getInputDataInfo().setDataLoaderType(InputData.DataLoaderType.SCIFIOLoader);
         Reader reader;
         try {
-            reader = ScifioWrapper.getReader(((FileInputData)getInputDataInfo()).getFilePath());
+            reader = ScifioWrapper.getReader(((FileInputData) getInputDataInfo()).getFilePath());
         } catch (IOException | FormatException e) {
             parseErrorOccurred = true;
             errorBuilder.append("Failed to get SCIFIO reader for file.\n");
@@ -544,11 +553,17 @@ public class ParsedCliOptions extends CompressionOptions implements Cloneable {
         }
 
 
-        sb.append("InputFile: ").append(((FileInputData)getInputDataInfo()).getFilePath()).append('\n');
+        sb.append("InputFile: ").append(((FileInputData) getInputDataInfo()).getFilePath()).append('\n');
         sb.append("Output: ").append(getOutputFilePath()).append('\n');
         sb.append("BitsPerCodebookIndex: ").append(getBitsPerCodebookIndex()).append('\n');
-        if (hasCodebookCacheFolder()) {
-            sb.append("CodebookCacheFolder: ").append(getCodebookCacheFolder()).append('\n');
+
+        switch (getCodebookType()) {
+            case MiddlePlane:
+                sb.append("Use middle plane for codebook training\n");
+                break;
+            case Global:
+                sb.append("CodebookCacheFolder: ").append(getCodebookCacheFolder()).append('\n');
+                break;
         }
 
         if (hasQuantizationType(method)) {
@@ -559,9 +574,6 @@ public class ParsedCliOptions extends CompressionOptions implements Cloneable {
             sb.append("PlaneIndex: ").append(getInputDataInfo().getPlaneIndex()).append('\n');
         }
 
-        if (shouldUseMiddlePlane()) {
-            sb.append("Use middle plane for codebook training\n");
-        }
 
         if (getInputDataInfo().isPlaneRangeSet()) {
             sb.append("FromPlaneIndex: ").append(getInputDataInfo().getPlaneRange().getFrom()).append('\n');
diff --git a/src/main/java/azgracompress/compression/CompressionOptions.java b/src/main/java/azgracompress/compression/CompressionOptions.java
index 53738f953bbd70974793abf64d0338864467e78f..da0384dde8d460a3736122dd4b2051d97ff3eba9 100644
--- a/src/main/java/azgracompress/compression/CompressionOptions.java
+++ b/src/main/java/azgracompress/compression/CompressionOptions.java
@@ -8,6 +8,14 @@ import azgracompress.fileformat.QuantizationType;
  * Options for the compressor/decompressor.
  */
 public class CompressionOptions {
+
+    public enum CodebookType {
+        Individual,
+        MiddlePlane,
+        Global,
+        Invalid
+    }
+
     /**
      * Input image or compressed file.
      */
@@ -23,6 +31,11 @@ public class CompressionOptions {
      */
     private QuantizationType quantizationType;
 
+    /**
+     * Type of the codebook.
+     */
+    private CodebookType codebookType = CodebookType.Individual;
+
     /**
      * Directory which contains codebook caches.
      */
@@ -39,11 +52,6 @@ public class CompressionOptions {
      */
     private V2i vectorDimension = new V2i(0);
 
-    /**
-     * Flag, whether to use middle plane as reference plane for codebook creation.
-     */
-    private boolean useMiddlePlane = false;
-
     /**
      * Number of workers to be used for different operations.
      */
@@ -55,10 +63,6 @@ public class CompressionOptions {
     private boolean verbose;
 
 
-    public boolean hasCodebookCacheFolder() {
-        return codebookCacheFolder != null;
-    }
-
     protected void setVerbose(boolean verbose) {
         this.verbose = verbose;
     }
@@ -117,14 +121,6 @@ public class CompressionOptions {
         this.vectorDimension = vectorDimension;
     }
 
-    public boolean shouldUseMiddlePlane() {
-        return useMiddlePlane;
-    }
-
-    public void setUseMiddlePlane(boolean useMiddlePlane) {
-        this.useMiddlePlane = useMiddlePlane;
-    }
-
     public int getWorkerCount() {
         return workerCount;
     }
@@ -132,4 +128,12 @@ public class CompressionOptions {
     public void setWorkerCount(int workerCount) {
         this.workerCount = workerCount;
     }
+
+    public CodebookType getCodebookType() {
+        return codebookType;
+    }
+
+    public void setCodebookType(CodebookType codebookType) {
+        this.codebookType = codebookType;
+    }
 }
diff --git a/src/main/java/azgracompress/compression/ImageCompressor.java b/src/main/java/azgracompress/compression/ImageCompressor.java
index 812e0c0c93e2aeb17592a9af509568ae8401f496..495b5890065cb09dbe2ed9c9ea48a7b1bfe8bffd 100644
--- a/src/main/java/azgracompress/compression/ImageCompressor.java
+++ b/src/main/java/azgracompress/compression/ImageCompressor.java
@@ -142,9 +142,7 @@ public class ImageCompressor extends CompressorDecompressorBase {
         header.setQuantizationType(options.getQuantizationType());
         header.setBitsPerCodebookIndex((byte) options.getBitsPerCodebookIndex());
 
-        // 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.setCodebookPerPlane(options.getCodebookType() == CompressionOptions.CodebookType.Individual);
 
         header.setImageSizeX(options.getInputDataInfo().getDimensions().getX());
         header.setImageSizeY(options.getInputDataInfo().getDimensions().getY());
diff --git a/src/main/java/azgracompress/compression/SQImageCompressor.java b/src/main/java/azgracompress/compression/SQImageCompressor.java
index c0cab1ec261360dd76c5e6fb500372d5ba9d08d6..598f231bbb93df1ddeebe29f3f190119f3d37924 100644
--- a/src/main/java/azgracompress/compression/SQImageCompressor.java
+++ b/src/main/java/azgracompress/compression/SQImageCompressor.java
@@ -90,7 +90,7 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm
     public long[] compress(DataOutputStream compressStream) throws ImageCompressionException {
         final InputData inputDataInfo = options.getInputDataInfo();
         Stopwatch stopwatch = new Stopwatch();
-        final boolean hasGeneralQuantizer = options.hasCodebookCacheFolder() || options.shouldUseMiddlePlane();
+        final boolean hasGeneralQuantizer = options.getCodebookType() != CompressionOptions.CodebookType.Individual;
 
         final IPlaneLoader planeLoader;
         try {
@@ -102,7 +102,7 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm
         ScalarQuantizer quantizer = null;
         Huffman huffman = null;
         final int[] huffmanSymbols = createHuffmanSymbols(getCodebookSize());
-        if (options.hasCodebookCacheFolder()) {
+        if (options.getCodebookType() == CompressionOptions.CodebookType.Global) {
             Log("Loading codebook from cache file.");
 
             quantizer = loadQuantizerFromCache();
@@ -110,7 +110,7 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm
 
             Log("Cached quantizer with huffman coder created.");
             writeCodebookToOutputStream(quantizer, compressStream);
-        } else if (options.shouldUseMiddlePlane()) {
+        } else if (options.getCodebookType() == CompressionOptions.CodebookType.MiddlePlane) {
             stopwatch.restart();
             ImageU16 middlePlane = null;
             final int middlePlaneIndex = getMiddlePlaneIndex();
diff --git a/src/main/java/azgracompress/compression/VQImageCompressor.java b/src/main/java/azgracompress/compression/VQImageCompressor.java
index 3979841e7d136da0f6c5b4a58421198477889e3e..e1f89b4768f84d88639252cbc14cb049da419599 100644
--- a/src/main/java/azgracompress/compression/VQImageCompressor.java
+++ b/src/main/java/azgracompress/compression/VQImageCompressor.java
@@ -94,7 +94,7 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
     public long[] compress(DataOutputStream compressStream) throws ImageCompressionException {
         final InputData inputDataInfo = options.getInputDataInfo();
         Stopwatch stopwatch = new Stopwatch();
-        final boolean hasGeneralQuantizer = options.hasCodebookCacheFolder() || options.shouldUseMiddlePlane();
+        final boolean hasGeneralQuantizer = options.getCodebookType() != CompressionOptions.CodebookType.Individual;
         final IPlaneLoader planeLoader;
         final int[] huffmanSymbols = createHuffmanSymbols(getCodebookSize());
         try {
@@ -105,13 +105,13 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
         VectorQuantizer quantizer = null;
         Huffman huffman = null;
 
-        if (options.hasCodebookCacheFolder()) {
+        if (options.getCodebookType() == CompressionOptions.CodebookType.Global) {
             Log("Loading codebook from cache file.");
             quantizer = loadQuantizerFromCache();
             huffman = createHuffmanCoder(huffmanSymbols, quantizer.getFrequencies());
             Log("Cached quantizer with huffman coder created.");
             writeQuantizerToCompressStream(quantizer, compressStream);
-        } else if (options.shouldUseMiddlePlane()) {
+        } else if (options.getCodebookType() == CompressionOptions.CodebookType.MiddlePlane) {
             stopwatch.restart();
 
             final int middlePlaneIndex = getMiddlePlaneIndex();