HTML5とJavaScriptでローカル画像をドラッグで画像処理する
あむちょです。
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]




