[3][HTML][canvas]canvasで画像解析
「canvasタグとそのAPIを使って、画像のピクセルデータが取得できる」というのを知って、「それならばユーザが投稿した画像を解析してどうこうすることもJavaScriptで可能か」と思い試してみた。
やり方としては「画像ファイルをアップロード>imgタグとして表示>canvasに取り込み>画像解析」の流れでやってみた。
index.htmlの中身の抜粋。jquery.uploadを使って非同期にアップロード出来るようにしてみた。サーバサイドはCGI.pmを使用。
<script type="text/javascript" src="js/jquery.upload-1.0.2.min.js"></script> <input type="file" name="filename" id="file"> // jquery.uploadがiframe作ってアップロードしてくれるのでformタグ無し
upload.cgiの中身。セキュリティはあまり考えていない。
#!/usr/bin/perl use strict; use warnings; use CGI; use CGI::Carp qw(fatalsToBrowser); use File::Copy; use File::Basename; my $upload_dir = 'upload'; my $q = CGI->new(); my $fh = $q->upload('filename'); my $temp_path = $q->tmpFileName($fh); fileparse_set_fstype('MSDOS'); my $filename = basename($fh); my $upload_path = "$upload_dir/$filename"; move ($temp_path, $upload_path) or die $!; close($fh); print $q->header( -type=>'text/plain', -charset=>'UTF-8', ); print <<"END_OF_HTML"; $upload_dir/$filename END_OF_HTML exit; __END__
JavaScriptでonchangeイベントにアップロードを仕込んでおく。
$(document).on('change', '#file', function() { $(this).upload('upload.cgi', function(res) { // canvasタグを取得 var c = document.getElementById('gazo'); var ctx = c.getContext('2d'); // resに画像パスが返ってくるので // 読み込んでonloadでcanvasに取り込む var img = new Image(); img.src = path; // 投稿された画像へのパス img.onload = function() { // 画像サイズに合わせてcanvasのサイズ変更 c.width = img.width; c.height = img.height; ctx.drawImage(img, 0, 0); // 画像読み込み } }, 'text'); });
canvasに画像データが入れば後はcontextから画像情報を取得することが出来る。
var ctx = canvas.getContext('2d'); var id = ctx.getImageData(0, 0, w, h);
ここで取得出来るImageDataは配列で1次元配列が帰って来る。配列の要素が1ピクセル分を表しているのかと思いきや、4つの要素を使ってRGBとアルファ値(それぞれは0~255の値を取りうる)を表しているらしい。分かりづらいので図で書いてみると以下の様な感じ。上の0~が配列の添字で、画像の左から右、上から下の順番で入っている。
ここまで来れば画像情報が取れているので、後は煮くなり焼くなりすればいい。アップロードされた画像の顔認識をして、自動的にサムネイルの位置を決めてトリミングとか出来るだろう。