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

Move symbol decoding to HuffmanDecoder class.

parent 8768db39
No related branches found
No related tags found
No related merge requests found
...@@ -3,6 +3,7 @@ package cz.it4i.qcmp.compression; ...@@ -3,6 +3,7 @@ package cz.it4i.qcmp.compression;
import cz.it4i.qcmp.compression.exception.ImageCompressionException; 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.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;
...@@ -106,6 +107,12 @@ public abstract class CompressorDecompressorBase { ...@@ -106,6 +107,12 @@ public abstract class CompressorDecompressorBase {
return huffman; return huffman;
} }
protected HuffmanDecoder createHuffmanDecoder(final int[] symbols, final long[] frequencies) {
final HuffmanTreeBuilder huffman = new HuffmanTreeBuilder(symbols, frequencies);
huffman.buildHuffmanTree();
return new HuffmanDecoder(huffman.getRoot());
}
protected int[] getPlaneIndicesForCompression(final InputData inputData) { protected int[] getPlaneIndicesForCompression(final InputData inputData) {
if (inputData.isPlaneIndexSet()) { if (inputData.isPlaneIndexSet()) {
return new int[]{inputData.getPlaneIndex()}; return new int[]{inputData.getPlaneIndex()};
......
...@@ -5,6 +5,7 @@ import cz.it4i.qcmp.cache.ICacheFile; ...@@ -5,6 +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.HuffmanTreeBuilder; 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;
...@@ -20,7 +21,7 @@ import java.io.IOException; ...@@ -20,7 +21,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 HuffmanTreeBuilder cachedHuffman; private HuffmanDecoder cachedHuffmanDecoder;
public SQImageCompressor(final CompressionOptions options) { public SQImageCompressor(final CompressionOptions options) {
super(options); super(options);
...@@ -45,7 +46,8 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm ...@@ -45,7 +46,8 @@ 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);
cachedHuffman = createHuffmanCoder(createHuffmanSymbols(cachedCodebook.getCodebookSize()), cachedCodebook.getSymbolFrequencies()); cachedHuffmanDecoder = createHuffmanDecoder(createHuffmanSymbols(cachedCodebook.getCodebookSize()),
cachedCodebook.getSymbolFrequencies());
} }
/** /**
......
...@@ -4,8 +4,7 @@ import cz.it4i.qcmp.cache.ICacheFile; ...@@ -4,8 +4,7 @@ import cz.it4i.qcmp.cache.ICacheFile;
import cz.it4i.qcmp.cache.SQCacheFile; import cz.it4i.qcmp.cache.SQCacheFile;
import cz.it4i.qcmp.compression.exception.ImageDecompressionException; import cz.it4i.qcmp.compression.exception.ImageDecompressionException;
import cz.it4i.qcmp.fileformat.QCMPFileHeader; import cz.it4i.qcmp.fileformat.QCMPFileHeader;
import cz.it4i.qcmp.huffman.HuffmanNode; import cz.it4i.qcmp.huffman.HuffmanDecoder;
import cz.it4i.qcmp.huffman.HuffmanTreeBuilder;
import cz.it4i.qcmp.io.InBitStream; import cz.it4i.qcmp.io.InBitStream;
import cz.it4i.qcmp.quantization.scalar.SQCodebook; import cz.it4i.qcmp.quantization.scalar.SQCodebook;
import cz.it4i.qcmp.utilities.Stopwatch; import cz.it4i.qcmp.utilities.Stopwatch;
...@@ -17,7 +16,7 @@ import java.io.IOException; ...@@ -17,7 +16,7 @@ import java.io.IOException;
public class SQImageDecompressor extends CompressorDecompressorBase implements IImageDecompressor { public class SQImageDecompressor extends CompressorDecompressorBase implements IImageDecompressor {
private SQCodebook cachedCodebook = null; private SQCodebook cachedCodebook = null;
private HuffmanTreeBuilder cachedHuffman = null; private HuffmanDecoder cachedHuffmanDecoder = null;
public SQImageDecompressor(final CompressionOptions options) { public SQImageDecompressor(final CompressionOptions options) {
super(options); super(options);
...@@ -52,12 +51,12 @@ public class SQImageDecompressor extends CompressorDecompressorBase implements I ...@@ -52,12 +51,12 @@ public class SQImageDecompressor extends CompressorDecompressorBase implements I
final int planePixelCount = header.getImageSizeX() * header.getImageSizeY(); final int planePixelCount = header.getImageSizeX() * header.getImageSizeY();
SQCodebook codebook = null; SQCodebook codebook = null;
HuffmanTreeBuilder huffman = null; HuffmanDecoder huffmanDecoder = null;
if (!header.isCodebookPerPlane()) { if (!header.isCodebookPerPlane()) {
// There is only one codebook. // There is only one codebook.
reportStatusToListeners("Loading single codebook and huffman coder."); reportStatusToListeners("Loading single codebook and huffman coder.");
codebook = readScalarQuantizationValues(compressedStream, codebookSize); codebook = readScalarQuantizationValues(compressedStream, codebookSize);
huffman = createHuffmanCoder(huffmanSymbols, codebook.getSymbolFrequencies()); huffmanDecoder = createHuffmanDecoder(huffmanSymbols, codebook.getSymbolFrequencies());
} }
final Stopwatch stopwatch = new Stopwatch(); final Stopwatch stopwatch = new Stopwatch();
...@@ -66,9 +65,9 @@ public class SQImageDecompressor extends CompressorDecompressorBase implements I ...@@ -66,9 +65,9 @@ public class SQImageDecompressor extends CompressorDecompressorBase implements I
if (header.isCodebookPerPlane()) { if (header.isCodebookPerPlane()) {
reportStatusToListeners("Loading plane codebook..."); reportStatusToListeners("Loading plane codebook...");
codebook = readScalarQuantizationValues(compressedStream, codebookSize); codebook = readScalarQuantizationValues(compressedStream, codebookSize);
huffman = createHuffmanCoder(huffmanSymbols, codebook.getSymbolFrequencies()); huffmanDecoder = createHuffmanDecoder(huffmanSymbols, codebook.getSymbolFrequencies());
} }
assert (codebook != null && huffman != null); assert (codebook != null && huffmanDecoder != null);
reportStatusToListeners(String.format("Decompressing plane %d...", planeIndex)); reportStatusToListeners(String.format("Decompressing plane %d...", planeIndex));
byte[] decompressedPlaneData = null; byte[] decompressedPlaneData = null;
...@@ -82,13 +81,8 @@ public class SQImageDecompressor extends CompressorDecompressorBase implements I ...@@ -82,13 +81,8 @@ public class SQImageDecompressor extends CompressorDecompressorBase implements I
final int[] decompressedValues = new int[planePixelCount]; final int[] decompressedValues = new int[planePixelCount];
final int[] quantizationValues = codebook.getCentroids(); final int[] quantizationValues = codebook.getCentroids();
for (int pixel = 0; pixel < planePixelCount; pixel++) { for (int pixel = 0; pixel < planePixelCount; pixel++) {
HuffmanNode currentHuffmanNode = huffman.getRoot(); final int decodedSymbol = huffmanDecoder.decodeSymbol(inBitStream);
boolean bit; decompressedValues[pixel] = quantizationValues[decodedSymbol];
while (!currentHuffmanNode.isLeaf()) {
bit = inBitStream.readBit();
currentHuffmanNode = currentHuffmanNode.traverse(bit);
}
decompressedValues[pixel] = quantizationValues[currentHuffmanNode.getSymbol()];
} }
decompressedPlaneData = decompressedPlaneData =
...@@ -116,7 +110,8 @@ public class SQImageDecompressor extends CompressorDecompressorBase implements I ...@@ -116,7 +110,8 @@ public class SQImageDecompressor extends CompressorDecompressorBase implements I
final SQCacheFile codebookCache = (SQCacheFile) codebookCacheFile; final SQCacheFile codebookCache = (SQCacheFile) codebookCacheFile;
cachedCodebook = codebookCache.getCodebook(); cachedCodebook = codebookCache.getCodebook();
cachedHuffman = createHuffmanCoder(createHuffmanSymbols(cachedCodebook.getCodebookSize()), cachedCodebook.getSymbolFrequencies()); cachedHuffmanDecoder = createHuffmanDecoder(createHuffmanSymbols(cachedCodebook.getCodebookSize()),
cachedCodebook.getSymbolFrequencies());
} }
@Override @Override
...@@ -130,20 +125,20 @@ public class SQImageDecompressor extends CompressorDecompressorBase implements I ...@@ -130,20 +125,20 @@ public class SQImageDecompressor extends CompressorDecompressorBase implements I
final int planePixelCount = header.getImageSizeX() * header.getImageSizeY(); final int planePixelCount = header.getImageSizeX() * header.getImageSizeY();
SQCodebook codebook = null; SQCodebook codebook = null;
HuffmanTreeBuilder huffman = null; HuffmanDecoder huffmanDecoder = null;
if (!header.isCodebookPerPlane()) { if (!header.isCodebookPerPlane()) {
// There is only one codebook. // There is only one codebook.
codebook = readScalarQuantizationValues(compressedStream, codebookSize); codebook = readScalarQuantizationValues(compressedStream, codebookSize);
huffman = createHuffmanCoder(huffmanSymbols, codebook.getSymbolFrequencies()); huffmanDecoder = createHuffmanDecoder(huffmanSymbols, codebook.getSymbolFrequencies());
} }
for (int planeIndex = 0; planeIndex < planeCountForDecompression; planeIndex++) { for (int planeIndex = 0; planeIndex < planeCountForDecompression; planeIndex++) {
reportProgressToListeners(planeIndex, planeCountForDecompression, "Decompressing plane %d", planeIndex); reportProgressToListeners(planeIndex, planeCountForDecompression, "Decompressing plane %d", planeIndex);
if (header.isCodebookPerPlane()) { if (header.isCodebookPerPlane()) {
codebook = readScalarQuantizationValues(compressedStream, codebookSize); codebook = readScalarQuantizationValues(compressedStream, codebookSize);
huffman = createHuffmanCoder(huffmanSymbols, codebook.getSymbolFrequencies()); huffmanDecoder = createHuffmanDecoder(huffmanSymbols, codebook.getSymbolFrequencies());
} }
assert (codebook != null && huffman != null); assert (codebook != null && huffmanDecoder != null);
final int planeDataSize = (int) header.getPlaneDataSizes()[planeIndex]; final int planeDataSize = (int) header.getPlaneDataSizes()[planeIndex];
try (final InBitStream inBitStream = new InBitStream(compressedStream, header.getBitsPerCodebookIndex(), planeDataSize)) { try (final InBitStream inBitStream = new InBitStream(compressedStream, header.getBitsPerCodebookIndex(), planeDataSize)) {
...@@ -153,13 +148,8 @@ public class SQImageDecompressor extends CompressorDecompressorBase implements I ...@@ -153,13 +148,8 @@ public class SQImageDecompressor extends CompressorDecompressorBase implements I
final int[] decompressedValues = new int[planePixelCount]; final int[] decompressedValues = new int[planePixelCount];
final int[] quantizationValues = codebook.getCentroids(); final int[] quantizationValues = codebook.getCentroids();
for (int pixel = 0; pixel < planePixelCount; pixel++) { for (int pixel = 0; pixel < planePixelCount; pixel++) {
HuffmanNode currentHuffmanNode = huffman.getRoot(); final int decodedSymbol = huffmanDecoder.decodeSymbol(inBitStream);
boolean bit; decompressedValues[pixel] = quantizationValues[decodedSymbol];
while (!currentHuffmanNode.isLeaf()) {
bit = inBitStream.readBit();
currentHuffmanNode = currentHuffmanNode.traverse(bit);
}
decompressedValues[pixel] = quantizationValues[currentHuffmanNode.getSymbol()];
} }
buffer[planeIndex] = TypeConverter.intArrayToShortArray(decompressedValues); buffer[planeIndex] = TypeConverter.intArrayToShortArray(decompressedValues);
......
...@@ -6,8 +6,7 @@ import cz.it4i.qcmp.compression.exception.ImageDecompressionException; ...@@ -6,8 +6,7 @@ import cz.it4i.qcmp.compression.exception.ImageDecompressionException;
import cz.it4i.qcmp.data.*; import cz.it4i.qcmp.data.*;
import cz.it4i.qcmp.fileformat.QCMPFileHeader; import cz.it4i.qcmp.fileformat.QCMPFileHeader;
import cz.it4i.qcmp.fileformat.QuantizationType; import cz.it4i.qcmp.fileformat.QuantizationType;
import cz.it4i.qcmp.huffman.HuffmanNode; import cz.it4i.qcmp.huffman.HuffmanDecoder;
import cz.it4i.qcmp.huffman.HuffmanTreeBuilder;
import cz.it4i.qcmp.io.InBitStream; import cz.it4i.qcmp.io.InBitStream;
import cz.it4i.qcmp.quantization.vector.VQCodebook; import cz.it4i.qcmp.quantization.vector.VQCodebook;
import cz.it4i.qcmp.utilities.Stopwatch; import cz.it4i.qcmp.utilities.Stopwatch;
...@@ -20,7 +19,7 @@ import java.io.IOException; ...@@ -20,7 +19,7 @@ import java.io.IOException;
public class VQImageDecompressor extends CompressorDecompressorBase implements IImageDecompressor { public class VQImageDecompressor extends CompressorDecompressorBase implements IImageDecompressor {
private VQCodebook cachedCodebook = null; private VQCodebook cachedCodebook = null;
private HuffmanTreeBuilder cachedHuffman = null; private HuffmanDecoder cachedHuffmanDecoder = null;
private interface DecompressCallback { private interface DecompressCallback {
void process(final Block imageBlock, final int planeIndex) throws ImageDecompressionException; void process(final Block imageBlock, final int planeIndex) throws ImageDecompressionException;
...@@ -73,7 +72,8 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I ...@@ -73,7 +72,8 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I
final VQCacheFile codebookCache = (VQCacheFile) codebookCacheFile; final VQCacheFile codebookCache = (VQCacheFile) codebookCacheFile;
cachedCodebook = codebookCache.getCodebook(); cachedCodebook = codebookCache.getCodebook();
cachedHuffman = createHuffmanCoder(createHuffmanSymbols(cachedCodebook.getCodebookSize()), cachedCodebook.getVectorFrequencies()); cachedHuffmanDecoder = createHuffmanDecoder(createHuffmanSymbols(cachedCodebook.getCodebookSize()),
cachedCodebook.getVectorFrequencies());
} }
...@@ -122,19 +122,19 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I ...@@ -122,19 +122,19 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I
VQCodebook codebook = null; VQCodebook codebook = null;
HuffmanTreeBuilder huffman = null; HuffmanDecoder huffmanDecoder = null;
if (!header.isCodebookPerPlane()) { if (!header.isCodebookPerPlane()) {
// There is only one codebook. // There is only one codebook.
codebook = readCodebook(compressedStream, codebookSize, vectorSize); codebook = readCodebook(compressedStream, codebookSize, vectorSize);
huffman = createHuffmanCoder(huffmanSymbols, codebook.getVectorFrequencies()); huffmanDecoder = createHuffmanDecoder(huffmanSymbols, codebook.getVectorFrequencies());
} }
for (int planeIndex = 0; planeIndex < planeCountForDecompression; planeIndex++) { for (int planeIndex = 0; planeIndex < planeCountForDecompression; planeIndex++) {
if (header.isCodebookPerPlane()) { if (header.isCodebookPerPlane()) {
codebook = readCodebook(compressedStream, codebookSize, vectorSize); codebook = readCodebook(compressedStream, codebookSize, vectorSize);
huffman = createHuffmanCoder(huffmanSymbols, codebook.getVectorFrequencies()); huffmanDecoder = createHuffmanDecoder(huffmanSymbols, codebook.getVectorFrequencies());
} }
assert (codebook != null && huffman != null); assert (codebook != null && huffmanDecoder != null);
final int planeDataSize = (int) header.getPlaneDataSizes()[planeIndex]; final int planeDataSize = (int) header.getPlaneDataSizes()[planeIndex];
...@@ -146,14 +146,8 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I ...@@ -146,14 +146,8 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I
final int[][] decompressedVectors = new int[(int) planeVectorCount][vectorSize]; final int[][] decompressedVectors = new int[(int) planeVectorCount][vectorSize];
for (int vecIndex = 0; vecIndex < planeVectorCount; vecIndex++) { for (int vecIndex = 0; vecIndex < planeVectorCount; vecIndex++) {
HuffmanNode currentHuffmanNode = huffman.getRoot(); final int decodedSymbol = huffmanDecoder.decodeSymbol(inBitStream);
boolean bit; System.arraycopy(codebook.getVectors()[decodedSymbol], 0, decompressedVectors[vecIndex], 0, vectorSize);
while (!currentHuffmanNode.isLeaf()) {
bit = inBitStream.readBit();
currentHuffmanNode = currentHuffmanNode.traverse(bit);
}
System.arraycopy(codebook.getVectors()[currentHuffmanNode.getSymbol()],
0, decompressedVectors[vecIndex], 0, vectorSize);
} }
...@@ -177,7 +171,7 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I ...@@ -177,7 +171,7 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I
final QCMPFileHeader header, final QCMPFileHeader header,
final DecompressCallback callback) throws ImageDecompressionException { final DecompressCallback callback) throws ImageDecompressionException {
assert (cachedCodebook != null && cachedHuffman != null); assert (cachedCodebook != null && cachedHuffmanDecoder != null);
assert (header.getVectorSizeZ() == 1); assert (header.getVectorSizeZ() == 1);
final int planeCountForDecompression = header.getImageSizeZ(); final int planeCountForDecompression = header.getImageSizeZ();
final long planeVectorCount = calculatePlaneVectorCount(header); final long planeVectorCount = calculatePlaneVectorCount(header);
...@@ -197,7 +191,7 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I ...@@ -197,7 +191,7 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I
final int[][] decompressedVectors = new int[(int) planeVectorCount][vectorSize]; final int[][] decompressedVectors = new int[(int) planeVectorCount][vectorSize];
int huffmanIndex; int huffmanIndex;
for (int vecIndex = 0; vecIndex < planeVectorCount; vecIndex++) { for (int vecIndex = 0; vecIndex < planeVectorCount; vecIndex++) {
huffmanIndex = decodeHuffmanSymbol(cachedHuffman, inBitStream); huffmanIndex = cachedHuffmanDecoder.decodeSymbol(inBitStream);
System.arraycopy(cachedCodebook.getVectors()[huffmanIndex], 0, decompressedVectors[vecIndex], 0, vectorSize); System.arraycopy(cachedCodebook.getVectors()[huffmanIndex], 0, decompressedVectors[vecIndex], 0, vectorSize);
} }
...@@ -245,7 +239,7 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I ...@@ -245,7 +239,7 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I
final VQCodebook codebook = readCodebook(compressedStream, codebookSize, vectorSize); final VQCodebook codebook = readCodebook(compressedStream, codebookSize, vectorSize);
final HuffmanTreeBuilder huffman = createHuffmanCoder(huffmanSymbols, codebook.getVectorFrequencies()); final HuffmanDecoder huffmanDecoder = createHuffmanDecoder(huffmanSymbols, codebook.getVectorFrequencies());
final int voxelLayerCount = VQImageCompressor.calculateVoxelLayerCount(header.getImageSizeZ(), header.getVectorSizeZ()); final int voxelLayerCount = VQImageCompressor.calculateVoxelLayerCount(header.getImageSizeZ(), header.getVectorSizeZ());
final Stopwatch stopwatch = new Stopwatch(); final Stopwatch stopwatch = new Stopwatch();
...@@ -267,7 +261,7 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I ...@@ -267,7 +261,7 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I
inBitStream.setAllowReadFromUnderlyingStream(false); inBitStream.setAllowReadFromUnderlyingStream(false);
for (int voxelIndex = 0; voxelIndex < voxelLayerVoxelCount; voxelIndex++) { for (int voxelIndex = 0; voxelIndex < voxelLayerVoxelCount; voxelIndex++) {
final int huffmanSymbol = decodeHuffmanSymbol(huffman, inBitStream); final int huffmanSymbol = huffmanDecoder.decodeSymbol(inBitStream);
System.arraycopy(codebook.getVectors()[huffmanSymbol], 0, decompressedVoxels[voxelIndex], 0, vectorSize); System.arraycopy(codebook.getVectors()[huffmanSymbol], 0, decompressedVoxels[voxelIndex], 0, vectorSize);
} }
...@@ -325,7 +319,7 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I ...@@ -325,7 +319,7 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I
inBitStream.setAllowReadFromUnderlyingStream(false); inBitStream.setAllowReadFromUnderlyingStream(false);
for (int voxelIndex = 0; voxelIndex < voxelLayerVoxelCount; voxelIndex++) { for (int voxelIndex = 0; voxelIndex < voxelLayerVoxelCount; voxelIndex++) {
final int huffmanSymbol = decodeHuffmanSymbol(cachedHuffman, inBitStream); final int huffmanSymbol = cachedHuffmanDecoder.decodeSymbol(inBitStream);
System.arraycopy(cachedCodebook.getVectors()[huffmanSymbol], 0, decompressedVoxels[voxelIndex], 0, vectorSize); System.arraycopy(cachedCodebook.getVectors()[huffmanSymbol], 0, decompressedVoxels[voxelIndex], 0, vectorSize);
} }
...@@ -379,15 +373,6 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I ...@@ -379,15 +373,6 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I
}); });
} }
private int decodeHuffmanSymbol(final HuffmanTreeBuilder huffman, final InBitStream inBitStream) throws IOException {
HuffmanNode currentHuffmanNode = huffman.getRoot();
while (!currentHuffmanNode.isLeaf()) {
currentHuffmanNode = currentHuffmanNode.traverse(inBitStream.readBit());
}
return currentHuffmanNode.getSymbol();
}
@Override @Override
public short[] decompressStreamMode(final DataInputStream compressedStream, public short[] decompressStreamMode(final DataInputStream compressedStream,
final QCMPFileHeader header) throws ImageDecompressionException { final QCMPFileHeader header) throws ImageDecompressionException {
......
package cz.it4i.qcmp.huffman;
import cz.it4i.qcmp.io.InBitStream;
import java.io.IOException;
/**
* Simply wrapper around root huffman node to provide easy decode function.
*/
public class HuffmanDecoder {
private final HuffmanNode root;
/**
* Create huffman decoder from the root node.
*
* @param root Root huffman node.
*/
public HuffmanDecoder(final HuffmanNode root) {
this.root = root;
}
/**
* Decode huffman symbol by reading binary code from stream.
*
* @param inBitStream Binary input stream.
* @return Decoded symbol.
* @throws IOException when fails to read from input stream.
*/
public int decodeSymbol(final InBitStream inBitStream) throws IOException {
HuffmanNode currentNode = root;
while (!currentNode.isLeaf()) {
currentNode = currentNode.traverse(inBitStream.readBit());
}
return currentNode.getSymbol();
}
}
...@@ -23,9 +23,7 @@ public class HuffmanTreeBuilder { ...@@ -23,9 +23,7 @@ public class HuffmanTreeBuilder {
final HuffmanNode parentA = queue.poll(); final HuffmanNode parentA = queue.poll();
final HuffmanNode parentB = queue.poll(); final HuffmanNode parentB = queue.poll();
if (!(parentA.getProbability() <= parentB.getProbability())) { if (!(parentA.getProbability() <= parentB.getProbability())) {
System.err.println(String.format("Parent A prob: %.6f\nParent B prob: %.6f", System.err.printf("Parent A prob: %.6f\nParent B prob: %.6f%n", parentA.getProbability(), parentB.getProbability());
parentA.getProbability(),
parentB.getProbability()));
assert (parentA.getProbability() <= parentB.getProbability()); assert (parentA.getProbability() <= parentB.getProbability());
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment