カメラで写した写真をカメラロールに保存する

2011年12月5日(月)
PROJECT KySS

ページが非アクティブになった時呼び出されるメソッド

イメージソース ストリームを破棄し、カメラのオブジェクトによって使用されているリソースを解放します。
全てのオブジェクトの関連付けを破棄します。
RemoveHandlerステートメントで、イベントとイベント ハンドラの関連付けを解除します。
  Protected Overrides Sub OnNavigatedFrom(e As System.Windows.Navigation.NavigationEventArgs)
    If myPhotoCamera Is Nothing = False Then
      myPhotoCamera.Dispose()
      myPhotoCamera = Nothing
      Try
        RemoveHandler myPhotoCamera.CaptureCompleted, AddressOf myPhotoCamera_CaptureCompleted
        RemoveHandler myPhotoCamera.CaptureImageAvailable, AddressOf myPhotoCamera_CaptureImageAvailable
      Catch
        Exit Sub
      End Try
    End If
    MyBase.OnNavigatedFrom(e)
  End Sub

[Auto Focus]ボタンがクリックされた時の処理

AddHandlerステートメントで、フォーカス操作が完了した後に発生するAutoFocusCompletedイベントに、myPhotoCamera_AutoFocusCompletedイベントハンドラを追加します。
Focusメソッドで、カメラオートフォーカス操作を開始します。
  Private Sub focusButton_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles focusButton.Click
    If myPhotoCamera Is Nothing = True Then
      Exit Sub
    Else
      AddHandler myPhotoCamera.AutoFocusCompleted, AddressOf myPhotoCamera_AutoFocusCompleted
      myPhotoCamera.Focus()
    End If
  End Sub

フォーカス操作が完了した後に発生するイベント

RemoveHandlerステートメントで、イベントとイベント ハンドラの関連付けを解除します。
「フォーカス完了」のメッセージを表示します。Me.Dispatcher.BeginInvokeメソッドで、別スレッドからメッセージを呼び出します。
  Private Sub myPhotoCamera_AutoFocusCompleted(sender As Object, e As CameraOperationCompletedEventArgs)
    RemoveHandler myPhotoCamera.AutoFocusCompleted, AddressOf myPhotoCamera_AutoFocusCompleted
    Me.Dispatcher.BeginInvoke(Sub() MessageBox.Show("オートフォーカス完了"))
  End Sub

イメージが利用可能な場合に発生する処理

新しいMediaLibrayのインスタンスmyLibrayオブジェクトを作成します。
カウントされる変数counterと拡張子.jpgを連結した文字列をfilename変数に格納しておきます。
MediaLibrayクラスのSavePictureToCameraRollメソッドで、Xnaメディアライブラリを使用して画像を、カメラロールに保存します。
変数storageを、ファイルとディレクトリを格納している分離ストレージ領域を表すIsolateStorageFileクラスとして宣言します。FileExistsメソッドでfilenameに格納しているのと同じファイルが存在する場合は、DeleteFileメソッドで同名ファイルを削除します。
IsolatedStorageFileクラスのOpenFileメソッドでfilename変数内のファイルを、指定したファイルアクセスを使用して指定したモードでファイルを開きます。バイト型として4095の領域を確保します。e.ImageStream.Readメソッドで、イメージストリームからバイト数を読み取り、変数myByteReadに格納します。この変数が、0より大きい間、IsolatedStorageFileStream.Writeメソッドで、読み込んだイメージストリームのバイト数をバッファーに書き込んでいきます。
写真の撮影とエンコードが正しくできているかは、ContentReadyEventArgs.ImageStreamプロパティから取得できますので、これを分離ストレージへ保存します。e.ImageStreamを閉じ、保存した旨のメッセージを表示します。
e.ImageStream.Readの書式は下記の通りです。

e.ImageStream.Read(バイト配列, データの格納を開始するバッファー内のバイト オフセット(通常0を指定), 
現在のストリームから読み取るバイトの最大数。)

IsolatedStorageFileStream.Writeメソッドの書式は下記の通りです。

IsolatedStorageFileStream.Write(書き込むバッファー, 開始位置を示すバッファー内のバイト オフセット(通常0を指定) ,書き込む最大バイト数,)

  Private Sub myPhotoCamera_CaptureImageAvailable(sender As Object, e As ContentReadyEventArgs)
    Dim myLibray As New MediaLibrary
    Dim filename As String = counter & ".jpg"
    myLibray.SavePictureToCameraRoll(filename, e.ImageStream)
 
    Dim storage As IsolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication
    If storage.FileExists(filename) = True Then
      storage.DeleteFile(filename)
    End If
    Using myStream As IsolatedStorageFileStream = storage.OpenFile(filename, FileMode.Create, FileAccess.Write)
      Dim myBuffer(4095) As Byte
      Dim myByteRead As Integer = -1
      Do
        myByteRead = e.ImageStream.Read(myBuffer, 0, myBuffer.Length)
        myStream.Write(myBuffer, 0, myByteRead)
      Loop While (myByteRead > 0)
      e.ImageStream.Close()
      Me.Dispatcher.BeginInvoke(Sub() MessageBox.Show("保存しました。"))
    End Using
  End Sub

[Shutter]ボタンがクリックされた時の処理

PhotoCameraにファインダーに表示されるイメージがある場合は、CaptureImageメソッドで、ファインダーに表示される現在のイメージのフル解像度キャプチャを開始します。例外が発生した場合は「エラーです。」と表示します。
  Private Sub shutterButton_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles shutterButton.Click
    If myPhotoCamera Is Nothing = False Then
      Try
        myPhotoCamera.CaptureImage()
      Catch
        Me.Dispatcher.BeginInvoke(Sub() MessageBox.Show("エラーです。"))
      End Try
    End If
  End Sub

キャプチャ シーケンスが完了すると発生するイベント

Sharedステートメントで宣言したcounterの値を1ずつ増加させます。
  Private Sub myPhotoCamera_CaptureCompleted(sender As Object, e As CameraOperationCompletedEventArgs)
    counter = counter + 1
  End Sub

[解像度を低に設定]ボタンがクリックされた時の処理

AvailableResolutionsプロパティで、使用できるカメラの解像度を照会します。
カメラでキャプチャしたイメージの解像度を設定できる、Resolutionプロパティに、先に取得したmyResolutionの一番先頭の解像度を指定します。一番先頭の解像度は640×480の解像度です。
解像度を設定した旨のメッセージを表示します。
  Private Sub resolutionButton_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles resolutionButton.Click
    Dim myResolution As IEnumerable(Of Size) = myPhotoCamera.AvailableResolutions
    myPhotoCamera.Resolution = myResolution.First
    MessageBox.Show("撮影可能な解像度を" & myPhotoCamera.Resolution.ToString & "に設定しました。")
  End Sub
End Class
  • 「カメラで写した写真をカメラロールに保存する」サンプルプログラム

四国のSOHO。薬師寺国安(VBプログラマ)と、薬師寺聖(デザイナ、エンジニア)によるコラボレーション・ユニット。1997年6月、Dynamic HTMLとDirectAnimationの普及を目的として結成。共同開発やユニット名義での執筆活動を行う。XMLおよび.NETに関する著書や連載多数。最新刊は「Silverlight実践プログラミング」両名とも、Microsoft MVP for Development Platforms - Client App Dev (Oct 2003-Sep 2012)。http://www.PROJECTKySS.NET/

連載バックナンバー

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています