Repository: deeplearning4j/deeplearning4j
Issue: DataVec: Unit test failure - TestNativeImageLoader.testAsMatrix

This is very likely related to long shapes, but couldn't at first glance see what the fix would be.


```
java.lang.IndexOutOfBoundsException: 3
	at org.bytedeco.javacpp.indexer.Indexer.checkIndex(Indexer.java:90)
	at org.bytedeco.javacpp.indexer.FloatRawIndexer.put(FloatRawIndexer.java:90)
	at org.bytedeco.javacpp.indexer.FloatRawIndexer.put(FloatRawIndexer.java:110)
	at org.datavec.image.loader.NativeImageLoader.asMat(NativeImageLoader.java:724)
	at org.datavec.image.loader.NativeImageLoader.asMat(NativeImageLoader.java:684)
	at org.datavec.image.loader.TestNativeImageLoader.testAsMatrix(TestNativeImageLoader.java:235)
```

Changed files:
datavec/datavec-data/datavec-data-image/src/main/java/org/datavec/image/loader/LFWLoader.java
datavec/datavec-data/datavec-data-image/src/main/java/org/datavec/image/loader/BaseImageLoader.java
datavec/datavec-data/datavec-data-image/src/test/java/org/datavec/image/loader/TestNativeImageLoader.java
datavec/datavec-api/src/main/java/org/datavec/api/io/filters/BalancedPathFilter.java
datavec/datavec-data/datavec-data-image/src/test/java/org/datavec/image/loader/LoaderTests.java
datavec/datavec-data/datavec-data-image/src/main/java/org/datavec/image/loader/ImageLoader.java
datavec/datavec-data/datavec-data-image/src/main/java/org/datavec/image/recordreader/ImageRecordReader.java
datavec/datavec-data/datavec-data-image/src/main/java/org/datavec/image/loader/NativeImageLoader.java
datavec/datavec-data/datavec-data-image/src/main/java/org/datavec/image/recordreader/BaseImageRecordReader.java
datavec/datavec-api/src/main/java/org/datavec/api/io/filters/RandomPathFilter.java

diff --git a/datavec/datavec-api/src/main/java/org/datavec/api/io/filters/BalancedPathFilter.java b/datavec/datavec-api/src/main/java/org/datavec/api/io/filters/BalancedPathFilter.java
index 3242e0315a..8c0168d428 100644
--- a/datavec/datavec-api/src/main/java/org/datavec/api/io/filters/BalancedPathFilter.java
+++ b/datavec/datavec-api/src/main/java/org/datavec/api/io/filters/BalancedPathFilter.java
@@ -32,7 +32,7 @@ import java.util.*;
 public class BalancedPathFilter extends RandomPathFilter {
 
     protected PathLabelGenerator labelGenerator;
-    protected int maxLabels = 0, minPathsPerLabel = 0, maxPathsPerLabel = 0;
+    protected long maxLabels = 0, minPathsPerLabel = 0, maxPathsPerLabel = 0;
     protected String[] labels = null;
 
     /** Calls {@code this(random, extensions, labelGenerator, 0, 0, 0, 0)}. */
@@ -41,25 +41,25 @@ public class BalancedPathFilter extends RandomPathFilter {
     }
 
     /** Calls {@code this(random, null, labelGenerator, 0, 0, 0, maxPathsPerLabel)}. */
-    public BalancedPathFilter(Random random, PathLabelGenerator labelGenerator, int maxPathsPerLabel) {
+    public BalancedPathFilter(Random random, PathLabelGenerator labelGenerator, long maxPathsPerLabel) {
         this(random, null, labelGenerator, 0, 0, 0, maxPathsPerLabel);
     }
 
     /** Calls {@code this(random, extensions, labelGenerator, 0, 0, 0, maxPathsPerLabel)}. */
     public BalancedPathFilter(Random random, String[] extensions, PathLabelGenerator labelGenerator,
-                    int maxPathsPerLabel) {
+                    long maxPathsPerLabel) {
         this(random, extensions, labelGenerator, 0, 0, 0, maxPathsPerLabel);
     }
 
     /** Calls {@code this(random, extensions, labelGenerator, 0, maxLabels, 0, maxPathsPerLabel)}. */
-    public BalancedPathFilter(Random random, PathLabelGenerator labelGenerator, int maxPaths, int maxLabels,
-                    int maxPathsPerLabel) {
+    public BalancedPathFilter(Random random, PathLabelGenerator labelGenerator, long maxPaths, long maxLabels,
+                    long maxPathsPerLabel) {
         this(random, null, labelGenerator, maxPaths, maxLabels, 0, maxPathsPerLabel);
     }
 
     /** Calls {@code this(random, extensions, labelGenerator, 0, maxLabels, 0, maxPathsPerLabel)}. */
-    public BalancedPathFilter(Random random, String[] extensions, PathLabelGenerator labelGenerator, int maxLabels,
-                    int maxPathsPerLabel) {
+    public BalancedPathFilter(Random random, String[] extensions, PathLabelGenerator labelGenerator, long maxLabels,
+                    long maxPathsPerLabel) {
         this(random, extensions, labelGenerator, 0, maxLabels, 0, maxPathsPerLabel);
     }
 
@@ -77,8 +77,8 @@ public class BalancedPathFilter extends RandomPathFilter {
      * @param maxPathsPerLabel max number of paths per labels to return (0 == unlimited)
      * @param labels           of the paths to keep (empty set == keep all paths)
      */
-    public BalancedPathFilter(Random random, String[] extensions, PathLabelGenerator labelGenerator, int maxPaths,
-                    int maxLabels, int minPathsPerLabel, int maxPathsPerLabel, String... labels) {
+    public BalancedPathFilter(Random random, String[] extensions, PathLabelGenerator labelGenerator, long maxPaths,
+                    long maxLabels, long minPathsPerLabel, long maxPathsPerLabel, String... labels) {
         super(random, extensions, maxPaths);
         this.labelGenerator = labelGenerator;
         this.maxLabels = maxLabels;
@@ -121,14 +121,15 @@ public class BalancedPathFilter extends RandomPathFilter {
             pathList.add(path);
         }
 
-        int minCount = maxPathsPerLabel > 0 ? maxPathsPerLabel : Integer.MAX_VALUE;
+        int minCount = maxPathsPerLabel > 0 ?
+                (int)Math.min(maxPathsPerLabel, Integer.MAX_VALUE) : Integer.MAX_VALUE;
         for (List<URI> pathList : labelPaths.values()) {
             if (minCount > pathList.size()) {
                 minCount = pathList.size();
             }
         }
         if (minCount < minPathsPerLabel) {
-            minCount = minPathsPerLabel;
+            minCount = (int)Math.min(minPathsPerLabel, Integer.MAX_VALUE);
         }
 
         ArrayList<URI> newpaths = new ArrayList<URI>();
diff --git a/datavec/datavec-api/src/main/java/org/datavec/api/io/filters/RandomPathFilter.java b/datavec/datavec-api/src/main/java/org/datavec/api/io/filters/RandomPathFilter.java
index 92158c0314..d1636731c6 100644
--- a/datavec/datavec-api/src/main/java/org/datavec/api/io/filters/RandomPathFilter.java
+++ b/datavec/datavec-api/src/main/java/org/datavec/api/io/filters/RandomPathFilter.java
@@ -29,7 +29,7 @@ public class RandomPathFilter implements PathFilter {
 
     protected Random random;
     protected String[] extensions;
-    protected int maxPaths = 0;
+    protected long maxPaths = 0;
 
     /** Calls {@code this(random, extensions, 0)}. */
     public RandomPathFilter(Random random, String... extensions) {
@@ -43,7 +43,7 @@ public class RandomPathFilter implements PathFilter {
      * @param extensions of files to keep
      * @param maxPaths   max number of paths to return (0 == unlimited)
      */
-    public RandomPathFilter(Random random, String[] extensions, int maxPaths) {
+    public RandomPathFilter(Random random, String[] extensions, long maxPaths) {
         this.random = random;
         this.extensions = extensions;
         this.maxPaths = maxPaths;
diff --git a/datavec/datavec-data/datavec-data-image/src/main/java/org/datavec/image/loader/BaseImageLoader.java b/datavec/datavec-data/datavec-data-image/src/main/java/org/datavec/image/loader/BaseImageLoader.java
index 9f6be773b1..28bd4e2244 100644
--- a/datavec/datavec-data/datavec-data-image/src/main/java/org/datavec/image/loader/BaseImageLoader.java
+++ b/datavec/datavec-data/datavec-data-image/src/main/java/org/datavec/image/loader/BaseImageLoader.java
@@ -43,9 +43,9 @@ public abstract class BaseImageLoader implements Serializable {
     public static final String[] ALLOWED_FORMATS = {"tif", "jpg", "png", "jpeg", "bmp", "JPEG", "JPG", "TIF", "PNG"};
     protected Random rng = new Random(System.currentTimeMillis());
 
-    protected int height = -1;
-    protected int width = -1;
-    protected int channels = -1;
+    protected long height = -1;
+    protected long width = -1;
+    protected long channels = -1;
     protected boolean centerCropIfNeeded = false;
     protected ImageTransform imageTransform = null;
     protected NativeImageLoader.MultiPageMode multiPageMode = null;
diff --git a/datavec/datavec-data/datavec-data-image/src/main/java/org/datavec/image/loader/ImageLoader.java b/datavec/datavec-data/datavec-data-image/src/main/java/org/datavec/image/loader/ImageLoader.java
index d00816c9a4..89c99224ea 100644
--- a/datavec/datavec-data/datavec-data-image/src/main/java/org/datavec/image/loader/ImageLoader.java
+++ b/datavec/datavec-data/datavec-data-image/src/main/java/org/datavec/image/loader/ImageLoader.java
@@ -65,7 +65,7 @@ public class ImageLoader extends BaseImageLoader {
      * @param width  the width to load
     
      */
-    public ImageLoader(int height, int width) {
+    public ImageLoader(long height, long width) {
         super();
         this.height = height;
         this.width = width;
@@ -79,7 +79,7 @@ public class ImageLoader extends BaseImageLoader {
      * @param width  the width to load
      * @param channels the number of channels for the image*
      */
-    public ImageLoader(int height, int width, int channels) {
+    public ImageLoader(long height, long width, long channels) {
         super();
         this.height = height;
         this.width = width;
@@ -94,7 +94,7 @@ public class ImageLoader extends BaseImageLoader {
      * @param channels the number of channels for the image*
      * @param centerCropIfNeeded to crop before rescaling and converting
      */
-    public ImageLoader(int height, int width, int channels, boolean centerCropIfNeeded) {
+    public ImageLoader(long height, long width, long channels, boolean centerCropIfNeeded) {
         this(height, width, channels);
         this.centerCropIfNeeded = centerCropIfNeeded;
     }
@@ -349,7 +349,9 @@ public class ImageLoader extends BaseImageLoader {
 
         int w = image.getWidth(), h = image.getHeight();
         int bands = image.getSampleModel().getNumBands();
-        int[][][] ret = new int[channels][h][w];
+        int[][][] ret = new int[(int)Math.min(channels, Integer.MAX_VALUE)]
+                               [(int)Math.min(h, Integer.MAX_VALUE)]
+                               [(int)Math.min(w, Integer.MAX_VALUE)];
         byte[] pixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
 
         for (int i = 0; i < h; i++) {
@@ -357,7 +359,7 @@ public class ImageLoader extends BaseImageLoader {
                 for (int k = 0; k < channels; k++) {
                     if (k >= bands)
                         break;
-                    ret[k][i][j] = pixels[channels * w * i + channels * j + k];
+                    ret[k][i][j] = pixels[(int)Math.min(channels * w * i + channels * j + k, Integer.MAX_VALUE)];
                 }
             }
         }
diff --git a/datavec/datavec-data/datavec-data-image/src/main/java/org/datavec/image/loader/LFWLoader.java b/datavec/datavec-data/datavec-data-image/src/main/java/org/datavec/image/loader/LFWLoader.java
index 9b5b5d1a4a..1e08a43d50 100644
--- a/datavec/datavec-data/datavec-data-image/src/main/java/org/datavec/image/loader/LFWLoader.java
+++ b/datavec/datavec-data/datavec-data-image/src/main/java/org/datavec/image/loader/LFWLoader.java
@@ -83,13 +83,17 @@ public class LFWLoader extends BaseImageLoader implements Serializable {
     }
 
     public LFWLoader(boolean useSubset) {
-        this(new int[] {HEIGHT, WIDTH, CHANNELS,}, null, useSubset);
+        this(new long[] {HEIGHT, WIDTH, CHANNELS,}, null, useSubset);
     }
 
     public LFWLoader(int[] imgDim, boolean useSubset) {
         this(imgDim, null, useSubset);
     }
 
+    public LFWLoader(long[] imgDim, boolean useSubset) {
+        this(imgDim, null, useSubset);
+    }
+
     public LFWLoader(int[] imgDim, ImageTransform imgTransform, boolean useSubset) {
         this.height = imgDim[0];
         this.width = imgDim[1];
@@ -101,6 +105,17 @@ public class LFWLoader extends BaseImageLoader implements Serializable {
         generateLfwMaps();
     }
 
+    public LFWLoader(long[] imgDim, ImageTransform imgTransform, boolean useSubset) {
+        this.height = imgDim[0];
+        this.width = imgDim[1];
+        this.channels = imgDim[2];
+        this.imageTransform = imgTransform;
+        this.useSubset = useSubset;
+        this.localDir = useSubset ? localSubDir : localDir;
+        this.fullDir = new File(BASE_DIR, localDir);
+        generateLfwMaps();
+    }
+
     public void generateLfwMaps() {
         if (useSubset) {
             // Subset of just faces with a name starting with A
@@ -124,7 +139,7 @@ public class LFWLoader extends BaseImageLoader implements Serializable {
         load(NUM_IMAGES, NUM_IMAGES, NUM_LABELS, LABEL_PATTERN, 1, rng);
     }
 
-    public void load(int batchSize, int numExamples, int numLabels, PathLabelGenerator labelGenerator,
+    public void load(long batchSize, long numExamples, long numLabels, PathLabelGenerator labelGenerator,
                     double splitTrainTest, Random rng) {
         if (!imageFilesExist()) {
             if (!fullDir.exists() || fullDir.listFiles() == null || fullDir.listFiles().length == 0) {
@@ -163,42 +178,69 @@ public class LFWLoader extends BaseImageLoader implements Serializable {
     }
 
 
-    public RecordReader getRecordReader(int numExamples) {
-        return getRecordReader(numExamples, numExamples, new int[] {height, width, channels},
+    public RecordReader getRecordReader(long numExamples) {
+        return getRecordReader(numExamples, numExamples, new long[] {height, width, channels},
                         useSubset ? SUB_NUM_LABELS : NUM_LABELS, LABEL_PATTERN, true, 1,
                         new Random(System.currentTimeMillis()));
     }
 
-    public RecordReader getRecordReader(int batchSize, int numExamples, int numLabels, Random rng) {
-        return getRecordReader(numExamples, batchSize, new int[] {height, width, channels}, numLabels, LABEL_PATTERN,
+    public RecordReader getRecordReader(long batchSize, long numExamples, long numLabels, Random rng) {
+        return getRecordReader(numExamples, batchSize, new long[] {height, width, channels}, numLabels, LABEL_PATTERN,
                         true, 1, rng);
     }
 
-    public RecordReader getRecordReader(int batchSize, int numExamples, boolean train, double splitTrainTest) {
-        return getRecordReader(numExamples, batchSize, new int[] {height, width, channels},
+    public RecordReader getRecordReader(long batchSize, long numExamples, boolean train, double splitTrainTest) {
+        return getRecordReader(numExamples, batchSize, new long[] {height, width, channels},
                         useSubset ? SUB_NUM_LABELS : NUM_LABELS, LABEL_PATTERN, train, splitTrainTest,
                         new Random(System.currentTimeMillis()));
     }
 
-    public RecordReader getRecordReader(int batchSize, int numExamples, int[] imgDim, boolean train,
+    public RecordReader getRecordReader(long batchSize, long numExamples, int[] imgDim, boolean train,
                     double splitTrainTest, Random rng) {
         return getRecordReader(numExamples, batchSize, imgDim, useSubset ? SUB_NUM_LABELS : NUM_LABELS, LABEL_PATTERN,
                         train, splitTrainTest, rng);
     }
 
-    public RecordReader getRecordReader(int batchSize, int numExamples, PathLabelGenerator labelGenerator,
+    public RecordReader getRecordReader(long batchSize, long numExamples, long[] imgDim, boolean train,
+                    double splitTrainTest, Random rng) {
+        return getRecordReader(numExamples, batchSize, imgDim, useSubset ? SUB_NUM_LABELS : NUM_LABELS, LABEL_PATTERN,
+                        train, splitTrainTest, rng);
+    }
+
+    public RecordReader getRecordReader(long batchSize, long numExamples, PathLabelGenerator labelGenerator,
                     boolean train, double splitTrainTest, Random rng) {
-        return getRecordReader(numExamples, batchSize, new int[] {height, width, channels},
+        return getRecordReader(numExamples, batchSize, new long[] {height, width, channels},
                         useSubset ? SUB_NUM_LABELS : NUM_LABELS, labelGenerator, train, splitTrainTest, rng);
     }
 
-    public RecordReader getRecordReader(int batchSize, int numExamples, int[] imgDim, PathLabelGenerator labelGenerator,
+    public RecordReader getRecordReader(long batchSize, long numExamples, int[] imgDim, PathLabelGenerator labelGenerator,
                     boolean train, double splitTrainTest, Random rng) {
         return getRecordReader(numExamples, batchSize, imgDim, useSubset ? SUB_NUM_LABELS : NUM_LABELS, labelGenerator,
                         train, splitTrainTest, rng);
     }
 
-    public RecordReader getRecordReader(int batchSize, int numExamples, int[] imgDim, int numLabels,
+    public RecordReader getRecordReader(long batchSize, long numExamples, long[] imgDim, PathLabelGenerator labelGenerator,
+                    boolean train, double splitTrainTest, Random rng) {
+        return getRecordReader(numExamples, batchSize, imgDim, useSubset ? SUB_NUM_LABELS : NUM_LABELS, labelGenerator,
+                        train, splitTrainTest, rng);
+    }
+
+    public RecordReader getRecordReader(long batchSize, long numExamples, int[] imgDim, long numLabels,
+                    PathLabelGenerator labelGenerator, boolean train, double splitTrainTest, Random rng) {
+        load(batchSize, numExamples, numLabels, labelGenerator, splitTrainTest, rng);
+        RecordReader recordReader =
+                        new ImageRecordReader(imgDim[0], imgDim[1], imgDim[2], labelGenerator, imageTransform);
+
+        try {
+            InputSplit data = train ? inputSplit[0] : inputSplit[1];
+            recordReader.initialize(data);
+        } catch (IOException | InterruptedException e) {
+            e.printStackTrace();
+        }
+        return recordReader;
+    }
+
+    public RecordReader getRecordReader(long batchSize, long numExamples, long[] imgDim, long numLabels,
                     PathLabelGenerator labelGenerator, boolean train, double splitTrainTest, Random rng) {
         load(batchSize, numExamples, numLabels, labelGenerator, splitTrainTest, rng);
         RecordReader recordReader =
diff --git a/datavec/datavec-data/datavec-data-image/src/main/java/org/datavec/image/loader/NativeImageLoader.java b/datavec/datavec-data/datavec-data-image/src/main/java/org/datavec/image/loader/NativeImageLoader.java
index fb3608f989..09e265201f 100644
--- a/datavec/datavec-data/datavec-data-image/src/main/java/org/datavec/image/loader/NativeImageLoader.java
+++ b/datavec/datavec-data/datavec-data-image/src/main/java/org/datavec/image/loader/NativeImageLoader.java
@@ -46,7 +46,7 @@ import static org.bytedeco.javacpp.opencv_imgproc.*;
  * @author saudet
  */
 public class NativeImageLoader extends BaseImageLoader {
-    private static final int MIN_BUFFER_STEP_SIZE = 1024*1024;
+    private static final int MIN_BUFFER_STEP_SIZE = 64 * 1024;
     private byte[] buffer = null;
     private Mat bufferMat = null;
 
@@ -72,7 +72,7 @@ public class NativeImageLoader extends BaseImageLoader {
      * @param width  the width to load
     
      */
-    public NativeImageLoader(int height, int width) {
+    public NativeImageLoader(long height, long width) {
         this.height = height;
         this.width = width;
     }
@@ -85,7 +85,7 @@ public class NativeImageLoader extends BaseImageLoader {
      * @param width  the width to load
      * @param channels the number of channels for the image*
      */
-    public NativeImageLoader(int height, int width, int channels) {
+    public NativeImageLoader(long height, long width, long channels) {
         this.height = height;
         this.width = width;
         this.channels = channels;
@@ -99,7 +99,7 @@ public class NativeImageLoader extends BaseImageLoader {
      * @param channels the number of channels for the image*
      * @param centerCropIfNeeded to crop before rescaling and converting
      */
-    public NativeImageLoader(int height, int width, int channels, boolean centerCropIfNeeded) {
+    public NativeImageLoader(long height, long width, long channels, boolean centerCropIfNeeded) {
         this(height, width, channels);
         this.centerCropIfNeeded = centerCropIfNeeded;
     }
@@ -112,7 +112,7 @@ public class NativeImageLoader extends BaseImageLoader {
      * @param channels the number of channels for the image*
      * @param imageTransform to use before rescaling and converting
      */
-    public NativeImageLoader(int height, int width, int channels, ImageTransform imageTransform) {
+    public NativeImageLoader(long height, long width, long channels, ImageTransform imageTransform) {
         this(height, width, channels);
         this.imageTransform = imageTransform;
     }
@@ -125,7 +125,7 @@ public class NativeImageLoader extends BaseImageLoader {
      * @param channels the number of channels for the image*
      * @param mode how to load multipage image
      */
-    public NativeImageLoader(int height, int width, int channels, MultiPageMode mode) {
+    public NativeImageLoader(long height, long width, long channels, MultiPageMode mode) {
         this(height, width, channels);
         this.multiPageMode = mode;
     }
@@ -347,9 +347,9 @@ public class NativeImageLoader extends BaseImageLoader {
 
 
     protected void fillNDArray(Mat image, INDArray ret) {
-        int rows = image.rows();
-        int cols = image.cols();
-        int channels = image.channels();
+        long rows = image.rows();
+        long cols = image.cols();
+        long channels = image.channels();
 
         if (ret.lengthLong() != rows * cols * channels) {
             throw new ND4JIllegalStateException("INDArray provided to store image not equal to image: {channels: "
@@ -369,9 +369,9 @@ public class NativeImageLoader extends BaseImageLoader {
                             new long[] {channels, rows, cols}, new long[] {stride[0], stride[1], stride[2]}, direct);
             if (idx instanceof UByteIndexer) {
                 UByteIndexer ubyteidx = (UByteIndexer) idx;
-                for (int k = 0; k < channels; k++) {
-                    for (int i = 0; i < rows; i++) {
-                        for (int j = 0; j < cols; j++) {
+                for (long k = 0; k < channels; k++) {
+                    for (long i = 0; i < rows; i++) {
+                        for (long j = 0; j < cols; j++) {
                             retidx.put(k, i, j, ubyteidx.get(i, j, k));
                         }
                     }
@@ -379,9 +379,9 @@ public class NativeImageLoader extends BaseImageLoader {
                 done = true;
             } else if (idx instanceof UShortIndexer) {
                 UShortIndexer ushortidx = (UShortIndexer) idx;
-                for (int k = 0; k < channels; k++) {
-                    for (int i = 0; i < rows; i++) {
-                        for (int j = 0; j < cols; j++) {
+                for (long k = 0; k < channels; k++) {
+                    for (long i = 0; i < rows; i++) {
+                        for (long j = 0; j < cols; j++) {
                             retidx.put(k, i, j, ushortidx.get(i, j, k));
                         }
                     }
@@ -389,9 +389,9 @@ public class NativeImageLoader extends BaseImageLoader {
                 done = true;
             } else if (idx instanceof IntIndexer) {
                 IntIndexer intidx = (IntIndexer) idx;
-                for (int k = 0; k < channels; k++) {
-                    for (int i = 0; i < rows; i++) {
-                        for (int j = 0; j < cols; j++) {
+                for (long k = 0; k < channels; k++) {
+                    for (long i = 0; i < rows; i++) {
+                        for (long j = 0; j < cols; j++) {
                             retidx.put(k, i, j, intidx.get(i, j, k));
                         }
                     }
@@ -399,9 +399,9 @@ public class NativeImageLoader extends BaseImageLoader {
                 done = true;
             } else if (idx instanceof FloatIndexer) {
                 FloatIndexer floatidx = (FloatIndexer) idx;
-                for (int k = 0; k < channels; k++) {
-                    for (int i = 0; i < rows; i++) {
-                        for (int j = 0; j < cols; j++) {
+                for (long k = 0; k < channels; k++) {
+                    for (long i = 0; i < rows; i++) {
+                        for (long j = 0; j < cols; j++) {
                             retidx.put(k, i, j, floatidx.get(i, j, k));
                         }
                     }
@@ -413,9 +413,9 @@ public class NativeImageLoader extends BaseImageLoader {
                             new long[] {channels, rows, cols}, new long[] {stride[0], stride[1], stride[2]}, direct);
             if (idx instanceof UByteIndexer) {
                 UByteIndexer ubyteidx = (UByteIndexer) idx;
-                for (int k = 0; k < channels; k++) {
-                    for (int i = 0; i < rows; i++) {
-                        for (int j = 0; j < cols; j++) {
+                for (long k = 0; k < channels; k++) {
+                    for (long i = 0; i < rows; i++) {
+                        for (long j = 0; j < cols; j++) {
                             retidx.put(k, i, j, ubyteidx.get(i, j, k));
                         }
                     }
@@ -423,9 +423,9 @@ public class NativeImageLoader extends BaseImageLoader {
                 done = true;
             } else if (idx instanceof UShortIndexer) {
                 UShortIndexer ushortidx = (UShortIndexer) idx;
-                for (int k = 0; k < channels; k++) {
-                    for (int i = 0; i < rows; i++) {
-                        for (int j = 0; j < cols; j++) {
+                for (long k = 0; k < channels; k++) {
+                    for (long i = 0; i < rows; i++) {
+                        for (long j = 0; j < cols; j++) {
                             retidx.put(k, i, j, ushortidx.get(i, j, k));
                         }
                     }
@@ -433,9 +433,9 @@ public class NativeImageLoader extends BaseImageLoader {
                 done = true;
             } else if (idx instanceof IntIndexer) {
                 IntIndexer intidx = (IntIndexer) idx;
-                for (int k = 0; k < channels; k++) {
-                    for (int i = 0; i < rows; i++) {
-                        for (int j = 0; j < cols; j++) {
+                for (long k = 0; k < channels; k++) {
+                    for (long i = 0; i < rows; i++) {
+                        for (long j = 0; j < cols; j++) {
                             retidx.put(k, i, j, intidx.get(i, j, k));
                         }
                     }
@@ -443,9 +443,9 @@ public class NativeImageLoader extends BaseImageLoader {
                 done = true;
             } else if (idx instanceof FloatIndexer) {
                 FloatIndexer floatidx = (FloatIndexer) idx;
-                for (int k = 0; k < channels; k++) {
-                    for (int i = 0; i < rows; i++) {
-                        for (int j = 0; j < cols; j++) {
+                for (long k = 0; k < channels; k++) {
+                    for (long i = 0; i < rows; i++) {
+                        for (long j = 0; j < cols; j++) {
                             retidx.put(k, i, j, floatidx.get(i, j, k));
                         }
                     }
@@ -456,9 +456,9 @@ public class NativeImageLoader extends BaseImageLoader {
 
 
         if (!done) {
-            for (int k = 0; k < channels; k++) {
-                for (int i = 0; i < rows; i++) {
-                    for (int j = 0; j < cols; j++) {
+            for (long k = 0; k < channels; k++) {
+                for (long i = 0; i < rows; i++) {
+                    for (long j = 0; j < cols; j++) {
                         if (channels > 1) {
                             ret.putScalar(k, i, j, idx.getDouble(i, j, k));
                         } else {
@@ -522,7 +522,7 @@ public class NativeImageLoader extends BaseImageLoader {
             int code = -1;
             switch (image.channels()) {
                 case 1:
-                    switch (channels) {
+                    switch ((int)channels) {
                         case 3:
                             code = CV_GRAY2BGR;
                             break;
@@ -532,7 +532,7 @@ public class NativeImageLoader extends BaseImageLoader {
                     }
                     break;
                 case 3:
-                    switch (channels) {
+                    switch ((int)channels) {
                         case 1:
                             code = CV_BGR2GRAY;
                             break;
@@ -542,7 +542,7 @@ public class NativeImageLoader extends BaseImageLoader {
                     }
                     break;
                 case 4:
-                    switch (channels) {
+                    switch ((int)channels) {
                         case 1:
                             code = CV_RGBA2GRAY;
                             break;
@@ -617,10 +617,12 @@ public class NativeImageLoader extends BaseImageLoader {
         return scalingIfNeed(image, height, width);
     }
 
-    protected Mat scalingIfNeed(Mat image, int dstHeight, int dstWidth) {
+    protected Mat scalingIfNeed(Mat image, long dstHeight, long dstWidth) {
         Mat scaled = image;
         if (dstHeight > 0 && dstWidth > 0 && (image.rows() != dstHeight || image.cols() != dstWidth)) {
-            resize(image, scaled = new Mat(), new Size(dstWidth, dstHeight));
+            resize(image, scaled = new Mat(), new Size(
+                    (int)Math.min(dstWidth, Integer.MAX_VALUE),
+                    (int)Math.min(dstHeight, Integer.MAX_VALUE)));
         }
         return scaled;
     }
@@ -708,7 +710,8 @@ public class NativeImageLoader extends BaseImageLoader {
         if (dataType < 0) {
             dataType = pointer instanceof DoublePointer ? CV_64F : CV_32F;
         }
-        Mat mat = new Mat(rows, cols, CV_MAKETYPE(dataType, (int) channels));
+        Mat mat = new Mat((int)Math.min(rows, Integer.MAX_VALUE), (int)Math.min(cols, Integer.MAX_VALUE),
+                CV_MAKETYPE(dataType, (int)Math.min(channels, Integer.MAX_VALUE)));
         boolean direct = !Loader.getPlatform().startsWith("android");
         Indexer matidx = mat.createIndexer(direct);
 
@@ -718,9 +721,9 @@ public class NativeImageLoader extends BaseImageLoader {
             FloatIndexer ptridx = FloatIndexer.create((FloatPointer)pointer, new long[] {channels, rows, cols},
                     new long[] {stride[rank == 3 ? 0 : 1], stride[rank == 3 ? 1 : 2], stride[rank == 3 ? 2 : 3]}, direct);
             FloatIndexer idx = (FloatIndexer)matidx;
-            for (int k = 0; k < channels; k++) {
-                for (int i = 0; i < rows; i++) {
-                    for (int j = 0; j < cols; j++) {
+            for (long k = 0; k < channels; k++) {
+                for (long i = 0; i < rows; i++) {
+                    for (long j = 0; j < cols; j++) {
                         idx.put(i, j, k, ptridx.get(k, i, j));
                     }
                 }
@@ -730,9 +733,9 @@ public class NativeImageLoader extends BaseImageLoader {
             DoubleIndexer ptridx = DoubleIndexer.create((DoublePointer)pointer, new long[] {channels, rows, cols},
                     new long[] {stride[rank == 3 ? 0 : 1], stride[rank == 3 ? 1 : 2], stride[rank == 3 ? 2 : 3]}, direct);
             DoubleIndexer idx = (DoubleIndexer)matidx;
-            for (int k = 0; k < channels; k++) {
-                for (int i = 0; i < rows; i++) {
-                    for (int j = 0; j < cols; j++) {
+            for (long k = 0; k < channels; k++) {
+                for (long i = 0; i < rows; i++) {
+                    for (long j = 0; j < cols; j++) {
                         idx.put(i, j, k, ptridx.get(k, i, j));
                     }
                 }
@@ -741,9 +744,9 @@ public class NativeImageLoader extends BaseImageLoader {
         }
 
         if (!done) {
-            for (int k = 0; k < channels; k++) {
-                for (int i = 0; i < rows; i++) {
-                    for (int j = 0; j < cols; j++) {
+            for (long k = 0; k < channels; k++) {
+                for (long i = 0; i < rows; i++) {
+                    for (long j = 0; j < cols; j++) {
                         if (rank == 3) {
                             matidx.putDouble(new long[] {i, j, k}, array.getDouble(k, i, j));
                         } else {
@@ -764,7 +767,7 @@ public class NativeImageLoader extends BaseImageLoader {
      * @return INDArray
      * @throws IOException
      */
-    private INDArray asMatrix(BytePointer bytes, int length) throws IOException {
+    private INDArray asMatrix(BytePointer bytes, long length) throws IOException {
         PIXA pixa;
         pixa = pixaReadMemMultipageTiff(bytes, length);
         INDArray data;
diff --git a/datavec/datavec-data/datavec-data-image/src/main/java/org/datavec/image/recordreader/BaseImageRecordReader.java b/datavec/datavec-data/datavec-data-image/src/main/java/org/datavec/image/recordreader/BaseImageRecordReader.java
index 4da2ec5477..383ef3e3fd 100644
--- a/datavec/datavec-data/datavec-data-image/src/main/java/org/datavec/image/recordreader/BaseImageRecordReader.java
+++ b/datavec/datavec-data/datavec-data-image/src/main/java/org/datavec/image/recordreader/BaseImageRecordReader.java
@@ -67,7 +67,7 @@ public abstract class BaseImageRecordReader extends BaseRecordReader {
     protected boolean writeLabel = false;
     protected List<Writable> record;
     protected boolean hitImage = false;
-    protected int height = 28, width = 28, channels = 1;
+    protected long height = 28, width = 28, channels = 1;
     protected boolean cropImage = false;
     protected ImageTransform imageTransform;
     protected BaseImageLoader imageLoader;
@@ -86,20 +86,20 @@ public abstract class BaseImageRecordReader extends BaseRecordReader {
 
     public BaseImageRecordReader() {}
 
-    public BaseImageRecordReader(int height, int width, int channels, PathLabelGenerator labelGenerator) {
+    public BaseImageRecordReader(long height, long width, long channels, PathLabelGenerator labelGenerator) {
         this(height, width, channels, labelGenerator, null);
     }
 
-    public BaseImageRecordReader(int height, int width, int channels, PathMultiLabelGenerator labelGenerator) {
+    public BaseImageRecordReader(long height, long width, long channels, PathMultiLabelGenerator labelGenerator) {
         this(height, width, channels, null, labelGenerator,null);
     }
 
-    public BaseImageRecordReader(int height, int width, int channels, PathLabelGenerator labelGenerator,
+    public BaseImageRecordReader(long height, long width, long channels, PathLabelGenerator labelGenerator,
                                  ImageTransform imageTransform) {
         this(height, width, channels, labelGenerator, null, imageTransform);
     }
 
-    protected BaseImageRecordReader(int height, int width, int channels, PathLabelGenerator labelGenerator,
+    protected BaseImageRecordReader(long height, long width, long channels, PathLabelGenerator labelGenerator,
                                     PathMultiLabelGenerator labelMultiGenerator, ImageTransform imageTransform) {
         this.height = height;
         this.width = width;
@@ -173,9 +173,9 @@ public abstract class BaseImageRecordReader extends BaseRecordReader {
     public void initialize(Configuration conf, InputSplit split) throws IOException, InterruptedException {
         this.appendLabel = conf.getBoolean(APPEND_LABEL, appendLabel);
         this.labels = new ArrayList<>(conf.getStringCollection(LABELS));
-        this.height = conf.getInt(HEIGHT, height);
-        this.width = conf.getInt(WIDTH, width);
-        this.channels = conf.getInt(CHANNELS, channels);
+        this.height = conf.getLong(HEIGHT, height);
+        this.width = conf.getLong(WIDTH, width);
+        this.channels = conf.getLong(CHANNELS, channels);
         this.cropImage = conf.getBoolean(CROP_IMAGE, cropImage);
         if ("imageio".equals(conf.get(IMAGE_LOADER))) {
             this.imageLoader = new ImageLoader(height, width, channels, cropImage);
@@ -327,7 +327,7 @@ public abstract class BaseImageRecordReader extends BaseRecordReader {
             cnt++;
         }
 
-        INDArray features = Nd4j.createUninitialized(new int[] {cnt, channels, height, width}, 'c');
+        INDArray features = Nd4j.createUninitialized(new long[] {cnt, channels, height, width}, 'c');
         Nd4j.getAffinityManager().tagLocation(features, AffinityManager.Location.HOST);
         for (int i = 0; i < cnt; i++) {
             try {
diff --git a/datavec/datavec-data/datavec-data-image/src/main/java/org/datavec/image/recordreader/ImageRecordReader.java b/datavec/datavec-data/datavec-data-image/src/main/java/org/datavec/image/recordreader/ImageRecordReader.java
index 0855f04cfa..7195ea4790 100644
--- a/datavec/datavec-data/datavec-data-image/src/main/java/org/datavec/image/recordreader/ImageRecordReader.java
+++ b/datavec/datavec-data/datavec-data-image/src/main/java/org/datavec/image/recordreader/ImageRecordReader.java
@@ -40,38 +40,38 @@ public class ImageRecordReader extends BaseImageRecordReader {
     }
 
     /** Loads images with given height, width, and channels, appending labels returned by the generator. */
-    public ImageRecordReader(int height, int width, int channels, PathLabelGenerator labelGenerator) {
+    public ImageRecordReader(long height, long width, long channels, PathLabelGenerator labelGenerator) {
         super(height, width, channels, labelGenerator);
     }
 
     /** Loads images with given height, width, and channels, appending labels returned by the generator. */
-    public ImageRecordReader(int height, int width, int channels, PathMultiLabelGenerator labelGenerator) {
+    public ImageRecordReader(long height, long width, long channels, PathMultiLabelGenerator labelGenerator) {
         super(height, width, channels, labelGenerator);
     }
 
     /** Loads images with given height, width, and channels, appending no labels. */
-    public ImageRecordReader(int height, int width, int channels) {
+    public ImageRecordReader(long height, long width, long channels) {
         super(height, width, channels, (PathLabelGenerator) null);
     }
 
     /** Loads images with given height, width, and channels, appending labels returned by the generator. */
-    public ImageRecordReader(int height, int width, int channels, PathLabelGenerator labelGenerator,
+    public ImageRecordReader(long height, long width, long channels, PathLabelGenerator labelGenerator,
                     ImageTransform imageTransform) {
         super(height, width, channels, labelGenerator, imageTransform);
     }
 
     /** Loads images with given height, width, and channels, appending no labels. */
-    public ImageRecordReader(int height, int width, int channels, ImageTransform imageTransform) {
+    public ImageRecordReader(long height, long width, long channels, ImageTransform imageTransform) {
         super(height, width, channels, null, imageTransform);
     }
 
     /** Loads images with given  height, width, and channels, appending labels returned by the generator. */
-    public ImageRecordReader(int height, int width, PathLabelGenerator labelGenerator) {
+    public ImageRecordReader(long height, long width, PathLabelGenerator labelGenerator) {
         super(height, width, 1, labelGenerator);
     }
 
     /** Loads images with given height, width, and channels = 1, appending no labels. */
-    public ImageRecordReader(int height, int width) {
+    public ImageRecordReader(long height, long width) {
         super(height, width, 1, null, null);
     }
 
diff --git a/datavec/datavec-data/datavec-data-image/src/test/java/org/datavec/image/loader/LoaderTests.java b/datavec/datavec-data/datavec-data-image/src/test/java/org/datavec/image/loader/LoaderTests.java
index d78e356bcb..28791810d0 100644
--- a/datavec/datavec-data/datavec-data-image/src/test/java/org/datavec/image/loader/LoaderTests.java
+++ b/datavec/datavec-data/datavec-data-image/src/test/java/org/datavec/image/loader/LoaderTests.java
@@ -56,7 +56,7 @@ public class LoaderTests {
         rr.initialize(inputSplit[0]);
         List<String> exptedLabel = rr.getLabels();
 
-        RecordReader rr2 = new LFWLoader(new int[] {250, 250, 3}, true).getRecordReader(1, 1, 1, new Random(42));
+        RecordReader rr2 = new LFWLoader(new long[] {250, 250, 3}, true).getRecordReader(1, 1, 1, new Random(42));
 
         assertEquals(exptedLabel.get(0), rr2.getLabels().get(0));
     }
diff --git a/datavec/datavec-data/datavec-data-image/src/test/java/org/datavec/image/loader/TestNativeImageLoader.java b/datavec/datavec-data/datavec-data-image/src/test/java/org/datavec/image/loader/TestNativeImageLoader.java
index 6a161f83ab..a81728d526 100644
--- a/datavec/datavec-data/datavec-data-image/src/test/java/org/datavec/image/loader/TestNativeImageLoader.java
+++ b/datavec/datavec-data/datavec-data-image/src/test/java/org/datavec/image/loader/TestNativeImageLoader.java
@@ -121,7 +121,7 @@ public class TestNativeImageLoader {
         assertEquals(w4, array6.size(3));
 
         int ch5 = 4, pages1 = 1;
-        NativeImageLoader loader6 = new NativeImageLoader(h4, w4, ch5, NativeImageLoader.MultiPageMode.CHANNELS);
+        NativeImageLoader loader6 = new NativeImageLoader(h4, w4, 1, NativeImageLoader.MultiPageMode.CHANNELS);
         INDArray array7 = null;
         try {
             array7 = loader6.asMatrix(
@@ -249,6 +249,14 @@ public class TestNativeImageLoader {
         Java2DNativeImageLoader loader4 = new Java2DNativeImageLoader();
         BufferedImage img12 = loader4.asBufferedImage(array1);
         assertEquals(array1, loader4.asMatrix(img12));
+
+        NativeImageLoader loader5 = new NativeImageLoader(0, 0, 0);
+        INDArray array7 = loader5.asMatrix(f3);
+        assertEquals(4, array7.rank());
+        assertEquals(1, array7.size(0));
+        assertEquals(3, array7.size(1));
+        assertEquals(32, array7.size(2));
+        assertEquals(32, array7.size(3));
     }
 
     @Test