[HTML5]使用Canvas處理濾鏡效果

  • 1960
  • 0
  • 2016-03-05

摘要:[HTML5]使用Canvas處理濾鏡效果

Canvas是HTML中的一個元素<canvas>,跟<img>有點像,但<img>只是用來顯示圖片,<canvas>卻可以用來對圖片進行加工處理。既然可以對圖片進行加工,所以用Canvas做濾鏡效果,也是很合理的一件事。這次要做的事情,是透過file input來選取電腦上的圖片檔,在透過canvas加上不同濾鏡,顯示在網頁上。其效果如下所示:

 

 

Canvas概念


在實作之前,要瞭解一些基本的Canvas概念。<casvas>是畫布的概念,可以在上面繪製圓形、長方形,也可以把圖片檔畫上去。這些繪製的動作,其實是交由一個由canvas產生的Context物件進行處理。因為我們繪製的是平面的圖片,所以是透過以下的參數以取得Context物件。

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

 

取得Context物件後,就可以開始在畫布上畫些東西。如果要把圖片檔畫在畫布上,就需要使用Context物件的drawImage() 函數。drawImage()可以接受以下幾種資料型態作為繪圖的來源:

  • <img> element:除了<img>元素外,也包含用Image() 建立的Image物件
  • <video> element:可抓取影片的畫格畫在canvas上
  • <canvas> element:可把另一個canvas元素內容畫在目前的canvas上

 

讀取本機圖片檔


除了由<img>取得Image物件外,另一個更自由的方式是透過file input來選取自己電腦上的圖片檔。只要透過HTML5的FileReader API的readAsDataURL(),就可以輕鬆地將本機的圖片檔讀進瀏覽器中。之後,就可以把該圖片檔當作drawImage()的資料來源,畫在<canvas>畫布上。

var reader = new FileReader();
var file = document.getElementById("fileUploadBtn").files[0];
reader.readAsDataURL(file);
reader.onload = function(e){   
	//讀取檔案完成後,繼續進行圖片的處理工作
	
}

 

建立縮圖用的Canvas


取得檔案後,考量到圖片的尺寸可能很大,所以可以使用Canvas把影像畫得小一點。Canvas可以指定把影像畫成不同尺寸,利用這個特性,就可以做到縮圖的效果。

var tempCanvas = document.createElement('canvas');
var thumbnailsSize = getSizeByMaxLength(img.width,img.height,200);
tempCanvas.width = thumbnailsSize.width;
tempCanvas.height = thumbnailsSize.height;
tempCanvas.getContext('2d').drawImage(img, 0, 0, thumbnailsSize.width, thumbnailsSize.height);

 

濾鏡效果


想要做到濾鏡效果,就需要透過Context物件的getImageData()函式以取得ImageData物件。ImageData物件定義了canvas 上的pixel資訊,它是一個陣列,內容記錄了每個pixel的RGBA值。透過數學函式運算這些RBGA值,就可以做到濾鏡的效果。這個網頁-Image Filters with Canvas介紹了一些簡單的濾鏡效果的處理方式。我將其中幾個列出如下:

var Filters = {
  
  getPixels: function(img) {
    var c = this.getCanvas(img.width, img.height);
    var ctx = c.getContext('2d');
    ctx.drawImage(img,0,0);
    return ctx.getImageData(0,0,c.width,c.height);
  },

  getCanvas: function(w,h) {
    var c = document.createElement('canvas');
    c.width = w;
    c.height = h;
    return c;
  },

  filterImage: function(filter, image, var_args) {
    var args = [this.getPixels(image)];
    for (var i=2; i<arguments.length; i++) {
      args.push(arguments[i]);
    }
    return filter.apply(null, args);
  },

  grayscale: function(pixels, args) {
    var d = pixels.data;
    for (var i=0; i<d.length; i+=4) {
      var r = d[i];
      var g = d[i+1];
      var b = d[i+2];
      var v = 0.2126*r + 0.7152*g + 0.0722*b;
      d[i] = d[i+1] = d[i+2] = v;
    }
    return pixels;
  },

  brightness: function(pixels, adjustment) {
    var d = pixels.data;
    for (var i=0; i<d.length; i+=4) {
      d[i] += adjustment;
      d[i+1] += adjustment;
      d[i+2] += adjustment;
    }
    return pixels;
  },

  threshold: function(pixels, threshold) {
    var d = pixels.data;
    for (var i=0; i<d.length; i+=4) {
      var r = d[i];
      var g = d[i+1];
      var b = d[i+2];
      var v = (0.2126*r + 0.7152*g + 0.0722*b >= threshold) ? 255 : 0;
      d[i] = d[i+1] = d[i+2] = v;
    }
    return pixels;
  }

}

 

最後,將以上的資訊全部集合在一起,就可以做到我們所要的功能。這個Demo放在以下的JS Bin中

JS Bin on jsbin.com

 


參考資訊: