diff --git a/src/main/java/azgracompress/cache/VQCacheFile.java b/src/main/java/azgracompress/cache/VQCacheFile.java
index 3710810e63c48955d4aedd86464df9a256869ec8..986a22a035eae4c238c00e6e7697588cd2f5b9ee 100644
--- a/src/main/java/azgracompress/cache/VQCacheFile.java
+++ b/src/main/java/azgracompress/cache/VQCacheFile.java
@@ -1,6 +1,5 @@
package azgracompress.cache;
-import azgracompress.quantization.vector.CodebookEntry;
import azgracompress.quantization.vector.VQCodebook;
import java.io.DataInputStream;
@@ -23,9 +22,9 @@ public class VQCacheFile implements ICacheFile {
public void writeToStream(DataOutputStream outputStream) throws IOException {
header.writeToStream(outputStream);
- final CodebookEntry[] entries = codebook.getVectors();
- for (final CodebookEntry entry : entries) {
- for (final int vectorValue : entry.getVector()) {
+ final int[][] entries = codebook.getVectors();
+ for (final int[] entry : entries) {
+ for (final int vectorValue : entry) {
outputStream.writeShort(vectorValue);
}
}
@@ -45,16 +44,16 @@ public class VQCacheFile implements ICacheFile {
@Override
public void readFromStream(DataInputStream inputStream, CacheFileHeader header) throws IOException {
final int codebookSize = header.getCodebookSize();
- final CodebookEntry[] vectors = new CodebookEntry[codebookSize];
- final long[] frequencies = new long[codebookSize];
final int entrySize = header.getVectorSizeX() * header.getVectorSizeY() * header.getVectorSizeZ();
+ final int[][] vectors = new int[codebookSize][entrySize];
+ final long[] frequencies = new long[codebookSize];
+
for (int i = 0; i < codebookSize; i++) {
- int[] vector = new int[entrySize];
+ //int[] vector = new int[entrySize];
for (int j = 0; j < entrySize; j++) {
- vector[j] = inputStream.readUnsignedShort();
+ vectors[i][j] = inputStream.readUnsignedShort();
}
- vectors[i] = new CodebookEntry(vector);
}
for (int i = 0; i < codebookSize; i++) {
@@ -73,10 +72,12 @@ public class VQCacheFile implements ICacheFile {
@Override
public void report(StringBuilder builder) {
- final CodebookEntry[] vectors = codebook.getVectors();
- for (int i = 0; i < vectors.length; i++) {
+ final int[][] vectors = codebook.getVectors();
+ for (int[] vector : vectors) {
builder.append("- - - - - - - - - - - - - - - - - - - - - - - - -\n");
- vectors[i].getVectorString(builder);
+ for (final int x : vector) {
+ builder.append(x).append(';');
+ }
}
}
}
diff --git a/src/main/java/azgracompress/compression/VQImageCompressor.java b/src/main/java/azgracompress/compression/VQImageCompressor.java
index b32a93d272039b770bbfbdc2094085df45a116b5..670a9322c8c770300772dfeb1ed670b95c64221b 100644
--- a/src/main/java/azgracompress/compression/VQImageCompressor.java
+++ b/src/main/java/azgracompress/compression/VQImageCompressor.java
@@ -47,11 +47,10 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
*/
private void writeQuantizerToCompressStream(final VectorQuantizer quantizer,
DataOutputStream compressStream) throws ImageCompressionException {
- final CodebookEntry[] codebook = quantizer.getCodebookVectors();
+ final int[][] codebook = quantizer.getCodebookVectors();
try {
- for (final CodebookEntry entry : codebook) {
- final int[] entryVector = entry.getVector();
- for (final int vecVal : entryVector) {
+ for (final int[] entry : codebook) {
+ for (final int vecVal : entry) {
compressStream.writeShort(vecVal);
}
}
@@ -160,7 +159,7 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
assert (quantizer != null);
// Use BestBinFirst KDTree for codebook lookup.
-// final int[] indices = quantizer.quantizeIntoIndicesUsingKDTree(planeVectors, options.getWorkerCount());
+ // final int[] indices = quantizer.quantizeIntoIndicesUsingKDTree(planeVectors, options.getWorkerCount());
// Use BruteForce for codebook lookup.
final int[] indices = quantizer.quantizeIntoIndices(planeVectors, options.getWorkerCount());
diff --git a/src/main/java/azgracompress/compression/VQImageDecompressor.java b/src/main/java/azgracompress/compression/VQImageDecompressor.java
index 590fd413ad4699a5d5b45d967ce380000188fc3f..383dea0c4b6ea094497df08a70660a6e4fe1e566 100644
--- a/src/main/java/azgracompress/compression/VQImageDecompressor.java
+++ b/src/main/java/azgracompress/compression/VQImageDecompressor.java
@@ -7,7 +7,6 @@ import azgracompress.fileformat.QuantizationType;
import azgracompress.huffman.Huffman;
import azgracompress.huffman.HuffmanNode;
import azgracompress.io.InBitStream;
-import azgracompress.quantization.vector.CodebookEntry;
import azgracompress.quantization.vector.VQCodebook;
import azgracompress.utilities.Stopwatch;
import azgracompress.utilities.TypeConverter;
@@ -48,15 +47,14 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I
final int codebookSize,
final int vectorSize) throws ImageDecompressionException {
- final CodebookEntry[] codebookVectors = new CodebookEntry[codebookSize];
+ final int[][] codebookVectors = new int[codebookSize][vectorSize];
final long[] frequencies = new long[codebookSize];
try {
for (int codebookIndex = 0; codebookIndex < codebookSize; codebookIndex++) {
- final int[] vector = new int[vectorSize];
+ // final int[] vector = new int[vectorSize];
for (int vecIndex = 0; vecIndex < vectorSize; vecIndex++) {
- vector[vecIndex] = compressedStream.readUnsignedShort();
+ codebookVectors[codebookIndex][vecIndex] = compressedStream.readUnsignedShort();
}
- codebookVectors[codebookIndex] = new CodebookEntry(vector);
}
for (int codebookIndex = 0; codebookIndex < codebookSize; codebookIndex++) {
frequencies[codebookIndex] = compressedStream.readLong();
@@ -166,7 +164,7 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I
bit = inBitStream.readBit();
currentHuffmanNode = currentHuffmanNode.traverse(bit);
}
- System.arraycopy(codebook.getVectors()[currentHuffmanNode.getSymbol()].getVector(),
+ System.arraycopy(codebook.getVectors()[currentHuffmanNode.getSymbol()],
0, decompressedVectors[vecIndex], 0, vectorSize);
}
@@ -239,7 +237,7 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I
for (int voxelIndex = 0; voxelIndex < voxelLayerVoxelCount; voxelIndex++) {
final int huffmanSymbol = decodeHuffmanSymbol(huffman, inBitStream);
- System.arraycopy(codebook.getVectors()[huffmanSymbol].getVector(), 0, decompressedVoxels[voxelIndex], 0, vectorSize);
+ System.arraycopy(codebook.getVectors()[huffmanSymbol], 0, decompressedVoxels[voxelIndex], 0, vectorSize);
}
} catch (Exception e) {
diff --git a/src/main/java/azgracompress/quantization/vector/CodebookEntry.java b/src/main/java/azgracompress/quantization/vector/CodebookEntry.java
deleted file mode 100644
index 72cf8648d097fabca1b06a1a96bdf4dae46afc45..0000000000000000000000000000000000000000
--- a/src/main/java/azgracompress/quantization/vector/CodebookEntry.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package azgracompress.quantization.vector;
-
-public class CodebookEntry {
-
- final int[] vector;
- final int width;
- final int height;
-
- public CodebookEntry(final int[] codebook) {
-
- this.vector = codebook;
- this.width = codebook.length;
- this.height = 1;
- }
-
- @Override
- public boolean equals(final Object obj) {
- if (obj instanceof CodebookEntry) {
- final CodebookEntry ceObj = (CodebookEntry) obj;
- if (vector.length != ceObj.vector.length) {
- return false;
- }
- for (int i = 0; i < vector.length; i++) {
- if (vector[i] != ceObj.vector[i]) {
- return false;
- }
- }
- return true;
- }
- return super.equals(obj);
- }
-
- public int getWidth() {
- return width;
- }
-
- public int getHeight() {
- return height;
- }
-
- public int[] getVector() {
- return vector;
- }
-
- public String getVectorString(StringBuilder sb) {
- for (int i = 0; i < vector.length; i++) {
- sb.append(vector[i]);
- if (i != (vector.length - 1))
- sb.append(';');
- }
- sb.append('\n');
- return sb.toString();
- }
-
- public String getVectorString() {
- return getVectorString(new StringBuilder());
- }
-}
diff --git a/src/main/java/azgracompress/quantization/vector/LBGResult.java b/src/main/java/azgracompress/quantization/vector/LBGResult.java
index da4a27c5064defbe180639aff5e8c32a9f34e2d2..4b72a79698c4241f4447ac50314f54829553f49d 100644
--- a/src/main/java/azgracompress/quantization/vector/LBGResult.java
+++ b/src/main/java/azgracompress/quantization/vector/LBGResult.java
@@ -4,14 +4,14 @@ import azgracompress.data.V3i;
public class LBGResult {
- private final CodebookEntry[] codebookVectors;
+ private final int[][] codebookVectors;
private final long[] frequencies;
private final double averageMse;
private final double psnr;
private final V3i vectorDims;
public LBGResult(final V3i vectorDims,
- final CodebookEntry[] codebook,
+ final int[][] codebook,
final long[] frequencies,
final double averageMse,
final double psnr) {
diff --git a/src/main/java/azgracompress/quantization/vector/LBGVectorQuantizer.java b/src/main/java/azgracompress/quantization/vector/LBGVectorQuantizer.java
index b431e3f5659e745850e55dfdee8ea8e3c5cfa786..0ad49cfe228318c31965150924253292089dda80 100644
--- a/src/main/java/azgracompress/quantization/vector/LBGVectorQuantizer.java
+++ b/src/main/java/azgracompress/quantization/vector/LBGVectorQuantizer.java
@@ -92,13 +92,12 @@ public class LBGVectorQuantizer {
assert (uniqueTrainingVectors != null) : "uniqueTrainingVectors aren't initialized.";
reportStatus("There is only %d unique vectors. Creating codebook from unique vectors...",
uniqueTrainingVectors.size());
- CodebookEntry[] codebook = new CodebookEntry[codebookSize];
- int[] zeros = new int[vectorSize];
- Arrays.fill(zeros, 0);
- CodebookEntry zeroEntry = new CodebookEntry(zeros);
+ final int[][] codebook = new int[codebookSize][vectorSize];
+ int[] zeroEntry = new int[vectorSize];
+ Arrays.fill(zeroEntry, 0);
for (int i = 0; i < codebookSize; i++) {
if (i < uniqueVectorCount) {
- codebook[i] = new CodebookEntry(uniqueTrainingVectors.get(i).getVector());
+ codebook[i] = uniqueTrainingVectors.get(i).getVector();
} else {
codebook[i] = zeroEntry;
}
@@ -141,10 +140,10 @@ public class LBGVectorQuantizer {
* @param learningCodebook Source array of LearningCodebookEntry.
* @return Array of CodebookEntries.
*/
- private CodebookEntry[] learningCodebookToCodebook(final LearningCodebookEntry[] learningCodebook) {
- CodebookEntry[] codebook = new CodebookEntry[learningCodebook.length];
+ private int[][] learningCodebookToCodebook(final LearningCodebookEntry[] learningCodebook) {
+ final int[][] codebook = new int[learningCodebook.length][vectorSize];
for (int i = 0; i < codebook.length; i++) {
- codebook[i] = new CodebookEntry(learningCodebook[i].getVector());
+ codebook[i] = learningCodebook[i].getVector();
}
return codebook;
}
@@ -168,14 +167,17 @@ public class LBGVectorQuantizer {
}
}
+ private double averageMse(final LearningCodebookEntry[] codebook) {
+ return averageMse(learningCodebookToCodebook(codebook));
+ }
+
/**
* Calculate the average mean square error of the codebook.
*
* @param codebook Codebook of vectors.
* @return Mean square error.
*/
- private double averageMse(final CodebookEntry[] codebook) {
- Stopwatch s = Stopwatch.startNew("averageMse");
+ private double averageMse(final int[][] codebook) {
double mse = 0.0;
resetFrequencies();
if (workerCount > 1) {
@@ -202,7 +204,8 @@ public class LBGVectorQuantizer {
qIndex = quantizer.quantizeToIndex(vector);
++workerFrequencies[qIndex];
- qVector = quantizer.getCodebookVectors()[qIndex].getVector();
+
+ qVector = quantizer.getCodebookVectors()[qIndex];
for (int vI = 0; vI < vectorSize; vI++) {
threadMse += Math.pow(((double) vector[vI] - (double) qVector[vI]), 2);
}
@@ -233,7 +236,7 @@ public class LBGVectorQuantizer {
int[] qVector;
for (final TrainingVector trV : trainingVectors) {
qIndex = quantizer.quantizeToIndex(trV.getVector());
- qVector = quantizer.getCodebookVectors()[qIndex].getVector();
+ qVector = quantizer.getCodebookVectors()[qIndex];
++frequencies[qIndex];
for (int i = 0; i < vectorSize; i++) {
mse += Math.pow(((double) trV.getVector()[i] - (double) qVector[i]), 2);
@@ -241,10 +244,6 @@ public class LBGVectorQuantizer {
}
mse /= (double) trainingVectors.length;
}
- s.stop();
- // if (this.verbose) {
- //// System.out.println(s);
- // }
return mse;
}
diff --git a/src/main/java/azgracompress/quantization/vector/LearningCodebookEntry.java b/src/main/java/azgracompress/quantization/vector/LearningCodebookEntry.java
index 30cbee3d2bb3fe687d889b1e9d9b866906d86bfd..4492e4c90d83658d9512a16e341660bd887e4117 100644
--- a/src/main/java/azgracompress/quantization/vector/LearningCodebookEntry.java
+++ b/src/main/java/azgracompress/quantization/vector/LearningCodebookEntry.java
@@ -1,31 +1,36 @@
package azgracompress.quantization.vector;
-public class LearningCodebookEntry extends CodebookEntry {
+public class LearningCodebookEntry {
+ private final int[] codebookVector;
private int vectorCount = -1;
private double averageDistortion = -1.0f;
private double[] perturbationVector;
- public LearningCodebookEntry(int[] codebook) {
- super(codebook);
+ public LearningCodebookEntry(int[] codebookVector) {
+ this.codebookVector = codebookVector;
}
/**
* Set codebook entry properties from helper object.
*
- * @param info Helper object with property informations.
+ * @param info Helper object with property information.
*/
public void setInfo(final EntryInfo info) {
this.vectorCount = info.vectorCount;
this.averageDistortion = info.calculateAverageDistortion();
final int[] newCentroid = info.calculateCentroid();
- assert (newCentroid.length == vector.length);
- System.arraycopy(newCentroid, 0, this.vector, 0, newCentroid.length);
+ assert (newCentroid.length == codebookVector.length);
+ System.arraycopy(newCentroid, 0, this.codebookVector, 0, newCentroid.length);
this.perturbationVector = info.calculatePRTVector();
}
+ public int[] getVector() {
+ return codebookVector;
+ }
+
/**
* Get perturbation vector for splitting this entry.
*
diff --git a/src/main/java/azgracompress/quantization/vector/VQCodebook.java b/src/main/java/azgracompress/quantization/vector/VQCodebook.java
index 1afb8d2274d81aa703df336b0ce86c18e86e2dcf..d56fc6b3d611d92f5493fb64ca2119b6e7e1f17f 100644
--- a/src/main/java/azgracompress/quantization/vector/VQCodebook.java
+++ b/src/main/java/azgracompress/quantization/vector/VQCodebook.java
@@ -9,7 +9,7 @@ public class VQCodebook {
/**
* Quantization vectors.
*/
- private final CodebookEntry[] vectors;
+ private final int[][] vectors;
/**
* Absolute frequencies of quantization vectors.
@@ -26,7 +26,7 @@ public class VQCodebook {
*/
private final V3i vectorDims;
- public VQCodebook(final V3i vectorDims, final CodebookEntry[] vectors, final long[] vectorFrequencies) {
+ public VQCodebook(final V3i vectorDims, final int[][] vectors, final long[] vectorFrequencies) {
//assert (vectors.length == vectorFrequencies.length);
this.vectorDims = vectorDims;
this.vectors = vectors;
@@ -39,20 +39,10 @@ public class VQCodebook {
*
* @return Quantization vectors.
*/
- public CodebookEntry[] getVectors() {
+ public int[][] getVectors() {
return vectors;
}
- public int[][] getRawVectors() {
- assert (codebookSize == vectors.length);
- assert (vectors[0].getVector().length == (int) vectorDims.multiplyTogether());
- final int[][] rawCodebook = new int[vectors.length][(int) vectorDims.multiplyTogether()];
- for (int i = 0; i < codebookSize; i++) {
- rawCodebook[i] = vectors[i].getVector();
- }
- return rawCodebook;
- }
-
/**
* Get frequencies of codebook vectors at indices.
*
diff --git a/src/main/java/azgracompress/quantization/vector/VectorQuantizer.java b/src/main/java/azgracompress/quantization/vector/VectorQuantizer.java
index 4fcc8caa6eb4d1b9f53f6989c58c305325091627..efca6ebb9b8bfd27a0c1afb205ebcfbaf9e87469 100644
--- a/src/main/java/azgracompress/quantization/vector/VectorQuantizer.java
+++ b/src/main/java/azgracompress/quantization/vector/VectorQuantizer.java
@@ -11,7 +11,7 @@ public class VectorQuantizer {
}
private final VectorDistanceMetric metric = VectorDistanceMetric.Euclidean;
- private final CodebookEntry[] codebookVectors;
+ private final int[][] codebookVectors;
private final int vectorSize;
private final long[] frequencies;
@@ -19,16 +19,15 @@ public class VectorQuantizer {
public VectorQuantizer(final VQCodebook codebook) {
this.codebookVectors = codebook.getVectors();
- this.vectorSize = codebookVectors[0].getVector().length;
+ this.vectorSize = codebook.getVectors()[0].length;
this.frequencies = codebook.getVectorFrequencies();
- kdTree = new KDTreeBuilder(this.vectorSize, 8).buildTree(codebook.getRawVectors());
+ kdTree = new KDTreeBuilder(this.vectorSize, 8).buildTree(codebook.getVectors());
}
public int[] quantize(final int[] dataVector) {
assert (dataVector.length > 0 && dataVector.length % vectorSize == 0) : "Wrong vector size";
- final CodebookEntry closestEntry = findClosestCodebookEntry(dataVector, metric);
- return closestEntry.getVector();
+ return findClosestCodebookEntry(dataVector, metric);
}
public int quantizeToIndex(final int[] dataVector) {
@@ -42,13 +41,12 @@ public class VectorQuantizer {
if (workerCount == 1) {
for (int vectorIndex = 0; vectorIndex < dataVectors.length; vectorIndex++) {
- final CodebookEntry closestEntry = findClosestCodebookEntry(dataVectors[vectorIndex], metric);
- result[vectorIndex] = closestEntry.getVector();
+ result[vectorIndex] = findClosestCodebookEntry(dataVectors[vectorIndex], metric);
}
} else {
final int[] indices = quantizeIntoIndices(dataVectors, workerCount);
for (int i = 0; i < dataVectors.length; i++) {
- result[i] = codebookVectors[indices[i]].getVector();
+ result[i] = codebookVectors[indices[i]];
}
}
@@ -142,11 +140,11 @@ public class VectorQuantizer {
return 0.0;
}
- private CodebookEntry findClosestCodebookEntry(final int[] dataVector) {
+ private int[] findClosestCodebookEntry(final int[] dataVector) {
return findClosestCodebookEntry(dataVector, metric);
}
- private CodebookEntry findClosestCodebookEntry(final int[] dataVector, final VectorDistanceMetric metric) {
+ private int[] findClosestCodebookEntry(final int[] dataVector, final VectorDistanceMetric metric) {
return codebookVectors[findClosestCodebookEntryIndex(dataVector, metric)];
}
@@ -156,7 +154,7 @@ public class VectorQuantizer {
for (int entryIndex = 0; entryIndex < codebookVectors.length; entryIndex++) {
- final double dist = distanceBetweenVectors(dataVector, codebookVectors[entryIndex].getVector(), metric);
+ final double dist = distanceBetweenVectors(dataVector, codebookVectors[entryIndex], metric);
if (dist < minDist) {
minDist = dist;
closestEntryIndex = entryIndex;
@@ -166,7 +164,7 @@ public class VectorQuantizer {
return closestEntryIndex;
}
- public CodebookEntry[] getCodebookVectors() {
+ public int[][] getCodebookVectors() {
return codebookVectors;
}