canvasに描いた絵(画像)をサーバに保存

canvasに描かれたデータを取得するには、canvas.toDataURL() を使います。
toDataURL()で得られるのは、base64エンコードされた画像情報なので、
それをサーバに送って、base64デコードして保存という流れです。


toDataURL()して、そのデータをPOSTする部分のjavascript (ajax部分が面倒なので、prototype.jsを使用)

function saveImage() {
    var imgdata = $('canvas_id').toDataURL();  // デフォルトだとpng, 引数でjpegとかも可能
    imgdata = imgdata.replace('data:image/png;base64,', '');  // 頭のいらない部分を落とす

    new Ajax.Request(<画像保存CGIのURL>, {
        parameters: 'img=' + imgdata,  // 画像データを送信
        onComplete: function(res) {  // callback 別になくてもよいが。
            if (res.responseText != 'ok') alert('error');
        }
    });
}


サーバ側(画像保存CGI

#!/usr/bin/perl

use strict;
use warnings;
use CGI;
use MIME::Base64;

my $q   = CGI->new;
my $img = $q->param('img');  # base64エンコードされた画像データを取得

my $res_msg = 'error';
if ($img) {
    open(my $fh, '>', 'image.png') or die $!;  # 保存するファイル名でopen
    print $fh MIME::Base64::decode($img);  # base64デコード
    close($fh);

    $res_msg = 'ok';
}

print "Content-type:text/plain\n\n";
print $res_msg;
exit;

これで、image.pngcanvasの画像が保存されます。

origin-clean flag

canvasにはセキュリティの面から、origin-cleanフラグというものが存在しているらしいです。
このフラグが false になっている場合、toDataURL()は「security error」となって、失敗します。


これに関する原文は、以下です。
http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#security-with-canvas-elements


canvasは、最初はorigin-cleanフラグがtrueにセットされていますが、
いくつか特定のアクションをするとorigin-cleanフラグがfalseになります。


例えば、以前の記事 でやった画像の読み込み(drawImage)とかで、
その画像が canvasを表示しているページと同じドメインの画像なら toDataURL()できますが、
ドメインの画像をcanvasに描画してしまうと、origin-cleanフラグがfalseになって、toDataURL()できなくなります。


なので、外部の画像を読み込ませて、お絵かきさせて、サーバで保存とかしたい場合は、
一度サーバ側で画像をダウンロードして、それをcanvasに描画する必要がありそうです。