How fast can I split an image?

One way would be to first extract the ImageData, Partition it, ArrayPad with {1, 1, 1}, convert it to Image, and finally use ImageAssemble.

arrPadImage = (ArrayPad[#, {{1}, {1}}, Hold[{1, 1, 1}]] // ReleaseHold // Image) &;
imagePartitionPad[img_, n_] := 
  Partition[ImageData[img], Floor@(ImageDimensions[img]/n)] // 
   ImageAssemble[Outer[arrPadImage, #, 2]] &;

For the given image, this method takes about 0.34 s compared to yours which takes about 3.63 s.

imagePartitionPad[imsq, 64]

enter image description here

ImageData[imagePartitionPad[imsq, 64]] == ImageData[showParts[splitImage[imsq, 64]]]

True


This is almost the other answer, just slightly more vectorized and using integers for the data array which seems to be faster:

split[img_, n_] := Image[ArrayFlatten[ArrayPad[Partition[
      ImageData[img, "Byte"], Reverse[Floor[ImageDimensions[img]/n]]],
       {{0, 0}, {0, 0}, {1, 1}, {1, 1}}, {{{{{255, 255, 255}}}}}]], "Byte"]

split[ImageAssemble[{{img, img}}], 64]

Edit: To extract parts:

Clear[split];
split[im_, n_] := Partition[ImageData[im, "Byte"], Reverse[Floor[ImageDimensions[im]/n]]]

show[parts_] := Image[ArrayFlatten[ArrayPad[parts, {{0, 0}, {0, 0}, {1, 1}, {1, 1}},
                                                   {{{{{255, 255, 255}}}}}]], "Byte"]

parts = split[ImageAssemble[{{img, img}}], 64];
subImages = Map[Image[#, "Byte"] &, parts, {2}];

show[parts]

Here's a super naive (but nonetheless very fast) method for generating the padded image, not for splitting (since that problem is almost trivially handled via Partition) that preserves the ImageColorSpace and leverages the power of PackedArray by not padding with 1 but rather with 1.:

splitty[img_, n_, padColor : {__?NumericQ} | _?NumericQ : 1] :=

  Module[
   {
    data = ImageData@img,
    dd,
    ins1,
    ins2,
    paddy
    },
   dd = Dimensions[data];
   paddy =
    N@
     Switch[padColor,
      _?NumericQ,
      ConstantArray[padColor, dd[[3]]],
      _,
      PadRight[padColor, dd[[3]], 1][[;; dd[[3]]]]
      ];
   ins1 =
    Insert[data, 
     paddy,
     Flatten[
      Table[
       {i, j},
       {i, 1, dd[[1]]},
       {j, 1, dd[[2]], Floor[dd[[1]]/n]}
       ],
      1
      ]
     ];
   ins2 =
    Insert[
     ins1,
     ConstantArray[paddy, Length@ins1[[1]]],
     List /@ Range[1, Length@ins1,  Floor[dd[[2]]/n]]
     ];
   Image[ins2,
    ColorSpace -> ImageColorSpace@img
    ]
   ];

Note that it performs surprisingly well:

splitty[img, 64] // RepeatedTiming // First

0.014

splitty[img, 64]

asdasdas

And you can insert an arbitrary color:

splitty[img, 100, .5]

graygray

splitty[img, 100, {.6, .6, 0}]

wowwowowow