diff --git a/src/main/java/azgracompress/compression/IImageDecompressor.java b/src/main/java/azgracompress/compression/IImageDecompressor.java index 7e2d35cabca3759ea4efc65fdbe9252b48409e87..340d9b93c5914759f3f8a48edaae35dc8cb9c978 100644 --- a/src/main/java/azgracompress/compression/IImageDecompressor.java +++ b/src/main/java/azgracompress/compression/IImageDecompressor.java @@ -1,5 +1,6 @@ package azgracompress.compression; +import azgracompress.cache.ICacheFile; import azgracompress.compression.exception.ImageDecompressionException; import azgracompress.fileformat.QCMPFileHeader; @@ -38,4 +39,11 @@ public interface IImageDecompressor extends IListenable { void decompressToBuffer(DataInputStream compressedStream, short[][] buffer, final QCMPFileHeader header) throws ImageDecompressionException; + + /** + * Preload decompressor codebook and Huffman tree for stream decompressor from provided cache file. + * + * @param codebookCacheFile Codebook cache file. + */ + void preloadGlobalCodebook(final ICacheFile codebookCacheFile); } diff --git a/src/main/java/azgracompress/compression/SQImageDecompressor.java b/src/main/java/azgracompress/compression/SQImageDecompressor.java index 5be07a8769e84a17b3832ec61376f64a9de2f452..0fda46eeea9e5240fc5b83282faaf5fd37d7beb6 100644 --- a/src/main/java/azgracompress/compression/SQImageDecompressor.java +++ b/src/main/java/azgracompress/compression/SQImageDecompressor.java @@ -1,5 +1,8 @@ package azgracompress.compression; +import azgracompress.cache.ICacheFile; +import azgracompress.cache.SQCacheFile; +import azgracompress.cache.VQCacheFile; import azgracompress.compression.exception.ImageDecompressionException; import azgracompress.fileformat.QCMPFileHeader; import azgracompress.huffman.Huffman; @@ -14,6 +17,9 @@ import java.io.DataOutputStream; import java.io.IOException; public class SQImageDecompressor extends CompressorDecompressorBase implements IImageDecompressor { + private SQCodebook cachedCodebook = null; + private Huffman cachedHuffman = null; + public SQImageDecompressor(CompressionOptions options) { super(options); } @@ -88,8 +94,8 @@ public class SQImageDecompressor extends CompressorDecompressorBase implements I byte[] decompressedPlaneData = null; final int planeDataSize = (int) header.getPlaneDataSizes()[planeIndex]; try (InBitStream inBitStream = new InBitStream(compressedStream, - header.getBitsPerCodebookIndex(), - planeDataSize)) { + header.getBitsPerCodebookIndex(), + planeDataSize)) { inBitStream.readToBuffer(); inBitStream.setAllowReadFromUnderlyingStream(false); @@ -124,7 +130,19 @@ public class SQImageDecompressor extends CompressorDecompressorBase implements I } @Override - public void decompressToBuffer(DataInputStream compressedStream, short[][] buffer, QCMPFileHeader header) throws ImageDecompressionException { + public void preloadGlobalCodebook(final ICacheFile codebookCacheFile) { + assert (codebookCacheFile instanceof SQCacheFile) : "Incorrect codebook cache file type for SQImageDecompressor"; + + SQCacheFile codebookCache = (SQCacheFile) codebookCacheFile; + + cachedCodebook = codebookCache.getCodebook(); + cachedHuffman = createHuffmanCoder(createHuffmanSymbols(cachedCodebook.getCodebookSize()), cachedCodebook.getSymbolFrequencies()); + } + + @Override + public void decompressToBuffer(DataInputStream compressedStream, + short[][] buffer, + QCMPFileHeader header) throws ImageDecompressionException { final int codebookSize = (int) Math.pow(2, header.getBitsPerCodebookIndex()); final int[] huffmanSymbols = createHuffmanSymbols(codebookSize); final int planeCountForDecompression = header.getImageSizeZ(); @@ -166,8 +184,12 @@ public class SQImageDecompressor extends CompressorDecompressorBase implements I buffer[planeIndex] = TypeConverter.intArrayToShortArray(decompressedValues); } catch (Exception ex) { - throw new ImageDecompressionException("SQImageDecompressor::decompressToBuffer() - Unable to read indices from InBitStream.", ex); + throw new ImageDecompressionException("SQImageDecompressor::decompressToBuffer() - Unable to read indices from " + + "InBitStream.", + ex); } } + + } } diff --git a/src/main/java/azgracompress/compression/VQImageDecompressor.java b/src/main/java/azgracompress/compression/VQImageDecompressor.java index 383dea0c4b6ea094497df08a70660a6e4fe1e566..12b6bb8fe189f7cef67ada2bab1590761b15c486 100644 --- a/src/main/java/azgracompress/compression/VQImageDecompressor.java +++ b/src/main/java/azgracompress/compression/VQImageDecompressor.java @@ -1,5 +1,8 @@ package azgracompress.compression; +import azgracompress.cache.ICacheFile; +import azgracompress.cache.SQCacheFile; +import azgracompress.cache.VQCacheFile; import azgracompress.compression.exception.ImageDecompressionException; import azgracompress.data.*; import azgracompress.fileformat.QCMPFileHeader; @@ -17,6 +20,9 @@ import java.io.IOException; public class VQImageDecompressor extends CompressorDecompressorBase implements IImageDecompressor { + private VQCodebook cachedCodebook = null; + private Huffman cachedHuffman = null; + private interface DecompressCallback { void process(final Block imageBlock, final int planeIndex) throws ImageDecompressionException; } @@ -67,6 +73,15 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I return new VQCodebook(new V3i(0), codebookVectors, frequencies); } + @Override + public void preloadGlobalCodebook(final ICacheFile codebookCacheFile) { + assert (codebookCacheFile instanceof VQCacheFile) : "Incorrect codebook cache file type for VQImageDecompressor"; + VQCacheFile codebookCache = (VQCacheFile) codebookCacheFile; + + cachedCodebook = codebookCache.getCodebook(); + cachedHuffman = createHuffmanCoder(createHuffmanSymbols(cachedCodebook.getCodebookSize()), cachedCodebook.getVectorFrequencies()); + } + private Block reconstructImageFromQuantizedVectors(final int[][] vectors, final V2i qVector,