カメラ機能の作成(2)
プレビューの表示
次に、カメラのプレビューを画面に表示してみましょう。取得したCameraControlオブジェクトを<video>のストリームとしてmozSrcObjectプロパティにセットします。
<div id="previewContainer"> <video id="preview"></video> </div>
var previewVideo = document.getElementById('preview'); function onSuccess(success) { // スコープ外に値を保持 camera = success; console.log('getCamera:success', camera); // プレビューの再生 previewVideo.mozSrcObject = camera; previewVideo.play(); }
プレビュー映像は、実際のアプリでは、取得した状態だと横向きに表示されてしまうため、<div>で<video>を囲い、CSSのtransformで回転させて縦向きの画像として見えるようにしています。
カメラからの画像の取得・保存
実際にカメラの画像を保存するには、CameraControl.takePicture()を利用します。指定するオプションで画像サイズやファイルのフォーマット、EXIF情報などを指定することができます。
<span id="captureBtn" class="capture-btn"></span>
// ストレージ var storage = navigator.getDeviceStorage('pictures'); // キャプチャボタン var captureBtn = document.getElementById('captureBtn'); captureBtn.addEventListener('touchstart', captureStart, false); captureBtn.addEventListener('touchend', captureEnd, false); function captureStart(e) { console.log('captureStart', e); if(!camera) return; function onSuccess(success) { console.log('autoFocus:success', success); } function onError(error) { console.warn('autoFocus:error', error); } camera.autoFocus(onSuccess, onError); } function captureEnd(e) { console.log('captureEnd', e); if(!camera) return; var options = { pictureSize: camera.capabilities.pictureSizes[0], // 最大サイズ fileFormat: 'jpeg' }; function onSuccess(success) { console.log('takePicture:success', success); // 画像をストレージへ保存 var filename = 'fxcam_' + Date.now() + '.jpg'; storage.addNamed(success, filename); alert("画像を保存しました\n" + filename); // プレビューの再開 camera.resumePreview(); }; function onError(error) { console.log('takePicture:error', error); // カメラ取得失敗時の処理 }; camera.takePicture(options, onSuccess, onError); }
このコードでは、キャプチャボタンのtouchstart時にオートフォーカスで照準を合わせ、touchend時に撮影画像を取得します。
カメラの画像を保存する際、取得できる画像サイズは端末のスペックに依存するため、CameraControlオブジェクトからカメラに関する情報をCameraCapabilitiesオブジェクトで受け取ります。
画像が取得できると、成功時のコールバックにBlobオブジェクトとして画像が渡されます。BlobオブジェクトはDeviceStorage.addNamed()を利用してストレージに保存することができます。なお、ストレージへの初回アクセス時には、カメラへのアクセスと同様に、ユーザに対してAPI利用の承認画面が表示されます。
また、CameraControl.takePicture()を呼ぶと、一旦プレビューが停止するため、CameraControl.resumePreview()でプレビュー映像を再開します。
Camera APIで利用できる画像のエフェクト処理
CameraCapabilitiesオブジェクトには、画像に対するエフェクトも含まれています。
エフェクトは、OSのバージョンや端末によって数が変わりますが、今回利用した端末では、以下の12つのプロパティがありました。
- "none"(エフェクトなし)
- "mono"(モノクロ調)
- "negative"(ネガポジ反転)
- "solarize"(ソラリゼーション)
- "sepia"(セピア調)
- "posterize"(ポスター絵調)
- "whiteboard"(ホワイトボード:コントラスト強め)
- "blackboard"(ブラックボード:コントラスト弱め)
- "aqua"(アクア:青みがけ)
- "emboss"(エンボス加工)
- "sketch"(スケッチ風)
- "neon"(ネオン)
これらのプロパティをCameraControl.effectに指定することで、画像にエフェクトをかけることができます。プレビュー映像と、取得できる画像の両方にエフェクトが適用されます。
<span id="effectLabel" class="effect-label">none</span> <span id="effectRightBtn" class="effect-right-btn">›</span> <span id="effectLeftBtn" class="effect-left-btn">‹</span>
// エフェクト var effects = camera.capabilities.effects; var effectIndex = 0; // エフェクト名を表示するラベル var effectLabel = document.getElementById('effectLabel'); // エフェクト切替ボタン(右) var effectRightBtn = document.getElementById('effectRightBtn'); effectRightBtn.addEventListener('touchend', changeEffectRight, false); // エフェクト切替ボタン(左) var effectLeftBtn = document.getElementById('effectLeftBtn'); effectLeftBtn.addEventListener('touchend', changeEffectLeft, false); function changeEffectRight(e) { console.log('changeEffectRight', effectIndex); if(!camera) return; effectIndex = (effectIndex < effects.length-1) ? effectIndex + 1 : 0; effectLabel.innerHTML = camera.effect = effects[effectIndex]; } function changeEffectLeft(e) { console.log('changeEffectLeft', effectIndex); if(!camera) return; effectIndex = (effectIndex > 0) ? effectIndex - 1 : effects.length - 1; effectLabel.innerHTML = camera.effect = effects[effectIndex]; }
上記のコードでは、エフェクトの切替ボタンを左右に配置し、それぞれを押すとエフェクトが順番に切り替わるようにしました。
実際のコード
今回のアプリは、これだけのコードでカメラの制御とエフェクト加工が実現できます。もう少し整理したものをGitHubに公開していますので、参考にしてみてください。
また、OSに標準搭載されているカメラアプリもGitHub上で公開されています。こちらは少し読むのが難しいですが、Camera APIを余すところなく利用していますので、非常に参考になると思います。