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 32b62054975fec4337112abca419f3befb641b95..e2b59ee7e7d004c5ed20a2c2b82fde70914aca76 100644
--- a/src/main/java/cz/it4i/qcmp/cli/functions/DebugFunction.java
+++ b/src/main/java/cz/it4i/qcmp/cli/functions/DebugFunction.java
@@ -1,19 +1,7 @@
package cz.it4i.qcmp.cli.functions;
-import cz.it4i.qcmp.cache.QuantizationCacheManager;
-import cz.it4i.qcmp.cache.VqQvcFile;
import cz.it4i.qcmp.cli.CompressionOptionsCLIParser;
import cz.it4i.qcmp.cli.CustomFunctionBase;
-import cz.it4i.qcmp.huffman.HuffmanNode;
-import cz.it4i.qcmp.huffman.HuffmanTreeBuilder;
-import cz.it4i.qcmp.io.InBitStream;
-import cz.it4i.qcmp.io.OutBitStream;
-import cz.it4i.qcmp.quantization.vector.VQCodebook;
-import cz.it4i.qcmp.utilities.Utils;
-
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
@SuppressWarnings("ConstantConditions")
public class DebugFunction extends CustomFunctionBase {
@@ -29,38 +17,37 @@ public class DebugFunction extends CustomFunctionBase {
@Override
public boolean run() {
- final VQCodebook codebook = ((VqQvcFile) QuantizationCacheManager.readCacheFile("D:\\tmp\\codebook.qvc")).getCodebook();
-
- final int[] symbols = new int[codebook.getCodebookSize()];
- for (int i = 0; i < codebook.getCodebookSize(); i++) {
- symbols[i] = i;
- }
-
- 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)) {
- huffmanBuilder.createEncoder().getRoot().writeToBinaryStream(bitStream);
- } catch (final IOException e) {
- e.printStackTrace();
- }
-
-
- HuffmanNode readRoot = null;
- try (final InBitStream inBitStream = new InBitStream(new FileInputStream("D:\\tmp\\huffman_tree.data"), bitsPerSymbol, 256)) {
- readRoot = HuffmanNode.readFromStream(inBitStream);
- } catch (final IOException ex) {
- ex.printStackTrace();
- }
-
- readRoot.
-
- final boolean equal = huffmanBuilder.createEncoder().getRoot().treeEqual(readRoot);
-
- System.out.println(readRoot != null);
+ // final VQCodebook codebook = ((VqQvcFile) QuantizationCacheManager.readCacheFile("D:\\tmp\\codebook.qvc")).getCodebook();
+ //
+ // final int[] symbols = new int[codebook.getCodebookSize()];
+ // for (int i = 0; i < codebook.getCodebookSize(); i++) {
+ // symbols[i] = i;
+ // }
+ //
+ // 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)) {
+ // huffmanBuilder.createEncoder().getRoot().writeToBinaryStream(bitStream);
+ // } catch (final IOException e) {
+ // e.printStackTrace();
+ // }
+ //
+ //
+ // HuffmanNode readRoot = null;
+ // try (final InBitStream inBitStream = new InBitStream(new FileInputStream("D:\\tmp\\huffman_tree.data"), bitsPerSymbol,
+ // 256)) {
+ // readRoot = HuffmanNode.readFromStream(inBitStream);
+ // } catch (final IOException ex) {
+ // ex.printStackTrace();
+ // }
+ //
+ // final boolean equal = huffmanBuilder.createEncoder().getRoot().treeEqual(readRoot);
+ //
+ // System.out.println(readRoot != null);
return true;
}
diff --git a/src/main/java/cz/it4i/qcmp/compression/CompressorDecompressorBase.java b/src/main/java/cz/it4i/qcmp/compression/CompressorDecompressorBase.java
index f41106e7bbcc8eebf1ac90ceba9899272a4e7b8e..0278a0eec9ec3cd3e1cf1a58257d2e5f679e96e3 100644
--- a/src/main/java/cz/it4i/qcmp/compression/CompressorDecompressorBase.java
+++ b/src/main/java/cz/it4i/qcmp/compression/CompressorDecompressorBase.java
@@ -3,9 +3,7 @@ package cz.it4i.qcmp.compression;
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,19 +99,7 @@ public abstract class CompressorDecompressorBase {
}
return symbols;
}
-
- protected HuffmanEncoder createHuffmanEncoder(final int[] symbols, final long[] frequencies) {
- final HuffmanTreeBuilder huffman = new HuffmanTreeBuilder(symbols, frequencies);
- huffman.buildHuffmanTree();
- return huffman.createEncoder();
- }
-
- protected HuffmanDecoder createHuffmanDecoder(final int[] symbols, final long[] frequencies) {
- final HuffmanTreeBuilder huffman = new HuffmanTreeBuilder(symbols, frequencies);
- huffman.buildHuffmanTree();
- return huffman.createDecoder();
- }
-
+
protected int[] getPlaneIndicesForCompression(final InputData inputData) {
if (inputData.isPlaneIndexSet()) {
return new int[]{inputData.getPlaneIndex()};
diff --git a/src/main/java/cz/it4i/qcmp/compression/SQImageCompressor.java b/src/main/java/cz/it4i/qcmp/compression/SQImageCompressor.java
index b782dcc81cf57ed0680e3cc282151fea418e4209..effc516fc4262ec7e3d8ef13f0a0af87040829ce 100644
--- a/src/main/java/cz/it4i/qcmp/compression/SQImageCompressor.java
+++ b/src/main/java/cz/it4i/qcmp/compression/SQImageCompressor.java
@@ -45,8 +45,7 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm
public void preloadGlobalCodebook(final IQvcFile codebookCacheFile) {
final SQCodebook cachedCodebook = ((SqQvcFile) codebookCacheFile).getCodebook();
cachedQuantizer = new ScalarQuantizer(cachedCodebook);
- cachedHuffmanEncoder = createHuffmanEncoder(createHuffmanSymbols(cachedCodebook.getCodebookSize()),
- cachedCodebook.getSymbolFrequencies());
+ cachedHuffmanEncoder = cachedCodebook.getHuffmanEncoder();
}
/**
@@ -89,8 +88,7 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm
trainAndSaveCodebook();
}
- final SQCodebook codebook = cacheManager.loadSQCodebook(options.getInputDataInfo().getCacheFileName(),
- getCodebookSize());
+ final SQCodebook codebook = cacheManager.loadSQCodebook(options.getInputDataInfo().getCacheFileName(), getCodebookSize());
if (codebook == null) {
throw new ImageCompressionException("Failed to read quantization values from cache file.");
}
@@ -123,7 +121,7 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm
reportStatusToListeners("Loading codebook from cache file.");
quantizer = loadQuantizerFromCache();
- huffmanEncoder = createHuffmanEncoder(huffmanSymbols, quantizer.getCodebook().getSymbolFrequencies());
+ huffmanEncoder = quantizer.getCodebook().getHuffmanEncoder();
reportStatusToListeners("Cached quantizer with huffman coder created.");
writeCodebookToOutputStream(quantizer, compressStream);
@@ -139,7 +137,7 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm
reportStatusToListeners(String.format("Training scalar quantizer from middle plane %d.", middlePlaneIndex));
quantizer = trainScalarQuantizerFromData(middlePlaneData);
- huffmanEncoder = createHuffmanEncoder(huffmanSymbols, quantizer.getCodebook().getSymbolFrequencies());
+ huffmanEncoder = quantizer.getCodebook().getHuffmanEncoder();
stopwatch.stop();
writeCodebookToOutputStream(quantizer, compressStream);
@@ -175,7 +173,7 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm
quantizer = trainScalarQuantizerFromData(planeData);
writeCodebookToOutputStream(quantizer, compressStream);
- huffmanEncoder = createHuffmanEncoder(huffmanSymbols, quantizer.getCodebook().getSymbolFrequencies());
+ huffmanEncoder = quantizer.getCodebook().getHuffmanEncoder();
}
assert (quantizer != null) : "Scalar Quantizer wasn't initialized.";
@@ -200,7 +198,7 @@ public class SQImageCompressor extends CompressorDecompressorBase implements IIm
} catch (final Exception e) {
throw new ImageCompressionException("Unable to create SCIFIO reader. " + e.getMessage());
}
- int[] trainData = null;
+ final int[] trainData;
if (options.getCodebookType() == CompressionOptions.CodebookType.MiddlePlane) {
final int middlePlaneIndex = getMiddlePlaneIndex();
diff --git a/src/main/java/cz/it4i/qcmp/compression/SQImageDecompressor.java b/src/main/java/cz/it4i/qcmp/compression/SQImageDecompressor.java
index 703beda0fe4ddf5f18f30f927a4b0bda395301ea..e3433a4d1a529e8173606ab57cbbac5cfe5fa802 100644
--- a/src/main/java/cz/it4i/qcmp/compression/SQImageDecompressor.java
+++ b/src/main/java/cz/it4i/qcmp/compression/SQImageDecompressor.java
@@ -5,6 +5,7 @@ import cz.it4i.qcmp.cache.SqQvcFile;
import cz.it4i.qcmp.compression.exception.ImageDecompressionException;
import cz.it4i.qcmp.fileformat.QCMPFileHeader;
import cz.it4i.qcmp.huffman.HuffmanDecoder;
+import cz.it4i.qcmp.huffman.HuffmanTreeBuilder;
import cz.it4i.qcmp.io.InBitStream;
import cz.it4i.qcmp.quantization.scalar.SQCodebook;
import cz.it4i.qcmp.utilities.Stopwatch;
@@ -22,8 +23,7 @@ public class SQImageDecompressor extends CompressorDecompressorBase implements I
super(options);
}
- private SQCodebook readScalarQuantizationValues(final DataInputStream compressedStream,
- final int codebookSize) throws ImageDecompressionException {
+ private SQCodebook readSqCodebook(final DataInputStream compressedStream, final int codebookSize) throws ImageDecompressionException {
final int[] quantizationValues = new int[codebookSize];
final long[] symbolFrequencies = new long[codebookSize];
try {
@@ -36,7 +36,9 @@ public class SQImageDecompressor extends CompressorDecompressorBase implements I
} catch (final IOException ioEx) {
throw new ImageDecompressionException("Unable to read quantization values from compressed stream.", ioEx);
}
- return new SQCodebook(quantizationValues, symbolFrequencies);
+ final HuffmanTreeBuilder builder = new HuffmanTreeBuilder(createHuffmanSymbols(codebookSize), symbolFrequencies);
+ builder.buildHuffmanTree();
+ return new SQCodebook(quantizationValues, builder.getRoot());
}
@Override
@@ -45,7 +47,6 @@ public class SQImageDecompressor extends CompressorDecompressorBase implements I
final QCMPFileHeader header) throws ImageDecompressionException {
final int codebookSize = (int) Math.pow(2, header.getBitsPerCodebookIndex());
- final int[] huffmanSymbols = createHuffmanSymbols(codebookSize);
final int planeCountForDecompression = header.getImageSizeZ();
final int planePixelCount = header.getImageSizeX() * header.getImageSizeY();
@@ -55,8 +56,8 @@ public class SQImageDecompressor extends CompressorDecompressorBase implements I
if (!header.isCodebookPerPlane()) {
// There is only one codebook.
reportStatusToListeners("Loading single codebook and huffman coder.");
- codebook = readScalarQuantizationValues(compressedStream, codebookSize);
- huffmanDecoder = createHuffmanDecoder(huffmanSymbols, codebook.getSymbolFrequencies());
+ codebook = readSqCodebook(compressedStream, codebookSize);
+ huffmanDecoder = codebook.getHuffmanDecoder();
}
final Stopwatch stopwatch = new Stopwatch();
@@ -64,8 +65,8 @@ public class SQImageDecompressor extends CompressorDecompressorBase implements I
stopwatch.restart();
if (header.isCodebookPerPlane()) {
reportStatusToListeners("Loading plane codebook...");
- codebook = readScalarQuantizationValues(compressedStream, codebookSize);
- huffmanDecoder = createHuffmanDecoder(huffmanSymbols, codebook.getSymbolFrequencies());
+ codebook = readSqCodebook(compressedStream, codebookSize);
+ huffmanDecoder = codebook.getHuffmanDecoder();
}
assert (codebook != null && huffmanDecoder != null);
@@ -110,8 +111,7 @@ public class SQImageDecompressor extends CompressorDecompressorBase implements I
final SqQvcFile codebookCache = (SqQvcFile) codebookCacheFile;
cachedCodebook = codebookCache.getCodebook();
- cachedHuffmanDecoder = createHuffmanDecoder(createHuffmanSymbols(cachedCodebook.getCodebookSize()),
- cachedCodebook.getSymbolFrequencies());
+ cachedHuffmanDecoder = cachedCodebook.getHuffmanDecoder();
}
@Override
@@ -119,7 +119,6 @@ public class SQImageDecompressor extends CompressorDecompressorBase implements I
final short[][] buffer,
final QCMPFileHeader header) throws ImageDecompressionException {
final int codebookSize = (int) Math.pow(2, header.getBitsPerCodebookIndex());
- final int[] huffmanSymbols = createHuffmanSymbols(codebookSize);
final int planeCountForDecompression = header.getImageSizeZ();
final int planePixelCount = header.getImageSizeX() * header.getImageSizeY();
@@ -128,15 +127,15 @@ public class SQImageDecompressor extends CompressorDecompressorBase implements I
HuffmanDecoder huffmanDecoder = null;
if (!header.isCodebookPerPlane()) {
// There is only one codebook.
- codebook = readScalarQuantizationValues(compressedStream, codebookSize);
- huffmanDecoder = createHuffmanDecoder(huffmanSymbols, codebook.getSymbolFrequencies());
+ codebook = readSqCodebook(compressedStream, codebookSize);
+ huffmanDecoder = codebook.getHuffmanDecoder();
}
for (int planeIndex = 0; planeIndex < planeCountForDecompression; planeIndex++) {
reportProgressToListeners(planeIndex, planeCountForDecompression, "Decompressing plane %d", planeIndex);
if (header.isCodebookPerPlane()) {
- codebook = readScalarQuantizationValues(compressedStream, codebookSize);
- huffmanDecoder = createHuffmanDecoder(huffmanSymbols, codebook.getSymbolFrequencies());
+ codebook = readSqCodebook(compressedStream, codebookSize);
+ huffmanDecoder = codebook.getHuffmanDecoder();
}
assert (codebook != null && huffmanDecoder != null);
diff --git a/src/main/java/cz/it4i/qcmp/compression/VQImageCompressor.java b/src/main/java/cz/it4i/qcmp/compression/VQImageCompressor.java
index babbf166675a3995e480c4271c5bf1b6d9c1a86c..b273f83c9d606fc00b09b54048cae6e1f7cf7058 100644
--- a/src/main/java/cz/it4i/qcmp/compression/VQImageCompressor.java
+++ b/src/main/java/cz/it4i/qcmp/compression/VQImageCompressor.java
@@ -16,7 +16,6 @@ import cz.it4i.qcmp.quantization.vector.VQCodebook;
import cz.it4i.qcmp.quantization.vector.VectorQuantizer;
import cz.it4i.qcmp.utilities.Stopwatch;
import cz.it4i.qcmp.utilities.Utils;
-import org.jetbrains.annotations.NotNull;
import java.io.DataOutputStream;
import java.io.IOException;
@@ -36,8 +35,7 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
public void preloadGlobalCodebook(final IQvcFile codebookCacheFile) {
final VQCodebook cachedCodebook = ((VqQvcFile) codebookCacheFile).getCodebook();
cachedQuantizer = new VectorQuantizer(cachedCodebook);
- cachedHuffmanEncoder = createHuffmanEncoder(createHuffmanSymbols(cachedCodebook.getCodebookSize()),
- cachedCodebook.getVectorFrequencies());
+ cachedHuffmanEncoder = cachedCodebook.getHuffmanEncoder();
}
public boolean shouldUseKdTree() {
@@ -74,6 +72,7 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
*/
private void writeQuantizerToCompressStream(final VectorQuantizer quantizer,
final DataOutputStream compressStream) throws ImageCompressionException {
+ // TODO
final int[][] codebook = quantizer.getCodebookVectors();
try {
for (final int[] entry : codebook) {
@@ -143,7 +142,6 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
return compress1D2DVectors(compressStream, true, inputData);
}
- @NotNull
private long[] compress1D2DVectors(final DataOutputStream compressStream,
final boolean streamMode,
final InputData inputData) throws ImageCompressionException {
@@ -166,7 +164,7 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
if (options.getCodebookType() == CompressionOptions.CodebookType.Global) {
reportStatusToListeners("Loading codebook from cache file.");
quantizer = loadQuantizerFromCache();
- huffmanEncoder = createHuffmanEncoder(huffmanSymbols, quantizer.getFrequencies());
+ huffmanEncoder = quantizer.getCodebook().getHuffmanEncoder();
reportStatusToListeners("Cached quantizer with huffman coder created.");
writeQuantizerToCompressStream(quantizer, compressStream);
} else if (options.getCodebookType() == CompressionOptions.CodebookType.MiddlePlane) {
@@ -175,7 +173,7 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
final int[][] refPlaneVectors = planeLoader.loadVectorsFromPlaneRange(0, options,
Utils.singlePlaneRange(getMiddlePlaneIndex()));
quantizer = trainVectorQuantizerFromPlaneVectors(refPlaneVectors);
- huffmanEncoder = createHuffmanEncoder(huffmanSymbols, quantizer.getFrequencies());
+ huffmanEncoder = quantizer.getCodebook().getHuffmanEncoder();
stopwatch.stop();
reportStatusToListeners("Middle plane codebook created in: " + stopwatch.getElapsedTimeString());
writeQuantizerToCompressStream(quantizer, compressStream);
@@ -209,7 +207,7 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
if (!streamMode && !hasGeneralQuantizer) {
reportStatusToListeners(String.format("Training vector quantizer from plane %d.", planeIndex));
quantizer = trainVectorQuantizerFromPlaneVectors(planeVectors);
- huffmanEncoder = createHuffmanEncoder(huffmanSymbols, quantizer.getFrequencies());
+ huffmanEncoder = quantizer.getCodebook().getHuffmanEncoder();
writeQuantizerToCompressStream(quantizer, compressStream);
}
@@ -258,7 +256,6 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
final InputData inputData) throws ImageCompressionException {
assert (options.getCodebookType() == CompressionOptions.CodebookType.Global);
final IPlaneLoader planeLoader;
- final int[] huffmanSymbols = createHuffmanSymbols(getCodebookSize());
try {
planeLoader = PlaneLoaderFactory.getPlaneLoaderForInputFile(inputData);
planeLoader.setWorkerCount(options.getWorkerCount());
@@ -286,7 +283,7 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
final VectorQuantizer quantizer = (cachedQuantizer != null) ? cachedQuantizer : loadQuantizerFromCache();
final HuffmanEncoder huffmanEncoder = (cachedHuffmanEncoder != null)
? cachedHuffmanEncoder
- : createHuffmanEncoder(huffmanSymbols, quantizer.getFrequencies());
+ : quantizer.getCodebook().getHuffmanEncoder();
if (!streamMode)
writeQuantizerToCompressStream(quantizer, compressStream);
@@ -387,8 +384,7 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
codebookTrainer.findOptimalCodebook(vqCodebook -> {
try {
- assert ((vqCodebook.getCodebookSize() == vqCodebook.getVectors().length) &&
- (vqCodebook.getCodebookSize() == vqCodebook.getVectorFrequencies().length))
+ assert (vqCodebook.getCodebookSize() == vqCodebook.getVectors().length)
: "Codebook size, Vector count, Frequencies count mismatch";
qcm.saveCodebook(options.getInputDataInfo().getCacheFileName(), vqCodebook);
} catch (final IOException e) {
diff --git a/src/main/java/cz/it4i/qcmp/compression/VQImageDecompressor.java b/src/main/java/cz/it4i/qcmp/compression/VQImageDecompressor.java
index 9262328746cf2fbec3d6cf5bbcd85edaccfa1871..65af70fe3057f6ee6ddce0c808e0b5528aaf8ce4 100644
--- a/src/main/java/cz/it4i/qcmp/compression/VQImageDecompressor.java
+++ b/src/main/java/cz/it4i/qcmp/compression/VQImageDecompressor.java
@@ -7,6 +7,7 @@ import cz.it4i.qcmp.data.*;
import cz.it4i.qcmp.fileformat.QCMPFileHeader;
import cz.it4i.qcmp.fileformat.QuantizationType;
import cz.it4i.qcmp.huffman.HuffmanDecoder;
+import cz.it4i.qcmp.huffman.HuffmanTreeBuilder;
import cz.it4i.qcmp.io.InBitStream;
import cz.it4i.qcmp.quantization.vector.VQCodebook;
import cz.it4i.qcmp.utilities.Stopwatch;
@@ -36,8 +37,8 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I
}
private long calculatePlaneVectorCount(final QCMPFileHeader header) {
- final int vectorXCount = (int) Math.ceil((double) header.getImageSizeX() / (double) header.getVectorSizeX());
- final int vectorYCount = (int) Math.ceil((double) header.getImageSizeY() / (double) header.getVectorSizeY());
+ final long vectorXCount = (long) Math.ceil((double) header.getImageSizeX() / (double) header.getVectorSizeX());
+ final long vectorYCount = (long) Math.ceil((double) header.getImageSizeY() / (double) header.getVectorSizeY());
// Number of vectors per plane.
return (vectorXCount * vectorYCount);
}
@@ -62,8 +63,11 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I
throw new ImageDecompressionException("Unable to read quantization values from compressed stream.", ioEx);
}
+ final HuffmanTreeBuilder builder = new HuffmanTreeBuilder(createHuffmanSymbols(codebookSize), frequencies);
+ builder.buildHuffmanTree();
+
// We don't care about vector dimensions in here.
- return new VQCodebook(new V3i(0), codebookVectors, frequencies);
+ return new VQCodebook(new V3i(0), codebookVectors, builder.getRoot());
}
@Override
@@ -72,8 +76,7 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I
final VqQvcFile codebookCache = (VqQvcFile) codebookCacheFile;
cachedCodebook = codebookCache.getCodebook();
- cachedHuffmanDecoder = createHuffmanDecoder(createHuffmanSymbols(cachedCodebook.getCodebookSize()),
- cachedCodebook.getVectorFrequencies());
+ cachedHuffmanDecoder = cachedCodebook.getHuffmanDecoder();
}
@@ -118,21 +121,19 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I
final int planeCountForDecompression = header.getImageSizeZ();
final long planeVectorCount = calculatePlaneVectorCount(header);
final V2i qVector = new V2i(header.getVectorSizeX(), header.getVectorSizeY());
- final int[] huffmanSymbols = createHuffmanSymbols(codebookSize);
-
VQCodebook codebook = null;
HuffmanDecoder huffmanDecoder = null;
if (!header.isCodebookPerPlane()) {
// There is only one codebook.
codebook = readCodebook(compressedStream, codebookSize, vectorSize);
- huffmanDecoder = createHuffmanDecoder(huffmanSymbols, codebook.getVectorFrequencies());
+ huffmanDecoder = codebook.getHuffmanDecoder();
}
for (int planeIndex = 0; planeIndex < planeCountForDecompression; planeIndex++) {
if (header.isCodebookPerPlane()) {
codebook = readCodebook(compressedStream, codebookSize, vectorSize);
- huffmanDecoder = createHuffmanDecoder(huffmanSymbols, codebook.getVectorFrequencies());
+ huffmanDecoder = codebook.getHuffmanDecoder();
}
assert (codebook != null && huffmanDecoder != null);
@@ -239,7 +240,7 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I
final VQCodebook codebook = readCodebook(compressedStream, codebookSize, vectorSize);
- final HuffmanDecoder huffmanDecoder = createHuffmanDecoder(huffmanSymbols, codebook.getVectorFrequencies());
+ final HuffmanDecoder huffmanDecoder = codebook.getHuffmanDecoder();
final int voxelLayerCount = VQImageCompressor.calculateVoxelLayerCount(header.getImageSizeZ(), header.getVectorSizeZ());
final Stopwatch stopwatch = new Stopwatch();
diff --git a/src/main/java/cz/it4i/qcmp/quantization/scalar/LloydMaxU16ScalarQuantization.java b/src/main/java/cz/it4i/qcmp/quantization/scalar/LloydMaxU16ScalarQuantization.java
index 0dc3f31dfff51768f2eec7a8ce1e99d634c39f92..18915031145478bcd74d2514ba0aee662abb68b1 100644
--- a/src/main/java/cz/it4i/qcmp/quantization/scalar/LloydMaxU16ScalarQuantization.java
+++ b/src/main/java/cz/it4i/qcmp/quantization/scalar/LloydMaxU16ScalarQuantization.java
@@ -2,6 +2,7 @@ package cz.it4i.qcmp.quantization.scalar;
import cz.it4i.qcmp.U16;
import cz.it4i.qcmp.compression.listeners.IStatusListener;
+import cz.it4i.qcmp.huffman.HuffmanTreeBuilder;
import cz.it4i.qcmp.quantization.QTrainIteration;
import cz.it4i.qcmp.utilities.MinMaxResult;
import cz.it4i.qcmp.utilities.Stopwatch;
@@ -258,7 +259,9 @@ public class LloydMaxU16ScalarQuantization {
}
public SQCodebook getCodebook() {
- return new SQCodebook(centroids, frequencies);
+ final HuffmanTreeBuilder builder = new HuffmanTreeBuilder(codebookSize, frequencies);
+ builder.buildHuffmanTree();
+ return new SQCodebook(centroids, builder.getRoot());
}
}
diff --git a/src/main/java/cz/it4i/qcmp/quantization/vector/LBGResult.java b/src/main/java/cz/it4i/qcmp/quantization/vector/LBGResult.java
index 2bb63affb7f42f6161eed7a94af3dea96db241dd..4d0156e888244bd7e028fef9030c8782298b0cf2 100644
--- a/src/main/java/cz/it4i/qcmp/quantization/vector/LBGResult.java
+++ b/src/main/java/cz/it4i/qcmp/quantization/vector/LBGResult.java
@@ -1,6 +1,7 @@
package cz.it4i.qcmp.quantization.vector;
import cz.it4i.qcmp.data.V3i;
+import cz.it4i.qcmp.huffman.HuffmanTreeBuilder;
public class LBGResult {
@@ -23,7 +24,9 @@ public class LBGResult {
}
public VQCodebook getCodebook() {
- return new VQCodebook(vectorDims, codebookVectors, frequencies);
+ final HuffmanTreeBuilder builder = new HuffmanTreeBuilder(codebookVectors.length, frequencies);
+ builder.buildHuffmanTree();
+ return new VQCodebook(vectorDims, codebookVectors, builder.getRoot());
}
public double getAverageMse() {
diff --git a/src/main/java/cz/it4i/qcmp/quantization/vector/LBGVectorQuantizer.java b/src/main/java/cz/it4i/qcmp/quantization/vector/LBGVectorQuantizer.java
index 86d93dc147286d4dabb962ce1a020518a2c5540f..4f3aa5f81db4c482b3451f90e4ede7856ff7e67e 100644
--- a/src/main/java/cz/it4i/qcmp/quantization/vector/LBGVectorQuantizer.java
+++ b/src/main/java/cz/it4i/qcmp/quantization/vector/LBGVectorQuantizer.java
@@ -3,6 +3,7 @@ package cz.it4i.qcmp.quantization.vector;
import cz.it4i.qcmp.U16;
import cz.it4i.qcmp.compression.listeners.IStatusListener;
import cz.it4i.qcmp.data.V3i;
+import cz.it4i.qcmp.huffman.HuffmanTreeBuilder;
import cz.it4i.qcmp.utilities.Stopwatch;
import cz.it4i.qcmp.utilities.Utils;
@@ -207,9 +208,7 @@ public class LBGVectorQuantizer {
workers[wId] = new Thread(() -> {
final long[] workerFrequencies = new long[codebook.length];
- final VectorQuantizer quantizer = new VectorQuantizer(new VQCodebook(vectorDimensions,
- codebook,
- frequencies));
+ final VectorQuantizer quantizer = new VectorQuantizer(new VQCodebook(vectorDimensions, codebook, null));
double threadMse = 0.0;
int[] vector;
@@ -245,9 +244,7 @@ public class LBGVectorQuantizer {
}
mse = _mse / (double) workerCount;
} else {
- final VectorQuantizer quantizer = new VectorQuantizer(new VQCodebook(vectorDimensions,
- codebook,
- frequencies));
+ final VectorQuantizer quantizer = new VectorQuantizer(new VQCodebook(vectorDimensions, codebook, null));
int qIndex;
int[] qVector;
for (final TrainingVector trV : trainingVectors) {
@@ -412,9 +409,10 @@ public class LBGVectorQuantizer {
final long[] codebookFrequencies = new long[codebook.length];
System.arraycopy(frequencies, 0, codebookFrequencies, 0, codebook.length);
- codebookFoundCallback.process(new VQCodebook(vectorDimensions,
- learningCodebookToCodebook(codebook),
- codebookFrequencies));
+
+ final HuffmanTreeBuilder builder = new HuffmanTreeBuilder(codebook.length, frequencies);
+ builder.buildHuffmanTree();
+ codebookFoundCallback.process(new VQCodebook(vectorDimensions, learningCodebookToCodebook(codebook), builder.getRoot()));
}
}
return codebook;
diff --git a/src/main/java/cz/it4i/qcmp/quantization/vector/VQCodebook.java b/src/main/java/cz/it4i/qcmp/quantization/vector/VQCodebook.java
index a47f71c411b6e0a2f6c8148e60ce75f6c177976b..cc618cf898a0993a2ec78c281315d61be9257e02 100644
--- a/src/main/java/cz/it4i/qcmp/quantization/vector/VQCodebook.java
+++ b/src/main/java/cz/it4i/qcmp/quantization/vector/VQCodebook.java
@@ -32,6 +32,7 @@ public class VQCodebook extends Codebook {
* @param huffmanRoot Root of the huffman tree.
*/
public VQCodebook(final V3i vectorDims, final int[][] vectors, final HuffmanNode huffmanRoot) {
+ super(huffmanRoot);
this.vectorDims = vectorDims;
this.vectors = vectors;
this.codebookSize = vectors.length;
diff --git a/src/main/java/cz/it4i/qcmp/quantization/vector/VectorQuantizer.java b/src/main/java/cz/it4i/qcmp/quantization/vector/VectorQuantizer.java
index fe7341497d35bec39130d8e3da998f8167b3f62f..639d7eec024bc021747eb79ef3ec9fdc8de5d0b9 100644
--- a/src/main/java/cz/it4i/qcmp/quantization/vector/VectorQuantizer.java
+++ b/src/main/java/cz/it4i/qcmp/quantization/vector/VectorQuantizer.java
@@ -11,16 +11,15 @@ public class VectorQuantizer {
private final VectorDistanceMetric metric = VectorDistanceMetric.Euclidean;
private final int[][] codebookVectors;
private final int vectorSize;
- private final long[] frequencies;
+ private final VQCodebook codebook;
- // private final KDTree kdTree;
+ // private final KDTree kdTree;
public VectorQuantizer(final VQCodebook codebook) {
+ this.codebook = codebook;
this.codebookVectors = codebook.getVectors();
this.vectorSize = codebook.getVectors()[0].length;
- this.frequencies = codebook.getVectorFrequencies();
-
- // kdTree = new KDTreeBuilder(this.vectorSize, 8).buildTree(codebook.getVectors());
+ // kdTree = new KDTreeBuilder(this.vectorSize, 8).buildTree(codebook.getVectors());
}
public int[] quantize(final int[] dataVector) {
@@ -167,8 +166,8 @@ public class VectorQuantizer {
return codebookVectors;
}
- public long[] getFrequencies() {
- return frequencies;
+ public VQCodebook getCodebook() {
+ return codebook;
}
}