SPICY SPACE BLOG

愛犬家WEBエンジニアの日常。

File APIとCanvasで画像をリサイズしてアップロード

以前自分の結婚式のために作った画像投稿サイトで、クライアント側で画像のリサイズを行う投稿フォームを作ったときのことを書きます。


自分の結婚式に写真投稿サイト作ってみた話。 - SPICY SPACE BLOG

 

HTMLで画像投稿する必要性

結婚式の来場者に、式中の写真をスマホから投稿してもらうサイトなので、

スマホで撮影した2MB近い画像を、3G回線でアップロードするにはムリがあります。

かといって撮った写真を別アプリでリサイズしてからアップして下さいっていうのはユーザーに負担をかけすぎなのでナシ。

そもそもスマホアプリとして作るというのも検討しましたが、iOSの場合、アプリを一般公開しないといけないですし、まぁ結婚式の準備と平行してiOSAndroid両対応のアプリを作る余裕は全くありませんでした(笑)

ということで、Webサイト上でスマホの写真をリサイズする必要がありました。

 

実装方法

スマホのブラウザでファイルのアップロード

iOS6以降、Android2.2以降で<input type="file">でカメラの起動 or カメラロールの写真選択が可能となっています。

FileAPI

HTML5 では、File APIを介してローカルファイルにアクセスできます。

<input type="file">で指定した画像ファイルを読み込んで処理することが可能です。

参考サイト:JavaScript でのローカル ファイルの読み込み - HTML5 Rocks

ブラウザ対応状況は2014年9月時点でこんな感じです。

f:id:sp_ice:20140902121830j:plain

引用サイト:ファイル アクセス - HTML5 Rocks

 

今回の実装

  1. <input type="file">のchangeイベントを登録。
  2. 写真がアップされたら、写真のEXIF情報からOrientation(回転)情報を取得、スマホで撮った写真が正しい向きになるよう調整。
  3. 取得した写真をリサイズしてcanvasに描画。
  4. canvas上の描画データをbase64エンコードし、<input type="hidden">でテキストとしてフォーム送信。

  

実際の動きはコチラをご覧下さい。

http://da20140329.herokuapp.com/snap/post

 

ぶつかった問題

すんなりうまく行くことなんて無いのが世の常です。。。

問題① iOSで画像が潰れるバグ

こちらのサイトで詳細に説明されています。

iOSの制限として、2Mピクセルを超えるJPEG画像はサブサンプルの対象となり、情報が間引かれてしまいます。

この画像をCanvasに対してdrawImageなどしてリサイズする場合、不都合が起きます。サブサンプルされる場合とされない画像で描画の結果が異なってしまいます。

回避策として、一旦小さなCanvasに元画像の一部をコピーし、それを張り合わせて対象のCanvasにdrawImageすることで対応しました。またその際、サブサンプルされている画像とそうでないものを描画結果から判別し、サブサンプルされているものには縮尺を補正してあげるようにしています。

引用サイト:iOS6でメガピクセル画像をCanvasに描画するとおかしくなってしまう件と、その対処 - snippets from shinichitomita’s journal

 

なんとこの現象を回避するためのライブラリ「ios-imagefile-megapixel」を公開してくださっていたので、今回利用させて頂きました。

 

問題② canvasのリサイズが汚い

今回、canvasのリサイズは問題①で使用したライブラリ「ios-imagefile-megapixel」が受け持ってくれていたのですが、

drawImageメソッドで幅、高さを指定することで実現しています。

context.drawImage(image, dx, dy, dw, dh)

このリサイズの結果が汚い!↓の記事に画像の比較がありますが、canvasの画像処理はそんなに性能がよくありません。

 参考サイト:琴線探査: HTML5 Canvasで画像のリサイズするならコレ!「JS-Image-Resizer」

こちらの記事の中で紹介されている「JS-Image-Resizer」も試してみたかったのですが、問題①対策のライブラリとマージする時間がなかったため、諦めました。。。

通常のcanvasでのリサイズよりかなりキレイな仕上がりになるようです。

 

問題③ canvasの描画データをbase64エンコードするときに ブラウザが落ちる 

機種変前に使用していたiPhone4が手元にあったので、こちらで試してみたところ、ブラウザが落ちてしまいました。

どこで落ちているのか、少しずつコメントアウトしながら検証した結果、

var imgData = resCanvas1.toDataURL();

 ↑ここでした。toDataURLはcanvasで描画したデータを、Base64エンコードした文字列で取得するメソッドです。

ここのjsの処理がiPhone4のスペックでは足りないようです。

結婚式に来ていただくゲストに「このサイト、落ちちゃうんだけど…^^;」なんて言わせたくありません…

iPhone4ならもしかしてまだ使っている人もいるかも、Androidの古い機種はもっとスペック低いんじゃないか…という心配から、

せめてiPhone4で落ちない程度の画像サイズにするという結論に至りました。

その結果、300✕400に収まる画像サイズまで落として描画することにしました。ただでさえcanvasのリサイズで汚くなっているのに、このサイズはRetinaディスプレイで見るともう悲惨です。

ここは本当に妥協してしまったので、もう少し対応機種を絞れば良かったかなぁというのが反省点です。

 

まとめ

 

なんとか無理矢理使ってみたけど問題は山積みです。

  • iOSで画像が潰れるバグ
  • canvasのリサイズは性能が悪い
  • スペックの低いスマホ端末ではブラウザが落ちる

現状では、フォーム投稿時のサムネイルに使う程度なら有用かと思います。

どうしてもスマホからWebで画像アップロードするときは、対応機種を絞ればこの方法でも行けそうです。

それにしても画像を投稿するコンテンツはどう考えてもネイティブアプリで作った方がいいですね。リサイズなんて当たり前にできますし、アプリをインストールする敷居もどんどん下がってますしね。

【ペット見守りシステム開発日記②】JavaScriptでArduinoとシリアル通信

前回までのあらすじ

外出先から室温の確認と、エアコン操作をするための開発日記。
前回はArduinoで室温取得とエアコン操作を実装。


ペット見守りシステム構築日記①】Arduinoでエアコン操作してみた - SPICY SPACE BLOG

 

外出先からArduinoを操作するには

最近注目してるブラウザ間通信を実現できるWebRTCという技術を使えば、ブラウザから自宅の遠隔管理ができるかも!
 
iPhoneではまだサポートされてないのが痛いところだけど、固定IPやダイナミックDNSを使わなくてもいいところが魅力。
 
ということで、まずはローカルPCのブラウザからArduinoとシリアル通信ができるよう実装してみます。
 
 
 

jsとarduinoの橋渡し

Serialport-server by shokai

ライブラリを使いました。

「Serialport-server」はWebSocketでjsからシリアル通信の橋渡しをしてくれる仮想サーバーです。

こんな便利なもの作ってくれている人がいるなんて!しかもgemでインストールできるようにしてくれてるなんて!すばらしい。

gem install serialport-servermacなら一発でインストールできるはず、と書いてあったんですが、

OS X 10.9だとERROR: Failed to build gem native extensionのエラーが発生してしまいました。Apple Developerサイトから「Command Line Tools (OS X Mavericks) for Xcode」をインストールすることで、無事インストールできました。

 

インストールできたら、serialport-server /dev/tty.デバイス名を実行することでサーバを起動できます。

デバイス名はArduino IDEツール->シリアルボードから確認できます。

f:id:sp_ice:20140901004305p:plain

 

 

Arduino側は前回記事のソースを利用します。

js側のソースはこんな感じ

 

できました!

とりあえず、ローカルPCのブラウザからエアコンON/OFFができるようになりました

 

arduinoでエアコンON/OFFでけたー。これで夏に愛犬を留守番させるのもすこし安心。

 

まとめ

すごい人が作ったツールはすごい(当たり前)

次回は外出先からの操作の実装!

 

ペット見守りシステム構築日記①】Arduinoでエアコン操作してみた

ペット飼い主の憂鬱
暑い日が続いていますね。
我が家は共働きなので、うちの愛犬は平日は家で留守番をさせています。
いつもクーラーを26度設定でONしてから家を出ていますが、
「クーラーが壊れて室温が高くなっていたらどうしよう」
「停電でクーラーが切れてしまったらどうしよう」
など、飼い主には心配のつきない季節です。
 
最近はスマート家電などで、外出先から室温の確認、エアコンのON、OFFができるものも出ていますが、すぐに買い替えよう!というわけには行きません。
 
そこで、Arduinoで自作しちゃえ!ヽ(# `Д´)ノムキー!!
ということで作ってみた記録です。
 
材料
Arduinoエントリーキット 

 

Arduinoエントリーキット

Arduinoエントリーキット

 

 

 

線やセンサーが色々セットになっているスターターキットをAmazonでポチリ。  
全部使用するわけではないのですが、とりあえずarduinoで遊んでみたかったので購入。
【参考サイト】Arduino入門 (全12回) - プログラミングならドットインストール
こちらでお勉強できます。
 
それ以外に必要なもの
赤外線LED:OSI5LA5113A (秋月)
赤外線リモコン受信モジュール:OSRB38C9AA (秋月)
抵抗 47Ω (秋月)
【参考サイト】Arduinoでリモコン作成
こちらのブログを参考に、全く同じ部品を秋月で購入し使わせて頂きました。

これでそろいました。

f:id:sp_ice:20140524113047j:plain


 
作ってみる
リモコン作成
エアコンのリモコンから出ている赤外線を読み取って、同じ信号をarduinoからエアコンに発信することで、実装します。
【参考サイト】Arduinoでリモコン作成
エアコン操作は先ほどのブログに載っていた回路図、ソースを拝借して、カスタマイズしました。ありがとうございます。
 
温度計測
これに室温を測るための温度センサーを繋げて回路図はこんな感じ。

f:id:sp_ice:20140821003228p:plain


右から赤外線LED(OSI5LA5113A)、赤外線リモコン受信モジュール(OSRB38C9AA )、温度センサ(LM35DZ)となります。
配線がヘタクソなのはご愛嬌ということで。。。
 

 
 Arduinoソース
リモコンの信号の配列を変数に格納しようとしてはまりました。
「大きい配列を用意するとプログラムが停止する可能性がある。」と参考サイトにも書いてありましたが、コンパイルは通るのに実際は動いていないという状態だったため、気づくのにかなり時間がかかってしまいました。
PROGMEMを使用し、SRAMのかわりにFlashメモリ(プログラム領域)へデータを格納することで正常に動作するようになりました。
【参考サイト】
http://www.musashinodenpa.com/arduino/ref/index.php?f=0&pos=1824
 
ソースはこんな感じ。

 
完成!!



 
まとめ
抵抗の色ってそういう意味があったんだ!レベルの回路の知識ゼロの僕でも簡単にこんなんできるなんて!超楽しい!
次回は外出先からArduinoを操作するためのこと書いてみます。  

つなげたモノを何でも楽器にするシンセ「Ototo」が届いたので遊んでみた

昨日待ちに待ってたOtotoが届きましたよ!

kickstarterで初めて出資してみたので、本当に実物が届いて感動です。
普通に買い物するよりハラハラするこの感じがいいんでしょうね!
前置きはこれくらいにして…
 

Ototoとは

つなげたモノを何でも楽器にするシンセサイザーです
 
電気を通すものにクリップを繋げるだけでおっけー!
 

開封の義

早速あけてみます!
f:id:sp_ice:20140819202458j:plain
f:id:sp_ice:20140819202522j:plain
f:id:sp_ice:20140819202539j:plain
f:id:sp_ice:20140819202554j:plain
f:id:sp_ice:20140819202606j:plain
入ってるものはこんな感じ!
基盤むき出しの本体と、色とりどりのクリップ、センサー各種!
 

早速鳴らしてみる

さて!えーと電源は、micro usbっと!
えーと…、ん??
 
入ってない!
 
持ってたからいいけど!笑
 
繋ぐもの。何か電気を通すもの。何でもいいと言われると逆に困りますね… 
とりあえず部屋にあった鉄琴につないでみました。
 
 
鉄琴のシンセサイザー化!www
 
色んな音が出ます
 
ドラムも!
  

まとめ

とりあえず、鳴らしてみただけですが、超楽しい!
MIDIデバイスとしても使えるはずなので、これでソフトシンセ鳴らしたり、MIDI信号受け取って何かするとか色々アイデアがふくらみます。
色々と試してみよう! 
 
これ↓みたいなのがやりたい!
 

HTML5 Japan Cupに「PetTime」というWebサービスを応募しました

HTML5 Japan Cupに応募したので、一応ブログにも書いとこう。

 

【PetTime -ぺっとたいむ-】

・サイトURL

http://pettime.herokuapp.com

・応募ページ

https://5jcup.org/works/53b169256bb223aa5c00142e

(※以下、上記ページのコピペです)

ブラウザから自宅のペットとビデオチャットできるWebサービスです。

インストール不要、ブラウザのみで使用できます。

使い方はログインし、自宅のPCと外出先のPCでそれぞれ通話ページを開くだけ!

自動的に自宅とビデオチャットが始まります。

また、自宅のペットから飼い主のあなたに発信することができます。

ペットが「ワン」と吠えると、あなたのTwitterアカウントにDMが届きます。 (PCのマイクで一定以上の音を拾った場合に通知されます。)

DMに記載されているリンクをクリックすることで、ビデオチャットが開始されます。

 

使用技術

  • WebRTC(ビデオチャット
  • Skyway(WebRTCを簡単に使用するAPI
  • Web Audio API(ペットの声で発信)
  • FuelPHP(サーバサイド)
  • Heroku(公開サーバ)
  • Opauth(Twitter認証に使用したライブラリ)

 

感想

今回使用したWebRTCは、現状はChrome(iOSを除く)およびFirefoxのみ対応してます。

スマホから見たいよ!ってのがすごくあるんだけど、iPhoneからはまだムリ。。。

appleさんお願いします!

 

そして、こんな簡易なサービスを作るのにもまだまだ時間がかかりすぎる。

特に今回は、SkywayとかTwitterとか特定のドメインじゃないと動かないやつの実装をするのに、いちいちgitでpushして、Heroku上で確認とかやってしまったので、超非効率でした。どうするのが正解だったんだろう。

もっとサクサク作れるようになりたい。

HerokuがPHPに正式対応したのでFuelPHP動かしてみた

これまでHerokuでPHPの設定をいじるにはbuildpackという仕組みを使っていましたが、必要なくなりました。

操作手順を一通りメモ。

  

環境構築手順

1.fuelphpのプロジェクト作成

oil create [プロジェクト名]

 

2.gitで管理するために

不要なものを削除

rm -rf .git .gitmodules *.md docs fuel/core fuel/packages

削除したコアファイルをサブモジュールとして追加

git submodule add git://github.com/fuel/core.git fuel/core
git submodule add git://github.com/fuel/oil.git fuel/packages/oil
git submodule add git://github.com/fuel/auth.git fuel/packages/auth
git submodule add git://github.com/fuel/parser.git fuel/packages/parser
git submodule add git://github.com/fuel/orm.git fuel/packages/orm
git submodule add git://github.com/fuel/email.git fuel/packages/email

 

3. .gitignoreを編集

/composer.lockの行を削除

これをしないとherokuにpushしたときに、次のエラーが出てしまいます。

Your composer.json specifies dependencies, but no composer.lock was found, please check it into your repository along with composer.json!

 

4.Procfileの作成

ルートにファイル名Procfileを作成。apacheかNginXかと、Document Rootが指定できます。

web: vendor/bin/heroku-php-apache2 public/

参考:https://devcenter.heroku.com/articles/custom-php-settings#setting-the-document-root

 

5.composer.json

ルートにこのファイルがあれば、herokuがPHPを使用すると判断します。

mbstringなどの拡張もここで指定できます。

FuelPHPのプロジェクトには最初からルートにcomposer.jsonが配置されているので、そのまま使用します。

ここでハマってしまったのですが、push時にはエラーにならないのですが、webからアクセスをするとApplication Errorで何も表示されませんでした。

heroku logsでログを確認するとbash: vendor/bin/heroku-php-apache2: No such file or directoryとエラーが出ており、herokuのプロセス自体が起動していませんでした。

Procfileを使用する場合はそのままでは動かずcomposer.jsonを書き換える必要がありました。

公式のドキュメントをよく読むとvendor/binのパスはheroku側でComposerにて設定されているそうで、composer.jsonにconfigの項があると、これが上書きされてしまうみたいです。(Symfonyとかも同じ現象になるみたい)

下記のbin-dirの設定を追記することで解決!

"config": {
"bin-dir": "vendor/bin",
"vendor-dir": "fuel/vendor"
},

参考:https://devcenter.heroku.com/articles/php-support

 

6.herokuにcommit & push

heroku openでfuelPHPのスタートページが表示されれば完了!

 

まとめ

今回は超時間がかかってしまいましたが、次回からはさくっとfuelPHPの環境が構築できそうです。

 

参考サイト

http://kayakuguri.github.io/blog/2014/06/11/heroku-php/

http://qiita.com/L_e_k_o/items/956bd92645769dece5e7

 

関連する記事


FuelPHPプロジェクト作成してHerokuで公開するシェルを作りました。 - SPICY SPACE BLOG

ビジュアルコーディング練習日記001〜ランダムに線を引く〜

fladdictさんのブログを読んで触発されたので、今さらながらprocessingを触ってみてます。

頭に思い描いた動きを、すぐにコードにできるようになりたい。

 

とりあえず、以前購入していたProcessingでアートしよう!な本が家に転がりっぱなしだったので、これをやってみます。

体系的にアートの勉強。いいじゃないですか。

 

ジェネラティブ・アート -Processingによる実践ガイド

ジェネラティブ・アート -Processingによる実践ガイド

  • 作者: Matt Pearson,久保田晃弘,沖啓介
  • 出版社/メーカー: ビー・エヌ・エヌ新社
  • 発売日: 2012/12/21
  • メディア: 単行本(ソフトカバー)
  • クリック: 9回
  • この商品を含むブログ (7件) を見る
 

 

まず、ランダム性を操る術を身につける。

世の中には完全にランダムなものはほとんど無いそうです。

ランダムの中に垣間見える法則、数学って美しい。

 

まずは完全なランダム

 

ランダムな数を加算

 

パーリンノイズを使用

 

サインの3乗+パーリンノイズ

 

乱数の5乗

 

単純に線を引くだけでも、奥が深い。

毎日短時間でも練習を続けたいと思います。