Skip to content
Snippets Groups Projects
Commit ce5fa4e6 authored by Vojtech Moravec's avatar Vojtech Moravec
Browse files

Move encode functionality to HuffmanEncoder class.

parent eafefe04
No related branches found
No related tags found
No related merge requests found
...@@ -36,14 +36,14 @@ public class DebugFunction extends CustomFunctionBase { ...@@ -36,14 +36,14 @@ public class DebugFunction extends CustomFunctionBase {
symbols[i] = i; symbols[i] = i;
} }
final HuffmanTreeBuilder huffman = new HuffmanTreeBuilder(symbols, codebook.getVectorFrequencies()); final HuffmanTreeBuilder huffmanBuilder = new HuffmanTreeBuilder(symbols, codebook.getVectorFrequencies());
huffman.buildHuffmanTree(); huffmanBuilder.buildHuffmanTree();
final int bitsPerSymbol = (int) Utils.log2(codebook.getCodebookSize()); final int bitsPerSymbol = (int) Utils.log2(codebook.getCodebookSize());
try (final OutBitStream bitStream = new OutBitStream(new FileOutputStream("D:\\tmp\\huffman_tree.data", false), try (final OutBitStream bitStream = new OutBitStream(new FileOutputStream("D:\\tmp\\huffman_tree.data", false),
bitsPerSymbol, bitsPerSymbol,
64)) { 64)) {
huffman.getRoot().writeToBinaryStream(bitStream); huffmanBuilder.createEncoder().getRoot().writeToBinaryStream(bitStream);
} catch (final IOException e) { } catch (final IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
...@@ -56,7 +56,7 @@ public class DebugFunction extends CustomFunctionBase { ...@@ -56,7 +56,7 @@ public class DebugFunction extends CustomFunctionBase {
ex.printStackTrace(); ex.printStackTrace();
} }
final boolean equal = huffman.getRoot().treeEqual(readRoot); final boolean equal = huffmanBuilder.createEncoder().getRoot().treeEqual(readRoot);
System.out.println(readRoot != null); System.out.println(readRoot != null);
......
...@@ -4,6 +4,7 @@ import cz.it4i.qcmp.compression.exception.ImageCompressionException; ...@@ -4,6 +4,7 @@ import cz.it4i.qcmp.compression.exception.ImageCompressionException;
import cz.it4i.qcmp.compression.listeners.IProgressListener; import cz.it4i.qcmp.compression.listeners.IProgressListener;
import cz.it4i.qcmp.compression.listeners.IStatusListener; import cz.it4i.qcmp.compression.listeners.IStatusListener;
import cz.it4i.qcmp.huffman.HuffmanDecoder; import cz.it4i.qcmp.huffman.HuffmanDecoder;
import cz.it4i.qcmp.huffman.HuffmanEncoder;
import cz.it4i.qcmp.huffman.HuffmanTreeBuilder; import cz.it4i.qcmp.huffman.HuffmanTreeBuilder;
import cz.it4i.qcmp.io.InputData; import cz.it4i.qcmp.io.InputData;
import cz.it4i.qcmp.io.OutBitStream; import cz.it4i.qcmp.io.OutBitStream;
...@@ -101,16 +102,16 @@ public abstract class CompressorDecompressorBase { ...@@ -101,16 +102,16 @@ public abstract class CompressorDecompressorBase {
return symbols; 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); final HuffmanTreeBuilder huffman = new HuffmanTreeBuilder(symbols, frequencies);
huffman.buildHuffmanTree(); huffman.buildHuffmanTree();
return huffman; return huffman.createEncoder();
} }
protected HuffmanDecoder createHuffmanDecoder(final int[] symbols, final long[] frequencies) { protected HuffmanDecoder createHuffmanDecoder(final int[] symbols, final long[] frequencies) {
final HuffmanTreeBuilder huffman = new HuffmanTreeBuilder(symbols, frequencies); final HuffmanTreeBuilder huffman = new HuffmanTreeBuilder(symbols, frequencies);
huffman.buildHuffmanTree(); huffman.buildHuffmanTree();
return new HuffmanDecoder(huffman.getRoot()); return huffman.createDecoder();
} }
protected int[] getPlaneIndicesForCompression(final InputData inputData) { protected int[] getPlaneIndicesForCompression(final InputData inputData) {
...@@ -158,17 +159,17 @@ public abstract class CompressorDecompressorBase { ...@@ -158,17 +159,17 @@ public abstract class CompressorDecompressorBase {
* Write huffman encoded indices to the compress stream. * Write huffman encoded indices to the compress stream.
* *
* @param compressStream Compress stream. * @param compressStream Compress stream.
* @param huffman Huffman encoder. * @param huffmanEncoder Huffman encoder.
* @param indices Indices to write. * @param indices Indices to write.
* @return Number of bytes written. * @return Number of bytes written.
* @throws ImageCompressionException when fails to write to compress stream. * @throws ImageCompressionException when fails to write to compress stream.
*/ */
protected long writeHuffmanEncodedIndices(final DataOutputStream compressStream, protected long writeHuffmanEncodedIndices(final DataOutputStream compressStream,
final HuffmanTreeBuilder huffman, final HuffmanEncoder huffmanEncoder,
final int[] indices) throws ImageCompressionException { final int[] indices) throws ImageCompressionException {
try (final OutBitStream outBitStream = new OutBitStream(compressStream, options.getBitsPerCodebookIndex(), 2048)) { try (final OutBitStream outBitStream = new OutBitStream(compressStream, options.getBitsPerCodebookIndex(), 2048)) {
for (final int index : indices) { for (final int index : indices) {
outBitStream.write(huffman.getCode(index)); outBitStream.write(huffmanEncoder.getSymbolCode(index));
} }
return outBitStream.getBytesWritten(); return outBitStream.getBytesWritten();
} catch (final Exception ex) { } catch (final Exception ex) {
......
...@@ -5,8 +5,7 @@ import cz.it4i.qcmp.cache.ICacheFile; ...@@ -5,8 +5,7 @@ import cz.it4i.qcmp.cache.ICacheFile;
import cz.it4i.qcmp.cache.QuantizationCacheManager; import cz.it4i.qcmp.cache.QuantizationCacheManager;
import cz.it4i.qcmp.cache.SQCacheFile; import cz.it4i.qcmp.cache.SQCacheFile;
import cz.it4i.qcmp.compression.exception.ImageCompressionException; import cz.it4i.qcmp.compression.exception.ImageCompressionException;
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.InputData;
import cz.it4i.qcmp.io.loader.IPlaneLoader; import cz.it4i.qcmp.io.loader.IPlaneLoader;
import cz.it4i.qcmp.io.loader.PlaneLoaderFactory; import cz.it4i.qcmp.io.loader.PlaneLoaderFactory;
...@@ -21,7 +20,7 @@ import java.io.IOException; ...@@ -21,7 +20,7 @@ import java.io.IOException;
public class SQImageCompressor extends CompressorDecompressorBase implements IImageCompressor { public class SQImageCompressor extends CompressorDecompressorBase implements IImageCompressor {
private ScalarQuantizer cachedQuantizer; private ScalarQuantizer cachedQuantizer;
private HuffmanDecoder cachedHuffmanDecoder; private HuffmanEncoder cachedHuffmanEncoder;
public SQImageCompressor(final CompressionOptions options) { public SQImageCompressor(final CompressionOptions options) {
super(options); super(options);
...@@ -46,7 +45,7 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm ...@@ -46,7 +45,7 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm
public void preloadGlobalCodebook(final ICacheFile codebookCacheFile) { public void preloadGlobalCodebook(final ICacheFile codebookCacheFile) {
final SQCodebook cachedCodebook = ((SQCacheFile) codebookCacheFile).getCodebook(); final SQCodebook cachedCodebook = ((SQCacheFile) codebookCacheFile).getCodebook();
cachedQuantizer = new ScalarQuantizer(cachedCodebook); cachedQuantizer = new ScalarQuantizer(cachedCodebook);
cachedHuffmanDecoder = createHuffmanDecoder(createHuffmanSymbols(cachedCodebook.getCodebookSize()), cachedHuffmanEncoder = createHuffmanEncoder(createHuffmanSymbols(cachedCodebook.getCodebookSize()),
cachedCodebook.getSymbolFrequencies()); cachedCodebook.getSymbolFrequencies());
} }
...@@ -118,13 +117,13 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm ...@@ -118,13 +117,13 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm
} }
ScalarQuantizer quantizer = null; ScalarQuantizer quantizer = null;
HuffmanTreeBuilder huffman = null; HuffmanEncoder huffmanEncoder = null;
final int[] huffmanSymbols = createHuffmanSymbols(getCodebookSize()); final int[] huffmanSymbols = createHuffmanSymbols(getCodebookSize());
if (options.getCodebookType() == CompressionOptions.CodebookType.Global) { if (options.getCodebookType() == CompressionOptions.CodebookType.Global) {
reportStatusToListeners("Loading codebook from cache file."); reportStatusToListeners("Loading codebook from cache file.");
quantizer = loadQuantizerFromCache(); quantizer = loadQuantizerFromCache();
huffman = createHuffmanCoder(huffmanSymbols, quantizer.getCodebook().getSymbolFrequencies()); huffmanEncoder = createHuffmanEncoder(huffmanSymbols, quantizer.getCodebook().getSymbolFrequencies());
reportStatusToListeners("Cached quantizer with huffman coder created."); reportStatusToListeners("Cached quantizer with huffman coder created.");
writeCodebookToOutputStream(quantizer, compressStream); writeCodebookToOutputStream(quantizer, compressStream);
...@@ -140,7 +139,7 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm ...@@ -140,7 +139,7 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm
reportStatusToListeners(String.format("Training scalar quantizer from middle plane %d.", middlePlaneIndex)); reportStatusToListeners(String.format("Training scalar quantizer from middle plane %d.", middlePlaneIndex));
quantizer = trainScalarQuantizerFromData(middlePlaneData); quantizer = trainScalarQuantizerFromData(middlePlaneData);
huffman = createHuffmanCoder(huffmanSymbols, quantizer.getCodebook().getSymbolFrequencies()); huffmanEncoder = createHuffmanEncoder(huffmanSymbols, quantizer.getCodebook().getSymbolFrequencies());
stopwatch.stop(); stopwatch.stop();
writeCodebookToOutputStream(quantizer, compressStream); writeCodebookToOutputStream(quantizer, compressStream);
...@@ -176,16 +175,15 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm ...@@ -176,16 +175,15 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm
quantizer = trainScalarQuantizerFromData(planeData); quantizer = trainScalarQuantizerFromData(planeData);
writeCodebookToOutputStream(quantizer, compressStream); writeCodebookToOutputStream(quantizer, compressStream);
huffman = new HuffmanTreeBuilder(huffmanSymbols, quantizer.getCodebook().getSymbolFrequencies()); huffmanEncoder = createHuffmanEncoder(huffmanSymbols, quantizer.getCodebook().getSymbolFrequencies());
huffman.buildHuffmanTree();
} }
assert (quantizer != null) : "Scalar Quantizer wasn't initialized."; 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); final int[] indices = quantizer.quantizeIntoIndices(planeData, 1);
planeDataSizes[planeCounter++] = writeHuffmanEncodedIndices(compressStream, huffman, indices); planeDataSizes[planeCounter++] = writeHuffmanEncodedIndices(compressStream, huffmanEncoder, indices);
stopwatch.stop(); stopwatch.stop();
reportProgressToListeners(planeIndex, planeIndices.length, reportProgressToListeners(planeIndex, planeIndices.length,
......
...@@ -6,7 +6,7 @@ import cz.it4i.qcmp.cache.VQCacheFile; ...@@ -6,7 +6,7 @@ import cz.it4i.qcmp.cache.VQCacheFile;
import cz.it4i.qcmp.compression.exception.ImageCompressionException; import cz.it4i.qcmp.compression.exception.ImageCompressionException;
import cz.it4i.qcmp.data.Range; import cz.it4i.qcmp.data.Range;
import cz.it4i.qcmp.fileformat.QuantizationType; 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.InputData;
import cz.it4i.qcmp.io.loader.IPlaneLoader; import cz.it4i.qcmp.io.loader.IPlaneLoader;
import cz.it4i.qcmp.io.loader.PlaneLoaderFactory; import cz.it4i.qcmp.io.loader.PlaneLoaderFactory;
...@@ -24,7 +24,7 @@ import java.io.IOException; ...@@ -24,7 +24,7 @@ import java.io.IOException;
public class VQImageCompressor extends CompressorDecompressorBase implements IImageCompressor { public class VQImageCompressor extends CompressorDecompressorBase implements IImageCompressor {
private VectorQuantizer cachedQuantizer = null; private VectorQuantizer cachedQuantizer = null;
private HuffmanTreeBuilder cachedHuffman = null; private HuffmanEncoder cachedHuffmanEncoder = null;
private boolean useKdTree = false; private boolean useKdTree = false;
...@@ -36,7 +36,8 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm ...@@ -36,7 +36,8 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
public void preloadGlobalCodebook(final ICacheFile codebookCacheFile) { public void preloadGlobalCodebook(final ICacheFile codebookCacheFile) {
final VQCodebook cachedCodebook = ((VQCacheFile) codebookCacheFile).getCodebook(); final VQCodebook cachedCodebook = ((VQCacheFile) codebookCacheFile).getCodebook();
cachedQuantizer = new VectorQuantizer(cachedCodebook); cachedQuantizer = new VectorQuantizer(cachedCodebook);
cachedHuffman = createHuffmanCoder(createHuffmanSymbols(cachedCodebook.getCodebookSize()), cachedCodebook.getVectorFrequencies()); cachedHuffmanEncoder = createHuffmanEncoder(createHuffmanSymbols(cachedCodebook.getCodebookSize()),
cachedCodebook.getVectorFrequencies());
} }
public boolean shouldUseKdTree() { public boolean shouldUseKdTree() {
...@@ -158,14 +159,14 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm ...@@ -158,14 +159,14 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
} }
VectorQuantizer quantizer = cachedQuantizer; VectorQuantizer quantizer = cachedQuantizer;
HuffmanTreeBuilder huffman = cachedHuffman; HuffmanEncoder huffmanEncoder = cachedHuffmanEncoder;
assert (!streamMode || ((quantizer != null) && (huffman != null))); assert (!streamMode || ((quantizer != null) && (huffmanEncoder != null)));
if (!streamMode) { if (!streamMode) {
if (options.getCodebookType() == CompressionOptions.CodebookType.Global) { if (options.getCodebookType() == CompressionOptions.CodebookType.Global) {
reportStatusToListeners("Loading codebook from cache file."); reportStatusToListeners("Loading codebook from cache file.");
quantizer = loadQuantizerFromCache(); quantizer = loadQuantizerFromCache();
huffman = createHuffmanCoder(huffmanSymbols, quantizer.getFrequencies()); huffmanEncoder = createHuffmanEncoder(huffmanSymbols, quantizer.getFrequencies());
reportStatusToListeners("Cached quantizer with huffman coder created."); reportStatusToListeners("Cached quantizer with huffman coder created.");
writeQuantizerToCompressStream(quantizer, compressStream); writeQuantizerToCompressStream(quantizer, compressStream);
} else if (options.getCodebookType() == CompressionOptions.CodebookType.MiddlePlane) { } else if (options.getCodebookType() == CompressionOptions.CodebookType.MiddlePlane) {
...@@ -174,7 +175,7 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm ...@@ -174,7 +175,7 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
final int[][] refPlaneVectors = planeLoader.loadVectorsFromPlaneRange(0, options, final int[][] refPlaneVectors = planeLoader.loadVectorsFromPlaneRange(0, options,
Utils.singlePlaneRange(getMiddlePlaneIndex())); Utils.singlePlaneRange(getMiddlePlaneIndex()));
quantizer = trainVectorQuantizerFromPlaneVectors(refPlaneVectors); quantizer = trainVectorQuantizerFromPlaneVectors(refPlaneVectors);
huffman = createHuffmanCoder(huffmanSymbols, quantizer.getFrequencies()); huffmanEncoder = createHuffmanEncoder(huffmanSymbols, quantizer.getFrequencies());
stopwatch.stop(); stopwatch.stop();
reportStatusToListeners("Middle plane codebook created in: " + stopwatch.getElapsedTimeString()); reportStatusToListeners("Middle plane codebook created in: " + stopwatch.getElapsedTimeString());
writeQuantizerToCompressStream(quantizer, compressStream); writeQuantizerToCompressStream(quantizer, compressStream);
...@@ -208,13 +209,13 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm ...@@ -208,13 +209,13 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
if (!streamMode && !hasGeneralQuantizer) { if (!streamMode && !hasGeneralQuantizer) {
reportStatusToListeners(String.format("Training vector quantizer from plane %d.", planeIndex)); reportStatusToListeners(String.format("Training vector quantizer from plane %d.", planeIndex));
quantizer = trainVectorQuantizerFromPlaneVectors(planeVectors); quantizer = trainVectorQuantizerFromPlaneVectors(planeVectors);
huffman = createHuffmanCoder(huffmanSymbols, quantizer.getFrequencies()); huffmanEncoder = createHuffmanEncoder(huffmanSymbols, quantizer.getFrequencies());
writeQuantizerToCompressStream(quantizer, compressStream); writeQuantizerToCompressStream(quantizer, compressStream);
} }
final int[] indices = quantizeVectorsImpl(quantizer, planeVectors, options.getWorkerCount()); final int[] indices = quantizeVectorsImpl(quantizer, planeVectors, options.getWorkerCount());
planeDataSizes[planeCounter++] = writeHuffmanEncodedIndices(compressStream, huffman, indices); planeDataSizes[planeCounter++] = writeHuffmanEncodedIndices(compressStream, huffmanEncoder, indices);
stopwatch.stop(); stopwatch.stop();
if (options.isConsoleApplication()) { if (options.isConsoleApplication()) {
...@@ -283,8 +284,9 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm ...@@ -283,8 +284,9 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
final long[] voxelLayersSizes = new long[voxelLayerCount]; final long[] voxelLayersSizes = new long[voxelLayerCount];
final VectorQuantizer quantizer = (cachedQuantizer != null) ? cachedQuantizer : loadQuantizerFromCache(); final VectorQuantizer quantizer = (cachedQuantizer != null) ? cachedQuantizer : loadQuantizerFromCache();
final HuffmanTreeBuilder huffman = (cachedHuffman != null) ? cachedHuffman : createHuffmanCoder(huffmanSymbols, final HuffmanEncoder huffmanEncoder = (cachedHuffmanEncoder != null)
quantizer.getFrequencies()); ? cachedHuffmanEncoder
: createHuffmanEncoder(huffmanSymbols, quantizer.getFrequencies());
if (!streamMode) if (!streamMode)
writeQuantizerToCompressStream(quantizer, compressStream); writeQuantizerToCompressStream(quantizer, compressStream);
...@@ -309,7 +311,7 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm ...@@ -309,7 +311,7 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
final int[] indices = quantizeVectorsImpl(quantizer, voxelData, options.getWorkerCount()); final int[] indices = quantizeVectorsImpl(quantizer, voxelData, options.getWorkerCount());
voxelLayersSizes[voxelLayerIndex] = writeHuffmanEncodedIndices(compressStream, huffman, indices); voxelLayersSizes[voxelLayerIndex] = writeHuffmanEncodedIndices(compressStream, huffmanEncoder, indices);
stopwatch.stop(); stopwatch.stop();
if (options.isConsoleApplication()) { if (options.isConsoleApplication()) {
reportStatusToListeners("%d/%d Finished voxel layer %s compression pass in %s", reportStatusToListeners("%d/%d Finished voxel layer %s compression pass in %s",
......
...@@ -5,7 +5,7 @@ import cz.it4i.qcmp.io.InBitStream; ...@@ -5,7 +5,7 @@ import cz.it4i.qcmp.io.InBitStream;
import java.io.IOException; 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 { public class HuffmanDecoder {
private final HuffmanNode root; private final HuffmanNode root;
...@@ -33,4 +33,8 @@ public class HuffmanDecoder { ...@@ -33,4 +33,8 @@ public class HuffmanDecoder {
} }
return currentNode.getSymbol(); return currentNode.getSymbol();
} }
public HuffmanNode getRoot() {
return root;
}
} }
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;
}
}
package cz.it4i.qcmp.huffman; package cz.it4i.qcmp.huffman;
import java.util.*; import java.util.ArrayList;
import java.util.HashMap;
import java.util.PriorityQueue;
public class HuffmanTreeBuilder { public class HuffmanTreeBuilder {
private HuffmanNode root = null; private HuffmanNode root = null;
private HashMap<Integer, boolean[]> symbolCodes; private HashMap<Integer, boolean[]> symbolCodes;
private HashMap<Integer, Double> symbolProbabilityMap;
private final int[] symbols; private final int[] symbols;
private final long[] symbolFrequencies; private final long[] symbolFrequencies;
...@@ -76,7 +77,7 @@ public class HuffmanTreeBuilder { ...@@ -76,7 +77,7 @@ public class HuffmanTreeBuilder {
} }
private PriorityQueue<HuffmanNode> buildPriorityQueue() { private PriorityQueue<HuffmanNode> buildPriorityQueue() {
symbolProbabilityMap = new HashMap<>(symbols.length); final HashMap<Integer, Double> symbolProbabilityMap = new HashMap<>(symbols.length);
double totalFrequency = 0.0; double totalFrequency = 0.0;
for (final long symbolFrequency : symbolFrequencies) { for (final long symbolFrequency : symbolFrequencies) {
totalFrequency += symbolFrequency; totalFrequency += symbolFrequency;
...@@ -93,28 +94,18 @@ public class HuffmanTreeBuilder { ...@@ -93,28 +94,18 @@ public class HuffmanTreeBuilder {
return queue; return queue;
} }
/**
public boolean[] getCode(final int symbol) { * Create huffman encoder from symbol codes.
return symbolCodes.get(symbol); *
} * @return Huffman encoder.
*/
public HuffmanNode getRoot() { public HuffmanEncoder createEncoder() {
return root; assert (root != null && symbolCodes != null) : "Huffman tree was not build yet";
return new HuffmanEncoder(root, symbolCodes);
} }
public HashMap<Integer, Double> getSymbolProbabilityMap() { public HuffmanDecoder createDecoder() {
return createSortedHashMap(symbolProbabilityMap); assert (root != null) : "Huffman tree was not build yet";
} return new HuffmanDecoder(root);
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;
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment