Slicing an Image into Tiles in JavaScript

When dealing with a large number of images, sometimes it’s easier to group all of them in a single file rather than making a file for each image. This may make it easier to track related images, say, a group of sprites for a video game character. It can also make for more efficient compression, since you don’t need to store as much overhead as you would for a bunch of individual image files. Coincidentally, it also makes it easier to download test images for programs listed in blog posts.

The program shown loads a single image file (provided below as “RedGreenBlueYellow.png”) and breaks it into a bunch of equally sized tiles.

Note that certain browsers may have security features that throw errors if the HTML5 Canvas object’s toDataURL() function is called under certain circumstances. For example, to run the program in Google’s Chrome browser, it is necessary to run “chrome.exe” with the “–allow-file-access-from-files” switch.

var program = new ImageSlicingTest();
program.main();

function ImageSlicingTest()
{    
    this.main = function()
    {    
        var imageToSlice = new Image();
        imageToSlice.onload = main2;
        imageToSlice.src = "RedGreenBlueYellow.png";
    }

    function main2(event)
    {
        var imageToSlice = event.target;

        var imageTiles = new ImageHelper().sliceImageIntoTiles
        (
            imageToSlice,
            new Coords(4, 1)
        );

        var imageTileSize = new Coords(imageTiles[0].width, imageTiles[0].height);

        for (var i = 0; i < imageTiles.length; i++)
        {
            var imageTile = imageTiles[i];

            var drawPos = new Coords(i * 2, 0).multiply(imageTileSize);

            imageTile.style.left = drawPos.x;
            imageTile.style.top = drawPos.y;
            document.body.appendChild(imageTile);    
        }                
    }
}

function Coords(x, y)
{
    this.x = x;
    this.y = y;    

    this.clone = function()
    {
        return new Coords(this.x, this.y);
    }

    this.divide = function(other)
    {
        this.x /= other.x;
        this.y /= other.y;

        return this;
    }

    this.multiply = function(other)
    {
        this.x *= other.x;
        this.y *= other.y;

        return this;
    }

    this.overwriteWith = function(other)
    {
        this.x = other.x;
        this.y = other.y;

        return this;
    }

    this.toString = function()
    {
        return "(" + this.x + "," + this.y + ")";
    }
}

function ImageHelper()
{
    this.sliceImageIntoTiles = function(imageToSlice, sizeInTiles)
    {
        var returnImages = new Array();

        var imageToSliceSize = new Coords(imageToSlice.width, imageToSlice.height);
        var tileSize = imageToSliceSize.clone().divide(sizeInTiles);

        var tilePos = new Coords(0, 0);
        var sourcePos = new Coords(0, 0);

        for (var y = 0; y < sizeInTiles.y; y++)
        {
            tilePos.y = y;

            for (var x = 0; x < sizeInTiles.x; x++)
            {                            
                tilePos.x = x;

                var canvas         = document.createElement("canvas");
                canvas.id         = "tile_" + x + "_" + y;
                canvas.width         = tileSize.x;
                canvas.height         = tileSize.y;
                canvas.style.position     = "absolute";

                var graphics = canvas.getContext("2d");

                sourcePos.overwriteWith(tilePos).multiply(tileSize);

                graphics.drawImage
                (
                    imageToSlice,
                    sourcePos.x, sourcePos.y, // source pos
                    tileSize.x, tileSize.y, // source size
                    0, 0, // destination pos
                    tileSize.x, tileSize.y // destination size
                );

                // browser dependent?
                var imageFromCanvasURL = canvas.toDataURL("image/png");
                var imageFromCanvas = document.createElement("img");
                imageFromCanvas.width = canvas.width;
                imageFromCanvas.height = canvas.height;
                imageFromCanvas.style.position = "absolute";
                imageFromCanvas.src = imageFromCanvasURL;

                returnImages.push(imageFromCanvas);
            }
        }

        return returnImages;
    }
}
About these ads
This entry was posted in Uncategorized and tagged , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s