diff --git a/src/main/java/azgracompress/compression/VQImageDecompressor.java b/src/main/java/azgracompress/compression/VQImageDecompressor.java
index ec0d3795680948aed3e74a519ddafe143e6f4fe6..1c152848fb5dbdcbe8b7a16aad85ac9195a94dba 100644
--- a/src/main/java/azgracompress/compression/VQImageDecompressor.java
+++ b/src/main/java/azgracompress/compression/VQImageDecompressor.java
@@ -18,6 +18,13 @@ import java.io.IOException;
 
 @SuppressWarnings("DuplicatedCode")
 public class VQImageDecompressor extends CompressorDecompressorBase implements IImageDecompressor {
+
+    private interface DecompressVoxelCallback {
+        void process(final Voxel decompressedVoxel,
+                     final int[][] decompressedVoxelData,
+                     final int planeOffset) throws ImageDecompressionException;
+    }
+
     public VQImageDecompressor(CompressionOptions options) {
         super(options);
     }
@@ -171,6 +178,7 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I
         }
     }
 
+
     @Override
     public void decompressToBuffer(DataInputStream compressedStream,
                                    short[][] buffer,
@@ -240,16 +248,11 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I
         }
     }
 
-    private void decompressVoxelsToBuffer(DataInputStream compressedStream,
-                                          short[][] buffer,
-                                          QCMPFileHeader header) throws ImageDecompressionException {
 
-        throw new ImageDecompressionException("Implement this!!!");
-    }
+    private void decompressVoxelsImpl(DataInputStream compressedStream,
+                                      QCMPFileHeader header,
+                                      DecompressVoxelCallback callback) throws ImageDecompressionException {
 
-    private void decompressVoxels(DataInputStream compressedStream,
-                                  DataOutputStream decompressStream,
-                                  QCMPFileHeader header) throws ImageDecompressionException {
         assert (header.getQuantizationType() == QuantizationType.Vector3D);
         assert (!header.isCodebookPerPlane()); // SHOULD ALWAYS BE GLOBAL.
 
@@ -265,7 +268,6 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I
 
         final int voxelLayerCount = VQImageCompressor.calculateVoxelLayerCount(header.getImageSizeZ(), header.getVectorSizeZ());
         Stopwatch stopwatch = new Stopwatch();
-        ImageU16Dataset currentVoxelLayer;
         for (int voxelLayerIndex = 0; voxelLayerIndex < voxelLayerCount; voxelLayerIndex++) {
             stopwatch.restart();
 
@@ -277,31 +279,24 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I
             final int voxelLayerDataSize = (int) header.getPlaneDataSizes()[voxelLayerIndex];
             final int voxelLayerVoxelCount = Voxel.calculateRequiredVoxelCount(currentVoxelLayerDims, voxelDims);
 
+            int[][] decompressedVoxels = new int[voxelLayerVoxelCount][vectorSize];
+
             try (InBitStream inBitStream = new InBitStream(compressedStream, header.getBitsPerCodebookIndex(), voxelLayerDataSize)) {
                 inBitStream.readToBuffer();
                 inBitStream.setAllowReadFromUnderlyingStream(false);
 
-                int[][] decompressedVoxels = new int[voxelLayerVoxelCount][vectorSize];
                 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].getVector(), 0, decompressedVoxels[voxelIndex], 0, vectorSize);
                 }
 
-                final Voxel currentVoxel = new Voxel(currentVoxelLayerDims);
-                currentVoxelLayer = currentVoxel.reconstructFromVoxelsToDataset(voxelDims, decompressedVoxels);
             } catch (Exception e) {
                 throw new ImageDecompressionException("VQImageDecompressor::decompressVoxels() - Unable to read indices from InBitStream.",
                                                       e);
             }
 
-            for (int layer = 0; layer < currentVoxelLayerDims.getZ(); layer++) {
-                try {
-                    decompressStream.write(TypeConverter.unsignedShortArrayToByteArray(currentVoxelLayer.getPlaneData(layer), false));
-                } catch (IOException e) {
-                    throw new ImageDecompressionException("Unable to write to decompress stream.", e);
-                }
-            }
+            final Voxel currentVoxel = new Voxel(currentVoxelLayerDims);
+            callback.process(currentVoxel, decompressedVoxels, (voxelLayerIndex * voxelLayerDepth));
 
             stopwatch.stop();
             if (options.isConsoleApplication()) {
@@ -315,6 +310,36 @@ public class VQImageDecompressor extends CompressorDecompressorBase implements I
         }
     }
 
+
+    private void decompressVoxelsToBuffer(DataInputStream compressedStream,
+                                          short[][] buffer,
+                                          QCMPFileHeader header) throws ImageDecompressionException {
+
+        final V3i voxelDims = new V3i(header.getVectorSizeX(), header.getVectorSizeY(), header.getVectorSizeZ());
+
+        decompressVoxelsImpl(compressedStream, header, (decompressedVoxel, decompressedVoxelData, planeOffset) ->
+                decompressedVoxel.reconstructFromVoxels(voxelDims, decompressedVoxelData, buffer, planeOffset));
+    }
+
+    private void decompressVoxels(DataInputStream compressedStream,
+                                  DataOutputStream decompressStream,
+                                  QCMPFileHeader header) throws ImageDecompressionException {
+
+        final V3i voxelDims = new V3i(header.getVectorSizeX(), header.getVectorSizeY(), header.getVectorSizeZ());
+        decompressVoxelsImpl(compressedStream, header, (voxel, voxelData, planeOffset) -> {
+
+            ImageU16Dataset currentVoxelLayer = voxel.reconstructFromVoxelsToDataset(voxelDims, voxelData);
+
+            for (int layer = 0; layer < voxel.getDims().getZ(); layer++) {
+                try {
+                    decompressStream.write(TypeConverter.unsignedShortArrayToByteArray(currentVoxelLayer.getPlaneData(layer), false));
+                } catch (IOException e) {
+                    throw new ImageDecompressionException("Unable to write to decompress stream.", e);
+                }
+            }
+        });
+    }
+
     private int decodeHuffmanSymbol(Huffman huffman, InBitStream inBitStream) throws IOException {
         HuffmanNode currentHuffmanNode = huffman.getRoot();
         while (!currentHuffmanNode.isLeaf()) {
diff --git a/src/main/java/azgracompress/data/Voxel.java b/src/main/java/azgracompress/data/Voxel.java
index 5078efc5915eba4d2d042228c5b669f6894ad8e8..7a5944505738c86ee697b34457ab620f059bcc77 100644
--- a/src/main/java/azgracompress/data/Voxel.java
+++ b/src/main/java/azgracompress/data/Voxel.java
@@ -63,15 +63,10 @@ public final class Voxel {
         return (xChunkCount * yChunkCount * zChunkCount);
     }
 
-    /**
-     * Reconstruct an 3D dataset from voxels, which divided the original dataset.
-     *
-     * @param voxelDims Voxel dimensions.
-     * @param voxelData Voxel data.
-     * @return Dataset reconstructed from the voxel data.
-     */
-    public ImageU16Dataset reconstructFromVoxelsToDataset(final V3i voxelDims, final int[][] voxelData) {
-        final short[][] reconstructedData = new short[dims.getZ()][dims.toV2i().multiplyTogether()];
+    public void reconstructFromVoxels(final V3i voxelDims,
+                                      final int[][] voxelData,
+                                      final short[][] reconstructedData,
+                                      final int planeIndexOffset) {
 
         final int xVoxelCount = (int) Math.ceil((double) dims.getX() / (double) voxelDims.getX());
         final int yVoxelCount = (int) Math.ceil((double) dims.getY() / (double) voxelDims.getY());
@@ -110,7 +105,7 @@ public final class Voxel {
                             final int indexInsidePlane = Block.index(dstX, dstY, planeDimX);
 
                             // reconstructedData are 2D data while voxelData are 3D data!
-                            reconstructedData[planeIndex][indexInsidePlane] =
+                            reconstructedData[planeIndexOffset + planeIndex][indexInsidePlane] =
                                     (short) voxelData[(voxelOffset + voxelIndex)][indexInsideVoxel];
                         }
                     }
@@ -120,6 +115,18 @@ public final class Voxel {
             voxelOffset += planeVoxelCount;
         }
 
+    }
+
+    /**
+     * Reconstruct an 3D dataset from voxels, which divided the original dataset.
+     *
+     * @param voxelDims Voxel dimensions.
+     * @param voxelData Voxel data.
+     * @return Dataset reconstructed from the voxel data.
+     */
+    public ImageU16Dataset reconstructFromVoxelsToDataset(final V3i voxelDims, final int[][] voxelData) {
+        final short[][] reconstructedData = new short[dims.getZ()][dims.toV2i().multiplyTogether()];
+        reconstructFromVoxels(voxelDims, voxelData, reconstructedData, 0);
         return new ImageU16Dataset(dims.toV2i(), dims.getZ(), reconstructedData);
     }
 
@@ -174,4 +181,8 @@ public final class Voxel {
         }
         return reconstructedVoxel;
     }
+
+    public final V3i getDims() {
+        return dims;
+    }
 }