code: public static INDArray im2col(INDArray img, int kh, int kw, int sy, int sx, int ph, int pw, int pval,
                      boolean coverAll) {
          //number of images
          long n = img.size(0);
          //number of channels (depth)
          long c = img.size(1);
          //image height
          long h = img.size(2);
          //image width
          long w = img.size(3);
          long outHeight = outSize(h, kh, sy, ph, coverAll);
          long outWidth = outSize(w, kw, sx, pw, coverAll);
          INDArray padded = Nd4j.pad(img, new int[][] {{0, 0}, {0, 0}, {ph, ph + sy - 1}, {pw, pw + sx - 1}},
                          Nd4j.PadMode.CONSTANT);
          INDArray ret = Nd4j.create(n, c, kh, kw, outHeight, outWidth);
          for (int i = 0; i < kh; i++) {
              //offset for the row based on the stride and output height
              long iLim = i + sy * outHeight;
              for (int j = 0; j < kw; j++) {
                  //offset for the column based on stride and output width
                  long jLim = j + sx * outWidth;
                  INDArray get = padded.get(NDArrayIndex.all(), NDArrayIndex.all(), NDArrayIndex.interval(i, sy, iLim),
                                  NDArrayIndex.interval(j, sx, jLim));
                  ret.put(new INDArrayIndex[] {NDArrayIndex.all(), NDArrayIndex.all(), NDArrayIndex.point(i),
                                  NDArrayIndex.point(j), NDArrayIndex.all(), NDArrayIndex.all()}, get);
              }
          }
          return ret;
      }
docs: Implement column formatted images
  @param img the image to process
  @param kh the kernel height
  @param kw the kernel width
  @param sy the stride along y
  @param sx the stride along x
  @param ph the padding width
  @param pw the padding height
  @param pval the padding value
  @param coverAll whether to cover the whole image or not
  @return the column formatted image