diff --git a/src/main/java/azgracompress/compression/VQImageCompressor.java b/src/main/java/azgracompress/compression/VQImageCompressor.java index 723490e2a3cd9ff5f5d9eae825a86a1208dee974..714857e30d6a5463d6d18ab01a16315becbb29a1 100644 --- a/src/main/java/azgracompress/compression/VQImageCompressor.java +++ b/src/main/java/azgracompress/compression/VQImageCompressor.java @@ -1,6 +1,7 @@ package azgracompress.compression; import azgracompress.cache.QuantizationCacheManager; +import azgracompress.fileformat.QuantizationType; import azgracompress.io.InputData; import azgracompress.compression.exception.ImageCompressionException; import azgracompress.data.Chunk2D; @@ -29,9 +30,9 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm private VectorQuantizer trainVectorQuantizerFromPlaneVectors(final int[][] planeVectors) { LBGVectorQuantizer vqInitializer = new LBGVectorQuantizer(planeVectors, - getCodebookSize(), - options.getWorkerCount(), - options.getQuantizationVector()); + getCodebookSize(), + options.getWorkerCount(), + options.getQuantizationVector()); LBGResult vqResult = vqInitializer.findOptimalCodebook(); return new VectorQuantizer(vqResult.getCodebook()); } @@ -76,14 +77,14 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm QuantizationCacheManager cacheManager = new QuantizationCacheManager(options.getCodebookCacheFolder()); if (!cacheManager.doesVQCacheExists(options.getInputDataInfo().getCacheFileName(), - getCodebookSize(), - options.getQuantizationVector())) { + getCodebookSize(), + options.getQuantizationVector())) { trainAndSaveCodebook(); } final VQCodebook codebook = cacheManager.loadVQCodebook(options.getInputDataInfo().getCacheFileName(), - getCodebookSize(), - options.getQuantizationVector()); + getCodebookSize(), + options.getQuantizationVector()); if (codebook == null) { throw new ImageCompressionException("Failed to read quantization vectors from cache."); @@ -98,6 +99,11 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm * @throws ImageCompressionException When compress process fails. */ public long[] compress(DataOutputStream compressStream) throws ImageCompressionException { + if (options.getQuantizationType() == QuantizationType.Vector3D) { + return compressVoxels(compressStream); + } + assert (options.getQuantizationVector().getZ() == 1); + final InputData inputDataInfo = options.getInputDataInfo(); Stopwatch stopwatch = new Stopwatch(); final boolean hasGeneralQuantizer = options.getCodebookType() != CompressionOptions.CodebookType.Individual; @@ -130,7 +136,7 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm } reportStatusToListeners(String.format("Training vector quantizer from middle plane %d.", middlePlaneIndex)); - final int[][] refPlaneVectors = middlePlane.toQuantizationVectors(options.getQuantizationVector()); + final int[][] refPlaneVectors = middlePlane.toQuantizationVectors(options.getQuantizationVector().toV2i()); quantizer = trainVectorQuantizerFromPlaneVectors(refPlaneVectors); huffman = createHuffmanCoder(huffmanSymbols, quantizer.getFrequencies()); writeQuantizerToCompressStream(quantizer, compressStream); @@ -148,13 +154,12 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm ImageU16 plane = null; try { - plane = planeLoader.loadPlaneU16(planeIndex); } catch (IOException ex) { throw new ImageCompressionException("Unable to load plane data.", ex); } - final int[][] planeVectors = plane.toQuantizationVectors(options.getQuantizationVector()); + final int[][] planeVectors = plane.toQuantizationVectors(options.getQuantizationVector().toV2i()); if (!hasGeneralQuantizer) { reportStatusToListeners(String.format("Training vector quantizer from plane %d.", planeIndex)); @@ -171,7 +176,7 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm stopwatch.stop(); 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; } @@ -188,7 +193,7 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm private int[][] loadPlaneQuantizationVectors(final IPlaneLoader planeLoader, final int planeIndex) throws IOException { ImageU16 refPlane = planeLoader.loadPlaneU16(planeIndex); - return refPlane.toQuantizationVectors(options.getQuantizationVector()); + return refPlane.toQuantizationVectors(options.getQuantizationVector().toV2i()); } private int[][] loadConfiguredPlanesData() throws ImageCompressionException { @@ -200,13 +205,12 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm } catch (Exception e) { throw new ImageCompressionException("Unable to create SCIFIO reader. " + e.getMessage()); } - int[][] trainData = null; + int[][] trainData; Stopwatch s = new Stopwatch(); s.start(); if (inputDataInfo.isPlaneIndexSet()) { reportStatusToListeners("VQ: Loading single plane data."); try { - trainData = loadPlaneQuantizationVectors(planeLoader, inputDataInfo.getPlaneIndex()); } catch (IOException e) { throw new ImageCompressionException("Failed to load plane data.", e); @@ -215,9 +219,8 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm reportStatusToListeners(inputDataInfo.isPlaneRangeSet() ? "VQ: Loading plane range data." : "VQ: Loading all planes data."); final int[] planeIndices = getPlaneIndicesForCompression(); - final int chunkCountPerPlane = Chunk2D.calculateRequiredChunkCount( - inputDataInfo.getDimensions().toV2i(), - options.getQuantizationVector()); + final int chunkCountPerPlane = Chunk2D.calculateRequiredChunkCount(inputDataInfo.getDimensions().toV2i(), + options.getQuantizationVector().toV2i()); final int totalChunkCount = chunkCountPerPlane * planeIndices.length; trainData = new int[totalChunkCount][vectorSize]; @@ -230,14 +233,14 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm 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); + planeIndex), e); } System.arraycopy(planeVectors, - 0, - trainData, - (planeCounter * chunkCountPerPlane), - chunkCountPerPlane); + 0, + trainData, + (planeCounter * chunkCountPerPlane), + chunkCountPerPlane); ++planeCounter; } } @@ -251,9 +254,9 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm final int[][] trainingData = loadConfiguredPlanesData(); LBGVectorQuantizer vqInitializer = new LBGVectorQuantizer(trainingData, - getCodebookSize(), - options.getWorkerCount(), - options.getQuantizationVector()); + getCodebookSize(), + options.getWorkerCount(), + options.getQuantizationVector()); reportStatusToListeners("Starting LBG optimization."); vqInitializer.setStatusListener(this::reportStatusToListeners); LBGResult lbgResult = vqInitializer.findOptimalCodebook(); @@ -270,5 +273,8 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm reportStatusToListeners("Operation completed."); } + public long[] compressVoxels(DataOutputStream compressStream) throws ImageCompressionException { + + } } diff --git a/src/main/java/azgracompress/io/loader/RawDataLoader.java b/src/main/java/azgracompress/io/loader/RawDataLoader.java index c8a8919fec6621ffa84b181412e4360cb82d1603..e378215967a5f2fc5c3e6399270c4c2c211fa821 100644 --- a/src/main/java/azgracompress/io/loader/RawDataLoader.java +++ b/src/main/java/azgracompress/io/loader/RawDataLoader.java @@ -3,10 +3,12 @@ package azgracompress.io.loader; import azgracompress.data.ImageU16; import azgracompress.data.V3i; import azgracompress.io.FileInputData; -import azgracompress.io.InputData; import azgracompress.utilities.TypeConverter; -import java.io.*; +import java.io.BufferedInputStream; +import java.io.DataInputStream; +import java.io.FileInputStream; +import java.io.IOException; import java.util.Arrays; public class RawDataLoader implements IPlaneLoader { diff --git a/src/main/java/azgracompress/quantization/vector/VectorQuantizer.java b/src/main/java/azgracompress/quantization/vector/VectorQuantizer.java index 94a44241eaa50c7b1cc184ffa7272b024bc11efa..5413e9d009b39c82c19e91c5c96d56836135dfd6 100644 --- a/src/main/java/azgracompress/quantization/vector/VectorQuantizer.java +++ b/src/main/java/azgracompress/quantization/vector/VectorQuantizer.java @@ -3,13 +3,11 @@ package azgracompress.quantization.vector; public class VectorQuantizer { private final VectorDistanceMetric metric = VectorDistanceMetric.Euclidean; - private final VQCodebook codebook; private final CodebookEntry[] codebookVectors; private final int vectorSize; private final long[] frequencies; public VectorQuantizer(final VQCodebook codebook) { - this.codebook = codebook; this.codebookVectors = codebook.getVectors(); vectorSize = codebookVectors[0].getVector().length; this.frequencies = codebook.getVectorFrequencies();