CountDownControlを使ってカウントダウン後にカメラのシャッターを切る

2013年1月16日(水)
薬師寺 国安

シャッター音が鳴った後の処理

時間間隔を0で初期化しTimeSpanの新しいインスタンスmyPosに格納しておきます。MediaElementの開始時間を先頭に戻します。

GridViewをクリアし、撮った画像をGridViewに追加するAddPhotoプロシージャを実行します。

  Private Sub MediaElement1_MediaEnded(sender As Object, e As RoutedEventArgs) Handles MediaElement1.MediaEnded
    Dim myPos As New TimeSpan(0, 0, 0)
    TextBlock1.Text = "保存しました。"
    MediaElement1.Position = myPos
    GridView1.Items.Clear()
    AddPhoto()
  End Sub

GridViewに表示されている画像一覧から任意の画像を選択した時の処理

GridViewから選択された画像のインデックスを変数Indexに格納しておきます。ピクチャライブラリのPhotoImageサブフォルダーにアクセスします。CreationCollisionOption列挙体については下記URLを参照してください。
→ CreationCollisionOption enumeration (Windows)

GetFileAsyncメソッドでPhotoImageフォルダー内のファイルを取得し、ファイルのコレクションを表すメンバ変数myPictureFilesに格納しておきます。

新しいBitmapImageのインスタンスmyBmpオブジェクトを作成し、SetSourceメソッドに、Await myPictureFiles(Index).OpenReadAsyncと指定して、メンバ変数Indexに該当するコレクション変数myPictureFilesに格納されている画像ファイルを読み取って開きます。ImageのSourceプロパティにmyBmpオブジェクトを指定します。実寸の画像が表示されます。使用不可となっていた[Upload]ボタンの使用を可能にします。

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

  Private Async Sub GridView1_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) Handles GridView1.SelectionChanged
    Try
      messageTextBlock.Visibility = Windows.UI.Xaml.Visibility.Collapsed
      Index = GridView1.SelectedIndex
      Dim myFolder As StorageFolder = Windows.Storage.KnownFolders.PicturesLibrary
      Dim mySubFolder = Await myFolder.CreateFolderAsync("PhotoImage", CreationCollisionOption.OpenIfExists)
      myPictureFiles = Await mySubFolder.GetFilesAsync()
      Dim myBmp As New BitmapImage
      myBmp.SetSource(Await myPictureFiles(Index).OpenReadAsync)
      Image1.Source = myBmp
      uploadButton.IsEnabled = True
    Catch
      Exit Sub
    End Try
  End Sub

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

現在の「年月日時間分秒.jpg」ファイルを作成して変数fileNameに格納しておきます。

fileNameを引数に
String.Format("ユーザーのサーバー名/ImageFileUpload/Default.aspx?filename={0}", fileName)
の文字列を作成し変数_uriに格納しておきます。

非表示となっているdummyTextBoにfileNameの値を入れておきます。そうしないと時間が経過し続けてしまい、保存したファイル名とXMLに書きこむファイル名が異なる不具合が発生するためです。そのため、作成されたファイル名はdummyTextBoxに入れておいて、XMLを作成する際、ここの値を読み取ってきます。

ImageFileUpload/Default.aspxは、後ほど紹介(リスト3)する、サーバーにアップするためのASP.NETファイルです。

ピクチャライブラリのPhotoImageサブフォルダーにアクセスし、GetFileAsyncメソッドでファイルを取得しコレクションメンバ変数myPictureFilesに格納しておきます。Indexに該当するmyPictureFilesの画像ファイルを変数myFileで参照します。

BackgroundTransfer.BackgroundUploaderの新しいインスタンスmyUploaderオブジェクトを作成します。

BackgroundTransfer.BackgroundUploaderクラスは、ダウンロード、アップロード転送機能を有効にし、アップロード操作を実際に作成する前に、アップロードを構成するクラスです。
パスワード資格情報を表す、PasswordCredentialクラスの新しいインスタンス、myPassWordオブジェクトを作成します。
Passwordプロパティにサーバーに接続するためのパスワードを指定します。UserNameプロパティにはユーザー名を指定します。
サーバーの認証に使用する資格情報を設定する、ServerCredentialプロパティにmyPassWordオブジェクトを指定します。MethodにはPOSTを、Content-Typeにはmultipart/form-dataと、JPEGにはimage/jpgと指定します。
SetRequestHeaderメソッドで指定します。これはHTTP要求ヘッダーを設定するためのメソッドです。

非同期操作のアップロードを実行するUploadOperation型の変数uploadを宣言し、BackgroundUploader クラスのCreateUploadメソッドで、アップロード先、アップロードするファイルでUploadOperationを初期化します。
UploadOperation クラスのStartAsyncメソッドで、非同期のアップロードを開始します。

ドキュメントライブラリにアクセスします。前述もしましたが、このフォルダへのアクセスはWindows ストアへの申請の際エラーになりますので、ピクチャライブラリにフォルダを作って、その中のファイルを作成し、読み込むようにして下さい。ドキュメントライブラリに予め配置していたXML宣言とルート要素だけのImageFileList.xml(リスト4)を取得します。

XMLドキュメントの読み込みと、解析の際に使用される設定の含まれる、XmlLoadSettingsクラスの新しいインスタンス、mySettingオブジェクトを作成します。DTDは含めないので、ProhibitDtdプロパティにFalseと指定します。外部エンティティ参照もしませんので、ResolveExternalsプロパティにFalseと指定します。

XmlDocumentクラスのLoadFromFileAsyncメソッドで、指定されたファイルからXMLドキュメントを非同期的に読み込みます。ドキュメントは指定された設定を使用して解析されます。

XML文書ファイル(ImageFileList.xml)のルート要素を取得して、myRoot変数で参照します。CreateElementメソッドで「画像名」という要素を作成します。InnerTextプロパティで要素の内容テキストを作成します。内容テキストは非表示になっているdummyTextBoxに格納されているファイル名です。ルート要素にAppendChildメソッドで内容テキストの追加された要素を追加します。SaveToFileAsyncメソッドでImageFileList.xmlファイルにXMLドキュメントを非同期に保存します。

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

  Private Async Sub uploadButton_Click(sender As Object, e As RoutedEventArgs) Handles uploadButton.Click
    Dim fileName = DateTime.Now.ToString("yyyyMMddHHmmss") & ".jpg"
    Dim _uri As String = String.Format("http://2008r2.projectkyss.net/ImageFileUpload/Default.aspx?filename={0}", fileName)
    dummyTextBox.Text = fileName
    Dim myFolder As StorageFolder = Windows.Storage.KnownFolders.PicturesLibrary
    Dim mySubFolder = Await myFolder.CreateFolderAsync("PhotoImage", CreationCollisionOption.OpenIfExists)
    myPictureFiles = Await mySubFolder.GetFilesAsync()
    Dim myFile As StorageFile = myPictureFiles(Index)
 
    Dim myUploader = New BackgroundTransfer.BackgroundUploader
    Dim myPassWord As New PasswordCredential
    myPassWord.Password = "サーバーにアクセスするパスワード"
    myPassWord.UserName = "ユーザー名"
    myUploader.ServerCredential = myPassWord
    myUploader.Method = "POST"
    myUploader.SetRequestHeader("Content-Type", "multipart/form-data")
    myUploader.SetRequestHeader("JPEG", "image/jpg")
    Dim myUri = New Uri(_uri, UriKind.Absolute)
    Dim upload As UploadOperation = myUploader.CreateUpload(myUri, myFile)
 
    Await upload.StartAsync()
 
    Dim myStorageFolder As StorageFolder = Windows.Storage.KnownFolders.DocumentsLibrary
    Dim myXmlFile As StorageFile = Await myStorageFolder.GetFileAsync("ImageFileList.xml")
    Dim mySetting As New XmlLoadSettings
    mySetting.ProhibitDtd = False
    mySetting.ResolveExternals = False
 
    Dim xmldoc = Await XmlDocument.LoadFromFileAsync(myXmlFile, mySetting)
    Dim myRoot = xmldoc.DocumentElement
    Dim myElement = xmldoc.CreateElement("画像名")
    myElement.InnerText = dummyTextBox.Text
    myRoot.AppendChild(myElement)
    Await xmldoc.SaveToFileAsync(myXmlFile)
    messageTextBlock.Visibility = Windows.UI.Xaml.Visibility.Visible
  End Sub
End Class

リスト3 ASP.NETで作成した、ユーザーがサーバーに配置するImageFileUploadプロジェクトのDefault.aspx.vbファイル。

  • ※サーバーにアップした際のアクセス権の設定やIISの設定は各自が行ってください。
  • ※ダウンロードしたサンプルファイルにはImageFileUploadプロジェクトも一式含まれています。
Option Strict On
Imports System.IO
Imports System.Xml

Partial Class _Default
  Inherits System.Web.UI.Page
 
  Protected Sub Page_Load(sender As Object, e As System.EventArgs) Handles Me.Load
    Dim fileName As String = Context.Request.QueryString("fileName").ToString
    Dim filePath As String = Server.MapPath("./") & "ImageData/" & fileName
    Using stream As FileStream = File.Open(filePath, FileMode.Create)
      Dim buffer As Byte() = New Byte(4096) {}
      Dim myByteRead As Integer
 
      While (InlineAssignHelper(myByteRead, Context.Request.InputStream.Read(buffer, 0, buffer.Length))) <> 0
        stream.Write(buffer, 0, myByteRead)
      End While
 
      'stream.Flush()
      stream.Close()
      Response.Flush()
    End Using
  End Sub
 
  Private Shared Function InlineAssignHelper(Of T)(ByRef target As T, ByVal value As T) As T
    target = value
    Return value
  End Function
End Class

解説は省略いたします。

リスト4 予めドキュメントライブラリに配置しておくXMLファイル(ImageFileList.xml)

このXMLファイルに、サーバーにアップした画像のファイル名が記録されていきます。

<?xml version="1.0" encoding="utf-8"?>
<画像></画像>

今回はここまでです。ありがとうございました。

  • CountDownControlを使ってカウントダウン後にカメラのシャッターを切る

薬師寺国安事務所

薬師寺国安事務所代表。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メルマガ会員のサービス内容を見る

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