カメラの向きを取得し、縦横の位置を合わせて表示させる
2012年1月13日(金)
ロジックコードを記述する
リスト2 (MainPage.xaml.vb)
Option Strict On ランチャーやチューザーに関するクラスの含まれる、Microsoft.Phone.Tasks名前空間をインポートします。 Imports Microsoft.Phone.Tasks CameraCaptureTask を使って取得した写真や画像を、ExifLib を使って正しい方向に回転して表示させるため、ExifLibをインポートしておきます。 Imports ExifLib JPEG ファイルを WriteableBitmap オブジェクトにデコードするPictureDecorderクラスの含まれる、Microsoft.Phone名前空間をインポートします。 Imports Microsoft.Phone Imports System.IO 曲、アルバム、再生リスト、およびピクチャを列挙、再生、および表示するためのクラスの含まれる、Microsoft.Xna.Framework.Media名前空間をインポートします。ピクチャへのアクセスを提供するMediaLibrayクラスを使用するため、この名前空間のインポートが必要です。 Imports Microsoft.Xna.Framework.Media Imports System.Windows.Media.Imaging Partial Public Class MainPage Inherits PhoneApplicationPage ' コンストラクター Public Sub New() InitializeComponent() End Sub CameraCaptureTaskクラス型のメンバ変数myCameraCaptureTaskを宣言します。 Dim myCameraCaptureTask As CameraCaptureTask Exifの情報を元にして画像を回転するExifLib.ExifOrientaion型のメンバ変数myOrientationを宣言します。 Dim myOrientation As ExifLib.ExifOrientation バイト型の配列、imageByteをメンバ変数として宣言します。 Dim imageBytes As Byte() ストリーム型のmyCaptureImageメンバ変数を宣言します。 Dim myCaptureImage As Stream
ページがアクティブになった時呼び出されるメソッド
AddHandlerステートメントで、チューザータスクが完了した時に発生するCompletedイベントにイベントハンドラを追加します。イベントハンドラ内では以下の処理が実行されます。 カメラアプリケーションが起動して、写真がきちんと撮れた場合の処理です。 ストリーム型のmyCaptureImageメンバ変数に、写真のデータ(ChosenPhoto)を含むストリームを格納します。ChosenPhoto.Positionプロパティに0を指定し、写真データの、現在のストリーム内の位置を設定します。 ExifLibに属するJpegInfo型のinfo変数を宣言し、ExifReader.ReadJpegメソッドで、写真のEXIF データから向きを取得します。Exifの情報を元にして画像を回転するExifLib.ExifOrientaion型のメンバ変数myOrientationに、カメラの向きを格納します。カメラの向きがTopLeft、つまり横撮影であった場合は360画像を回転させます。カメラの向きがToRight、つまり縦撮影であった場合は90度画像を回転させます。 写真のデータを含む、ストリームのバイトの長さを取得し、バイト配列を作成します。Readメソッドで、現在のストリームからバイトシーケンスを読み取ります。 ChosenPhoto.Readの書式は以下の通りです。 ChosenPhoto.Read(バイト配列,0ベースのバイトオフセット(現在のストリームから読み取ったデータの格納を開始します), 現在のストリームから読み取るバイトの最大数) Seekメソッドで、現在のストリーム内の位置を設定します。書式は以下の通りです。 ChosePhoto.Seek(基点のパラメーターのバイト オフセット, 参照ポイントを示すSeekOrigin型の値) SeekOriginにはBeginを指定し、ストリームの先頭を指定しています。 WriteableBitmap型の変数imageSourceを宣言し、PictureDecoder.DecodeJpeg(resultArgs.ChosenPhoto)で、撮った写真をJPEGファイルとしてWriteableBitmapオブジェクトにデコードします。PictureDecoder.DecodeJpegメソッドはMicrosof.Phone名前空間に属しています。WriteableBitmapクラスは書き込み更新することのできるBitmapSourceを提供するクラスです。 Image2のSourceプロパティにデコードされたJPEGファイルを格納しているimageSourceオブジェクトを指定します。これでImage内に、撮った写真が表示されます。縦撮影の場合は縦向きで、横撮影の場合は横向きで表示されます。 カメラを起動している状態で撮影を中止した場合は、saveButton(フロッピーのアイコン)は使用不可のままで処理を抜けます。 Protected Overrides Sub OnNavigatedTo(e As System.Windows.Navigation.NavigationEventArgs) myCameraCaptureTask = New CameraCaptureTask AddHandler myCameraCaptureTask.Completed, Sub(resultSender As Object, resultArgs As PhotoResult) If resultArgs.TaskResult = TaskResult.OK Then myCaptureImage = resultArgs.ChosenPhoto resultArgs.ChosenPhoto.Position = 0 Dim info As JpegInfo = ExifReader.ReadJpeg(resultArgs.ChosenPhoto, resultArgs.OriginalFileName) myOrientation = info.Orientation Dim myAngle As Integer = 0 Select Case info.Orientation Case ExifOrientation.TopLeft 'カメラ横向き myAngle = 0 Exit Select Case ExifOrientation.TopRight 'カメラ縦向き myAngle = 90 Exit Select End Select myComposite.Rotation = myAngle imageBytes = New Byte(CInt(resultArgs.ChosenPhoto.Length)) {} resultArgs.ChosenPhoto.Read(imageBytes, 0, imageBytes.Length) resultArgs.ChosenPhoto.Seek(0, SeekOrigin.Begin) Dim imageSource As WriteableBitmap = PictureDecoder.DecodeJpeg(resultArgs.ChosenPhoto) Image2.Source = imageSource Else saveButton.IsEnabled = False Exit Sub End If End Sub MyBase.OnNavigatedTo(e) End Sub
カメラボタンがタップされた時の処理
カメラ機能を起動し、保存ボタン(フロッピーのアイコン)の使用を可能にします。 Private Sub cameraButton_Click(sender As Object, e As System.Windows.RoutedEventArgs) Handles cameraButton.Click MessageBox.Show("カメラの解像度を低く設定し、設定の保存を行って、写真を撮ってください。") myCameraCaptureTask.Show() saveButton.IsEnabled = True End Sub
保存(フロッピーのアイコン)ボタンがタップされた時の処理
保存する画像のファイル名を作成します。現在の日付と時間(秒を含む)を連結したファイル名にします。日付の/を-に、時間の:を-にReplace関数で書き換えます。このファイル名を変数imageFileNameに格納しておきます。 Stream.Seek メソッドで、写真データの現在のストリーム内の位置を0に設定します。 ピクチャへのアクセスを提供する新しいMediaLibrayクラスのインスタンス、myLibrayを作成します。 MediaLibrary.SavePictureメソッドで、ストリームオブジェクトに含まれる画像を、指定したファイル名で、メディアライブラリーに保存し、その保存した画像をピクチャオブジェクトとして返します。保存した旨のメッセージを表示します。 Private Sub saveButton_Click(sender As Object, e As System.Windows.RoutedEventArgs) Handles saveButton.Click Dim imageFileName As String = DateTime.Now.ToString("yyyyMMddHHmmss") &".jpg" myCaptureImage.Seek(0, 0) Dim myLibray As New MediaLibrary myLibray.SavePicture(imageFileName, myCaptureImage) MessageBox.Show("PicturesHubに保存しました。") End Sub End Class
今回でWindows Phone Tips集第2弾は終了です。いかがですか?「基本編」、「応用編」、「Tips」、「Tips第2弾」と、いろいろなサンプルを見てきましたが、Windows Phoneでのサンプルの作成方法は理解できましたでしょうか?とにかく自分で手を動かして作ってみることが重要です。今までのサンプルをヒントに自分なりのWindows Phoneアプリを作って、ぜひMarketplaceに申請していただきたいと思います。また機会があれば、Marketplaceへのアプリの申請方法についても紹介したいと思います。
この連載に引き続き、次回からはTips集の第3弾を公開しますのでご期待ください。では、どうもありがとうございました。
「撮った写真をカメラの向きに応じて表示させる」のサンプルファイル
連載バックナンバー
Think ITメルマガ会員登録受付中
Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。