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

Refactor VQ decompression to remove duplicate code.

parent 94c922c9
Branches
No related tags found
No related merge requests found
...@@ -164,8 +164,12 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm ...@@ -164,8 +164,12 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
planeDataSizes[planeCounter++] = writeHuffmanEncodedIndices(compressStream, huffman, indices); planeDataSizes[planeCounter++] = writeHuffmanEncodedIndices(compressStream, huffman, indices);
stopwatch.stop(); stopwatch.stop();
reportProgressToListeners(planeIndex, planeIndices.length, if (options.isConsoleApplication()) {
"Finished compression of plane %d in %s.", planeIndex, stopwatch.getElapsedTimeString()); reportStatusToListeners("Finished compression of plane %d in %s.", planeIndex, stopwatch.getElapsedTimeString());
} else {
reportProgressToListeners(planeIndex, planeIndices.length,
"Finished compression of plane %d in %s.", planeIndex, stopwatch.getElapsedTimeString());
}
} }
return planeDataSizes; return planeDataSizes;
} }
......
...@@ -16,9 +16,12 @@ import java.io.DataInputStream; ...@@ -16,9 +16,12 @@ import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
@SuppressWarnings("DuplicatedCode")
public class VQImageDecompressor extends CompressorDecompressorBase implements IImageDecompressor { public class VQImageDecompressor extends CompressorDecompressorBase implements IImageDecompressor {
private interface DecompressCallback {
void process(final Block imageBlock, final int planeIndex) throws ImageDecompressionException;
}
private interface DecompressVoxelCallback { private interface DecompressVoxelCallback {
void process(final Voxel decompressedVoxel, void process(final Voxel decompressedVoxel,
final int[][] decompressedVoxelData, final int[][] decompressedVoxelData,
...@@ -67,9 +70,9 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I ...@@ -67,9 +70,9 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I
} }
private ImageU16 reconstructImageFromQuantizedVectors(final int[][] vectors, private Block reconstructImageFromQuantizedVectors(final int[][] vectors,
final V2i qVector, final V2i qVector,
final V3i imageDims) { final V3i imageDims) {
Block reconstructedChunk = new Block(new V2i(imageDims.getX(), imageDims.getY())); Block reconstructedChunk = new Block(new V2i(imageDims.getX(), imageDims.getY()));
if (qVector.getY() > 1) { if (qVector.getY() > 1) {
...@@ -78,7 +81,7 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I ...@@ -78,7 +81,7 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I
// 1D vector // 1D vector
reconstructedChunk.reconstructFromVectors(vectors); reconstructedChunk.reconstructFromVectors(vectors);
} }
return reconstructedChunk.asImageU16(); return reconstructedChunk;
} }
@Override @Override
...@@ -110,84 +113,19 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I ...@@ -110,84 +113,19 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I
decompressVoxels(compressedStream, decompressStream, header); decompressVoxels(compressedStream, decompressStream, header);
return; return;
} }
final int codebookSize = (int) Math.pow(2, header.getBitsPerCodebookIndex());
assert (header.getVectorSizeZ() == 1);
final int vectorSize = header.getVectorSizeX() * header.getVectorSizeY() * header.getVectorSizeZ();
final int planeCountForDecompression = header.getImageSizeZ();
final long planeVectorCount = calculatePlaneVectorCount(header);
//final long planeDataSize = calculatePlaneDataSize(planeVectorCount, header.getBitsPerPixel());
final V2i qVector = new V2i(header.getVectorSizeX(), header.getVectorSizeY());
final int[] huffmanSymbols = createHuffmanSymbols(codebookSize);
VQCodebook codebook = null;
Huffman huffman = null;
if (!header.isCodebookPerPlane()) {
// There is only one codebook.
reportStatusToListeners("Loading codebook from cache...");
codebook = readCodebook(compressedStream, codebookSize, vectorSize);
huffman = createHuffmanCoder(huffmanSymbols, codebook.getVectorFrequencies());
}
Stopwatch stopwatch = new Stopwatch();
for (int planeIndex = 0; planeIndex < planeCountForDecompression; planeIndex++) {
stopwatch.restart();
if (header.isCodebookPerPlane()) {
reportStatusToListeners("Loading plane codebook...");
codebook = readCodebook(compressedStream, codebookSize, vectorSize);
huffman = createHuffmanCoder(huffmanSymbols, codebook.getVectorFrequencies());
}
assert (codebook != null && huffman != null);
byte[] decompressedPlaneData = null;
final int planeDataSize = (int) header.getPlaneDataSizes()[planeIndex];
try (InBitStream inBitStream = new InBitStream(compressedStream,
header.getBitsPerCodebookIndex(),
planeDataSize)) {
inBitStream.readToBuffer();
inBitStream.setAllowReadFromUnderlyingStream(false);
int[][] decompressedVectors = new int[(int) planeVectorCount][vectorSize];
for (int vecIndex = 0; vecIndex < planeVectorCount; vecIndex++) {
final int huffmanSymbol = decodeHuffmanSymbol(huffman, inBitStream);
System.arraycopy(codebook.getVectors()[huffmanSymbol].getVector(),
0, decompressedVectors[vecIndex], 0, vectorSize);
}
final ImageU16 decompressedPlane = reconstructImageFromQuantizedVectors(decompressedVectors,
qVector,
header.getImageDims());
decompressedPlaneData =
TypeConverter.unsignedShortArrayToByteArray(decompressedPlane.getData(), false);
} catch (Exception ex) {
throw new ImageDecompressionException("VQImageDecompressor::decompress() - Unable to read indices from InBitStream.", ex);
}
decompressImpl(compressedStream, header, (imageBlock, planeIndex) -> {
try { try {
decompressStream.write(decompressedPlaneData); decompressStream.write(TypeConverter.unsignedShortArrayToByteArray(imageBlock.getData(), false));
} catch (IOException e) { } catch (IOException e) {
throw new ImageDecompressionException("Unable to write decompressed data to decompress stream.", e); throw new ImageDecompressionException("Unable to write decompressed data to decompress stream.", e);
} }
});
stopwatch.stop();
reportProgressToListeners(planeIndex, planeCountForDecompression,
"Decompressed plane %d in %s", planeIndex, stopwatch.getElapsedTimeString());
}
} }
public void decompressImpl(DataInputStream compressedStream,
@Override QCMPFileHeader header,
public void decompressToBuffer(DataInputStream compressedStream, DecompressCallback callback) throws ImageDecompressionException {
short[][] buffer,
QCMPFileHeader header) throws ImageDecompressionException {
if (header.getQuantizationType() == QuantizationType.Vector3D) {
decompressVoxelsToBuffer(compressedStream, buffer, header);
return;
}
// NOTE(Moravec): Think how to remove the duplicate code.
final int codebookSize = (int) Math.pow(2, header.getBitsPerCodebookIndex()); final int codebookSize = (int) Math.pow(2, header.getBitsPerCodebookIndex());
assert (header.getVectorSizeZ() == 1); assert (header.getVectorSizeZ() == 1);
final int vectorSize = header.getVectorSizeX() * header.getVectorSizeY() * header.getVectorSizeZ(); final int vectorSize = header.getVectorSizeX() * header.getVectorSizeY() * header.getVectorSizeZ();
...@@ -233,11 +171,11 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I ...@@ -233,11 +171,11 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I
} }
final ImageU16 decompressedPlane = reconstructImageFromQuantizedVectors(decompressedVectors, final Block decompressedPlane = reconstructImageFromQuantizedVectors(decompressedVectors,
qVector, qVector,
header.getImageDims()); header.getImageDims());
buffer[planeIndex] = TypeConverter.intArrayToShortArray(decompressedPlane.getData()); callback.process(decompressedPlane, planeIndex);
} catch (Exception ex) { } catch (Exception ex) {
throw new ImageDecompressionException("VQImageDecompressor::decompressToBuffer() - Unable to read indices from " + throw new ImageDecompressionException("VQImageDecompressor::decompressToBuffer() - Unable to read indices from " +
"InBitStream.", "InBitStream.",
...@@ -249,6 +187,20 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I ...@@ -249,6 +187,20 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I
} }
@Override
public void decompressToBuffer(DataInputStream compressedStream,
short[][] buffer,
QCMPFileHeader header) throws ImageDecompressionException {
if (header.getQuantizationType() == QuantizationType.Vector3D) {
decompressVoxelsToBuffer(compressedStream, buffer, header);
return;
}
decompressImpl(compressedStream, header, (imageBlock, planeIndex) -> {
buffer[planeIndex] = TypeConverter.intArrayToShortArray(imageBlock.getData());
});
}
private void decompressVoxelsImpl(DataInputStream compressedStream, private void decompressVoxelsImpl(DataInputStream compressedStream,
QCMPFileHeader header, QCMPFileHeader header,
DecompressVoxelCallback callback) throws ImageDecompressionException { DecompressVoxelCallback callback) throws ImageDecompressionException {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment