写真を切りぬいて新しい写真を撮影するサンプル

前ページからの続きです。
ページがアクティブでなくなった時の処理
「フロッピー」の「保存」ボタンの使用を不可とします。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
写真を切りぬいて新しい写真を撮影するサンプル


