diff --git a/src/main/java/azgracompress/cache/QuantizationCacheManager.java b/src/main/java/azgracompress/cache/QuantizationCacheManager.java
index dbd07c83d947793e49dab0e7e7109627868692a4..d17d3ef9a8ac7a27549df0cb800131233e542dda 100644
--- a/src/main/java/azgracompress/cache/QuantizationCacheManager.java
+++ b/src/main/java/azgracompress/cache/QuantizationCacheManager.java
@@ -2,6 +2,7 @@ package azgracompress.cache;
 
 import azgracompress.data.V3i;
 import azgracompress.fileformat.QuantizationType;
+import azgracompress.quantization.QTrainIteration;
 import azgracompress.quantization.scalar.SQCodebook;
 import azgracompress.quantization.vector.VQCodebook;
 
@@ -36,7 +37,7 @@ public class QuantizationCacheManager {
     private File getCacheFilePathForSQ(final String trainFile, final int codebookSize) {
         final File inputFile = new File(trainFile);
         return new File(cacheFolder, String.format("%s_%d_bits.qvc",
-                                                   inputFile.getName(), codebookSize));
+                inputFile.getName(), codebookSize));
     }
 
     /**
@@ -52,7 +53,7 @@ public class QuantizationCacheManager {
                                        final V3i vDim) {
         final File inputFile = new File(trainFile);
         return new File(cacheFolder, String.format("%s_%d_%dx%d.qvc", inputFile.getName(), codebookSize,
-                                                   vDim.getX(), vDim.getY()));
+                vDim.getX(), vDim.getY()));
     }
 
 
@@ -140,8 +141,8 @@ public class QuantizationCacheManager {
      */
     public void saveCodebook(final String trainFile, final VQCodebook codebook) throws IOException {
         final String fileName = getCacheFilePathForVQ(trainFile,
-                                                      codebook.getCodebookSize(),
-                                                      codebook.getVectorDims()).getAbsolutePath();
+                codebook.getCodebookSize(),
+                codebook.getVectorDims()).getAbsolutePath();
 
         final CacheFileHeader header = createHeaderForVQ(new File(trainFile).getName(), codebook);
         final VQCacheFile cacheFile = new VQCacheFile(header, codebook);
@@ -172,15 +173,38 @@ public class QuantizationCacheManager {
         }
     }
 
+    /**
+     * Check if the SQ cache file for given image file exists.
+     *
+     * @param imageFile    Image file.
+     * @param codebookSize Scalar quantization codebook size.
+     * @return True if cache file exists and and can be loaded.
+     */
+    public boolean doesSQCacheExists(final String imageFile, final int codebookSize) {
+        return getCacheFilePathForSQ(imageFile, codebookSize).exists();
+    }
+
+    /**
+     * Check if the VQ cache file for given image file exists.
+     *
+     * @param imageFile    Image file.
+     * @param codebookSize Scalar quantization codebook size.
+     * @param vDim         Quantization vector dimensions.
+     * @return True if cache file exists and and can be loaded.
+     */
+    public boolean doesVQCacheExists(final String imageFile, final int codebookSize, final V3i vDim) {
+        return getCacheFilePathForVQ(imageFile, codebookSize, vDim).exists();
+    }
+
     /**
      * Load SQ cache file from disk.
      *
-     * @param trainFile    Input image file.
+     * @param imageFile    Input image file.
      * @param codebookSize Codebook size.
      * @return SQ cache file.
      */
-    private SQCacheFile loadSQCacheFile(final String trainFile, final int codebookSize) {
-        final File path = getCacheFilePathForSQ(trainFile, codebookSize);
+    private SQCacheFile loadSQCacheFile(final String imageFile, final int codebookSize) {
+        final File path = getCacheFilePathForSQ(imageFile, codebookSize);
         try {
             return (SQCacheFile) readCacheFile(path, new SQCacheFile());
         } catch (IOException e) {
@@ -293,4 +317,6 @@ public class QuantizationCacheManager {
         sb.append('\n');
         System.out.println(sb.toString());
     }
+
+
 }
diff --git a/src/main/java/azgracompress/cli/ParsedCliOptions.java b/src/main/java/azgracompress/cli/ParsedCliOptions.java
index 1ff3dfe5242e1d5e517ac1f376d9b412674103d1..d46ead03fc43393047459015858407776b209369 100644
--- a/src/main/java/azgracompress/cli/ParsedCliOptions.java
+++ b/src/main/java/azgracompress/cli/ParsedCliOptions.java
@@ -149,10 +149,14 @@ public class ParsedCliOptions extends CompressionOptions implements Cloneable {
         }
 
         if (!parseErrorOccurred) {
-            setOutputFilePath(cmd.getOptionValue(CliConstants.OUTPUT_LONG, getDefaultOutputFilePath(((FileInputData) getInputDataInfo()).getFilePath())));
+            setOutputFilePath(cmd.getOptionValue(CliConstants.OUTPUT_LONG, getDefaultOutputFilePath(getInputDataInfo().getFilePath())));
             setCodebookCacheFolder(cmd.getOptionValue(CliConstants.CODEBOOK_CACHE_FOLDER_LONG, null));
         }
 
+        if (getMethod() == ProgramMethod.TrainCodebook) {
+            setCodebookCacheFolder(getOutputFilePath());
+        }
+
         parseError = errorBuilder.toString();
     }
 
diff --git a/src/main/java/azgracompress/compression/SQImageCompressor.java b/src/main/java/azgracompress/compression/SQImageCompressor.java
index 598f231bbb93df1ddeebe29f3f190119f3d37924..7a3b067ed5ebb7bcf9df5b1391c4f55faddbb81e 100644
--- a/src/main/java/azgracompress/compression/SQImageCompressor.java
+++ b/src/main/java/azgracompress/compression/SQImageCompressor.java
@@ -73,8 +73,11 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm
     private ScalarQuantizer loadQuantizerFromCache() throws ImageCompressionException {
         QuantizationCacheManager cacheManager = new QuantizationCacheManager(options.getCodebookCacheFolder());
 
-        final SQCodebook codebook = cacheManager.loadSQCodebook(options.getInputDataInfo().getFilePath(),
-                getCodebookSize());
+        if (!cacheManager.doesSQCacheExists(options.getInputDataInfo().getCacheFileName(), getCodebookSize())) {
+            trainAndSaveCodebook();
+        }
+
+        final SQCodebook codebook = cacheManager.loadSQCodebook(options.getInputDataInfo().getCacheFileName(), getCodebookSize());
         if (codebook == null) {
             throw new ImageCompressionException("Failed to read quantization values from cache file.");
         }
@@ -220,9 +223,9 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm
         Log("Finished LloydMax training.");
 
         Log(String.format("Saving cache file to %s", options.getOutputFilePath()));
-        QuantizationCacheManager cacheManager = new QuantizationCacheManager(options.getOutputFilePath());
+        QuantizationCacheManager cacheManager = new QuantizationCacheManager(options.getCodebookCacheFolder());
         try {
-            cacheManager.saveCodebook(options.getInputDataInfo().getFilePath(), codebook);
+            cacheManager.saveCodebook(options.getInputDataInfo().getCacheFileName(), codebook);
         } catch (IOException e) {
             throw new ImageCompressionException("Unable to write cache.", e);
         }
diff --git a/src/main/java/azgracompress/compression/VQImageCompressor.java b/src/main/java/azgracompress/compression/VQImageCompressor.java
index e1f89b4768f84d88639252cbc14cb049da419599..d94984ca218d9262c006f50ea468e90f0acbfe0c 100644
--- a/src/main/java/azgracompress/compression/VQImageCompressor.java
+++ b/src/main/java/azgracompress/compression/VQImageCompressor.java
@@ -75,10 +75,16 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
 
         QuantizationCacheManager cacheManager = new QuantizationCacheManager(options.getCodebookCacheFolder());
 
+        if (!cacheManager.doesVQCacheExists(options.getInputDataInfo().getCacheFileName(),
+                getCodebookSize(),
+                options.getVectorDimension().toV3i())) {
+            trainAndSaveCodebook();
+        }
+
+        final VQCodebook codebook = cacheManager.loadVQCodebook(options.getInputDataInfo().getCacheFileName(),
+                getCodebookSize(),
+                options.getVectorDimension().toV3i());
 
-        final VQCodebook codebook = cacheManager.loadVQCodebook(options.getInputDataInfo().getFilePath(),
-                                                                getCodebookSize(),
-                                                                options.getVectorDimension().toV3i());
         if (codebook == null) {
             throw new ImageCompressionException("Failed to read quantization vectors from cache.");
         }
@@ -230,10 +236,10 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
                 }
 
                 System.arraycopy(planeVectors,
-                                 0,
-                                 trainData,
-                                 (planeCounter * chunkCountPerPlane),
-                                 chunkCountPerPlane);
+                        0,
+                        trainData,
+                        (planeCounter * chunkCountPerPlane),
+                        chunkCountPerPlane);
                 ++planeCounter;
             }
         }
@@ -256,9 +262,9 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
 
 
         Log("Saving cache file to %s", options.getOutputFilePath());
-        QuantizationCacheManager cacheManager = new QuantizationCacheManager(options.getOutputFilePath());
+        QuantizationCacheManager cacheManager = new QuantizationCacheManager(options.getCodebookCacheFolder());
         try {
-            cacheManager.saveCodebook(options.getInputDataInfo().getFilePath(), lbgResult.getCodebook());
+            cacheManager.saveCodebook(options.getInputDataInfo().getCacheFileName(), lbgResult.getCodebook());
         } catch (IOException e) {
             throw new ImageCompressionException("Unable to write VQ cache.", e);
         }
diff --git a/src/main/java/azgracompress/io/BufferInputData.java b/src/main/java/azgracompress/io/BufferInputData.java
index 9ab179dac8c57104e8f4a964ef13463f6cffba4c..3d0223aa4f1aec6b3e1975570d529caae382b151 100644
--- a/src/main/java/azgracompress/io/BufferInputData.java
+++ b/src/main/java/azgracompress/io/BufferInputData.java
@@ -12,6 +12,7 @@ public class BufferInputData extends InputData {
      */
     private final Object[] imageBuffers;
 
+    private final String cacheHint;
 
     /**
      * Create input data backed by buffer object.
@@ -19,12 +20,17 @@ public class BufferInputData extends InputData {
      * @param imageBuffers    Image buffer references.
      * @param imageDimensions Image dimensions.
      * @param pixelType       Image pixel type.
+     * @param cacheHint       Name of the image used in caching.
      */
-    public BufferInputData(final Object[] imageBuffers, final V3i imageDimensions, final PixelType pixelType) {
+    public BufferInputData(final Object[] imageBuffers,
+                           final V3i imageDimensions,
+                           final PixelType pixelType,
+                           final String cacheHint) {
         this.imageBuffers = imageBuffers;
         setDataLoaderType(DataLoaderType.ImageJBufferLoader);
         setDimension(imageDimensions);
         setPixelType(pixelType);
+        this.cacheHint = cacheHint;
     }
 
     /**
@@ -38,4 +44,9 @@ public class BufferInputData extends InputData {
         assert (planeIndex < imageBuffers.length);
         return imageBuffers[planeIndex];
     }
+
+    @Override
+    public String getCacheFileName() {
+        return cacheHint;
+    }
 }
diff --git a/src/main/java/azgracompress/io/FileInputData.java b/src/main/java/azgracompress/io/FileInputData.java
index 49fad663a4d9653f3647cbc24949ba660416f219..968fbd66d7a2302d61e2added34382470e7a0d30 100644
--- a/src/main/java/azgracompress/io/FileInputData.java
+++ b/src/main/java/azgracompress/io/FileInputData.java
@@ -12,6 +12,7 @@ public class FileInputData extends InputData {
 
     /**
      * Create input data backed by data file.
+     *
      * @param filePath
      */
     public FileInputData(String filePath) {
@@ -20,10 +21,16 @@ public class FileInputData extends InputData {
 
     /**
      * Get path to the data file.
+     *
      * @return
      */
     @Override
     public String getFilePath() {
         return filePath;
     }
+
+    @Override
+    public String getCacheFileName() {
+        return filePath;
+    }
 }
diff --git a/src/main/java/azgracompress/io/InputData.java b/src/main/java/azgracompress/io/InputData.java
index f4a27a9bb87b31ea373e34430382fcf4591ce5d9..966a706e8a63b019776616e4a78abb8565dfdaa1 100644
--- a/src/main/java/azgracompress/io/InputData.java
+++ b/src/main/java/azgracompress/io/InputData.java
@@ -97,9 +97,17 @@ public abstract class InputData {
 
     /**
      * Override in FileInputData!!!
+     *
      * @return null!
      */
     public String getFilePath() {
         return null;
     }
+
+    /**
+     * Get name used in creation of qcmp cache file.
+     *
+     * @return Name used for cache file.
+     */
+    public abstract String getCacheFileName();
 }