"Rasterbation" function to split an image into a grid
Before you opt for a &lt;canvas&gt; solution you might try adapting your current code with a few go-faster tricks.

var t = Date.now(); 
var img = new Image();
var length = 30;
var ylength = 20;
img.onload = function() {
    var width = this.width,
        height = this.height,
        _length = -length,
        i, j;

    // create a &lt;div/&gt; with all basic characteristics, to be cloned over and over in the loops below.
    var $basicDiv = jQuery('&lt;div/&gt;', {
        class: 'splitImg',
        css: {
            'width': Math.floor(width/length),
            'height': Math.floor(height/ylength),
            'background-image': 'url(' + img.src + ')'
        }
    });
    // Finding a node in the DOM is slow. Do it once and assign the returned jQuery collection.
    // Also, #wrapper's width can be set here.
    var $wrapper = $('#wrapper').width(width + length * 2); 

    for (i = 0; i &gt; _length; i--) {
        for (j = 0; j &gt; _length; j--) {
            $basicDiv.clone().css({'background-position': `${width/length * j}px ${height/ylength * i}px`}).appendTo($wrapper);
        }
    }
    console.log(Date.now() - t);
}
img.src = 'http://www.jqueryscript.net/images/Simplest-Responsive-jQuery-Image-Lightbox-Plugin-simple-lightbox.jpg';


Updated fiddle

Playing around with the code, I found all of the following to make a difference :


cloning a basic div created outside the nested loops,
avoiding assignments (other than loop counters) in the nested loops,
avoiding the need to multiply by -1 (twice) by counting backwards in the for(...) expressions,
using a template literal to build the background-position string. But beware, this is not yet well supported in browsers.


With the modified code, execution time on my computer halved from about 1200 - 2000 ms to 600 - 1000 ms.

You may well find a &lt;canvas&gt; approach to be even faster. I was surprised at what could be achieved with &lt;canvas&gt; when I wrote this answer.