diff --git a/src/main/java/azgracompress/compression/VQImageCompressor.java b/src/main/java/azgracompress/compression/VQImageCompressor.java
index 714857e30d6a5463d6d18ab01a16315becbb29a1..6292c15702129daba0064f278bb67965f285e03e 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.data.Chunk3D;
 import azgracompress.fileformat.QuantizationType;
 import azgracompress.io.InputData;
 import azgracompress.compression.exception.ImageCompressionException;
@@ -236,11 +237,7 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
                                                                       planeIndex), e);
                 }
 
-                System.arraycopy(planeVectors,
-                                 0,
-                                 trainData,
-                                 (planeCounter * chunkCountPerPlane),
-                                 chunkCountPerPlane);
+                System.arraycopy(planeVectors, 0, trainData, (planeCounter * chunkCountPerPlane), chunkCountPerPlane);
                 ++planeCounter;
             }
         }
@@ -273,8 +270,19 @@ public class VQImageCompressor extends CompressorDecompressorBase implements IIm
         reportStatusToListeners("Operation completed.");
     }
 
+
     public long[] compressVoxels(DataOutputStream compressStream) throws ImageCompressionException {
-        
+        int[][] voxels;
+        try {
+            IPlaneLoader loader = PlaneLoaderFactory.getPlaneLoaderForInputFile(options.getInputDataInfo());
+            final int[] data = loader.loadAllPlanesU16Data();
+            Chunk3D bigVoxel = new Chunk3D(options.getInputDataInfo().getDimensions(), data);
+            voxels = bigVoxel.divideInto3DVectors(options.getQuantizationVector());
+        } catch (Exception e) {
+            throw new ImageCompressionException("Unable to create data loader or load image data.", e);
+        }
+        return null;
+
     }
 
 }
diff --git a/src/main/java/azgracompress/data/Chunk2D.java b/src/main/java/azgracompress/data/Chunk2D.java
index e562d437d6798ce225d61cc651eef3d77e824a2f..51d6a480366baf352d1a10df50cab729d6304ad3 100644
--- a/src/main/java/azgracompress/data/Chunk2D.java
+++ b/src/main/java/azgracompress/data/Chunk2D.java
@@ -47,8 +47,8 @@ public class Chunk2D {
      * @return Index inside chunk dimension data array.
      */
     private int index(final int x, final int y, final V2i chunkDims) {
-        assert (x >= 0 && x < dims.getX()) : "Index X out of bounds.";
-        assert (y >= 0 && y < dims.getY()) : "Index Y out of bounds.";
+        assert (x >= 0 && x < chunkDims.getX()) : "Index X out of bounds.";
+        assert (y >= 0 && y < chunkDims.getY()) : "Index Y out of bounds.";
         return (y * chunkDims.getX()) + x;
     }
 
diff --git a/src/main/java/azgracompress/data/Chunk3D.java b/src/main/java/azgracompress/data/Chunk3D.java
index a3539dc5c9bea8e46a85929921d789f7b12320a4..7b90b37af8424eb48fb57264b13df3dd61a04dbc 100644
--- a/src/main/java/azgracompress/data/Chunk3D.java
+++ b/src/main/java/azgracompress/data/Chunk3D.java
@@ -1,7 +1,5 @@
 package azgracompress.data;
 
-import java.util.Arrays;
-
 public class Chunk3D {
     private final int FILL_VALUE = 0;
     private final int[] data;
@@ -40,9 +38,9 @@ public class Chunk3D {
      * @return Index inside chunk dimension data array.
      */
     private int index(final int x, final int y, final int z, final V3i chunkDims) {
-        assert (x >= 0 && x < dims.getX()) : "Index X out of bounds.";
-        assert (y >= 0 && y < dims.getY()) : "Index Y out of bounds.";
-        assert (z >= 0 && z < dims.getZ()) : "Index Z out of bounds.";
+        assert (x >= 0 && x < chunkDims.getX()) : "Index X out of bounds.";
+        assert (y >= 0 && y < chunkDims.getY()) : "Index Y out of bounds.";
+        assert (z >= 0 && z < chunkDims.getZ()) : "Index Z out of bounds.";
 
         // NOTE(Moravec): Description of the following calculation
         //               plane index      *        plane pixel count
@@ -60,7 +58,7 @@ public class Chunk3D {
         //             V
         // colOffset = x;
 
-        return (chunkDims.getZ() * (chunkDims.getX() * chunkDims.getY())) + (y * chunkDims.getX()) + x;
+        return (z * (chunkDims.getX() * chunkDims.getY())) + (y * chunkDims.getX()) + x;
     }
 
 
@@ -163,8 +161,4 @@ public class Chunk3D {
     public int[] getData() {
         return data;
     }
-
-    public void zeroData() {
-        Arrays.fill(data, 0);
-    }
 }
diff --git a/src/main/java/azgracompress/io/loader/IPlaneLoader.java b/src/main/java/azgracompress/io/loader/IPlaneLoader.java
index b629191af7641a4743ddf35e0ac3d0712d9b52c4..6e3ff5f9b9e8a3373077c188b47ed89a994e970f 100644
--- a/src/main/java/azgracompress/io/loader/IPlaneLoader.java
+++ b/src/main/java/azgracompress/io/loader/IPlaneLoader.java
@@ -1,6 +1,7 @@
 package azgracompress.io.loader;
 
 import azgracompress.data.ImageU16;
+import azgracompress.data.V3i;
 
 import java.io.IOException;
 
@@ -10,4 +11,8 @@ public interface IPlaneLoader {
     int[] loadPlanesU16Data(int[] planes) throws IOException;
 
     int[] loadAllPlanesU16Data() throws IOException;
+
+    default int[][] loadVoxels(final V3i voxelDim) throws IOException {
+        throw new IOException("NOT IMPLEMENTED");
+    }
 }
diff --git a/src/main/java/azgracompress/io/loader/ImageJBufferLoader.java b/src/main/java/azgracompress/io/loader/ImageJBufferLoader.java
index 6f6b42a187ea4dda5eca466e7486432010c30724..b9e70a22e393f8c171e6f92398d8ae0e0f04c733 100644
--- a/src/main/java/azgracompress/io/loader/ImageJBufferLoader.java
+++ b/src/main/java/azgracompress/io/loader/ImageJBufferLoader.java
@@ -1,5 +1,6 @@
 package azgracompress.io.loader;
 
+import azgracompress.data.Chunk3D;
 import azgracompress.data.ImageU16;
 import azgracompress.data.V3i;
 import azgracompress.io.BufferInputData;
@@ -39,8 +40,8 @@ public class ImageJBufferLoader implements IPlaneLoader {
                 final int planePixelCount = bufferInputData.getDimensions().getX() * bufferInputData.getDimensions().getY();
                 final short[] srcBuffer = (short[]) bufferInputData.getPixelBuffer(plane);
                 return new ImageU16(bufferInputData.getDimensions().getX(),
-                        bufferInputData.getDimensions().getY(),
-                        copyShortArray(srcBuffer, planePixelCount));
+                                    bufferInputData.getDimensions().getY(),
+                                    copyShortArray(srcBuffer, planePixelCount));
             }
             default:
                 throw new IOException("Unable to load unsupported pixel type.");
@@ -106,4 +107,133 @@ public class ImageJBufferLoader implements IPlaneLoader {
                 throw new IOException("Unable to load unsupported pixel type.");
         }
     }
+
+    @Override
+    public int[][] loadVoxels(V3i voxelDim) throws IOException {
+
+        switch (bufferInputData.getPixelType()) {
+            case Gray16: {
+                final V3i dims = bufferInputData.getDimensions();
+                final int voxelSize = (int) voxelDim.multiplyTogether();
+                final int voxelCount = Chunk3D.calculateRequiredChunkCount(bufferInputData.getDimensions(), voxelDim);
+
+                int[][] voxels = new int[voxelCount][voxelSize];
+                int voxelIndex = 0;
+
+                for (int chunkZOffset = 0; chunkZOffset < dims.getZ(); chunkZOffset += voxelDim.getZ()) {
+                    for (int chunkYOffset = 0; chunkYOffset < dims.getY(); chunkYOffset += voxelDim.getY()) {
+                        for (int chunkXOffset = 0; chunkXOffset < dims.getX(); chunkXOffset += voxelDim.getX()) {
+                            copyDataToVector(voxels[voxelIndex++], voxelDim, chunkXOffset, chunkYOffset, chunkZOffset);
+                        }
+                    }
+                }
+                return voxels;
+            }
+            default:
+                throw new IOException("Unable to load unsupported pixel type.");
+        }
+    }
+
+    private int readDataAt(final int x, final int y, final int z) {
+
+        final short[] srcBuffer = (short[]) bufferInputData.getPixelBuffer(z);
+        return srcBuffer[(y * bufferInputData.getDimensions().getX()) + x];
+    }
+
+    /**
+     * 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.
+     * @param chunkZOffset Chunk Z offset.
+     */
+    private void copyDataToVector(int[] vector,
+                                  final V3i qVectorDims,
+                                  final int chunkXOffset,
+                                  final int chunkYOffset,
+                                  final int chunkZOffset) {
+        int srcZ;
+        for (int z = 0; z < qVectorDims.getZ(); z++) {
+            srcZ = chunkZOffset + z;
+            fillVoxelFromPlane(vector, qVectorDims, srcZ, z, chunkXOffset, chunkYOffset);
+        }
+    }
+
+    private void fillVoxelFromPlane(int[] vector,
+                                    final V3i qVectorDims,
+                                    final int srcZ,
+                                    final int z,
+                                    final int chunkXOffset,
+                                    final int chunkYOffset) {
+
+        if (srcZ >= bufferInputData.getDimensions().getZ())
+            return;
+
+        final short[] srcBuffer = (short[]) bufferInputData.getPixelBuffer(srcZ);
+        final int width = bufferInputData.getDimensions().getX();
+
+        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, z, qVectorDims);
+                vector[dstIndex] = isInside(srcX, srcY, srcZ) ? srcBuffer[(srcY * width) + srcX] : 0;
+            }
+        }
+    }
+
+    private boolean isInside(final int x, final int y, final int z) {
+        return (((x >= 0) && (x < bufferInputData.getDimensions().getX())) && (y >= 0) &&
+                (y < bufferInputData.getDimensions().getY()) && (z >= 0) &&
+                (z < bufferInputData.getDimensions().getZ()));
+    }
+
+    /**
+     * Calculate the index inside data array.
+     *
+     * @param x Zero based x coordinate.
+     * @param y Zero based y coordinate.
+     * @param z Zero based z coordinate.
+     * @return Index inside data array.
+     */
+    private int index(final int x, final int y, final int z) {
+        return index(x, y, z, bufferInputData.getDimensions());
+    }
+
+    /**
+     * Calculate the index inside array of dimensions specified by chunkDims.
+     *
+     * @param x         Zero based x coordinate.
+     * @param y         Zero based y coordinate.
+     * @param z         Zero based z coordinate.
+     * @param chunkDims Chunk dimensions.
+     * @return Index inside chunk dimension data array.
+     */
+    private int index(final int x, final int y, final int z, final V3i chunkDims) {
+        assert (x >= 0 && x < chunkDims.getX()) : "Index X out of bounds.";
+        assert (y >= 0 && y < chunkDims.getY()) : "Index Y out of bounds.";
+        assert (z >= 0 && z < chunkDims.getZ()) : "Index Z out of bounds.";
+
+        // NOTE(Moravec): Description of the following calculation
+        //               plane index      *        plane pixel count
+        //                    |                            |
+        //                    V                            V
+        // planeOffset = chunkDims.getZ() * (chunkDims.getX() * chunkDims.getY())
+
+        //           row *  pixels in row
+        //             |         |
+        //             V         V
+        // rowOffset = y * chunkDims.getX();
+
+        //          column
+        //             |
+        //             V
+        // colOffset = x;
+
+        return (z * (chunkDims.getX() * chunkDims.getY())) + (y * chunkDims.getX()) + x;
+    }
 }
+