Canvasで描いた絵をクラシックASPでサーバー上に保存する方法


このブログでCanvasについてよく扱っていたタイミングで、会社からCanvasを用いた編集ツールを作ることになりました。ただし、うちの会社で使っているサーバーは少し古めのIISで、現状サーバープログラミングはクラシックASPしか使えないようです。
ただ、Canvasで作った画像はサーバーに保存しなければいけないので、その方法を調べる必要がありました。Canvasの画像データ自体はBase64にして得られるものの、そのBase64の文字列をデコードしてファイルとして保存する必要があります。そこで見つけたのが、BASP21 DLLというASP上で扱えるコンポーネント。どうやら、Base64でファイルをデコードする機能もあるようです(わざわざ、Base64の文字列を入れたテキストファイルを作る必要があるようですが)。とりあえずやってみたものの、小さい画像ではうまくいきましたが、ちょっと大きくなるとダメでした(確か、200px*200pxぐらいだともうダメだったかと)。

正直ちょっと諦めかけて、LhaplusみたいなBase64デコード対応のソフトをWScript.Shellで操作するのがいいんじゃないか。なんて思っていた所、下記のサイトを発見。
ScrapCode/VBS/BASE64 – 備忘録
ASPはVBSで書かれているので、この方法でうまくいくかもしれません。なぜXMLを読み込んだり書き込んだりするためのMicrosoft.XMLDOMというオブジェクトでBase64のデコードができるのか謎なのですが、とりあえず試してみました。

以下、サンプルコード。

CanvasのHTMLは、前に作った、canvasを使ったお絵描き投稿システムを利用し、投稿先URLを、”image-accept.php”ではなく、”image-accept.asp”として試してみました。acceptImageというパラメータで、Canvasから得られたBase64 URLを渡すようにしています
結果、うまくいったようです。実際に使う時にはファイルパスとBase64の文字列を渡して、ファイルを作成する関数を作ったほうがいいかもしれませんね。

Yahoo!メールをテキストファイル形式でバックアップする方法(Thunderbird利用)


ある事情で、父の使っているYahoo!メールにあるメール内容をテキストファイルにしてCD-ROMに入れなきゃいけなくなったので、その時のメモ。簡単にできるだとうと思って頼まれたんだろうし、自分もそこまで難しくないと思ってやってみたんですが、思った以上に手こずりました。
ちなみに、Yahoo!メールと書いてますが、Gmail(というより、Thunderbirdで受信できるメール)でも同じ手法でできるはずです。

結論としてはThunderbirdでYahoo!メールを受信するようにし、ImportExportToolsという拡張機能を使ってメールの中身をテキストファイルとして保存します。

以下、その手順。久々に画像多めのエントリーとなるため少し重いかもしれません。

まずは、Thunderbirdのインストールをしないと始まらないので、その説明から。リンク先の『無料ダウンロード』ボタンをクリックして、インストールファイルをダウンロードします。すでに、Thunderbirdをインストールしている人は、こちらへ。すでにThunderbirdでヤフーメールを受信している人はこちらへスキップしてください。
Thunderbirdの『無料ダウンロード』ボタンをクリック

ダウンロードができたら、ファイルをダブルクリックして起動します。すると、最初にプログレスバーのみの画面が出た後、下記のような画面になると思うので、『次へ』のボタンをクリック(ユーザーアカウント制御という画面がでた場合は『はい』をクリック)。
『次へ』のボタンをクリック

つづいて、インストールの種類の選択画面。『標準インストール』にチェックがついていると思うので、そのまま『次へ』をクリック。『Thunderbirdを規定のメールプログラムとして使用する』のチェックは任意です。すでに、OutlookやWindowsメールなど、別のメールプログラムを使ってる人はチェックをつけないほうがいいかも。
『次へ』をクリック。規定のプラグラムのチェエックは任意

規定のフォルダにインストールすることの確認画面になりますので、『インストール』ボタンをクリック。
『インストール』をクリック

しばらく待ちます。
しばらく待つ

インストールが完了したら下記の画面になるので、『今すぐ Mozilla Thunderbird を起動』にチェックをつけたまま、『完了』ボタンをクリック。
『完了』をクリック

Thunderbirdが起動して、下記のような画面になります。とりあえず、『統合をスキップ』をクリックすることに。
『統合をスキップ』をクリック

メールのアカウントを作成するので、『メール』をクリック。
『メール』をクリック

下記のような画面がでてくるので、『メールアカウントを設定する』ボタンをクリック。
mailbackup9

メールアカウント設定画面が開くのて、『あなたのお名前』入力欄に適当な名前を記入し、メールアドレスとパスワードの記入欄にはヤフーのメールアドレスとパスワードを入力する。その後、『続ける』ボタンをクリック。
メールアドレスとパスワード入力後、『続ける』をクリック

すると自動的にサーバー情報が取得されるはずなので、そのまま『完了』ボタンをクリック。
『完了』をクリック

その後、左上の『受信』ボタンを押すことにより、ヤフーメールのメールをダウンロードしていくので、しばらく待つ。もちろん、量が多ければ多いほど長く待つことになる(自分の場合、2時間程度かかった)。ちなみに、個別フォルダの中身はダウンロードされないので注意。自分は個別フォルダのメールをすべてフラグをつけて受信フォルダにいれ、Thunderbird側で受信できたら、フラグがついているものは個別フォルダに入れなおすという方法で個別フォルダにあるメールもダウンロードするようにしました。後、迷惑フォルダはダウンロードしてしまうので、Thunderbird側で受信する前に、ブラウザ側で削除したほうがいいかも。
メール受信中

自分の場合はダウンロードしている最中に、『RETRコマンドを正常に完了できず、メッセージを取得できませんでした。』というようなメッセージがでてダウンロードがストップしてしまう時が何度かあった。
RETRコマンドを正常に完了できず、メッセージを取得できませんでした。
このような場合にはいったんブラウザでヤフーメールを開き、ダウンロードできた最新のメールの次のメールを削除してから再度受信ボタンを押すと、大抵再受信が始まります(始まらない場合は、それとは違うメールが原因の可能性があります)。ちなみに、自分は英語だけのスパムメールを削除したらうまくいきました。

つづいて、ImportExportToolsというThunderbirdの拡張機能をダウンロードします。リンク先に行って、『 ImportExportTools』というリンクをクリックしてダウンロード。
 ImportExportTools

altキーを押してツールバーを表示させ、『ツール』をクリックして、でてきたメニューバーから『アドオン』をクリック。
ツールバーからアドオンをクリック

拡張機能ページを開きます。ところで、検索欄に『ImportExportTools』と記入した状態のキャプチャ画像を取得してしまいましたが、試しにここで『ImportExportTools』と検索しても何も見つかりませんでした。なので、先ほどダウンロードしたImportExportToolsのファイル(2013年2月23日現在だと、『ImportExportTools-2.8.0.4.xpi』という名前)をこの画面にドラッグアンドドロップします。
拡張機能ページを開く

下記のような画面が表示されるので、『今すぐインストール』をクリック。
『今すぐインストール』をクリック

下記のような画面になったら、『今すぐ再起動』をクリック。
『今すぐ再起動』をクリック

ImportExportToolsをインストールできたら、『受信トレイ』を右クリックし、でてきたメニューから『ImportExportTools』→『フォルダ内のすべてのメッセージをエクスポート』→『プレーンテキスト形式』を選ぶ(日本語になっていることに少し驚きました)。
プレーンテキストを選ぶ

フォルダダイアログが開くので、保存するフォルダに移動して『フォルダーの選択』ボタンをクリック。
フォルダーの選択

しばらく時間がたつと、指定したフォルダに、下記のようなフォルダができる。この『受信トレイ_(日付)』というフォルダの下には『メッセージ』というフォルダと、『index.html』があり、『メッセージ』フォルダの下にはメール本文のテキストファイルが入っている。
フォルダに新しく『受信トレイ_(日付)』というフォルダができる

index.htmlは下記のような感じ。メールのリストがテーブル形式で書かれている。
index.htmlの中身

試しに、一番上のリンクを開いてみたら、下記のような感じでした。ちなみに、ファイル名は『20030412-ようこそ Yahoo! メールへ-0.txt』となっていました(なんでコピーライトが2010になってるんだろう? 2003年のメールなのに)
メールの中身

ImportExportToolsは他にも、HTML形式での保存や、emlファイルのインポートなんかもできてしまうので、かなり便利そうです。それより、そもそもThunderbird自体が便利そうですね。今までメールは、Webメールを使っているためブラウザからしかメールチェックはしてませんでしたし、会社のメールもOutlookで利用しているので、Thunderbirdは全く利用したことがなかったのですが、すごいよさそうです。今度から、Thunderbirdを使おうか・・・。

オートコンプリートがオフのパスワード入力を自動入力するユーザースクリプト


自分がよく利用するサイトに、楽天リサーチhontoがあるのですが、この二つのサイトはログイン画面のフォームのオートコンプリートがオフになっており、ログイン画面を開くとパスワードが自動入力されていない状態となっています(IDは自動入力しているようです。hontoはチェックボックスにチェックを入れなければいけませんが)。

正直、毎回毎回パスワードを入力しなくちゃいけないのはすごい面倒です。面倒だから簡単なパスワードや使い回しのパスワードを使ってしまい、パスワードが簡単にバレてしまうという問題も起こりかねないと思うのですが・・・。

というわけで、簡単なものですが、パスワードの入力ボックスを自動入力するユーザースクリプトを作ってみました。

やっていることは単純で、URLを調べて該当の文字列があれば(今回の場合、hontoでは’honto.jp/reg/login.html’)、その中のパスワード入力ボックスを探してパスワードを入力するという処理を行っています。
上記のソースコードをコピーして、”********”の箇所を自分のパスワードに書き換え、拡張子が.user.jsとして保存し、Chromeの拡張機能ページ(chrome://extensions/)を開いた状態でドラッグアンドドロップすると機能するはずです。
自動的にログインボタンを押す機能もつけようと思ったらできるのですが、パスワードが間違っていた場合に無限ループに陥ってしまう可能性があるため、やめておきました。そういう場合でも対策はあるとは思うのですが・・・。

ところで、hontoのほうではgetElementByIdを使ってパスワード入力ボックスのDOMオブジェクトを取得し、楽天リサーチのほうではquerySelectorでinputタグのtype属性がpasswordになっているところを見つけてパスワード入力ボックスのDOMオブジェクトを取得しています。hontoのほうもdocument.querySelector(“input[type=’password’]”)で取得できると思いますが、最初はどちらもgetElementByIdで取得しようと思ったためにこういう書き方になっています。
なぜか、楽天リサーチのほうでgetElementByIdを使ってDOMオブジェクトを取得しようとするとうまくいきませんでした。パスワード入力ボックスのIDには”loginInner”というIDが振られているようなのですが、、document.getElementById(‘loginInner’)としてもなぜかうまくいかない・・・。おかしいなぁ。なんでだろう・・・。と思って詳しく調べてみたら・・・、なんとログインフォームを囲んだdivタグのID名がloginInner・・・。さらにはユーザIDの入力ボックスのID名もloginInner・・・。
知っている人も多いと思いますが、ID属性は一意識別子をあらわし、同じページでは同じID名を重複してはいけないということになっています(参考:id 属性 – グローバル属性 – HTML5 タグリファレンス – HTML5.JP)。
楽天のような大きな会社でもこういうページがあるということにちょっと驚きました(自分も想定外の仕様変更で重複させてしまったということはあるので、人のことは言える立場じゃないです・・・)。

canvasのお絵描きツールに『戻る』『進む』ボタンをつけてみる


描き間違いがあったときに一つ前の状態に戻る機能がほしくなったので、その機能を追加することに。とりあえず、五回分を保存できるようにしてみた。塗りつぶし機能よりは簡単に実装できました。

以下、JavaScriptのコード

以下、動作サンプル。
canvasを使ったお絵描き投稿システム

saveImageDataという関数は、初期状態やキャンバス上でマウスボタンやタッチが離された時に実行するようにしています。やっていることは単純で、17行目のgetImageDataメソッドで現在のキャンバスの状態をimageMemory という配列に保存し、戻るボタンや進むボタンをおした時に現在の番号(flagMemory)の前や次に対応したimageMemoryに入っているキャンバスのデータをputImageDataでキャンバス上に描画しています。
何度か戻った後に新しくキャンバスに絵を書いた場合、次の画像というものがないのが自然な気はしますが、わざわざ消す必要もないだろうと思い、消してません(面倒だっただけだろと突っ込まないでください)。

なんというか、本当思いついたらその分追加するだけのコードになっているので、汚い気はします。もっとキレイなコードを書けるようになりたいです。

canvasのお絵描きツールに塗りつぶし機能をつけてみる


塗りつぶし機能を作ってみようと思ったけど、いろいろ苦戦。再帰を使えば簡単にできると思ったのですが、小さい範囲ならともかく、ちょっと大きくなるとブラウザに怒られました。

というわけで、JavaScriptに以下のようなコードを記述。

上記関数を呼び出す時には下記のような記述。

以下、動作サンプル。
canvasを使ったお絵描き投稿システム

なんだか汚いコードですみません。似たような記述が二箇所にあったりしてますしね・・・。
ようは、ピクセルごとに色を取得して、選択したピクセルが塗りつぶす色と違うようであればそのピクセルを塗りつぶし、さらにその点の上下左右の点を見て先ほど選択したピクセルの元の色と同じであれば塗りつぶすということを繰り返しています。
あまりいいやり方とはいえないかも。多分、下記のようなアルゴリズムを使ったほうが効率的かもしれません。
塗りつぶしアルゴリズム(scanline seed fill algorithm) – jsdo.it – Share JavaScript, HTML5 and CSS
ペイント・ルーチン (2)アルゴリズムの高速化
ただ、自分には何をやってるのか全く分からなかったので、もっと分かりやすい方法で実装しています。その分、ちょっと遅いとは思います・・・。

線にアンチエイリアスがかかって塗りつぶしが思いもよらない結果になる時があるようです。てっきり、アンチエイリアスはアルファ値で調節してるだけだと思ったので、アルファ値を考慮しない(というより0かそうでないかしか見ていない)アルゴリズムにしたのだけれども、そういうわけではないよう。どうして、lineToの機能にアンチエイリアスをかけないようにする指定がないのだろうか・・・。
ctx.translate(0.5,0.5);としたらいいとどこかに書いてあったのだけれども、あまり関係なさそうだった。