diff --git a/pom.xml b/pom.xml
index ccc76c79c834426b21a4cc030259812f2b78c86f..e68ef3989c3e7d4f3a9b531146363b6f86ebbc85 100644
--- a/pom.xml
+++ b/pom.xml
@@ -85,7 +85,7 @@
 
     <groupId>cz.it4i</groupId>
     <artifactId>QcmpCompression</artifactId>
-    <version>0.5-SNAPSHOT</version>
+    <version>0.5.5-EXP-SNAPSHOT</version>
     <build>
         <plugins>
             <plugin>
@@ -157,7 +157,7 @@
         <dependency>
             <groupId>org.junit.jupiter</groupId>
             <artifactId>junit-jupiter</artifactId>
-            <version>RELEASE</version>
+            <version>5.7.0</version>
             <scope>test</scope>
         </dependency>
     </dependencies>
diff --git a/src/main/java/cz/it4i/qcmp/benchmark/SQBenchmark.java b/src/main/java/cz/it4i/qcmp/benchmark/SQBenchmark.java
index 5d99107ca84674d8bf564c85f938b06287cf58eb..00b69d86277656cead551f7b4fb691a0488d1119 100644
--- a/src/main/java/cz/it4i/qcmp/benchmark/SQBenchmark.java
+++ b/src/main/java/cz/it4i/qcmp/benchmark/SQBenchmark.java
@@ -37,6 +37,7 @@ public class SQBenchmark extends BenchmarkBase {
         if (planes.length < 1) {
             return;
         }
+
         final boolean dirCreated = new File(this.outputDirectory).mkdirs();
         System.out.println(String.format("|CODEBOOK| = %d", codebookSize));
         ScalarQuantizer quantizer = null;
diff --git a/src/main/java/cz/it4i/qcmp/data/HyperStackDimensions.java b/src/main/java/cz/it4i/qcmp/data/HyperStackDimensions.java
index 101a5f5d2099fdc3a62a00558f22d7be5127296c..258de2d57e5ff9496177f1a65abd9c7284b67ecd 100644
--- a/src/main/java/cz/it4i/qcmp/data/HyperStackDimensions.java
+++ b/src/main/java/cz/it4i/qcmp/data/HyperStackDimensions.java
@@ -1,5 +1,7 @@
 package cz.it4i.qcmp.data;
 
+import cz.it4i.qcmp.utilities.Utils;
+
 import java.util.Objects;
 
 /**
@@ -11,6 +13,7 @@ public class HyperStackDimensions {
     private final int height;
     private final int planeCount;
     private final int numberOfTimepoints;
+    private final int numberOfChannels;
 
     /**
      * Create HyperStackDimensions.
@@ -19,37 +22,34 @@ public class HyperStackDimensions {
      * @param height             Height of the plane.
      * @param planeCount         Plane count in the stack.
      * @param numberOfTimepoints Number of stack timepoints.
+     * @param channelCount       Number of image channels.
      */
-    public HyperStackDimensions(final int width, final int height, final int planeCount, final int numberOfTimepoints) {
+    public HyperStackDimensions(final int width,
+                                final int height,
+                                final int planeCount,
+                                final int numberOfTimepoints,
+                                final int channelCount) {
+        assert (channelCount == 1) : "QcmpCompressionLibrary support only single channel datasets.";
         this.width = width;
         this.height = height;
         this.planeCount = planeCount;
         this.numberOfTimepoints = numberOfTimepoints;
+        this.numberOfChannels = channelCount;
     }
 
     /**
-     * Get number of elements in hyperstack with dimensionality = dimension.
-     * When calculating the element count, overflow is checked. This is because result of this
-     * function is usually used in places where we want to allocate memory.
+     * Create HyperStackDimensions.
      *
-     * @param dimension Maximum dimension.
-     * @return Number of elements.
+     * @param width              Width of the plane.
+     * @param height             Height of the plane.
+     * @param planeCount         Plane count in the stack.
+     * @param numberOfTimepoints Number of stack timepoints.
      */
-    @SuppressWarnings("DuplicateExpressions")
-    public int getNumberOfElementsInDimension(final int dimension) {
-        switch (dimension) {
-            case 1:
-                return width;
-            case 2:
-                return Math.multiplyExact(width, height);
-            case 3:
-                return Math.multiplyExact(planeCount, Math.multiplyExact(width, height));
-            case 4:
-                return Math.multiplyExact(numberOfTimepoints, Math.multiplyExact(planeCount, Math.multiplyExact(width, height)));
-            default:
-                assert (false) : "Wrong dimension in getNumberOfElementsInDimension";
-                return -1;
-        }
+    public HyperStackDimensions(final int width,
+                                final int height,
+                                final int planeCount,
+                                final int numberOfTimepoints) {
+        this(width, height, planeCount, numberOfTimepoints, 1);
     }
 
     /**
@@ -60,7 +60,7 @@ public class HyperStackDimensions {
      * @param planeCount Plane count in the stack.
      */
     public HyperStackDimensions(final int width, final int height, final int planeCount) {
-        this(width, height, planeCount, 1);
+        this(width, height, planeCount, 1, 1);
     }
 
     /**
@@ -70,7 +70,46 @@ public class HyperStackDimensions {
      * @param height Height of the plane.
      */
     public HyperStackDimensions(final int width, final int height) {
-        this(width, height, 1, 1);
+        this(width, height, 1, 1, 1);
+    }
+
+    /**
+     * Create HyperStackDimensions from ij.ImagePlus dimensions array.
+     *
+     * @param imagePlusDimensions ImagePlus dimensions.
+     * @return Correct HyperStackDimensions.
+     */
+    public static HyperStackDimensions createFromImagePlusDimensions(final int[] imagePlusDimensions) {
+        // NOTE(Moravec):  ij.ImagePlus dimensions array = (width, height, nChannels, nSlices, nFrames)
+        return new HyperStackDimensions(imagePlusDimensions[0],
+                                        imagePlusDimensions[1],
+                                        imagePlusDimensions[3],
+                                        imagePlusDimensions[4],
+                                        imagePlusDimensions[2]);
+    }
+
+    /**
+     * Get number of elements in hyperstack with dimensionality = dimension.
+     * When calculating the element count, overflow is checked. This is because result of this
+     * function is usually used in places where we want to allocate memory.
+     *
+     * @param dimension Maximum dimension.
+     * @return Number of elements.
+     */
+    public int getNumberOfElementsInDimension(final int dimension) {
+        switch (dimension) {
+            case 1:
+                return width;
+            case 2:
+                return Math.multiplyExact(width, height);
+            case 3:
+                return Utils.multiplyExact(width, height, planeCount);
+            case 4:
+                return Utils.multiplyExact(width, height, planeCount, numberOfChannels);
+            default:
+                assert (false) : "Wrong dimension in getNumberOfElementsInDimension";
+                return -1;
+        }
     }
 
     /**
@@ -109,6 +148,14 @@ public class HyperStackDimensions {
         return new V2i(width, height);
     }
 
+    /**
+     * Get number of channels in the dataset.
+     *
+     * @return Channel count.
+     */
+    public int getNumberOfChannels() {
+        return numberOfChannels;
+    }
 
     /**
      * Get number of timepoints of the stack.
diff --git a/src/main/java/cz/it4i/qcmp/utilities/Utils.java b/src/main/java/cz/it4i/qcmp/utilities/Utils.java
index 3730c98670b4c585dca700e70fa46de29b14bc87..6d71079b747518e5bbd098cb6d5f6ca55be7a1f9 100644
--- a/src/main/java/cz/it4i/qcmp/utilities/Utils.java
+++ b/src/main/java/cz/it4i/qcmp/utilities/Utils.java
@@ -160,4 +160,36 @@ public class Utils {
         }
         return Math.sqrt(sum);
     }
+
+    /**
+     * Returns the product of the arguments,
+     * throwing an exception if the result overflows an {@code int}.
+     *
+     * @param numbers values to multiply
+     * @return the result
+     * @throws ArithmeticException if the result overflows an int
+     */
+    public static int multiplyExact(final int... numbers) throws ArithmeticException {
+        int result = numbers[0];
+        for (int i = 1; i < numbers.length; i++) {
+            result = Math.multiplyExact(result, numbers[i]);
+        }
+        return result;
+    }
+
+    /**
+     * Returns the product of the arguments,
+     * throwing an exception if the result overflows an {@code int}.
+     *
+     * @param numbers values to multiply
+     * @return the result
+     * @throws ArithmeticException if the result overflows an int
+     */
+    public static long multiplyExact(final long... numbers) throws ArithmeticException {
+        long result = numbers[0];
+        for (int i = 1; i < numbers.length; i++) {
+            result = Math.multiplyExact(result, numbers[i]);
+        }
+        return result;
+    }
 }
\ No newline at end of file
diff --git a/src/test/java/cz/it4i/qcmp/utilities/UtilsTest.java b/src/test/java/cz/it4i/qcmp/utilities/UtilsTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..6b6de6c0a15cbbf1858f76cd98d6f29ac800a2d1
--- /dev/null
+++ b/src/test/java/cz/it4i/qcmp/utilities/UtilsTest.java
@@ -0,0 +1,18 @@
+package cz.it4i.qcmp.utilities;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+class UtilsTest {
+
+    @Test
+    void multiplyExact() {
+        final int a = 200;
+        final int b = 54;
+        final int c = 783;
+
+        final int refResult = Math.multiplyExact(a, Math.multiplyExact(b, c));
+        final int result = Utils.multiplyExact(a, b, c);
+        Assertions.assertEquals(refResult, result);
+    }
+}
\ No newline at end of file