diff --git a/src/main/java/azgracompress/compression/CompressionOptions.java b/src/main/java/azgracompress/compression/CompressionOptions.java
index 82e7c5c61bf4d1aacf946f74f49d6ef3d41c4113..09c83fb5d3395150cd175f0d1de813dd28163321 100644
--- a/src/main/java/azgracompress/compression/CompressionOptions.java
+++ b/src/main/java/azgracompress/compression/CompressionOptions.java
@@ -67,7 +67,7 @@ public class CompressionOptions {
         this.workerCount = (cores / 2);
     }
 
-    protected void setVerbose(boolean verbose) {
+    public void setVerbose(boolean verbose) {
         this.verbose = verbose;
     }
 
diff --git a/src/main/java/azgracompress/compression/VQImageCompressor.java b/src/main/java/azgracompress/compression/VQImageCompressor.java
index 05539c6f994ba04f0ce8ca5327701d2607b7187c..4543ed9b2e6702f01f81d612dbea4bafe76317d1 100644
--- a/src/main/java/azgracompress/compression/VQImageCompressor.java
+++ b/src/main/java/azgracompress/compression/VQImageCompressor.java
@@ -32,7 +32,7 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
                 getCodebookSize(),
                 options.getWorkerCount(),
                 options.getVectorDimension().toV3i());
-        LBGResult vqResult = vqInitializer.findOptimalCodebook(false);
+        LBGResult vqResult = vqInitializer.findOptimalCodebook();
         return new VectorQuantizer(vqResult.getCodebook());
     }
 
@@ -255,7 +255,8 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
                 options.getWorkerCount(),
                 options.getVectorDimension().toV3i());
         reportStatusToListeners("Starting LBG optimization.");
-        LBGResult lbgResult = vqInitializer.findOptimalCodebook(options.isVerbose());
+        vqInitializer.setStatusListener(this::reportStatusToListeners);
+        LBGResult lbgResult = vqInitializer.findOptimalCodebook();
         reportStatusToListeners("Learned the optimal codebook.");
 
 
diff --git a/src/main/java/azgracompress/quantization/vector/LBGVectorQuantizer.java b/src/main/java/azgracompress/quantization/vector/LBGVectorQuantizer.java
index 6943a3edd8411a09c2eea8e1a683f812c33e063f..b431e3f5659e745850e55dfdee8ea8e3c5cfa786 100644
--- a/src/main/java/azgracompress/quantization/vector/LBGVectorQuantizer.java
+++ b/src/main/java/azgracompress/quantization/vector/LBGVectorQuantizer.java
@@ -1,6 +1,7 @@
 package azgracompress.quantization.vector;
 
 import azgracompress.U16;
+import azgracompress.compression.listeners.IStatusListener;
 import azgracompress.data.V3i;
 import azgracompress.utilities.Stopwatch;
 import azgracompress.utilities.Utils;
@@ -24,7 +25,7 @@ public class LBGVectorQuantizer {
 
     private long[] frequencies;
 
-    boolean verbose = false;
+    private IStatusListener statusListener = null;
     private double _mse = 0.0;
 
     public LBGVectorQuantizer(final int[][] vectors,
@@ -49,6 +50,19 @@ public class LBGVectorQuantizer {
         findUniqueVectors();
     }
 
+    public void setStatusListener(final IStatusListener statusListener) {
+        this.statusListener = statusListener;
+    }
+
+    private void reportStatus(final String message) {
+        if (statusListener != null)
+            statusListener.sendMessage(message);
+    }
+
+    private void reportStatus(final String format, final Object... arg) {
+        reportStatus(String.format(format, arg));
+    }
+
     private void findUniqueVectors() {
         uniqueVectorCount = 0;
         uniqueTrainingVectors = new ArrayList<>(codebookSize);
@@ -74,10 +88,10 @@ public class LBGVectorQuantizer {
     }
 
     private LBGResult createCodebookFromUniqueVectors() {
+
         assert (uniqueTrainingVectors != null) : "uniqueTrainingVectors aren't initialized.";
-        if (verbose) {
-            System.out.println("Creating codebook from unique vectors.");
-        }
+        reportStatus("There is only %d unique vectors. Creating codebook from unique vectors...",
+                     uniqueTrainingVectors.size());
         CodebookEntry[] codebook = new CodebookEntry[codebookSize];
         int[] zeros = new int[vectorSize];
         Arrays.fill(zeros, 0);
@@ -91,9 +105,7 @@ public class LBGVectorQuantizer {
         }
         final double mse = averageMse(codebook);
         final double psnr = Utils.calculatePsnr(mse, U16.Max);
-        if (verbose) {
-            System.out.println(String.format("Final MSE: %.4f\nFinal PSNR: %.4f (dB)", mse, psnr));
-        }
+        reportStatus("Unique vector codebook, MSE: %f  PSNR: %f(dB)", mse, psnr);
         return new LBGResult(vectorDimensions, codebook, frequencies, mse, psnr);
     }
 
@@ -103,40 +115,23 @@ public class LBGVectorQuantizer {
      * @return Result of the search.
      */
     public LBGResult findOptimalCodebook() {
-        return findOptimalCodebook(false);
-    }
-
-
-    /**
-     * Find the optimal codebook of vectors, used for vector quantization.
-     *
-     * @param isVerbose True if program algorithm should be verbose.
-     * @return Result of the search.
-     */
-    public LBGResult findOptimalCodebook(boolean isVerbose) {
-        Stopwatch stopwatch = Stopwatch.startNew("findOptimalCodebook");
-        this.verbose = isVerbose;
+        Stopwatch stopwatch = Stopwatch.startNew("LBG::findOptimalCodebook()");
 
         if (uniqueVectorCount < codebookSize) {
             return createCodebookFromUniqueVectors();
         }
 
         LearningCodebookEntry[] codebook = initializeCodebook();
-        if (verbose) {
-            System.out.println("Got initial codebook. Improving codebook...");
-        }
+        reportStatus("LBG::findOptimalCodebook() - Got initial codebook. Improving it...");
+
         LBG(codebook, EPSILON * 0.1);
         final double finalMse = averageMse(codebook);
         final double psnr = Utils.calculatePsnr(finalMse, U16.Max);
-        if (verbose) {
-            System.out.println(String.format("Improved codebook, final average MSE: %.4f PSNR: %.4f (dB)",
-                                             finalMse,
-                                             psnr));
-        }
+        reportStatus("LBG::findOptimalCodebook() - Improved the codebook. Final MSE: %f  PSNR: %f (dB)",
+                     finalMse,
+                     psnr);
         stopwatch.stop();
-        if (verbose) {
-            System.out.println(stopwatch);
-        }
+        reportStatus(stopwatch.toString());
         return new LBGResult(vectorDimensions, learningCodebookToCodebook(codebook), frequencies, finalMse, psnr);
     }
 
@@ -384,22 +379,17 @@ public class LBGVectorQuantizer {
             }
             codebook = newCodebook;
             assert (codebook.length == (currentCodebookSize * 2));
-            if (verbose) {
-                System.out.println(String.format("Split from %d -> %d", currentCodebookSize, currentCodebookSize * 2));
-            }
+            reportStatus("LBG::initializeCodebook() - Dividing codebook from %d --> %d",
+                         currentCodebookSize,
+                         2 * currentCodebookSize);
             currentCodebookSize *= 2;
 
             // Execute LBG Algorithm on current codebook to improve it.
-            if (verbose) {
-                System.out.println("Improving current codebook...");
-            }
             LBG(codebook);
 
 
             final double avgMse = averageMse(codebook);
-            if (verbose) {
-                System.out.println(String.format("Average MSE: %.4f", avgMse));
-            }
+            reportStatus("MSE of improved divided codebook: %f", avgMse);
         }
         return codebook;
     }
@@ -463,32 +453,26 @@ public class LBGVectorQuantizer {
             avgDistortion /= codebook.length;
 
             // Calculate distortion
-            double dist = (previousDistortion - avgDistortion) / avgDistortion;
-            if (verbose) {
-                System.out.println(String.format("---- It: %d Distortion: %.5f", iteration++, dist));
-                System.out.println(String.format("Last Dist: %.5f Current dist: %.5f", lastDist, dist));
-            }
+            double distortion = (previousDistortion - avgDistortion) / avgDistortion;
+            reportStatus("LBG::LBG() - Iteration: %d  Distortion: %.5f", iteration++, distortion);
 
-            if (Double.isNaN(dist)) {
-                if (verbose) {
-                    System.out.println("Distortion is NaN.");
-                }
+
+            if (Double.isNaN(distortion)) {
+                reportStatus("Distortion is NaN. Stopping LBG::LBG().");
                 break;
             }
 
-            if (dist > lastDist) {
-                if (verbose) {
-                    System.out.println("Previous distortion was better. Ending LBG...");
-                }
+            if (distortion > lastDist) {
+                reportStatus("Previous distortion was better. Stopping LBG::LBG().");
                 break;
             }
 
             // Check distortion against epsilon
-            if (dist < epsilon) {
+            if (distortion < epsilon) {
                 break;
             } else {
                 previousDistortion = avgDistortion;
-                lastDist = dist;
+                lastDist = distortion;
             }
         }
     }
@@ -665,7 +649,6 @@ public class LBGVectorQuantizer {
      */
     private void calculateEntryProperties(LearningCodebookEntry[] codebook) {
 
-        Stopwatch stopwatch = Stopwatch.startNew("calculateEntryProperties");
         int value;
         EntryInfo[] entryInfos = new EntryInfo[codebook.length];
         for (int i = 0; i < entryInfos.length; i++) {
@@ -695,10 +678,6 @@ public class LBGVectorQuantizer {
         for (int i = 0; i < codebook.length; i++) {
             codebook[i].setInfo(entryInfos[i]);
         }
-        stopwatch.stop();
-        if (this.verbose) {
-            System.out.println(stopwatch);
-        }
     }