iPhoneで「置くだけ転送」出来るアプリを作ってみたメモ

こういうの。

動機

  • 外出先で4Sで撮った写真をiPadでも見たいけどうちのiPadWiFiモデルだし4Sはテザリングできない
  • AndroidだとNFCとかでタッチして転送とか出来るんでしょ、持ってないけど
  • Bluetooth転送アプリもあるけど接続先をいちいち選択するのなんかアレ
  • iPhoneの画面とカメラで可視光通信したら面白そう
  • じゃあ可視光通信をキーにして接続先を選択してやれば、タッチして転送っぽいことが出来るはず

ステップ1:画像ファイルを転送する

AppleのサンプルコードPictureSharing。
https://developer.apple.com/library/mac/#samplecode/PictureSharing/Introduction/Intro.html
Bonjourによるサービスの公開/検索と、ソケットを使ってファイル転送する部分をここから頂戴した。

ステップ2:iPhoneでGameKitを使わずにBluetooth接続する

PictureSharingのコードのまんまだとWiFiでしか転送できないので、これをBluetooth対応にしたい。都合のいいことにBonjour over Bluetoothというのがあるので、これを使えばいいはず。
https://developer.apple.com/library/ios/#qa/qa1753/_index.html%23//apple_ref/doc/uid/DTS40011315
どうやらBonjour over BluetoothはNSNetServiceでは使えないっぽいので、もっとローレベルのAPIDNS-SDを使う必要があるっぽい。
でも大丈夫、AppleのサンプルコードDNSSDObjectsを使えば、NSNetServiceと同じような感じでObjective-Cから扱える。
https://developer.apple.com/library/mac/#samplecode/DNSSDObjects/Introduction/Intro.html

ステップ3:可視光通信する

リアルタイムの画像を得る

QRコードもある意味可視光通信だけど、なんか読み方とか分からないし、タッチするくらいの近距離だとそもそもカメラのピントが合わないので、光の点滅で通信しよう*1
iPhoneのカメラからリアルタイムの画像を得るには、AVCaptureなんたらを使う。
実践! iPhoneアプリ開発40 ビデオカメラアプリの作り方 (1) - セッションの作成
どうせ至近距離でボケるんだから画像のサイズも最小限でいい。今回はさらに3x3のサイズに縮小して、9ピクセルそれぞれから信号をデコードしている。どれかちゃんと受信できるだろ多分。

どうやってエンコードしようか

明暗を1と0にして通信すればいいけど、何msごとに明暗を判定するとか、ええとなんだその、クロックを同期させなければならない。一応30fpsにしたけどこれフレームレート保証されるわけじゃ無いんでしょ?どうしよっか?ということで、今回はこうしてみました。

  • シグナルをRGBに分ける
  • Rは常に点滅を繰り返す。Rの立ち上がりと立ち下がりの時点でその他のチャンネルを読む
  • GとBの明暗によって2bitのデータを得る。4回で8bit。1byteゲットだぜ
  • 一定時間Rの点滅がなかったら信号終わりかなってことで、文字列にしてみる

点滅を繰り返しながら、信号無しの時間を1秒間挟んでいる。この1秒間は画面側に白を表示して、カメラ側でも一定時間白だったら自動露出補正をオンにして露出を調整してから、自動露出補正をオフにして信号受信に備えている。

ステップ4:今後の課題

  • 今のままだとこれBonjourのサービス名を可視光通信で送ってるだけなので、可視光通信しなくても無差別に接続しちゃうクライアントがあったら画像送っちゃう。公開するんだったらここをもうちょっとなんとかすべき
  • 私が持ってるのはiPhone 4Sと4GSとiPad 3だけだから、他の機種のカメラでちゃんと認識できるのかわからない
  • というか私の全部カバーないから、カバー有りだとまた変わるかも分からない
  • 点滅繰り返してポケモンショックとかならないのか

あとなんかカシオでも似たようなのやってたみたいよ

*1:このあたりで実用性はログアウトしました