diff --git a/src/main/java/cz/it4i/qcmp/cli/functions/DebugFunction.java b/src/main/java/cz/it4i/qcmp/cli/functions/DebugFunction.java
index ca4dcf7f96406227f58c3a41f7d924d0997be12c..a5f0fea8631131f416119677c6878d1d70f5adbc 100644
--- a/src/main/java/cz/it4i/qcmp/cli/functions/DebugFunction.java
+++ b/src/main/java/cz/it4i/qcmp/cli/functions/DebugFunction.java
@@ -36,14 +36,14 @@ public class DebugFunction extends CustomFunctionBase {
             symbols[i] = i;
         }
 
-        final HuffmanTreeBuilder huffman = new HuffmanTreeBuilder(symbols, codebook.getVectorFrequencies());
-        huffman.buildHuffmanTree();
+        final HuffmanTreeBuilder huffmanBuilder = new HuffmanTreeBuilder(symbols, codebook.getVectorFrequencies());
+        huffmanBuilder.buildHuffmanTree();
 
         final int bitsPerSymbol = (int) Utils.log2(codebook.getCodebookSize());
         try (final OutBitStream bitStream = new OutBitStream(new FileOutputStream("D:\\tmp\\huffman_tree.data", false),
                                                              bitsPerSymbol,
                                                              64)) {
-            huffman.getRoot().writeToBinaryStream(bitStream);
+            huffmanBuilder.createEncoder().getRoot().writeToBinaryStream(bitStream);
         } catch (final IOException e) {
             e.printStackTrace();
         }
@@ -56,7 +56,7 @@ public class DebugFunction extends CustomFunctionBase {
             ex.printStackTrace();
         }
 
-        final boolean equal = huffman.getRoot().treeEqual(readRoot);
+        final boolean equal = huffmanBuilder.createEncoder().getRoot().treeEqual(readRoot);
 
         System.out.println(readRoot != null);
 
diff --git a/src/main/java/cz/it4i/qcmp/compression/CompressorDecompressorBase.java b/src/main/java/cz/it4i/qcmp/compression/CompressorDecompressorBase.java
index 4654ac8e280306ec577b0d584b3454d79181ce35..f41106e7bbcc8eebf1ac90ceba9899272a4e7b8e 100644
--- a/src/main/java/cz/it4i/qcmp/compression/CompressorDecompressorBase.java
+++ b/src/main/java/cz/it4i/qcmp/compression/CompressorDecompressorBase.java
@@ -4,6 +4,7 @@ import cz.it4i.qcmp.compression.exception.ImageCompressionException;
 import cz.it4i.qcmp.compression.listeners.IProgressListener;
 import cz.it4i.qcmp.compression.listeners.IStatusListener;
 import cz.it4i.qcmp.huffman.HuffmanDecoder;
+import cz.it4i.qcmp.huffman.HuffmanEncoder;
 import cz.it4i.qcmp.huffman.HuffmanTreeBuilder;
 import cz.it4i.qcmp.io.InputData;
 import cz.it4i.qcmp.io.OutBitStream;
@@ -101,16 +102,16 @@ public abstract class CompressorDecompressorBase {
         return symbols;
     }
 
-    protected HuffmanTreeBuilder createHuffmanCoder(final int[] symbols, final long[] frequencies) {
+    protected HuffmanEncoder createHuffmanEncoder(final int[] symbols, final long[] frequencies) {
         final HuffmanTreeBuilder huffman = new HuffmanTreeBuilder(symbols, frequencies);
         huffman.buildHuffmanTree();
-        return huffman;
+        return huffman.createEncoder();
     }
 
     protected HuffmanDecoder createHuffmanDecoder(final int[] symbols, final long[] frequencies) {
         final HuffmanTreeBuilder huffman = new HuffmanTreeBuilder(symbols, frequencies);
         huffman.buildHuffmanTree();
-        return new HuffmanDecoder(huffman.getRoot());
+        return huffman.createDecoder();
     }
 
     protected int[] getPlaneIndicesForCompression(final InputData inputData) {
@@ -158,17 +159,17 @@ public abstract class CompressorDecompressorBase {
      * Write huffman encoded indices to the compress stream.
      *
      * @param compressStream Compress stream.
-     * @param huffman        Huffman encoder.
+     * @param huffmanEncoder Huffman encoder.
      * @param indices        Indices to write.
      * @return Number of bytes written.
      * @throws ImageCompressionException when fails to write to compress stream.
      */
     protected long writeHuffmanEncodedIndices(final DataOutputStream compressStream,
-                                              final HuffmanTreeBuilder huffman,
+                                              final HuffmanEncoder huffmanEncoder,
                                               final int[] indices) throws ImageCompressionException {
         try (final OutBitStream outBitStream = new OutBitStream(compressStream, options.getBitsPerCodebookIndex(), 2048)) {
             for (final int index : indices) {
-                outBitStream.write(huffman.getCode(index));
+                outBitStream.write(huffmanEncoder.getSymbolCode(index));
             }
             return outBitStream.getBytesWritten();
         } catch (final Exception ex) {
diff --git a/src/main/java/cz/it4i/qcmp/compression/SQImageCompressor.java b/src/main/java/cz/it4i/qcmp/compression/SQImageCompressor.java
index e0f3451cfb2cddfe3e2a5c9de60bf8c2d6804302..06ee7b79632e8d81f8139b176c05459d4a954928 100644
--- a/src/main/java/cz/it4i/qcmp/compression/SQImageCompressor.java
+++ b/src/main/java/cz/it4i/qcmp/compression/SQImageCompressor.java
@@ -5,8 +5,7 @@ import cz.it4i.qcmp.cache.ICacheFile;
 import cz.it4i.qcmp.cache.QuantizationCacheManager;
 import cz.it4i.qcmp.cache.SQCacheFile;
 import cz.it4i.qcmp.compression.exception.ImageCompressionException;
-import cz.it4i.qcmp.huffman.HuffmanDecoder;
-import cz.it4i.qcmp.huffman.HuffmanTreeBuilder;
+import cz.it4i.qcmp.huffman.HuffmanEncoder;
 import cz.it4i.qcmp.io.InputData;
 import cz.it4i.qcmp.io.loader.IPlaneLoader;
 import cz.it4i.qcmp.io.loader.PlaneLoaderFactory;
@@ -21,7 +20,7 @@ import java.io.IOException;
 public class SQImageCompressor extends CompressorDecompressorBase implements IImageCompressor {
 
     private ScalarQuantizer cachedQuantizer;
-    private HuffmanDecoder cachedHuffmanDecoder;
+    private HuffmanEncoder cachedHuffmanEncoder;
 
     public SQImageCompressor(final CompressionOptions options) {
         super(options);
@@ -46,7 +45,7 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm
     public void preloadGlobalCodebook(final ICacheFile codebookCacheFile) {
         final SQCodebook cachedCodebook = ((SQCacheFile) codebookCacheFile).getCodebook();
         cachedQuantizer = new ScalarQuantizer(cachedCodebook);
-        cachedHuffmanDecoder = createHuffmanDecoder(createHuffmanSymbols(cachedCodebook.getCodebookSize()),
+        cachedHuffmanEncoder = createHuffmanEncoder(createHuffmanSymbols(cachedCodebook.getCodebookSize()),
                                                     cachedCodebook.getSymbolFrequencies());
     }
 
@@ -118,13 +117,13 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm
         }
 
         ScalarQuantizer quantizer = null;
-        HuffmanTreeBuilder huffman = null;
+        HuffmanEncoder huffmanEncoder = null;
         final int[] huffmanSymbols = createHuffmanSymbols(getCodebookSize());
         if (options.getCodebookType() == CompressionOptions.CodebookType.Global) {
             reportStatusToListeners("Loading codebook from cache file.");
 
             quantizer = loadQuantizerFromCache();
-            huffman = createHuffmanCoder(huffmanSymbols, quantizer.getCodebook().getSymbolFrequencies());
+            huffmanEncoder = createHuffmanEncoder(huffmanSymbols, quantizer.getCodebook().getSymbolFrequencies());
 
             reportStatusToListeners("Cached quantizer with huffman coder created.");
             writeCodebookToOutputStream(quantizer, compressStream);
@@ -140,7 +139,7 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm
 
             reportStatusToListeners(String.format("Training scalar quantizer from middle plane %d.", middlePlaneIndex));
             quantizer = trainScalarQuantizerFromData(middlePlaneData);
-            huffman = createHuffmanCoder(huffmanSymbols, quantizer.getCodebook().getSymbolFrequencies());
+            huffmanEncoder = createHuffmanEncoder(huffmanSymbols, quantizer.getCodebook().getSymbolFrequencies());
 
             stopwatch.stop();
             writeCodebookToOutputStream(quantizer, compressStream);
@@ -176,16 +175,15 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm
                 quantizer = trainScalarQuantizerFromData(planeData);
                 writeCodebookToOutputStream(quantizer, compressStream);
 
-                huffman = new HuffmanTreeBuilder(huffmanSymbols, quantizer.getCodebook().getSymbolFrequencies());
-                huffman.buildHuffmanTree();
+                huffmanEncoder = createHuffmanEncoder(huffmanSymbols, quantizer.getCodebook().getSymbolFrequencies());
             }
 
             assert (quantizer != null) : "Scalar Quantizer wasn't initialized.";
-            assert (huffman != null) : "Huffman wasn't initialized.";
+            assert (huffmanEncoder != null) : "Huffman wasn't initialized.";
 
             final int[] indices = quantizer.quantizeIntoIndices(planeData, 1);
 
-            planeDataSizes[planeCounter++] = writeHuffmanEncodedIndices(compressStream, huffman, indices);
+            planeDataSizes[planeCounter++] = writeHuffmanEncodedIndices(compressStream, huffmanEncoder, indices);
 
             stopwatch.stop();
             reportProgressToListeners(planeIndex, planeIndices.length,
diff --git a/src/main/java/cz/it4i/qcmp/compression/VQImageCompressor.java b/src/main/java/cz/it4i/qcmp/compression/VQImageCompressor.java
index 90d3cfd7d2f1ebe8f3822ee47034e34e175bbac1..063ff1c530f264c0e41dae68a6488378a55975de 100644
--- a/src/main/java/cz/it4i/qcmp/compression/VQImageCompressor.java
+++ b/src/main/java/cz/it4i/qcmp/compression/VQImageCompressor.java
@@ -6,7 +6,7 @@ import cz.it4i.qcmp.cache.VQCacheFile;
 import cz.it4i.qcmp.compression.exception.ImageCompressionException;
 import cz.it4i.qcmp.data.Range;
 import cz.it4i.qcmp.fileformat.QuantizationType;
-import cz.it4i.qcmp.huffman.HuffmanTreeBuilder;
+import cz.it4i.qcmp.huffman.HuffmanEncoder;
 import cz.it4i.qcmp.io.InputData;
 import cz.it4i.qcmp.io.loader.IPlaneLoader;
 import cz.it4i.qcmp.io.loader.PlaneLoaderFactory;
@@ -24,7 +24,7 @@ import java.io.IOException;
 public class VQImageCompressor extends CompressorDecompressorBase implements IImageCompressor {
 
     private VectorQuantizer cachedQuantizer = null;
-    private HuffmanTreeBuilder cachedHuffman = null;
+    private HuffmanEncoder cachedHuffmanEncoder = null;
 
     private boolean useKdTree = false;
 
@@ -36,7 +36,8 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
     public void preloadGlobalCodebook(final ICacheFile codebookCacheFile) {
         final VQCodebook cachedCodebook = ((VQCacheFile) codebookCacheFile).getCodebook();
         cachedQuantizer = new VectorQuantizer(cachedCodebook);
-        cachedHuffman = createHuffmanCoder(createHuffmanSymbols(cachedCodebook.getCodebookSize()), cachedCodebook.getVectorFrequencies());
+        cachedHuffmanEncoder = createHuffmanEncoder(createHuffmanSymbols(cachedCodebook.getCodebookSize()),
+                                                    cachedCodebook.getVectorFrequencies());
     }
 
     public boolean shouldUseKdTree() {
@@ -158,14 +159,14 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
         }
 
         VectorQuantizer quantizer = cachedQuantizer;
-        HuffmanTreeBuilder huffman = cachedHuffman;
-        assert (!streamMode || ((quantizer != null) && (huffman != null)));
+        HuffmanEncoder huffmanEncoder = cachedHuffmanEncoder;
+        assert (!streamMode || ((quantizer != null) && (huffmanEncoder != null)));
 
         if (!streamMode) {
             if (options.getCodebookType() == CompressionOptions.CodebookType.Global) {
                 reportStatusToListeners("Loading codebook from cache file.");
                 quantizer = loadQuantizerFromCache();
-                huffman = createHuffmanCoder(huffmanSymbols, quantizer.getFrequencies());
+                huffmanEncoder = createHuffmanEncoder(huffmanSymbols, quantizer.getFrequencies());
                 reportStatusToListeners("Cached quantizer with huffman coder created.");
                 writeQuantizerToCompressStream(quantizer, compressStream);
             } else if (options.getCodebookType() == CompressionOptions.CodebookType.MiddlePlane) {
@@ -174,7 +175,7 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
                 final int[][] refPlaneVectors = planeLoader.loadVectorsFromPlaneRange(0, options,
                                                                                       Utils.singlePlaneRange(getMiddlePlaneIndex()));
                 quantizer = trainVectorQuantizerFromPlaneVectors(refPlaneVectors);
-                huffman = createHuffmanCoder(huffmanSymbols, quantizer.getFrequencies());
+                huffmanEncoder = createHuffmanEncoder(huffmanSymbols, quantizer.getFrequencies());
                 stopwatch.stop();
                 reportStatusToListeners("Middle plane codebook created in: " + stopwatch.getElapsedTimeString());
                 writeQuantizerToCompressStream(quantizer, compressStream);
@@ -208,13 +209,13 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
             if (!streamMode && !hasGeneralQuantizer) {
                 reportStatusToListeners(String.format("Training vector quantizer from plane %d.", planeIndex));
                 quantizer = trainVectorQuantizerFromPlaneVectors(planeVectors);
-                huffman = createHuffmanCoder(huffmanSymbols, quantizer.getFrequencies());
+                huffmanEncoder = createHuffmanEncoder(huffmanSymbols, quantizer.getFrequencies());
                 writeQuantizerToCompressStream(quantizer, compressStream);
             }
 
             final int[] indices = quantizeVectorsImpl(quantizer, planeVectors, options.getWorkerCount());
 
-            planeDataSizes[planeCounter++] = writeHuffmanEncodedIndices(compressStream, huffman, indices);
+            planeDataSizes[planeCounter++] = writeHuffmanEncodedIndices(compressStream, huffmanEncoder, indices);
 
             stopwatch.stop();
             if (options.isConsoleApplication()) {
@@ -283,8 +284,9 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
         final long[] voxelLayersSizes = new long[voxelLayerCount];
 
         final VectorQuantizer quantizer = (cachedQuantizer != null) ? cachedQuantizer : loadQuantizerFromCache();
-        final HuffmanTreeBuilder huffman = (cachedHuffman != null) ? cachedHuffman : createHuffmanCoder(huffmanSymbols,
-                                                                                                        quantizer.getFrequencies());
+        final HuffmanEncoder huffmanEncoder = (cachedHuffmanEncoder != null)
+                ? cachedHuffmanEncoder
+                : createHuffmanEncoder(huffmanSymbols, quantizer.getFrequencies());
         if (!streamMode)
             writeQuantizerToCompressStream(quantizer, compressStream);
 
@@ -309,7 +311,7 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
 
             final int[] indices = quantizeVectorsImpl(quantizer, voxelData, options.getWorkerCount());
 
-            voxelLayersSizes[voxelLayerIndex] = writeHuffmanEncodedIndices(compressStream, huffman, indices);
+            voxelLayersSizes[voxelLayerIndex] = writeHuffmanEncodedIndices(compressStream, huffmanEncoder, indices);
             stopwatch.stop();
             if (options.isConsoleApplication()) {
                 reportStatusToListeners("%d/%d Finished voxel layer %s compression pass in %s",
diff --git a/src/main/java/cz/it4i/qcmp/huffman/HuffmanDecoder.java b/src/main/java/cz/it4i/qcmp/huffman/HuffmanDecoder.java
index 00ff44c52200b2d8ba66620e15ced8b2c294c50f..84c2e2e661a03e77000a9d2c96d057a724ce8f48 100644
--- a/src/main/java/cz/it4i/qcmp/huffman/HuffmanDecoder.java
+++ b/src/main/java/cz/it4i/qcmp/huffman/HuffmanDecoder.java
@@ -5,7 +5,7 @@ import cz.it4i.qcmp.io.InBitStream;
 import java.io.IOException;
 
 /**
- * Simply wrapper around root huffman node to provide easy decode function.
+ * Simple wrapper around root huffman node to provide easy decode function.
  */
 public class HuffmanDecoder {
     private final HuffmanNode root;
@@ -33,4 +33,8 @@ public class HuffmanDecoder {
         }
         return currentNode.getSymbol();
     }
+
+    public HuffmanNode getRoot() {
+        return root;
+    }
 }
diff --git a/src/main/java/cz/it4i/qcmp/huffman/HuffmanEncoder.java b/src/main/java/cz/it4i/qcmp/huffman/HuffmanEncoder.java
new file mode 100644
index 0000000000000000000000000000000000000000..1d34d4ad692d80dff7f1763ce9429e12b4f1f5aa
--- /dev/null
+++ b/src/main/java/cz/it4i/qcmp/huffman/HuffmanEncoder.java
@@ -0,0 +1,36 @@
+package cz.it4i.qcmp.huffman;
+
+import java.util.HashMap;
+
+/**
+ * Simple wrapper around root huffman symbol map to provide easy encode function.
+ */
+public class HuffmanEncoder {
+    private final HuffmanNode root;
+    private final HashMap<Integer, boolean[]> symbolCodes;
+
+    /**
+     * Create huffman encoder from symbol map.
+     *
+     * @param root        Huffman tree root.
+     * @param symbolCodes Huffman symbol map.
+     */
+    public HuffmanEncoder(final HuffmanNode root, final HashMap<Integer, boolean[]> symbolCodes) {
+        this.root = root;
+        this.symbolCodes = symbolCodes;
+    }
+
+    /**
+     * Get binary code for huffman symbol.
+     *
+     * @param symbol Huffman symbol.
+     * @return Binary code.
+     */
+    public boolean[] getSymbolCode(final int symbol) {
+        return symbolCodes.get(symbol);
+    }
+
+    public HuffmanNode getRoot() {
+        return root;
+    }
+}
diff --git a/src/main/java/cz/it4i/qcmp/huffman/HuffmanTreeBuilder.java b/src/main/java/cz/it4i/qcmp/huffman/HuffmanTreeBuilder.java
index 91571ceb73e1d5411dddc4c7bbee07c920b7e6cd..25b26dcf2624892d8d3dc619193260709ebfca79 100644
--- a/src/main/java/cz/it4i/qcmp/huffman/HuffmanTreeBuilder.java
+++ b/src/main/java/cz/it4i/qcmp/huffman/HuffmanTreeBuilder.java
@@ -1,11 +1,12 @@
 package cz.it4i.qcmp.huffman;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.PriorityQueue;
 
 public class HuffmanTreeBuilder {
     private HuffmanNode root = null;
     private HashMap<Integer, boolean[]> symbolCodes;
-    private HashMap<Integer, Double> symbolProbabilityMap;
     private final int[] symbols;
     private final long[] symbolFrequencies;
 
@@ -76,7 +77,7 @@ public class HuffmanTreeBuilder {
     }
 
     private PriorityQueue<HuffmanNode> buildPriorityQueue() {
-        symbolProbabilityMap = new HashMap<>(symbols.length);
+        final HashMap<Integer, Double> symbolProbabilityMap = new HashMap<>(symbols.length);
         double totalFrequency = 0.0;
         for (final long symbolFrequency : symbolFrequencies) {
             totalFrequency += symbolFrequency;
@@ -93,28 +94,18 @@ public class HuffmanTreeBuilder {
         return queue;
     }
 
-
-    public boolean[] getCode(final int symbol) {
-        return symbolCodes.get(symbol);
-    }
-
-    public HuffmanNode getRoot() {
-        return root;
+    /**
+     * Create huffman encoder from symbol codes.
+     *
+     * @return Huffman encoder.
+     */
+    public HuffmanEncoder createEncoder() {
+        assert (root != null && symbolCodes != null) : "Huffman tree was not build yet";
+        return new HuffmanEncoder(root, symbolCodes);
     }
 
-    public HashMap<Integer, Double> getSymbolProbabilityMap() {
-        return createSortedHashMap(symbolProbabilityMap);
-    }
-
-    private HashMap<Integer, Double> createSortedHashMap(final HashMap<Integer, Double> map) {
-        final List<Map.Entry<Integer, Double>> list = new LinkedList<Map.Entry<Integer, Double>>(map.entrySet());
-        //Custom Comparator
-        list.sort((t0, t1) -> (-(t0.getValue().compareTo(t1.getValue()))));
-        //copying the sorted list in HashMap to preserve the iteration order
-        final HashMap<Integer, Double> sortedHashMap = new LinkedHashMap<Integer, Double>();
-        for (final Map.Entry<Integer, Double> entry : list) {
-            sortedHashMap.put(entry.getKey(), entry.getValue());
-        }
-        return sortedHashMap;
+    public HuffmanDecoder createDecoder() {
+        assert (root != null) : "Huffman tree was not build yet";
+        return new HuffmanDecoder(root);
     }
 }