あむちょです。
HTML5を使ってアップロードなしで、ブラウザー上で画像処理をしてみました。
とりあえずやってみるのが手っ取り早いです。
適当な画像をドラッグでブラウザー内にほうりこんだあと、ボタン押すだけです。サンプル画像は友人のハネムーンの時のやつ。パソコン専用です。
Processing
Normalをクリックするとリセットされます。
以下やりかた。
まず、ドラッグによるブラウザーのデフォルトの動作を抑制する
<br /> window.addEventListener("dragover",function(event){<br /> event.preventDefault();<br /> },false);</p> <p>window.addEventListener("drop",function(event){<br /> event.preventDefault();<br /> },false);<br />
次にFile APIを利用して画像データを所得。上記の”drop”イベントに以下を追加。
<br /> var file=event.dataTransfer.files[0];</p> <p>var fileType = file.type;<br /> if (!fileType.match(/image\/\w+/)){<br /> alert("画像ファイル以外は利用できません");<br /> return;<br /> }</p> <p>var reader = new FileReader();<br /> reader.onload = function(){<br /> image = new Image();<br /> image.src=reader.result;<br /> };</p> <p>reader.readAsDataURL(file);<br />
これで、ドラッグによるイメージオブジェクトが生成できます。
次に、画像データをとり出す。今回は、canvas領域に描画されたものをデータに変換しているので、一度描画する必要があります。
<br /> context.drawImage(image,0,0);</p> <p>imgData=context.getImageData(0,0,image.width,image.height);<br />
あとは、データを直接、1pxづつ操作して加工します。
まずはセピア
<br /> sepia = function(){</p> <p> var data=imgData.data;<br /> for(var n=0,len=imgData.width*.imgData.height;n<len;n++){<br /> var r=data[n*4];<br /> var g=data[n*4+1];<br /> var b=data[n*4+2];</p> <p> data[n*4]=Math.round(0.393*r+0.769*g+0.189*b);<br /> data[n*4+1]=Math.round(0.349*r+0.686*g+0.168*b);<br /> data[n*4+2]=Math.round(0.272*r+0.534*g+0.131*b);<br /> }</p> <p>}<br />
反転
<br /> hanten = function(){</p> <p> var data=imgData.data;<br /> for(var n=0,len=imgData.width*imgData.height;n<len;n++){<br /> var r=data[n*4];<br /> var g=data[n*4+1];<br /> var b=data[n*4+2];</p> <p> data[n*4]=255-r;<br /> data[n*4+1]=255-g;<br /> data[n*4+2]=255-b;<br /> }</p> <p>}<br />
各RGBの値を最大値との差をとるだけです。
モノクロ
<br /> mono = function(){</p> <p> var data=imgData.data;<br /> var rRate=0.34;<br /> var gRate=0.33;<br /> var bRate=0.33;</p> <p> for(var n=0,len=imgData.width*imgData.height;n<len;n++){<br /> var r=data[n*4];<br /> var g=data[n*4+1];<br /> var b=data[n*4+2];</p> <p> data[n*4]=Math.round(rRate*r+gRate*g+bRate*b);<br /> data[n*4+1]=Math.round(rRate*r+gRate*g+bRate*b);<br /> data[n*4+2]=Math.round(rRate*r+gRate*g+bRate*b);<br /> }</p> <p>}<br />
各RGBの値が等しくなるようにすることで、黒色の濃淡だけになります。
二値化
<br /> nichi = function(){</p> <p> var data=imgData.data;<br /> var rRate=0.34;<br /> var gRate=0.33;<br /> var bRate=0.33;</p> <p> for(var n=0,len=this.imgData.width*this.imgData.height;n<len;n++){<br /> var r=data[n*4];<br /> var g=data[n*4+1];<br /> var b=data[n*4+2];<br /> var elem=Math.round(rRate*r+gRate*g+bRate*b);<br /> if(elem > 127){<br /> data[n*4]=255;<br /> data[n*4+1]=255;<br /> data[n*4+2]=2555;<br /> }<br /> else{<br /> data[n*4]=0;<br /> data[n*4+1]=0;<br /> data[n*4+2]=0;<br /> }<br /> }</p> <p>}<br />
モノクロと似ていますが、閾値を境に最小値か最大値のどちらかの値しかとりません。今回は半分の127を閾値としました。
縦×横ピクセル数だけ処理が繰り返されるので、大きい画像ほど時間が掛かります。変数の宣言とかfor文の外でやっといた方がいいです。
実際のソースはこんな感じ
ブラウザー上で画像処理ができるなんて技術の進歩はすごいですね。
API様々です
[ad]