During my work on the new AIE Ajax Image Editor, I have done some experiments with the new HTML5 features, especially the new Canvas tag. This script is basically a new implementation in JavaScript of a old Director-Movie which I have made about 10 years ago.


Simply move over the image to distort it. Click to switch effect. The script is very simple: first it gets the content of a image ("getImageData"-function).
    window.onload = function() {
      canvas = document.getElementById("area");
      context = canvas.getContext("2d");
      image = document.getElementById("canvasSource");
      context.drawImage(image, 0, 0);
      imgdo = context.getImageData(0, 0, imgsizex, imgsizey);
      document.getElementById("area").onmousemove=draw;
      document.getElementById("area").onclick=function(){ mode++; if(mode>2) mode=0; }; 
    };
Then it distorts the image using some trigonometric functions:
    function draw(){
      var imgd = context.getImageData(0, 0, imgsizex, imgsizey);
      var opix = imgdo.data;
      var npix = imgd.data;
      var mpos={x:100,y:100};
      var area=document.getElementById("area");
      mpos.x=Mouse.x-area.offsetLeft;
      mpos.y=Mouse.y-area.offsetTop;
      for (iy=0; iy90) wd=90;
                  var neww=grad2rad(w+wd/1);
                  var newa=Math.sin(neww)*c;
                  var newb=Math.cos(neww)*c;
                  var z=(iy*imgsizex+ix)*4;
                  var nz=Math.round((Math.round(mpos.y+newb)*imgsizex+Math.round(mpos.x+newa)))*4;
                }else if (mode==1){
                  var wd=90-(c);
                  if (wd<0) wd=0;
                  if (wd>90) wd=90;
                  var neww=grad2rad(w);
                  var newc=c+wd/10;
                  var newa=Math.sin(neww)*newc;
                  var newb=Math.cos(neww)*newc;
                  var z=(iy*imgsizex+ix)*4;
                  var nz=Math.round((Math.round(mpos.y+newb)*imgsizex+Math.round(mpos.x+newa)))*4;
                }else{
                  var wd=(c);
                  if (wd<0) wd=0;
                  if (wd>90) wd=90;
                  var neww=grad2rad(w);
                  var newc=c+wd/10;
                  var newa=Math.sin(neww)*newc;
                  var newb=Math.cos(neww)*newc;
                  var z=(iy*imgsizex+ix)*4;
                  var nz=Math.round((Math.round(mpos.y+newb)*imgsizex+Math.round(mpos.x+newa)))*4;
                }
          npix[z  ] = opix[nz  ] || 0;     // red
          npix[z+1] = opix[nz+1] || 0;     // green
          npix[z+2] = opix[nz+2] || 0;     // blue
        }
      }
      var a=10;
      var b=10;
      var c=Math.sqrt(a*a+b*b);        
      context.putImageData(imgd, 0, 0);
    }
It basically calculates the distance and the angle to the mouse position of every pixel. Then it adds a percentage of the distance to the angle and recalculates the new pixel-position. Then it copies the RGB-value of the pixel at the calculated position in the original image to the pixel in the new image. I have made those functions to convert between Rad and grad and to calculate the angle:
    function rad2grad(rad){
      return rad*180/Math.PI;
    }
    function grad2rad(grad){
      return grad*Math.PI/180;
    }
    function getwinkel(a,b){
      var c=Math.abs(Math.sqrt(Math.abs(a*a)+Math.abs(b*b)));
      var nw=rad2grad(Math.asin(a/c));
      if (a<0 && b<0){
        nw= -nw-180;
      }else if (b<0){
        nw= 180-nw;
      }
      return nw;
    }
...and the complete Code:
var Mouse = {x:0, y:0};
      $(document).mousemove(function(evt) {
        var e = window.event || evt;
        Mouse.x = e.x || e.pageX || 0;
        Mouse.y = e.y || e.pageY || 0;        
      });
      canvas = false;
      context = false;
      image = false;
      imgdo = false;
      imgsizex=140;
      imgsizey=185;
      mode=0;
      function draw(){
        var imgd = context.getImageData(0, 0, imgsizex, imgsizey);
        var opix = imgdo.data;
        var npix = imgd.data;
        var mpos={x:100,y:100};
        var area=document.getElementById("area");
        mpos.x=Mouse.x-area.offsetLeft;
        mpos.y=Mouse.y-area.offsetTop;
        for (iy=0; iy90) wd=90;
              var neww=grad2rad(w+wd/1);
              var newa=Math.sin(neww)*c;
              var newb=Math.cos(neww)*c;
              var z=(iy*imgsizex+ix)*4;
              var nz=Math.round((Math.round(mpos.y+newb)*imgsizex+Math.round(mpos.x+newa)))*4;
            }else if (mode==1){
              var wd=90-(c);
              if (wd<0) wd=0;
              if (wd>90) wd=90;
              var neww=grad2rad(w);
              var newc=c+wd/10;
              var newa=Math.sin(neww)*newc;
              var newb=Math.cos(neww)*newc;
              var z=(iy*imgsizex+ix)*4;
              var nz=Math.round((Math.round(mpos.y+newb)*imgsizex+Math.round(mpos.x+newa)))*4;
            }else{
              var wd=(c);
              if (wd<0) wd=0;
              if (wd>90) wd=90;
              var neww=grad2rad(w);
              var newc=c+wd/10;
              var newa=Math.sin(neww)*newc;
              var newb=Math.cos(neww)*newc;
              var z=(iy*imgsizex+ix)*4;
              var nz=Math.round((Math.round(mpos.y+newb)*imgsizex+Math.round(mpos.x+newa)))*4;
            }
            npix[z  ] = opix[nz  ] || 0;     // red
            npix[z+1] = opix[nz+1] || 0;     // green
            npix[z+2] = opix[nz+2] || 0;     // blue
          }
        }
        var a=10;
        var b=10;
        var c=Math.sqrt(a*a+b*b);        
        context.putImageData(imgd, 0, 0);
      }
      $(window).load(function(){
        canvas = document.getElementById("area");
        context = canvas.getContext("2d");
        image = document.getElementById("canvasSource");
        context.drawImage(image, 0, 0);
        imgdo = context.getImageData(0, 0, imgsizex, imgsizey);
        document.getElementById("area").onmousemove=draw; 
     document.getElementById("area").onclick=function(){ mode++; if(mode>2) mode=0; };
     draw();  
      });
      function rad2grad(rad){
        return rad*180/Math.PI;
      }
      function grad2rad(grad){
        return grad*Math.PI/180;
      }
      function getwinkel(a,b){
        var c=Math.abs(Math.sqrt(Math.abs(a*a)+Math.abs(b*b)));
        var nw=rad2grad(Math.asin(a/c));
        if (a<0 && b<0){
          nw= -nw-180;
        }else if (b<0){
          nw= 180-nw;
        }
        return nw;
      }

Posted on Sep 14, 2010 Tags: javascript programmieren