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

Enable new loading in all places.

This commit removes old methods from Chunk2D, which forced the change to
the new IPlaneLoader API. We have also added new default functions which
can load all three types of vectors from specified plane range.
parent 9aa915a5
Branches
No related tags found
No related merge requests found
package azgracompress.benchmark; package azgracompress.benchmark;
import azgracompress.U16;
import azgracompress.cache.QuantizationCacheManager;
import azgracompress.cli.ParsedCliOptions; import azgracompress.cli.ParsedCliOptions;
import azgracompress.compression.CompressionOptions; import azgracompress.data.Chunk2D;
import azgracompress.data.*; import azgracompress.data.ImageU16;
import azgracompress.io.loader.IPlaneLoader; import azgracompress.data.V2i;
import azgracompress.io.loader.PlaneLoaderFactory; import azgracompress.data.V3i;
import azgracompress.quantization.vector.LBGResult;
import azgracompress.quantization.vector.LBGVectorQuantizer;
import azgracompress.quantization.vector.VQCodebook;
import azgracompress.quantization.vector.VectorQuantizer;
import azgracompress.utilities.Utils;
import java.io.File;
import java.io.IOException;
public class VQBenchmark extends BenchmarkBase { public class VQBenchmark extends BenchmarkBase {
final static V2i DEFAULT_QVECTOR = new V2i(3, 3);
public VQBenchmark(final ParsedCliOptions options) { public VQBenchmark(final ParsedCliOptions options) {
super(options); super(options);
} }
@Override @Override
public void startBenchmark() { public void startBenchmark() {
startBenchmark(DEFAULT_QVECTOR); startBenchmark(options.getQuantizationVector());
} }
private ImageU16 reconstructImageFromQuantizedVectors(final ImageU16 plane, private ImageU16 reconstructImageFromQuantizedVectors(final int[][] vectors,
final int[][] vectors,
final V2i qVector) { final V2i qVector) {
Chunk2D reconstructedChunk = new Chunk2D(new V2i(rawImageDims.getX(), rawImageDims.getY())); Chunk2D reconstructedChunk = new Chunk2D(new V2i(rawImageDims.getX(), rawImageDims.getY()));
if (qVector.getY() > 1) { if (qVector.getY() > 1) {
...@@ -42,111 +29,98 @@ public class VQBenchmark extends BenchmarkBase { ...@@ -42,111 +29,98 @@ public class VQBenchmark extends BenchmarkBase {
return reconstructedChunk.asImageU16(); return reconstructedChunk.asImageU16();
} }
private int[][] getPlaneVectors(final ImageU16 plane, final V2i qVector) { public void startBenchmark(final V3i qVector) {
return plane.toQuantizationVectors(qVector); // NOTE(Moravec): This will be enabled once we need to benchmark something.
} // if (planes.length < 1) {
// return;
public void startBenchmark(final V2i qVector) { // }
if (planes.length < 1) { // IPlaneLoader planeLoader;
return; // try {
} // planeLoader = PlaneLoaderFactory.getPlaneLoaderForInputFile(options.getInputDataInfo());
IPlaneLoader planeLoader; // } catch (Exception e) {
try { // e.printStackTrace();
planeLoader = PlaneLoaderFactory.getPlaneLoaderForInputFile(options.getInputDataInfo()); // System.err.println("Unable to create specific reader.");
} catch (Exception e) { // return;
e.printStackTrace(); // }
System.err.println("Unable to create SCIFIO reader."); // if (qVector.getY() > 1) {
return; // System.out.println("2D qVector");
} // } else {
if (qVector.getY() > 1) { // System.out.println("1D qVector");
System.out.println("2D qVector"); // }
} else { // boolean dirCreated = new File(this.outputDirectory).mkdirs();
System.out.println("1D qVector"); // System.out.printf("|CODEBOOK| = %d%n", codebookSize);
} // VectorQuantizer quantizer = null;
boolean dirCreated = new File(this.outputDirectory).mkdirs(); //
System.out.println(String.format("|CODEBOOK| = %d", codebookSize)); // if (options.getCodebookType() == CompressionOptions.CodebookType.Global) {
VectorQuantizer quantizer = null; // System.out.println("Loading codebook from cache");
// QuantizationCacheManager cacheManager = new QuantizationCacheManager(cacheFolder);
if (options.getCodebookType() == CompressionOptions.CodebookType.Global) { // final VQCodebook codebook = cacheManager.loadVQCodebook(inputFile, codebookSize, qVector);
System.out.println("Loading codebook from cache"); // if (codebook == null) {
QuantizationCacheManager cacheManager = new QuantizationCacheManager(cacheFolder); // System.err.println("Failed to read quantization vectors from cache.");
final VQCodebook codebook = cacheManager.loadVQCodebook(inputFile, codebookSize, qVector.toV3i()); // return;
if (codebook == null) { // }
System.err.println("Failed to read quantization vectors from cache."); // quantizer = new VectorQuantizer(codebook);
return; // System.out.println("Created quantizer from cache");
} //
quantizer = new VectorQuantizer(codebook); // } else if (options.getCodebookType() == CompressionOptions.CodebookType.MiddlePlane) {
System.out.println("Created quantizer from cache"); // final int middlePlaneIndex = rawImageDims.getZ() / 2;
// int[][] refPlaneData;
} else if (options.getCodebookType() == CompressionOptions.CodebookType.MiddlePlane) { // try {
final int middlePlaneIndex = rawImageDims.getZ() / 2; // refPlaneData = planeLoader.loadVectorsFromPlaneRange(options, Utils.singlePlaneRange(middlePlaneIndex));
final ImageU16 middlePlane; // } catch (ImageCompressionException e) {
try { // e.printStackTrace();
// System.err.println("Failed to load middle plane data.");
middlePlane = new ImageU16(options.getInputDataInfo().getDimensions().toV2i(), planeLoader.loadPlaneData(middlePlaneIndex)); // return;
} catch (IOException e) { // }
e.printStackTrace(); //
System.err.println("Failed to load middle plane data."); // LBGVectorQuantizer vqInitializer = new LBGVectorQuantizer(refPlaneData, codebookSize, workerCount, qVector);
return; // final LBGResult vqResult = vqInitializer.findOptimalCodebook();
} //
// quantizer = new VectorQuantizer(vqResult.getCodebook());
final int[][] refPlaneData = getPlaneVectors(middlePlane, qVector); // System.out.println("Created quantizer from middle plane.");
LBGVectorQuantizer vqInitializer = new LBGVectorQuantizer(refPlaneData, // }
codebookSize, //
workerCount, // for (final int planeIndex : planes) {
qVector.toV3i()); // System.out.printf("Loading plane %d ...%n", planeIndex);
final LBGResult vqResult = vqInitializer.findOptimalCodebook(); //
quantizer = new VectorQuantizer(vqResult.getCodebook()); // int[][] planeData;
System.out.println("Created quantizer from middle plane."); // try {
} // planeData = planeLoader.loadVectorsFromPlaneRange(options, Utils.singlePlaneRange(planeIndex));
// } catch (ImageCompressionException e) {
for (final int planeIndex : planes) { // e.printStackTrace();
System.out.println(String.format("Loading plane %d ...", planeIndex)); // System.err.printf("Failed to load plane %d data.", planeIndex);
// return;
final ImageU16 plane; // }
try { //
plane = new ImageU16(options.getInputDataInfo().getDimensions().toV2i(), planeLoader.loadPlaneData(planeIndex)); //
} catch (IOException e) { // if (options.getCodebookType() == CompressionOptions.CodebookType.Individual) {
e.printStackTrace(); // LBGVectorQuantizer vqInitializer = new LBGVectorQuantizer(planeData, codebookSize, workerCount, qVector);
System.err.println(String.format("Failed to load plane %d data. Skipping plane.", planeIndex)); // LBGResult vqResult = vqInitializer.findOptimalCodebook();
return; // quantizer = new VectorQuantizer(vqResult.getCodebook());
} // System.out.println("Created plane quantizer.");
// }
final int[][] planeData = getPlaneVectors(plane, qVector); //
// final String quantizedFile = String.format(QUANTIZED_FILE_TEMPLATE, planeIndex, codebookSize);
// final String diffFile = String.format(DIFFERENCE_FILE_TEMPLATE, planeIndex, codebookSize);
if (options.getCodebookType() == CompressionOptions.CodebookType.Individual) { // final String absoluteDiffFile = String.format(ABSOLUTE_DIFFERENCE_FILE_TEMPLATE, planeIndex, codebookSize);
LBGVectorQuantizer vqInitializer = new LBGVectorQuantizer(planeData, //
codebookSize, // assert (quantizer != null);
workerCount, // final int[][] quantizedData = quantizer.quantize(planeData, workerCount);
qVector.toV3i()); //
LBGResult vqResult = vqInitializer.findOptimalCodebook(); // final ImageU16 quantizedImage = reconstructImageFromQuantizedVectors(quantizedData, qVector.toV2i());
quantizer = new VectorQuantizer(vqResult.getCodebook()); //
System.out.println("Created plane quantizer."); //
} // final int[] diffArray = Utils.getDifference(plane.getData(), quantizedImage.getData());
// final double mse = Utils.calculateMse(diffArray);
final String quantizedFile = String.format(QUANTIZED_FILE_TEMPLATE, planeIndex, codebookSize); // final double PSNR = Utils.calculatePsnr(mse, U16.Max);
final String diffFile = String.format(DIFFERENCE_FILE_TEMPLATE, planeIndex, codebookSize); // System.out.printf("MSE: %.4f\tPSNR: %.4f(dB)%n", mse, PSNR);
final String absoluteDiffFile = String.format(ABSOLUTE_DIFFERENCE_FILE_TEMPLATE, //
planeIndex, // if (!saveQuantizedPlaneData(quantizedImage.getData(), quantizedFile)) {
codebookSize); // System.err.println("Failed to save quantized plane.");
// return;
final int[][] quantizedData = quantizer.quantize(planeData, workerCount); // }
//
final ImageU16 quantizedImage = reconstructImageFromQuantizedVectors(plane, quantizedData, qVector); // saveDifference(diffArray, diffFile, absoluteDiffFile);
// }
final int[] diffArray = Utils.getDifference(plane.getData(), quantizedImage.getData());
final double mse = Utils.calculateMse(diffArray);
final double PSNR = Utils.calculatePsnr(mse, U16.Max);
System.out.println(String.format("MSE: %.4f\tPSNR: %.4f(dB)", mse, PSNR));
if (!saveQuantizedPlaneData(quantizedImage.getData(), quantizedFile)) {
System.err.println("Failed to save quantized plane.");
return;
}
saveDifference(diffArray, diffFile, absoluteDiffFile);
}
} }
} }
...@@ -2,8 +2,6 @@ package azgracompress.compression; ...@@ -2,8 +2,6 @@ package azgracompress.compression;
import azgracompress.cache.QuantizationCacheManager; import azgracompress.cache.QuantizationCacheManager;
import azgracompress.compression.exception.ImageCompressionException; import azgracompress.compression.exception.ImageCompressionException;
import azgracompress.data.Chunk2D;
import azgracompress.data.ImageU16;
import azgracompress.data.Range; import azgracompress.data.Range;
import azgracompress.fileformat.QuantizationType; import azgracompress.fileformat.QuantizationType;
import azgracompress.huffman.Huffman; import azgracompress.huffman.Huffman;
...@@ -12,6 +10,7 @@ import azgracompress.io.loader.IPlaneLoader; ...@@ -12,6 +10,7 @@ import azgracompress.io.loader.IPlaneLoader;
import azgracompress.io.loader.PlaneLoaderFactory; import azgracompress.io.loader.PlaneLoaderFactory;
import azgracompress.quantization.vector.*; import azgracompress.quantization.vector.*;
import azgracompress.utilities.Stopwatch; import azgracompress.utilities.Stopwatch;
import azgracompress.utilities.Utils;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.io.DataOutputStream; import java.io.DataOutputStream;
...@@ -32,9 +31,9 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm ...@@ -32,9 +31,9 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
private VectorQuantizer trainVectorQuantizerFromPlaneVectors(final int[][] planeVectors) { private VectorQuantizer trainVectorQuantizerFromPlaneVectors(final int[][] planeVectors) {
LBGVectorQuantizer vqInitializer = new LBGVectorQuantizer(planeVectors, LBGVectorQuantizer vqInitializer = new LBGVectorQuantizer(planeVectors,
getCodebookSize(), getCodebookSize(),
options.getWorkerCount(), options.getWorkerCount(),
options.getQuantizationVector()); options.getQuantizationVector());
LBGResult vqResult = vqInitializer.findOptimalCodebook(); LBGResult vqResult = vqInitializer.findOptimalCodebook();
return new VectorQuantizer(vqResult.getCodebook()); return new VectorQuantizer(vqResult.getCodebook());
} }
...@@ -79,14 +78,14 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm ...@@ -79,14 +78,14 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
QuantizationCacheManager cacheManager = new QuantizationCacheManager(options.getCodebookCacheFolder()); QuantizationCacheManager cacheManager = new QuantizationCacheManager(options.getCodebookCacheFolder());
if (!cacheManager.doesVQCacheExists(options.getInputDataInfo().getCacheFileName(), if (!cacheManager.doesVQCacheExists(options.getInputDataInfo().getCacheFileName(),
getCodebookSize(), getCodebookSize(),
options.getQuantizationVector())) { options.getQuantizationVector())) {
trainAndSaveCodebook(); trainAndSaveCodebook();
} }
final VQCodebook codebook = cacheManager.loadVQCodebook(options.getInputDataInfo().getCacheFileName(), final VQCodebook codebook = cacheManager.loadVQCodebook(options.getInputDataInfo().getCacheFileName(),
getCodebookSize(), getCodebookSize(),
options.getQuantizationVector()); options.getQuantizationVector());
if (codebook == null) { if (codebook == null) {
throw new ImageCompressionException("Failed to read quantization vectors from cache."); throw new ImageCompressionException("Failed to read quantization vectors from cache.");
...@@ -132,17 +131,8 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm ...@@ -132,17 +131,8 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
writeQuantizerToCompressStream(quantizer, compressStream); writeQuantizerToCompressStream(quantizer, compressStream);
} else if (options.getCodebookType() == CompressionOptions.CodebookType.MiddlePlane) { } else if (options.getCodebookType() == CompressionOptions.CodebookType.MiddlePlane) {
stopwatch.restart(); stopwatch.restart();
reportStatusToListeners("Training vector quantizer from middle plane.");
final int middlePlaneIndex = getMiddlePlaneIndex(); final int[][] refPlaneVectors = planeLoader.loadVectorsFromPlaneRange(options, Utils.singlePlaneRange(getMiddlePlaneIndex()));
ImageU16 middlePlane = null;
try {
middlePlane = new ImageU16(options.getInputDataInfo().getDimensions().toV2i(), planeLoader.loadPlaneData(middlePlaneIndex));
} catch (IOException ex) {
throw new ImageCompressionException("Unable to load reference plane data.", ex);
}
reportStatusToListeners(String.format("Training vector quantizer from middle plane %d.", middlePlaneIndex));
final int[][] refPlaneVectors = middlePlane.toQuantizationVectors(options.getQuantizationVector().toV2i());
quantizer = trainVectorQuantizerFromPlaneVectors(refPlaneVectors); quantizer = trainVectorQuantizerFromPlaneVectors(refPlaneVectors);
huffman = createHuffmanCoder(huffmanSymbols, quantizer.getFrequencies()); huffman = createHuffmanCoder(huffmanSymbols, quantizer.getFrequencies());
writeQuantizerToCompressStream(quantizer, compressStream); writeQuantizerToCompressStream(quantizer, compressStream);
...@@ -158,14 +148,7 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm ...@@ -158,14 +148,7 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
stopwatch.restart(); stopwatch.restart();
reportStatusToListeners(String.format("Loading plane %d.", planeIndex)); reportStatusToListeners(String.format("Loading plane %d.", planeIndex));
ImageU16 plane = null; final int[][] planeVectors = planeLoader.loadVectorsFromPlaneRange(options, Utils.singlePlaneRange(planeIndex));
try {
plane = new ImageU16(options.getInputDataInfo().getDimensions().toV2i(), planeLoader.loadPlaneData(planeIndex));
} catch (IOException ex) {
throw new ImageCompressionException("Unable to load plane data.", ex);
}
final int[][] planeVectors = plane.toQuantizationVectors(options.getQuantizationVector().toV2i());
if (!hasGeneralQuantizer) { if (!hasGeneralQuantizer) {
reportStatusToListeners(String.format("Training vector quantizer from plane %d.", planeIndex)); reportStatusToListeners(String.format("Training vector quantizer from plane %d.", planeIndex));
...@@ -182,99 +165,41 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm ...@@ -182,99 +165,41 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
stopwatch.stop(); stopwatch.stop();
reportProgressToListeners(planeIndex, planeIndices.length, reportProgressToListeners(planeIndex, planeIndices.length,
"Finished compression of plane %d in %s.", planeIndex, stopwatch.getElapsedTimeString()); "Finished compression of plane %d in %s.", planeIndex, stopwatch.getElapsedTimeString());
} }
return planeDataSizes; return planeDataSizes;
} }
@Override
/** public void trainAndSaveCodebook() throws ImageCompressionException {
* Load plane and convert the plane into quantization vectors. reportStatusToListeners("Loading image data...");
*
* @param planeIndex Zero based plane index.
* @return Quantization vectors of configured quantization.
* @throws IOException When reading fails.
*/
private int[][] loadPlaneQuantizationVectors(final IPlaneLoader planeLoader,
final int planeIndex) throws IOException {
ImageU16 refPlane = new ImageU16(options.getInputDataInfo().getDimensions().toV2i(), planeLoader.loadPlaneData(planeIndex));
return refPlane.toQuantizationVectors(options.getQuantizationVector().toV2i());
}
private int[][] loadConfiguredPlanesData() throws ImageCompressionException {
final IPlaneLoader planeLoader; final IPlaneLoader planeLoader;
try { try {
planeLoader = PlaneLoaderFactory.getPlaneLoaderForInputFile(options.getInputDataInfo()); planeLoader = PlaneLoaderFactory.getPlaneLoaderForInputFile(options.getInputDataInfo());
planeLoader.setWorkerCount(options.getWorkerCount());
} catch (Exception e) { } catch (Exception e) {
throw new ImageCompressionException("Unable to create reader. " + e.getMessage()); throw new ImageCompressionException("Unable to create plane reader. " + e.getMessage());
} }
if (options.getQuantizationType().isOneOf(QuantizationType.Vector1D, QuantizationType.Vector2D)) {
// TODO: Chunk2D operations should eventually be moved to loaders.
// Same as voxel loading, so that we wouldn't have to copy data twice.
final int vectorSize = options.getQuantizationVector().toV2i().multiplyTogether();
int[][] trainData;
Stopwatch s = Stopwatch.startNew();
if (options.getInputDataInfo().isPlaneIndexSet()) {
reportStatusToListeners("VQ: Loading single plane data.");
try {
trainData = loadPlaneQuantizationVectors(planeLoader, options.getInputDataInfo().getPlaneIndex());
} catch (IOException e) {
throw new ImageCompressionException("Failed to load plane data.", e);
}
} else {
reportStatusToListeners(options.getInputDataInfo().isPlaneRangeSet() ?
"VQ: Loading plane range data." : "VQ: Loading all planes data.");
final int[] planeIndices = getPlaneIndicesForCompression();
final int chunkCountPerPlane = Chunk2D.calculateRequiredChunkCount(options.getInputDataInfo().getDimensions().toV2i(),
options.getQuantizationVector().toV2i());
final int totalChunkCount = chunkCountPerPlane * planeIndices.length;
trainData = new int[totalChunkCount][vectorSize];
int[][] planeVectors;
int planeCounter = 0;
for (final int planeIndex : planeIndices) {
try {
planeVectors = loadPlaneQuantizationVectors(planeLoader, planeIndex);
assert (planeVectors.length == chunkCountPerPlane) : "Wrong chunk count per plane";
} catch (IOException e) {
throw new ImageCompressionException(String.format("Failed to load plane %d image data.", planeIndex), e);
}
System.arraycopy(planeVectors, 0, trainData, (planeCounter * chunkCountPerPlane), chunkCountPerPlane);
++planeCounter;
}
}
s.stop();
reportStatusToListeners("Quantization vector load took: " + s.getElapsedTimeString());
return trainData;
} else {
if (options.getQuantizationType() != QuantizationType.Vector3D) {
throw new ImageCompressionException("Invalid QuantizationType, expected: `QuantizationType.Vector3D`, but got: " +
options.getQuantizationType().toString());
}
try { int[][] trainingData;
return planeLoader.loadVoxels(options.getQuantizationVector()); if (options.getInputDataInfo().isPlaneIndexSet()) {
} catch (IOException e) { reportStatusToListeners("VQ: Loading single plane data.");
throw new ImageCompressionException("Unable to load voxels.", e); final int planeIndex = options.getInputDataInfo().getPlaneIndex();
} trainingData = planeLoader.loadVectorsFromPlaneRange(options, new Range<>(planeIndex, planeIndex + 1));
} else if (options.getInputDataInfo().isPlaneRangeSet()) {
reportStatusToListeners("VQ: Loading plane range data.");
trainingData = planeLoader.loadVectorsFromPlaneRange(options, options.getInputDataInfo().getPlaneRange());
} else {
reportStatusToListeners("VQ: Loading all planes data.");
trainingData = planeLoader.loadVectorsFromPlaneRange(options,
new Range<>(0, options.getInputDataInfo().getDimensions().getZ()));
} }
}
@Override
public void trainAndSaveCodebook() throws ImageCompressionException {
reportStatusToListeners("Loading image data...");
final int[][] trainingData = loadConfiguredPlanesData();
LBGVectorQuantizer vqInitializer = new LBGVectorQuantizer(trainingData, LBGVectorQuantizer vqInitializer = new LBGVectorQuantizer(trainingData,
getCodebookSize(), getCodebookSize(),
options.getWorkerCount(), options.getWorkerCount(),
options.getQuantizationVector()); options.getQuantizationVector());
reportStatusToListeners("Starting LBG optimization."); reportStatusToListeners("Starting LBG optimization.");
vqInitializer.setStatusListener(this::reportStatusToListeners); vqInitializer.setStatusListener(this::reportStatusToListeners);
...@@ -348,8 +273,8 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm ...@@ -348,8 +273,8 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
voxelLayersSizes[voxelLayerIndex] = writeHuffmanEncodedIndices(compressStream, huffman, indices); voxelLayersSizes[voxelLayerIndex] = writeHuffmanEncodedIndices(compressStream, huffman, indices);
stopwatch.stop(); stopwatch.stop();
reportProgressToListeners(voxelLayerIndex, voxelLayerCount, reportProgressToListeners(voxelLayerIndex, voxelLayerCount,
"%d/%d Finished voxel layer %s compression pass in %s", "%d/%d Finished voxel layer %s compression pass in %s",
voxelLayerIndex, voxelLayerCount, voxelLayerRange.toString(), stopwatch.getElapsedTimeString()); voxelLayerIndex, voxelLayerCount, voxelLayerRange.toString(), stopwatch.getElapsedTimeString());
} }
return voxelLayersSizes; return voxelLayersSizes;
......
...@@ -70,32 +70,6 @@ public class Chunk2D { ...@@ -70,32 +70,6 @@ public class Chunk2D {
return String.format("2D shape %s %d values", dims.toString(), data.length); return String.format("2D shape %s %d values", dims.toString(), data.length);
} }
/**
* Divide this Chunk to 1D row vector of given length.
*
* @param vectorSize Vector length.
* @return Array of row vectors.
*/
public int[][] divideInto1DVectors(final int vectorSize) {
final int rowVectorCount = (int) Math.ceil(dims.getX() / (float) vectorSize);
final int vectorCount = rowVectorCount * dims.getY();
int[][] imageVectors = new int[vectorCount][vectorSize];
int vec = 0;
int srcX;
for (int row = 0; row < dims.getY(); row++) {
for (int vecIndex = 0; vecIndex < rowVectorCount; vecIndex++) {
for (int x = 0; x < vectorSize; x++) {
srcX = (vecIndex * vectorSize) + x;
imageVectors[vec][x] = isInside(srcX, row) ? data[index(srcX, row)] : FILL_VALUE;
}
++vec;
}
}
return imageVectors;
}
/** /**
* Reconstruct this Chunk from array of 1D row vectors. * Reconstruct this Chunk from array of 1D row vectors.
* *
...@@ -125,27 +99,6 @@ public class Chunk2D { ...@@ -125,27 +99,6 @@ public class Chunk2D {
} }
} }
/**
* Divide this Chunk to 2D matrices of given dimensions.
*
* @param qVectorDims Matrix dimension.
* @return Array of matrix data.
*/
public int[][] divideInto2DVectors(final V2i qVectorDims) {
final int chunkSize = qVectorDims.getX() * qVectorDims.getY();
final int chunkCount = calculateRequiredChunkCount(qVectorDims);
int[][] vectors = new int[chunkCount][chunkSize];
int vecIndex = 0;
for (int chunkYOffset = 0; chunkYOffset < dims.getY(); chunkYOffset += qVectorDims.getY()) {
for (int chunkXOffset = 0; chunkXOffset < dims.getX(); chunkXOffset += qVectorDims.getX()) {
copyDataToVector(vectors[vecIndex++], qVectorDims, chunkXOffset, chunkYOffset);
}
}
return vectors;
}
/** /**
* Reconstruct this Chunk (copy data) from matrix vectors. * Reconstruct this Chunk (copy data) from matrix vectors.
* *
...@@ -169,17 +122,6 @@ public class Chunk2D { ...@@ -169,17 +122,6 @@ public class Chunk2D {
assert (vecIndex == vectors.length); assert (vecIndex == vectors.length);
} }
/**
* Calculate the number of required 2D matrices for plane.
*
* @param chunkDims Matrix dimension.
* @return Number of required chunks.
*/
private int calculateRequiredChunkCount(final V2i chunkDims) {
return calculateRequiredChunkCount(dims, chunkDims);
}
/** /**
* Calculate the number of required 2D matrices for plane of given dimensions. * Calculate the number of required 2D matrices for plane of given dimensions.
* *
...@@ -205,26 +147,6 @@ public class Chunk2D { ...@@ -205,26 +147,6 @@ public class Chunk2D {
return (((x >= 0) && (x < dims.getX())) && (y >= 0) && (y < dims.getY())); return (((x >= 0) && (x < dims.getX())) && (y >= 0) && (y < dims.getY()));
} }
/**
* Copy this chunk data to chunk vector.
*
* @param vector Chunk vector.
* @param qVectorDims Dimensions of the vector.
* @param chunkXOffset Chunk X offset
* @param chunkYOffset Chunk Y offset.
*/
private void copyDataToVector(int[] vector, final V2i qVectorDims, final int chunkXOffset, final int chunkYOffset) {
int srcX, srcY;
for (int y = 0; y < qVectorDims.getY(); y++) {
srcY = chunkYOffset + y;
for (int x = 0; x < qVectorDims.getX(); x++) {
srcX = chunkXOffset + x;
final int dstIndex = index(x, y, qVectorDims.getY());
vector[dstIndex] = isInside(srcX, srcY) ? data[index(srcX, srcY)] : FILL_VALUE;
}
}
}
/** /**
* Copy data from chunk vector to this chunk. * Copy data from chunk vector to this chunk.
* *
......
...@@ -54,20 +54,20 @@ public class ImageU16 { ...@@ -54,20 +54,20 @@ public class ImageU16 {
return height; return height;
} }
/** // /**
* Chunk the image data into quantization vectors of requested dimension. // * Chunk the image data into quantization vectors of requested dimension.
* // *
* @param qVectorDims Quantization vector dimension. // * @param qVectorDims Quantization vector dimension.
* @return Array of quantization vectors. // * @return Array of quantization vectors.
*/ // */
public int[][] toQuantizationVectors(final V2i qVectorDims) { // public int[][] toQuantizationVectors(final V2i qVectorDims) {
if (qVectorDims.getY() == 1) { // if (qVectorDims.getY() == 1) {
// 1D row vectors. // // 1D row vectors.
return as2dChunk().divideInto1DVectors(qVectorDims.getX()); // return as2dChunk().divideInto1DVectors(qVectorDims.getX());
} else { // } else {
// 2D matrix vectors. // // 2D matrix vectors.
return as2dChunk().divideInto2DVectors(qVectorDims); // return as2dChunk().divideInto2DVectors(qVectorDims);
//return Chunk2D.chunksAsImageVectors(as2dChunk().divideIntoChunks(qVectorDims)); // //return Chunk2D.chunksAsImageVectors(as2dChunk().divideIntoChunks(qVectorDims));
} // }
} // }
} }
package azgracompress.io.loader; package azgracompress.io.loader;
import azgracompress.compression.CompressionOptions;
import azgracompress.compression.exception.ImageCompressionException;
import azgracompress.data.Range; import azgracompress.data.Range;
import azgracompress.data.V2i; import azgracompress.data.V2i;
import azgracompress.data.V3i; import azgracompress.data.V3i;
...@@ -124,4 +126,33 @@ public interface IPlaneLoader { ...@@ -124,4 +126,33 @@ public interface IPlaneLoader {
* @param threadCount Available thread count for loader. * @param threadCount Available thread count for loader.
*/ */
void setWorkerCount(final int threadCount); void setWorkerCount(final int threadCount);
/**
* Load correct type of vectors (quantization type in options) from specified plane range.
*
* @param planeRange Plane range to load vectors from.
* @return Vector data from plane range.
* @throws ImageCompressionException When fails to load plane range.
*/
default int[][] loadVectorsFromPlaneRange(final CompressionOptions options,
final Range<Integer> planeRange) throws ImageCompressionException {
setWorkerCount(supportParallelLoading() ? options.getWorkerCount() : 1);
try {
switch (options.getQuantizationType()) {
case Vector1D:
return loadRowVectors(options.getQuantizationVector().getX(), planeRange);
case Vector2D:
return loadBlocks(options.getQuantizationVector().toV2i(), planeRange);
case Vector3D:
return loadVoxels(options.getQuantizationVector(), planeRange);
default: {
throw new ImageCompressionException("Invalid QuantizationType '" + options.getQuantizationType().toString() + "'");
}
}
} catch (IOException e) {
throw new ImageCompressionException("Unable to load vectors QuantizationType=" + options.getQuantizationType(), e);
}
}
} }
...@@ -18,7 +18,7 @@ public final class PlaneLoaderFactory { ...@@ -18,7 +18,7 @@ public final class PlaneLoaderFactory {
case RawDataLoader: case RawDataLoader:
return new RawDataLoader((FileInputData) inputDataInfo); return new RawDataLoader((FileInputData) inputDataInfo);
case SCIFIOLoader: case SCIFIOLoader:
return new SCIFIOLoader((FileInputData)inputDataInfo); return new SCIFIOLoader((FileInputData) inputDataInfo);
case ImageJBufferLoader: case ImageJBufferLoader:
return new ImageJBufferLoader((BufferInputData) inputDataInfo); return new ImageJBufferLoader((BufferInputData) inputDataInfo);
default: default:
......
package azgracompress.utilities; package azgracompress.utilities;
import azgracompress.U16; import azgracompress.U16;
import azgracompress.data.Range;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
...@@ -10,6 +11,10 @@ import java.util.ArrayList; ...@@ -10,6 +11,10 @@ import java.util.ArrayList;
public class Utils { public class Utils {
public static Range<Integer> singlePlaneRange(final int index) {
return new Range<>(index, index + 1);
}
public static double calculatePsnr(final double mse, final int signalMax) { public static double calculatePsnr(final double mse, final int signalMax) {
double psnr = 10.0 * Math.log10((Math.pow(signalMax, 2) / mse)); double psnr = 10.0 * Math.log10((Math.pow(signalMax, 2) / mse));
return psnr; return psnr;
...@@ -19,7 +24,7 @@ public class Utils { ...@@ -19,7 +24,7 @@ public class Utils {
FileInputStream fileStream = new FileInputStream(path); FileInputStream fileStream = new FileInputStream(path);
try { try {
throw new FileNotFoundException("Implement this actually!"); throw new FileNotFoundException("Implement this actually!");
// return fileStream.readAllBytes(); // return fileStream.readAllBytes();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment