HTML5 / Canvas / JavaScript – RGB Separator – canvas 3D Effect

HTML5 / Canvas / JavaScript – RGB Separator – canvas 3D Effect

HTML5 / Canvas / JavaScript – RGB Separator – canvas 3D Effect

Years ago … When Flash / ActionScript were king of the hill, we made a simular ActionScript 3.0 – RGB Separator – 3D Effect .. But evolutions do happen… The era of ActionScript is long gone, and front-end technologies have taken over… It was time to port this 3D image overlay effect to modern times. Re-creating the same result from back in the days making use of JavaScript and the HTML5 Canvas element.

With this JavaScript code sample we show how you can extract the RGB channels of a specified Image and create a ‘3D effect’. After the extraction, which returns an array with the different color channels, you can use each color channel for animation, or combine the channels to create a fake 3D-effect like below or go nasty with your own ideas ….

 

Abstract explanation

If you ever used 3D glasses you’ll have noticed that the image is RGB layered. The image is built upon different layers, each in a specific RGB [Red Green Blue] context. To simulate a 3D effect from a plain image, we’ll build a new layered composition of this reference image. Each layer will be representing a specific RGB color layer. Adding a position offset on the individual RGB layers we can produce a nice 3D look-a-like effect.

The JavaScript code will first load the base image, which we’ll use as reference. The base image is not shown on the canvas, but used as data source for generating the specific RGB layers. After creating the 3 seperate RGB layers – we’ll render them to the canvas element – having each a different offset.

 

Base image

 

Final result

DOWNLOAD SOURCE

 

JavaScript code

    // canvas vars 

    var canvas = document.getElementById('canvas');

    var ctx = canvas.getContext('2d');

    ctx.globalCompositeOperation = 'screen';

   

    // source image

    var img = new Image();

    var origData;

    var channels = [];

    img.src = 'image.jpg';

   

    // load initial image

    img.onload = function(){

        // draw & save

        ctx.drawImage(img, 0, 0);

        origData = ctx.getImageData(0, 0, img.width, img.height);

        // render channels

        generateChannels();

        // render channels

        renderChannels('red,blue,green', 3);

    }

   

    // render image from imageData

    function renderImageFromData(data, offset){

        // temp canvas & ctx

        var tempCanvas=document.createElement("canvas");

        var tempCtx=tempCanvas.getContext("2d");

        // set temp canvas size

        tempCanvas.width=canvas.width;

        tempCanvas.height=canvas.height;

        tempCtx.putImageData(data, offset, offset);

        // render

        var imgtemp = new Image();

        imgtemp.onload=function(){

            ctx.drawImage(imgtemp,0,0);

        }

        imgtemp.src = tempCanvas.toDataURL();

        return imgtemp;

    }

   

    // generate seperate RGB channels

    function generateChannels(){

        channels = [];

        channels['red'] = renderChannel(origData.data, "red");     

        channels['blue'] = renderChannel(origData.data, "blue");       

        channels['green'] = renderChannel(origData.data, "green");     

    }

   

    // render RGB channels for 3D effect

    // @param renderChannels - red,green,blue

    // @param offset - number

    function renderChannels(renderChannels, offset){

        // clear canvas before redraw

        ctx.clearRect(0, 0, canvas.width, canvas.height);

        // render seperate RGB channels

        renderChannels = renderChannels.split(',');

        // render channels

        if(renderChannels.indexOf('red') > -1) renderImageFromData(channels['red'], 0);

        if(renderChannels.indexOf('blue') > -1) renderImageFromData(channels['blue'], offset); 

        if(renderChannels.indexOf('green') > -1) renderImageFromData(channels['green'], offset*2);     

    }

   

    // render specific channel

    function renderChannel(data, ch){

        var channel = ctx.createImageData(img.width, img.height);      

        for (var i=0;i < data.length; i+=4) {      

            channel.data[i+0] = (ch === 'red') ?  data[i+0] : 2;

            channel.data[i+1] = (ch === 'green') ? data[i+1] : 0;

            channel.data[i+2] = (ch === 'blue') ?  data[i+2] : 0;

            channel.data[i+3] = data[i+3];

        }

        return channel;

    }

About the Author

Daan is a Creative-Geek who loves learning and sharing new techniques! Follow him on Twitter to keep up to date with the Creative-Geeks blog and other subjects. Contact him on e-mail : info[at]creative-geeks.com.