画像にFilterをかけてPicturesHUBに保存する
2012年1月23日(月)

次に、MainPage.xamlを展開して表示される、MainPage.xaml.vbをダブルクリックしてリスト2のコードを記述します。
ロジックコードを記述する
リスト2 (MainPage.xaml.vb)
Option Strict On
ランチャーやチューザーに関するクラスの含まれる、Microsoft.Phone.Tasks名前空間をインポートします。
Imports Microsoft.Phone.Tasks
Imports System.Windows.Media.Imaging
イメージを読み込んだり、操作したりする、コントロールやクラスの含まれる、基本の名前空間である、ImageToolsをインポートします。ImageTools.Filtering名前空間には、セピア、グレースケール、反転フィルタなどの画像フィルタが含まれています
Imports ImageTools
Imports ImageTools.Filtering
仮想ファイルシステムを作成および使用するための型が含まれている、System.IO.IsolatedStorage名前空間をインポートします。分離ストレージによって、安全なクライアント側のストレージが提供されます。
Imports System.IO.IsolatedStorage
曲、アルバム、再生リスト、およびピクチャを列挙、再生、および表示するためのクラスの含まれる、Microsoft.Xna.Framework.Media名前空間をインポートします。この名前空間をインポートしていないとMediaLibrayクラスが使用できませんので、注意してください。
Imports Microsoft.Xna.Framework.Media
Imports System.IO
Partial Public Class MainPage
Inherits PhoneApplicationPage
' コンストラクター
Public Sub New()
InitializeComponent()
End Sub
PicturesHUB内の写真を選択できる、PhotoChooseTaskクラス用のmyTaskメンバ変数を宣言します。
Dim myTask As PhotoChooserTask
loadImage、filterImageを、Image クラスのピクセルを格納し、ファイルやストリームのサイズ変更やカッティングのような操作から、イメージを読み込む機能を提供するクラスである、ExtendedImageクラス用メンバ変数として宣言します。
Dim loadImage As ExtendedImage
Dim filterImage As ExtendedImage
BitmapImageクラス用メンバ変数として、myImageを宣言します。BitmapImageクラスは、イメージを読み込むためのBitmapSourceを提供するクラスです。
Dim myImage As BitmapImage
ページがアクティブになった時の処理
新しいPhotoChooserTaskのインスタンスを生成します。AddHandlerステートメントで、タスクが完了した時のCompletedイベントハンドラを追加します。Completedイベント内では、完了イベントがTaskResult.OKで、正常に完了した場合は以下の処理を行います。
新しいBitmapImageのインスタンスを作成します。chooser での選択の結果は引数で渡されますので、SetSourceメソッドで、渡された画像を BitmapImage オブジェクトに格納します。Image1のSourceプロパティに、chooserで選択した画像を格納しているBitmapImageオブジェクトを指定します。Picturesで選択した画像が表示されます。
BitmapImageのインスタンスmyImageで初期化された新しいWriteableBitmapオブジェクトwbを作成します。WriteableBitmapクラスは、書き込みおよび更新が可能な BitmapSource を提供するクラスです。
新しいExtendedImageクラスのインスタンスを作成します。SetPixelsメソッドで、loadImageオブジェクトに画像のピクセル配列を設定します。書式は下記の通りです。
ImageBase.SetPixels(画像の新しいPixelWidth(0より大きい),画像の新しいPixelHeight(0より大きい), 色のバイト配列)
wb.ToByteArrayメソッドは、WriteableBitmap byte()に変換するメソッドです。「参照の追加(R)」から、WriteableBitmapEXWinPhone.dllを追加していなければ、wb.ToByteArrayメソッドが使用できませんので、注意してください。
Protected Overrides Sub OnNavigatedTo(e As System.Windows.Navigation.NavigationEventArgs)
myTask = New PhotoChooserTask
AddHandler myTask.Completed, Sub(resultSender As Object, resultArgs As PhotoResult)
If resultArgs.TaskResult = TaskResult.OK Then
myImage = New BitmapImage
myImage.SetSource(resultArgs.ChosenPhoto)
Image1.Source = myImage
Dim wb As WriteableBitmap = New WriteableBitmap(myImage)
loadImage = New ExtendedImage
loadImage.SetPixels(myImage.PixelWidth, myImage.PixelHeight, wb.ToByteArray())
End If
End Sub
MyBase.OnNavigatedTo(e)
End Sub
[画像読み込み]ボタンがタップされた時の処理
Showメソッドで、PhotoChooserTaskを実行します。これで、PicturesHUBより選択した画像が、Image1内に表示されます。ListBoxの使用を可能にします。
Private Sub imageReadButton_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles imageReadButton.Click
myTask.Show()
ListBox1.IsEnabled = True
End Sub
リストボックスより任意のフィルタが選択された時の処理。
ListBoxより選択されたフィルタ名を変数myItemに格納し、myItemの値によって条件分岐を行います。7つのフィルタの条件分岐を書いていますが、処理は全て同じですので、「セピア」についてのみ解説します。
Sepiaクラスとしてfilter変数を宣言します。新しいSepiaクラスのインスタンスを作成します。画像のピクセル配列が設定され、loadImageで初期化された新しい、ExtendedImageを作成しfilterImageオブジェクトで参照します。Sepia.Applyメソッドで、指定されたRectangleの領域で画像へのフィルタが適用されます。Applyメソッドの書式は下記の通りです。
Sepia.Apply(フィルタを適用するターゲットとなるイメージ,元のイメージ, フィルタが適用されるべき画像の領域を定義するRectangle)
Rectangleは下記の値で初期化されます。
New ImageToos.Rectangle(Rectangleの左上隅のx座標(通常0), Rectangleの左上隅のy座標(通常0),元のイメージのPixelWidth,元のイメージのPixelHeight)
フィルタの適用されたイメージを、ToBitmapメソッドでBitmapに変換し、Image1のSourceプロパティに指定します。[保存]ボタンの使用を可能にします。
プルウィットフィルタは、エッジ検出フィルタの一種で、水平方向と垂直方向があり、組み合わせて用いることもあります。ソーベルフィルタもエッジ検出フィルタの一種です。
Private Sub ListBox1_SelectionChanged(sender As Object, e As System.Windows.Controls.SelectionChangedEventArgs) Handles ListBox1.SelectionChanged
Dim myItem As String = DirectCast(ListBox1.SelectedItem, ListBoxItem).Content.ToString
Select Case myItem
Case "セピア"
Dim filter As Sepia
filter = New Sepia
filterImage = New ExtendedImage(loadImage)
filter.Apply(filterImage, loadImage, New ImageTools.Rectangle(0, 0, loadImage.PixelWidth, loadImage.PixelHeight))
Case "インバーター"
Dim filter As Inverter
filter = New Inverter
filterImage = New ExtendedImage(loadImage)
filter.Apply(filterImage, loadImage, New ImageTools.Rectangle(0, 0, loadImage.PixelWidth, loadImage.PixelHeight))
Case "白黒"
Dim filter As Grayscale
filter = New GrayscaleRMY
filterImage = New ExtendedImage(loadImage)
filter.Apply(filterImage, loadImage, New ImageTools.Rectangle(0, 0, loadImage.PixelWidth, loadImage.PixelHeight))
Case "プルウィットX"
Dim filter As PrewittX
filter = New PrewittX
filterImage = New ExtendedImage(loadImage)
filter.Apply(filterImage, loadImage, New ImageTools.Rectangle(0, 0, loadImage.PixelWidth, loadImage.PixelHeight))
Case "プルウィットY"
Dim filter As PrewittY
filter = New PrewittY
filterImage = New ExtendedImage(loadImage)
filter.Apply(filterImage, loadImage, New ImageTools.Rectangle(0, 0, loadImage.PixelWidth, loadImage.PixelHeight))
Case "ソーベルX"
Dim filter As SobelX
filter = New SobelX
filterImage = New ExtendedImage(loadImage)
filter.Apply(filterImage, loadImage, New ImageTools.Rectangle(0, 0, loadImage.PixelWidth, loadImage.PixelHeight))
Case "ソーベルY"
Dim filter As SobelY
filter = New SobelY
filterImage = New ExtendedImage(loadImage)
filter.Apply(filterImage, loadImage, New ImageTools.Rectangle(0, 0, loadImage.PixelWidth, loadImage.PixelHeight))
Case Else
Exit Select
End Select
Dim bitmap As WriteableBitmap= filterImage.ToBitmap
Image1.Source = bitmap
saveButton.IsEnabled = True
End Sub
[保存]ボタンがタップされた時の処理
PicturesHUBに保存するファイル名を現在の「年月日時間分秒.jpg」とします。
Image1で初期化された、新しいWriteableBitmapのオブジェクト、myWriteableBitmapを作成します。WriteableBitmapクラスの第2引数には、ビットマップに特定の変換を適用するTransformを指定できますが、ここではNothingを指定します。WriteableBitmapクラスは、書き込みおよび更新が可能な BitmapSourceを提供するクラスです。
変数storageを、ファイルとディレクトリを格納している分離ストレージ領域を表すIsolateStorageFileクラスとして宣言します。FileExistsメソッドでimageFileNameに格納しているファイルが存在しているかどうかをチェックし、存在している場合は、DeleteFileメソッドで同名ファイルを削除します。
分離ストレージ内のファイルを表すIsolatedStorageFileStreamクラス用オブジェクト変数myStream変数を用意し、IsolatedStorageFile.CreateFileメソッドで、分離ストレージ内にimageFileName変数の持っているファイルを作成します。
Extensions.SaveJpegメソッドで、WriteableBitmapオブジェクトを、JPEGストリームにエンコードし、画像ファイルを一時分離ストレージに保存します。これは、JPEGファイルのターゲットとなる幅と高さを設定するためのパラメータを持っています。書式は下記の通りです。
Extensions.SaveJpeg(WriteableBitmapオブジェクト,イメージデータストリーム,WriteableBitmapオブジェクトのPixelWidth, WriteableBitmapオブジェクトのPixelHeight,0(固定),0~100の間の写真の品質(70以上を指定))
ピクチャへのアクセスを提供する、新しいMediaLibrayクラスのインスタンス、myLibrayを作成します。分離ストレージ内のファイルを表すIsolatedStorageFileStreamクラス用オブジェクト変数Stream変数を用意し、IsolatedStorageFile.OpenFileメソッドで、imageFileNameに格納されているJPEGファイルを、指定したファイルアクセスを使用して指定したモードで開きます。MediaLibrary.SavePictureメソッドで、ストリームオブジェクトに含まれる画像を、メディアライブラリーに保存し、その保存した画像をピクチャオブジェクトとして返します。保存した旨のメッセージを表示します。これで、分離ストレージの画像ファイルがPicturesHUBに保存されます。
Private Sub saveButton_Click(sender As Object, e As System.Windows.RoutedEventArgs) Handles saveButton.Click
Dim imageFileName As String = DateTime.Now.ToString("yyyyMMddHHmmss") & ".jpg"
Dim myWriteableBitmap As WriteableBitmap
myWriteableBitmap = New WriteableBitmap(Image1, Nothing)
Dim storage As IsolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication
If storage.FileExists(imageFileName) = True Then
storage.DeleteFile(imageFileName)
End If
Using myStream As IsolatedStorageFileStream = storage.CreateFile(imageFileName)
System.Windows.Media.Imaging.Extensions.SaveJpeg(myWriteableBitmap, myStream, myWriteableBitmap.PixelWidth, myWriteableBitmap.PixelHeight, 0, 85)
End Using
Dim myLibray As New MediaLibrary
Using Stream As IsolatedStorageFileStream = storage.OpenFile(imageFileName, FileMode.Open, FileAccess.Read)
myLibray.SavePicture(imageFileName, Stream)
MessageBox.Show("PicturesHubに保存しました。")
End Using
End Sub
End Class
「画像にFilterをかけてPicturesHUBに保存する」サンプルプログラム
連載バックナンバー
Think ITメルマガ会員登録受付中
Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。


