Webカメラで撮影した写真をセピア調に演出するアプリを作る

2013年9月3日(火)
薬師寺 国安

画像の一覧から「削除」ボタン付き画像が選択された時の処理

画像が選択されていない場合は処理を抜けます。選択されている場合は以下の処理をおこないます。

ピクチャライブラリのサブフォルダSepiaSourceImageにアクセスします。
GetFilesAsyncメソッドでファイルを取得し、コレクションメンバ変数myPictureFilesに格納します。
コレクション変数myPictureFilesが格納しているファイルで、GridViewのSelectedIndexに該当するファイルをmyFileで参照します。
新しいBitmapImageのインスタンスsaveBmpオブジェクトを作成します。SetSourceメソッドに、

Await myFile.OpenReadAsync

と指定し、OpenReadAsyncメソッドで、現在のファイルのランダムアクセスストリームを開き、BitmapSourceのソースイメージに設定します。
Image1のSourceプロパティにsaveBmpオブジェクトを指定します。これで、選択された画像が、大きな画像としてImage1に表示されます。

非同期処理で行われるため、メソッドの先頭にAsyncを追加します。

  Private Async Sub GridView1_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) Handles GridView1.SelectionChanged
    myIndex = GridView1.SelectedIndex
    If myIndex < 0 Then
      Exit Sub
    Else
      Dim myFolder As StorageFolder = Windows.Storage.KnownFolders.PicturesLibrary
      Dim mySubFolder = Await myFolder.CreateFolderAsync("SepiaSourceImage", CreationCollisionOption.OpenIfExists)
      myPictureFiles = Await mySubFolder.GetFilesAsync()
      Dim myFile As StorageFile = myPictureFiles(myIndex)
      saveBmp = New BitmapImage
      saveBmp.SetSource(Await myFile.OpenReadAsync)
      Image1.Source = saveBmp
    End If
  End Sub

Webカメラのデバイスの種類が選択された時の処理

デバイスの表示されている選択ボックスから選択したインデックス番号を、メンバ変数CameraNoに格納します。

AppBar1を表示状態にしておきます。

MediaCaptureの新しいインスタンスmyMediaCaptureオブジェクトを作成します。

InitializeAsyncメソッドで、以下の内容でMediaCaptureオブジェクトを初期化します。

新しいMediaCaptureInitializationSettingsクラスのインスタンスを作成します。MediaCaptureInitializationSettingsクラスは、MediaCaptureオブジェクトの初期化設定をするクラスです。
VideoDevideIdプロパティにComboBox1より選択されたインデックスに対応する、コレクション変数myCameraのデバイスIDを指定します。

CaptureElement1のSourceプロパティに、デバイスIDで初期化されたmyMediaCaptureを指定します。
StartPreviewAsyncメソッドでプレビューを開始します。
これで、Webカメラの画像が表示されます。
マウスの右クリックで表示される、「Attach Camera」アイコンの使用を可能にします。非同期処理で行われるため、メソッドの先頭にAsyncを追加します。

  Private Async Sub cameraComboBox_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) Handles cameraComboBox.SelectionChanged
    Try
           cameraNo = cameraComboBox.SelectedIndex
      AppBar1.Visibility = Xaml.Visibility.Visible
      myMediaCapture = New MediaCapture
      Await myMediaCapture.InitializeAsync(New MediaCaptureInitializationSettings With {.VideoDeviceId = myCamera(cameraComboBox.SelectedIndex).Id})
      CaptureElement1.Source = myMediaCapture
      Await myMediaCapture.StartPreviewAsync
      shutterButton.IsEnabled = True
    Catch
      Exit Sub
    End Try
  End Sub

「Attach Camera」アイコンがタップされた時の処理

MediaElement1を再生します。つまりシャッター音が鳴ります。

ピクチャライブラリにアクセスし、CreateFolderAsyncメソッドで、ピクチャフォルダ内にSepiaSourceImageというサブフォルダを作成します。その際、CreationCollisionOption.OpenIfExistsと指定しておくと、同名フォルダやファイルがある場合は、そのフォルダやファイル名を返し、ない場合は新規に作成してくれます。

CreateFileAsyncメソッドで現在の年月日時間分秒.jpgファイルを作成します。
メンバ変数myImageFileNameに、このjpgファイル名を格納しておきます。

イメージストリームの書式を表す、新しいImageEncodingPropertiesクラスのインスタンスmyImageEncodingPropertyオブジェクトを作成します。
書式のサブタイプを表すSubtypeプロパティにjpegを指定し、Widthに640、Heightに480と指定します。

CapturePhotoToStorageFileAsyncメソッドで、ストレージファイルにフォトをキャプチャします。書式は以下の通りです。

CapturePhotoToStorageFileAsync(ImageEncodingProperties,IStorageFile)

「ピクチャライブラリのSepiaSourceImageフォルダに保存しました。」のメッセージを表示します。

GetFilesAsyncメソッドでSepiaSourceImageサブフォルダ内のファイルを取得し、コレクションメンバ変数myPictureFilesに格納します。
Countプロパティでファイルの個数を取得して、変数Indexに格納します。

新しいBitmapImageのインスタンス、saveBmpを作成します。SetSourceメソッドに、

Await myPictureFiles(Index - 1).OpenReadAsync

と指定し、OpenReadAsyncメソッドで、現在のファイルのランダムアクセスストリームを開きBitmapSourceのソースイメージに設定します。-1しているのは、コレクションメンバ変数myPictureFilesに格納されているファイルのインデックスが0から始まるためです。
Image1のSourceプロパティにsaveBmpオブジェクトを指定します。
GridView内をクリアし、「Sepia調に変換」ボタンの使用を可能にして、再描画するためにAddPhotoプロシージャを実行します。これで、写真が撮られると、保存された画像が、GridViewに追加されて選択状態になり、Image1に大きな画像として表示されます。

非同期処理で行われるためメソッドの先頭にAsyncを追加します。

  Private Async Sub shutterButton_Click(sender As Object, e As RoutedEventArgs) Handles shutterButton.Click
    MediaElement1.Play()
    Dim myFolder As StorageFolder = Windows.Storage.KnownFolders.PicturesLibrary
    Dim mySubFolder As StorageFolder = Await myFolder.CreateFolderAsync("SepiaSourceImage", CreationCollisionOption.OpenIfExists)
    Dim myFile As StorageFile = Await mySubFolder.CreateFileAsync(DateTime.Now.ToString("yyyy年MM月dd日HH時mm分ss秒") & ".jpg")
    myImageFileName = DateTime.Now.ToString("yyyy年MM月dd日HH時mm分ss秒") & ".jpg"
    Dim myImageEncodingProperty As New ImageEncodingProperties
    myImageEncodingProperty.Subtype = "jpeg"
    myImageEncodingProperty.Width = 640
    myImageEncodingProperty.Height = 480
    Await myMediaCapture.CapturePhotoToStorageFileAsync(myImageEncodingProperty, myFile)
    Dim message As New MessageDialog("ピクチャライブラリのSepiaSourceImageフォルダに保存しました。")
    Await message.ShowAsync
 
    myPictureFiles = Await mySubFolder.GetFilesAsync()
    Index = myPictureFiles.Count
    saveBmp = New BitmapImage
    saveBmp.SetSource(Await myPictureFiles(Index - 1).OpenReadAsync)
    Image1.Source = saveBmp
    GridView1.Items.Clear()

    changeSepiaButton.IsEnabled = True
    AddPhoto()
  End Sub
薬師寺国安事務所

薬師寺国安事務所代表。Visual Basic プログラミングと、マイクロソフト系の技術をテーマとした、書籍や記事の執筆を行う。
1950年生まれ。事務系のサラリーマンだった40歳から趣味でプログラミングを始め、1996年より独学でActiveXに取り組む。1997年に薬師寺聖とコラボレーション・ユニット PROJECT KySS を結成。2003年よりフリーになり、PROJECT KySS の活動に本格的に参加、.NETやRIAに関する書籍や記事を多数執筆する傍ら、受託案件のプログラミングも手掛ける。Windows Phoneアプリ開発を経て、現在はWindows ストア アプリを多数公開中

Microsoft MVP for Development Platforms - Client App Dev (Oct 2003-Sep 2012)。Microsoft MVP for Development Platforms - Windows Phone Development(Oct 2012-Sep 2013)。Microsoft MVP for Development Platforms - Client Development(Oct 2013-Sep 2014)。Microsoft MVP for Development Platforms-Windows Platform Development (Oct 2014-Sep 2015)。

連載バックナンバー

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

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

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

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