使用canvas進行圖像處理

使用canvas進行圖像處理

canvas基礎知識:MDN

主要知識點

一、canvas做爲一個繪圖面板,能夠直接的獲取圖像的數據,進而對圖像進行處理。javascript

二、圖像添加水印,縮放圖像,放大鏡效果。html

三、像素級的處理,圖像濾鏡。(本身查閱算法來進行絢麗的變換,這部分是關鍵,找幾個比較有意思的算法來試驗一下)java

四、計算機圖像藝術。算法

canvas圖像基礎  drawImage()  

  基礎知識:chrome

    一、html:<canvas id="canvas"></canvas>canvas

    二、Javascript:var canvas=document.getElementById('canvas');瀏覽器

           var context=canvas.getContext('2d');dom

  canvas繪圖接口:drawImageide

    語法:context.drawImage(image,dx,dy);函數

  將圖像放在畫布當中的代碼:

 1 <!DOCTYPE html>
 2 <html>
 3 <head lang="en">
 4     <meta charset="UTF-8">
 5     <title></title>
 6 </head>
 7 <body>
 8     <canvas id="canvas" style="display:block;margin:0 auto;border:1px solid #aaa;">
 9     您的瀏覽器尚不支持canvas
10     </canvas>
11     <script>
12         var canvas = document.getElementById("canvas"); 13 var context = canvas.getContext("2d"); 14 var image = new Image(); 15 window.onload = function(){ 16 canvas.width = 1152; 17 canvas.height = 768; 18 image.src = "img.jpg"; 19 image.onload = function(){//如下幾種應用 20 //context.drawImage(image,0,0); 21 //context.drawImage(image,0,0,canvas.width,canvas.height); 22 //context.drawImage(image,600,200,400,400,200,200,400,400); 23 context.drawImage(image,600,200,400,400,0,0,canvas.width,canvas.height); 24  } 25  } 26 </script> 27 </body> 28 </html>

  drawImage的參數:一、context.drawImage(image,dx,dy,dw,dh);可對圖像進行縮放。

             二、對源圖像進行操做,以下截圖

            

   畫布中心縮放圖,使用滑桿元素與圖像交互

  

<body style="background: black;">
    <canvas id="canvas" style="display:block;margin:0 auto;border:1px solid #aaa;">您的瀏覽器尚不支持canvas   </canvas>
    <input type="range" id="scale-range" min="0.5" max="3.0" step="0.01" value="1.0" style="display:block;margin:20px auto;width:800px"/>
    <script>
        var canvas = document.getElementById("canvas")
        var context = canvas.getContext("2d") var slider = document.getElementById("scale-range") var image = new Image() window.onload = function(){ canvas.width = 1152 canvas.height = 768 var scale = slider.value image.src = "img-lg.jpg" image.onload = function(){ drawImageByScale( scale ) // slider.onchange = function(){ // scale = slider.value // drawImage( image , scale ) // } slider.onmousemove = function(){ scale = slider.value drawImageByScale( scale ) } } } function drawImageByScale( scale ){ var imageWidth = 1152 * scale*0.5 var imageHeight = 768 * scale*0.5 //var sx = imageWidth / 2 - canvas.width / 2 //var sy = imageHeight / 2 - canvas.height / 2 //context.drawImage( image , sx , sy , canvas.width , canvas.height , 0 , 0 , canvas.width , canvas.height ) x = canvas.width /2 - imageWidth / 2 y = canvas.height / 2 - imageHeight / 2 context.clearRect( 0 , 0 , canvas.width , canvas.height ) context.drawImage( image , x , y , imageWidth , imageHeight ) } </script> </body>

離屏canvas,用於浮於原canvas上面

  一、水印效果

  二、放大鏡效果

  

  

<body style="background: black;">
    <canvas id="canvas" style="display:block;margin:0 auto;border:1px solid #aaa;">覽器尚不支持canvas</canvas>
    <canvas id="offCanvas" style="display:none;"></canvas>
    <script>
        var canvas = document.getElementById("canvas");
        var context = canvas.getContext("2d"); var offCanvas = document.getElementById("offCanvas"); var offContext = offCanvas.getContext("2d"); var image = new Image(); var isMouseDown = false;//保存按鍵的狀態 按下||鬆開 var scale=2;//放大倍數 window.onload = function(){//頁面全部元素都加載完成 canvas.width = 1152;//畫布的長寬 canvas.height = 768; image.src = "img-lg.jpg";//給圖片對象添加src屬性 image.onload = function(){//圖片加載完成 offCanvas.width = image.width;//直接加載成圖片的大小 offCanvas.height = image.height; scale = offCanvas.width / canvas.width;//放大倍數,等於實際的寬度/畫布的 //調用drawImage渲染圖片到頁面中,整圖與放大的圖 context.drawImage(image,0,0,canvas.width,canvas.height); offContext.drawImage(image,0,0); } } function windowToCanvas(x,y){//轉換座標,x與y表示:鼠標在navigator對象中的座標位置。 // 這個方法返回一個矩形對象,包含四個屬性:left、top、right和bottom。分別表示元素各邊與頁面上邊和左邊的距離。 var bbox = canvas.getBoundingClientRect(); return {x:x-bbox.left , y:y-bbox.top}; } canvas.onmousedown = function(e){//鼠標按下 //http://www.w3school.com.cn/jsref/event_preventdefault.asp e.preventDefault();//阻止鼠標按下的默認行爲 isMouseDown = true;//鼠標按下置爲true point = windowToCanvas(e.clientX,e.clientY);//point保存鼠標相對於canvas畫布的位置 // 事件對象 event 事件 http://www.w3school.com.cn/jsref/dom_obj_event.asp  console.log( point.x , point.y); console.log(e); drawCanvasWithMagnifier(true,point); } canvas.onmouseup = function(e){//鼠標在畫布上鬆開的時候  e.preventDefault(); isMouseDown = false; drawCanvasWithMagnifier(false); } canvas.onmouseout = function(e){//鼠標不在畫布上的時候  e.preventDefault(); isMouseDown = false; drawCanvasWithMagnifier(false); } canvas.onmousemove = function(e){//鼠標移動的時候  e.preventDefault(); if(isMouseDown == true){ point = windowToCanvas(e.clientX,e.clientY); console.log(point.x,point.y); drawCanvasWithMagnifier(true,point); } } function drawCanvasWithMagnifier(isShowMagnifier,point){//是否顯示放大器 context.clearRect(0,0,canvas.width ,canvas.height);//繪製以前,清除已經畫到頁面中的。 context.drawImage(image,0,0,canvas.width,canvas.height);//繪製原來的小圖 if(isShowMagnifier==true){ drawMagnifier(point);//繪製放大器  } } function drawMagnifier(point){//依據中心點畫到頁面中,把點擊的位置看成中心 var mr = 200;//半徑 var imageLG_cx = point.x*scale;//大圖中的座標位置 var imageLG_cy = point.y*scale; var sx = imageLG_cx - mr;//-mr就是把這個位置調整到左上角位置 var sy = imageLG_cy - mr; var dx = point.x - mr; var dy = point.y - mr; //應用到畫布上面的效果是能夠累積的,於是就能夠利用幾個簡單的函數來「組合」出效果來。 //save和restore函數爲應用這些累積的效果提供了一種簡單的機制,能夠將應用了這些效果的圖像或圖形繪製到畫布上,而後「撤銷」這些 改變。 //save函數把當前的繪製狀態推動棧裏,而restore函數則把最後一個狀態彈出棧。 context.save();//調用save函數(保存當前的繪製狀態) context.lineWidth = 10.0;//線寬 context.strokeStyle = "#069";//strokeStyle 屬性設置或返回用於筆觸的顏色、漸變或模式。 context.beginPath();//線的起始點 //context.arc(x, y, radius, startAngle, endAngle, anticlockwise) //畫圓(弧),畫圓或者圓弧。x,y爲圓心座標,radius爲半徑,startAngle,endAngle爲開始/結束劃圓的角度,anticlockwise爲是否逆時針畫圓(True爲逆時針,False爲順時針)。 context.arc(point.x,point.y,mr,0,Math.PI*2,false); context.stroke(); context.clip();//clip() 方法從原始畫布中剪切任意形狀和尺寸。用前面的代碼來剪切前面的正方形 context.drawImage(offCanvas,sx,sy,2*mr,2*mr,dx,dy,2*mr,2*mr);//左上角開始畫2*mr的正方形, context.restore();//restore() 方法將繪圖狀態置爲保存值。  } </script> </body>

使用Canvas進行像素級操做

  一、ImageData對象保存三個主要信息:

    一、width

    二、height  

    三、data

  二、主要方法

    一、getImageData(x,y,w,h);

    二、putImageData(imageData,dx,dy,dirtyX,dirtyY,dirtyW,dirtyH);

           三、createImageData(w,h);  

<body>
    <div style="margin: 20px auto; width:1700px;">
        <canvas id="canvasa" width="800" height="560" style="display:block;float:left;border:1px solid #aaa;">
        </canvas>
        <canvas id="canvasb" width="800" height="560" style="display:block;float:right;border:1px solid #aaa;">
        </canvas>
    </div>
    <div style="clear: both"></div>
    <div style="text-align: center; margin-top:50px;font-size:20px;">
        <a href = "javascript:greyEffect()">Grey Effect</a>
        <a href = "javascript:blackEffect()">Black and White Effect</a>
        <a href = "javascript:reverseEffect()">Reverse Effect</a>
        <a href = "javascript:blurEffect()">Blur Effect</a>
        <a href = "javascript:mosaicEffect()">Mosaic Effect</a>
        <a href = "javascript:reverseImage()">reverseImage Effect</a>
    </div>
    <input type="file" id="setPic" onchange="readFile(this)"/> 
    <img id="base64" src="" width="300px" height="300px" />
    <script>
        //原圖,左
        var canvasa = document.getElementById("canvasa")
        var contexta = canvasa.getContext("2d") //效果顯示窗口,右 var canvasb = document.getElementById("canvasb") var contextb = canvasb.getContext("2d") //讀取base64到瀏覽器本地 function readFile(obj){ console.log(obj.files[0].size); //這裏用來限制圖片的大小,彷佛能夠很大 if(obj.files[0].size<8000*1024){ var file = obj.files[0]; //判斷類型是否是圖片 if(!/image\/\w+/.test(file.type)){ alert("請確保文件爲圖像類型"); return false; } var reader = new FileReader(); reader.readAsDataURL(file); reader.onload = function(e){//確保加載完成 console.log(this); document.getElementById("base64").setAttribute("src",this.result); // 建立圖片對象 var image = new Image() // image.src = "autumn.jpg",原本的圖片是本地的一個地址,這種狀況下chrome的getImageData不可用,因此改成上傳base64,進而讀取圖片的內容 // 給圖片對象添加src的值 // image.src = document.getElementById("base64").getAttribute("src"); image.src = this.result; image.onload = function(){//圖片生成以後執行函數,在canvas畫布上繪製圖片 contexta.drawImage( image , 0 , 0 , canvasa.width , canvasa.height ) } } }else{ alert("上傳圖片不要大於8000kb!"); } }//讀取base64,生成圖片,以及canvas圖片 // 灰化的圖片函數 function greyEffect(){ //http://www.w3school.com.cn/tags/canvas_getimagedata.asp //var imgData=context.getImageData(x,y,width,height); var imageData = contexta.getImageData(0,0,canvasa.width,canvasa.height); //佔滿整個畫布,也就是畫布的長寬就等於實際圖像的長寬 //getImageData() 方法返回 ImageData 對象,該對象拷貝了畫布指定矩形的像素數據。 var pixelData = imageData.data; //對於 ImageData 對象中的每一個像素,都存在着四方面的信息,即 RGBA 值: //上邊對象的i*4+0表示:r(0~255),後邊的依次 for( var i=0;i<canvasb.width*canvasb.height; i++){ var r = pixelData[i*4+0]; var g = pixelData[i*4+1]; var b = pixelData[i*4+2]; var grey = r*0.3+g*0.59+b*0.11;//灰化計算算法 pixelData[i*4+0] = grey; pixelData[i*4+1] = grey; pixelData[i*4+2] = grey; } //http://www.w3school.com.cn/tags/canvas_putimagedata.asp //context.putImageData(imgData,x,y,dirtyX,dirtyY,dirtyWidth,dirtyHeight); //putImageData() 方法將圖像數據(從指定的 ImageData 對象)放回畫布上。 //dirtyX可選。水平值(x),以像素計,在畫布上放置圖像的位置。 //x ,ImageData 對象左上角的 x 座標,以像素計。 contextb.putImageData(imageData,0,0,0,0,canvasb.width,canvasb.height); } //黑白圖像 function blackEffect(){ var imageData = contexta.getImageData(0,0,canvasa.width, canvasa.height); var pixelData = imageData.data; for( var i=0;i<canvasb.width*canvasb.height;i++){ var r = pixelData[i*4+0] var g = pixelData[i*4+1] var b = pixelData[i*4+2] var grey = r*0.3+g*0.59+b*0.11; if(grey > 125){ pv = 255 }else{ pv = 0 } pixelData[i*4+0] = pv pixelData[i*4+1] = pv pixelData[i*4+2] = pv } contextb.putImageData( imageData , 0 , 0 , 0 , 0 , canvasa.width , canvasa.height ) } //反轉顏色值 function reverseEffect(){ var imageData = contexta.getImageData(0,0,canvasa.width,canvasa.height); var pixelData = imageData.data; for( var i=0;i<canvasb.width*canvasb.height;i++){ var r = pixelData[i*4+0]; var g = pixelData[i*4+1]; var b = pixelData[i*4+2]; pixelData[i*4+0] = 255 - r; pixelData[i*4+1] = 255 - g; pixelData[i*4+2] = 255 - b; } contextb.putImageData( imageData , 0 , 0 , 0 , 0 , canvasb.width , canvasb.height); } //模糊化處理,須要慘開一個像素周圍的像素值 function blurEffect(){ var tmpImageData = contexta.getImageData(0,0,canvasa.width,canvasa.height); var tmpPixelData = tmpImageData.data; var imageData = contexta.getImageData(0,0,canvasa.width,canvasa.height); var pixelData = imageData.data; var blurR = 3; var totalnum = (2*blurR + 1)*(2*blurR + 1); for(var i=blurR;i<canvasb.height-blurR;i++){//遍歷到(i,j)元素的時候 for(var j = blurR;j < canvasb.width - blurR;j ++){ var totalr = 0, totalg= 0 ,totalb = 0; for(var dx = -blurR;dx <= blurR;dx++){//基於中心的點在x,y方向上的平均值,一共走了九次 for(var dy = -blurR;dy <= blurR; dy++){ var x = i + dx; var y = j + dy; var p = x*canvasb.width + y; totalr += tmpPixelData[p*4+0]; totalg += tmpPixelData[p*4+1]; totalb += tmpPixelData[p*4+2]; } } var p = i*canvasb.width + j; pixelData[p*4+0] = totalr / totalnum;//中心點的像素等於周圍的方塊的平均值 pixelData[p*4+1] = totalg / totalnum; pixelData[p*4+2] = totalb / totalnum; } } contextb.putImageData( imageData , 0 , 0 , 0 , 0 , canvasb.width , canvasb.height); } //馬賽克處理,與模糊濾鏡的原理恰好相反,一個是多到一,一個是一到多 function mosaicEffect(){ var tmpImageData = contexta.getImageData(0,0,canvasa.width,canvasa.height); var tmpPixelData = tmpImageData.data; var imageData = contexta.getImageData(0,0,canvasa.width,canvasa.height); var pixelData = imageData.data; var size = 16; var totalnum = size*size; for(var i = 0;i<canvasb.height;i+=size){ for(var j = 0;j < canvasb.width;j += size){ var totalr = 0 , totalg = 0 , totalb = 0; for(var dx = 0 ; dx < size ; dx ++){ for(var dy = 0;dy < size ; dy ++){ var x = i + dx; var y = j + dy; var p = x*canvasb.width + y; totalr += tmpPixelData[p*4+0]; totalg += tmpPixelData[p*4+1]; totalb += tmpPixelData[p*4+2]; } } var p = i*canvasb.width+j; var resr = totalr / totalnum; var resg = totalg / totalnum; var resb = totalb / totalnum; for( var dx = 0;dx < size ; dx ++){ for( var dy = 0;dy < size; dy ++){ var x = i + dx; var y = j + dy; var p = x*canvasb.width + y; pixelData[p*4+0] = resr; pixelData[p*4+1] = resg; pixelData[p*4+2] = resb; } } } } contextb.putImageData( imageData , 0 , 0 , 0 , 0 , canvasb.width, canvasb.height); } // 反轉像素位值 function reverseImage(){ //獲取原始圖片的高度的數據 var tmpImageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height); //像素數據 var tmpPixelData = tmpImageData.data; // 生成的圖片的數據 var imageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height); //像素數據 var pixelData = imageData.data; var len = canvasb.width*canvasb.height; console.log(len); console.log(tmpPixelData); // for( var i=0;i<len;i++){ // pixelData[4*i+0] = tmpPixelData[4*(len-i)+2]; // pixelData[4*i+1] = tmpPixelData[4*(len-i)+1]; // pixelData[4*i+2] = tmpPixelData[4*(len-i)+0]; // } var len_width=canvasb.width; var len_height=canvasb.height; for(var i = 0;i<len_width;i++){ for(var j = 0;j<len_height;j++){ pixelData[4*(i*len_height-len_height+j)+0]=tmpPixelData[Math.floor(Math.random()*255)]; pixelData[4*(i*len_height-len_height+j)+1]=tmpPixelData[Math.floor(Math.random()*255)]; pixelData[4*(i*len_height-len_height+j)+2]=tmpPixelData[Math.floor(Math.random()*255)]; } } contextb.putImageData(imageData , 0 , 0 , 0 , 0 , canvasb.width, canvasb.height) } </script> </body>
相關文章
相關標籤/搜索