カメラ機能の作成(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を余すところなく利用していますので、非常に参考になると思います。

