写真を切りぬいて新しい写真を撮影するサンプル
前ページからの続きです。
ページがアクティブでなくなった時の処理
「フロッピー」の「保存」ボタンの使用を不可とします。backgroundImageとdummyEllipseコントロールの表示を非表示にします。
Protected Overrides Sub OnNavigatingFrom(e As System.Windows.Navigation.NavigatingCancelEventArgs) TryCast(ApplicationBar.Buttons(1), ApplicationBarIconButton).IsEnabled = False myImage = Nothing backgroundImage.Visibility = Windows.Visibility.Collapsed dummyEllipse.Visibility = Windows.Visibility.Collapsed MyBase.OnNavigatingFrom(e) End Sub
イメージが利用可能な場合に発生する処理
変数storageを、ファイルとディレクトリを格納している分離ストレージ領域を表すIsolateStorageFileクラスとして宣言します。Path.CombineでCameraInCameraというフォルダとimageFileNameに格納されている画像名とを連結し、変数filePathに格納します。
同様にCameraInCameraというフォルダとImageList.xmlというファイル名を連結して、変数xmlFilePathに格納します。
別スレッドで以下の処理を行います。
変数imageStorageを、ファイルとディレクトリを格納している分離ストレージ領域を表すIsolateStorageFileクラスとして宣言します。
IsolatedStorageFileクラスのCreateFileメソッドでCameraInCameraフォルダ内にbackgroundImage.jpgというファイルを作成し、Writeメソッドでストリームに書き出します。
分離ストレージ内のファイルを表すIsolatedStorageFileStreamクラス用オブジェクト変数myStream変数を用意し、IsolatedStorageFileクラスのCreateFileメソッドで、変数filePathに格納されているファイルを作成します。バイト型として5119の領域を確保します。
e.ImageStream.Readメソッドで、イメージストリームからバイト数を読み取り、変数myByteReadに格納します。この変数が、0より大きい間、IsolatedStorageFileStream.Writeメソッドで、読み込んだイメージストリームのバイト数をバッファに書き込んでいきます。
写真の撮影とエンコードが正しくできているかは、ContentReadyEventArgs.ImageStreamプロパティから取得できますので、これを分離ストレージへ保存します。e.ImageStreamを閉じます。
e.ImageStream.Readの書式は下記の通りです。
e.ImageStream.Read(バイト配列, データの格納を開始するバッファ内のバイト オフセット(通常0を指定), 現在のストリームから読み取るバイトの最大数。)
IsolatedStorageFileStream.Writeメソッドの書式は下記の通りです。
IsolatedStorageFileStream.Write(書き込むバッファ, 開始位置を示すバッファ内のバイト オフセット(通常0を指定) ,書き込む最大バイト数,)
分離ストレージ内のファイルを表すIsolatedStorageFileStreamクラス用オブジェクト変数stream変数を用意します。IsolatedStorageFileクラスのOpenFileメソッドで、分離ストレージのCameraInCameraに保存しておいた、backgroundImage.jpgを指定したモード、指定したファイルアクセスを使用して開きます。
Image1コントロールを非表示にして、代わりにbackgroundImageコントロールを表示します。
WriteableBitmap型の変数myImageSourceに、PictureDecoder.DecodeJpeg(stream)で、撮った写真をJPEGファイルとしてWriteableBitmapオブジェクトにデコードします。
backgroundImageコントロールのSourceプロパティにmyImageSourceオブジェクトを指定します。
分離ストレージ内のファイルを表すIsolatedStorageFileStreamクラス用オブジェクト変数stream2変数を用意します。IsolatedStorageFileクラスのOpenFileメソッドで、変数filePathに格納されているファイルを、指定したモード、指定したファイルアクセスを使用して開きます。
WriteableBitmap型の変数myImageSourceに、PictureDecoder.DecodeJpeg(stream2)で、撮った写真をJPEGファイルとしてWriteableBitmapオブジェクトにデコードします。
Ellipse1コントロールを非表示にし、代わりにdummyEllipseコントロールを表示します。
myImageBrushという名前のImageBrushにmyImageSourceオブジェクトを指定します。
InkPresenter1で初期化されたWriteableBitmapクラス用オブジェクト変数myWriteableBitmapを作成します。
分離ストレージ内のファイルを表すIsolatedStorageFileStreamクラス用オブジェクト変数stream3変数を用意し、IsolatedStorageFileクラスのCreateFileメソッドで、分離ストレージのCameraInCameraフォルダ内にメンバ変数imageFileNameの画像ファイルを作成します。
WriteableBitmap.SaveJpegメソッドで、WriteableBitmapオブジェクトを、JPEGストリームにエンコードします。これは、JPEGファイルのターゲットとなる幅と高さを設定するためのパラメータを持っています。書式は下記の通りです。
WriteableBitmap.SaveJpeg(イメージデータストリーム,WriteableBitmapオブジェクトのPixelWidth, WriteableBitmapオブジェクトのPixelHeight,0(固定),0~100の間の写真の品質(70以上を指定))
分離ストレージのCameraInCamera内に480×640サイズのJPGファイルが保存されます。
不要になったbackgroundImage.jpgファイルを削除します。
変数filePathに格納されているファイルを、指定したモード、指定したファイルアクセスを使用して開きます。
WriteableBitmap型の変数myImageSourceに、PictureDecoder.DecodeJpeg(stream2)で、撮った写真をJPEGファイルとしてWriteableBitmapオブジェクトにデコードします。
Ellipse1コントロールを非表示にし、代わりにdummyEllipseコントロールを表示します。myImageBrushという名前のImageBrushにmyImageSourceオブジェクトを指定します。
別スレッドの下記の処理を行います。
変数xmlStorageを、ファイルとディレクトリを格納している分離ストレージ領域を表すIsolateStorageFileクラスとして宣言します。CameraInCameraというフォルダ内にImageList.xmlが存在していない場合は、Visual Basic の埋め込み式を用いて、XML宣言とルート要素
分離ストレージ内のファイルを表すIsolatedStorageFileStreamクラス用オブジェクト変数xmlStreamを用意し、IsolatedStorageFile.CreateFileメソッドで、分離ストレージ内にxmlFilePath変数の持っているフォルダ名付きXMLファイルを作成します。
ImageList.xmlファイルが存在する場合は、新しいStreamWriter 生成し、IsolatedStorageFile.OpenFileメソッドで、指定したファイルアクセスを使用して指定したモードでファイルを開き、初期化します。Writeメソッドで埋め込み式のXMLをストリームに書き込みます。別スレッドで、保存した旨のメッセージを表示し、Image1とEllipse1コントロールを表示し、backgroundImageとdummyEllipsコントロールを非表示にします。
次は、既に最初からCameraInCameraフォルダ内にImageList.xmlが存在する場合の処理です。
IsolatedStorageFileクラスのOpenFileメソッドでCameraInCameraフォルダ内のImageList.xmlファイルを、指定したファイルアクセスを使用して指定したモードで開きます。
開いたファイルをStreamReaderで読み込んだら、ReadToEndメソッドでファイルの最後まで読み取り、変数readXmldoc変数に格納しておきます。
読み込んだXMLテキストをParseメソッドでXElementとして読み込みます。
追加する
新しく生成したXML要素を、読み込んだXMLにAddメソッドで追加します。IsolatedStorageFileStreamを閉じます。
ImageList.xmlファイルが存在する場合は、新しいStreamWriter 生成し、IsolatedStorageFile.OpenFileメソッドで、指定したファイルアクセスを使用して指定したモードで開きます。
新しい要素の追加されたXMLを、Writeメソッドでストリームに書き込みます。別スレッドで、保存した旨のメッセージを表示し、Image1とEllipseコントロールを表示し、backgroundImageとdummyEllipseコントロールを非表示にします。
Private Sub myCamera_CaptureImageAvailable(sender As Object, e As ContentReadyEventArgs) Dim storage As IsolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication Dim filePath As String = Path.Combine("CameraInCamera", imageFileName) Dim xmlFilePath As String = Path.Combine("CameraInCamera", "ImageList.xml") Deployment.Current.Dispatcher.BeginInvoke(Sub() Dim myImageSource As WriteableBitmap = Nothing Dim imageStorage As IsolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication Using cameraStream As IsolatedStorageFileStream = storage.CreateFile(Path.Combine("CameraInCamera", "backgroundImage.jpg")) cameraStream.Write(imageByte, 0, imageByte.Length) End Using Using myStream As IsolatedStorageFileStream = storage.CreateFile(filePath) Dim myBuffer(bufferValue) 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() End Using Using stream As IsolatedStorageFileStream = imageStorage.OpenFile(Path.Combine("CameraInCamera", "backgroundImage.jpg"), FileMode.Open, FileAccess.Read) Image1.Visibility = Windows.Visibility.Collapsed backgroundImage.Visibility = Windows.Visibility.Visible myImageSource = PictureDecoder.DecodeJpeg(stream, 480, 640) backgroundImage.Source = myImageSource End Using Using stream2 As IsolatedStorageFileStream = imageStorage.OpenFile(filePath, FileMode.Open, FileAccess.Read) myImageSource = PictureDecoder.DecodeJpeg(stream2, 480, 640) Ellipse1.Visibility = Windows.Visibility.Collapsed dummyEllipse.Visibility = Windows.Visibility.Visible myImageBrush.ImageSource = myImageSource End Using Dim myWriteableBitmap As WriteableBitmap = Nothing myWriteableBitmap = New WriteableBitmap(Inkpresenter1, Nothing) Using Stream3 As IsolatedStorageFileStream = storage.CreateFile(Path.Combine("CameraInCamera", imageFileName)) myWriteableBitmap.SaveJpeg(Stream3, 480, 640, 0, 85) End Using If storage.FileExists(Path.Combine("CameraInCamera", "backgroundImage.jpg")) = True Then storage.DeleteFile(Path.Combine("CameraInCamera", "backgroundImage.jpg")) End If End Sub) 'XMLファイルの保存 Dim xmlStorage As IsolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication If xmlStorage.FileExists(xmlFilePath) = False Then Dim xmldoc As XDocument = <?xml version="1.0" encoding="utf-8"?> <Pictures> <Picture RecordDate=<%= recordDate %>> <PictureName><%= imageFileName %></PictureName> </Picture> </Pictures> Using xmlStream As IsolatedStorageFileStream = xmlStorage.CreateFile(xmlFilePath) End Using If xmlStorage.FileExists(xmlFilePath) = True Then Using xmlwriter As StreamWriter = New StreamWriter(xmlStorage.OpenFile(xmlFilePath, FileMode.Open, FileAccess.Write), System.Text.Encoding.UTF8) xmlwriter.Flush() xmlwriter.Write(xmldoc.ToString) End Using Deployment.Current.Dispatcher.BeginInvoke(Sub() MessageBox.Show("画像とXMLファイルを保存しました。") Image1.Visibility = Windows.Visibility.Visible Ellipse1.Visibility = Windows.Visibility.Visible backgroundImage.Visibility = Windows.Visibility.Collapsed dummyEllipse.Visibility = Windows.Visibility.Collapsed End Sub) End If Else Dim xmlStream As IsolatedStorageFileStream = xmlStorage.OpenFile(xmlFilePath, FileMode.Open, FileAccess.Read) Using xmlreader As StreamReader = New StreamReader(xmlStream) Dim readXmldoc As String = xmlreader.ReadToEnd Dim doc As XElement = XElement.Parse(readXmldoc) Dim addXml As XElement = <Picture RecordDate=<%= recordDate %>> <PictureName><%= imageFileName %></PictureName> </Picture> doc.Add(addXml) xmlStream.Close() If xmlStorage.FileExists(xmlFilePath) = True Then Using xmlwriter As StreamWriter = New StreamWriter(storage.OpenFile(xmlFilePath, FileMode.Open, FileAccess.Write), System.Text.Encoding.UTF8) xmlwriter.Flush() xmlwriter.Write(doc.ToString) Deployment.Current.Dispatcher.BeginInvoke(Sub() MessageBox.Show("画像とXMLファイルを保存しました。") Image1.Visibility = Windows.Visibility.Visible Ellipse1.Visibility = Windows.Visibility.Visible backgroundImage.Visibility = Windows.Visibility.Collapsed dummyEllipse.Visibility = Windows.Visibility.Collapsed End Sub) End Using End If End Using End If End Sub
「カメラ」アイコンの「カメラ起動」ボタンがタップされた時の処理
「フロッピー」アイコンの「保存」ボタンの使用を可能にします。CameraCaptureTaskをShowメソッドで表示します。
Private Sub CameraGo(sender As Object, e As EventArgs) TryCast(ApplicationBar.Buttons(1), ApplicationBarIconButton).IsEnabled = True myCameraTask.Show() End Sub
「フロッピー」アイコンの「保存」ボタンがクリックされた時の処理
「フォルダ」アイコンの「データ一覧」ボタンの使用を可能にします。
メンバ変数imageFileNameに現在の、年月日時間分秒.jpgファイルの名前を格納します。メンバ変数recordDateに現在の、年/月/日/時間:分:秒の値を格納します。
CaptureImageメソッドで、ファインダーに表示される現在のイメージのフル解像度キャプチャを開始します。
例外が発生した場合は別スレッドで、メッセージを表示します。
Private Sub SaveGo(sender As Object, e As EventArgs) If myCamera Is Nothing = False Then Try TryCast(ApplicationBar.Buttons(2), ApplicationBarIconButton).IsEnabled = True imageFileName = DateTime.Now.ToString("yyyyMMddHHmmss") & ".jpg" recordDate = DateTime.Now.ToString("yyyy/MM/dd/HH:mm:ss") myCamera.CaptureImage() Catch Me.Dispatcher.BeginInvoke(Sub() MessageBox.Show("エラーが発生しましたが、データは保存されました。")) End Try End If End Sub
「フォルダ」アイコンの「データ一覧」ボタンがタップされ他時の処理
これから作成する、DataIchiranPage.xamlに遷移します。
Private Sub ListGo(sender As Object, e As EventArgs) NavigationService.Navigate(New Uri("/DataIchiranPage.xaml", UriKind.Relative)) End Sub End Class
写真を切りぬいて新しい写真を撮影するサンプル