選択した画像をトリミングして保存・削除・一括削除するには:2カ月で160本作った還暦開発者が送る10のアプリ開発ノウハウ(3)(4/4 ページ)
古(いにしえ)からのVBでWindows 8.1向けのさまざまな機能のアプリを開発する手順やコツを解説していく。今回は、選択した画像をトリミングして保存・削除・一括削除するアプリを作る方法について。
「切り出す」ボタンがタップされた時の処理(Button1_Clickメソッド処理)
Private Async Sub Button1_Click(sender As Object, e As RoutedEventArgs) Handles Button1.Click Try Dim myWriteableBitmap = New WriteableBitmap(CInt(Rectangle1.Width), CInt(Rectangle1.Height)) ‘ このプログラムの肝。矩形で選択された部分を切り出す処理だ。 Dim myCrop = Await myWriteableBitmap.FromStream(Await myFile.OpenReadAsync) mySelectedImage = myCrop.Crop(CInt(Rectangle1.Margin.Left), CInt(Rectangle1.Margin.Top), CInt(Rectangle1.Width), CInt(Rectangle1.Height)) resultImage.Width = Rectangle1.Width resultImage.Height = Rectangle1.Height resultImage.Source = mySelectedImage mySelectedImage.Invalidate() saveButton.Visibility = Windows.UI.Xaml.Visibility.Visible saveButton.IsEnabled = True Catch ErrorShow() End Try End Sub
これは、このアプリの肝となる処理だ。CodePlexのWriteableBitmapExのCropメソッドを使用して、矩形で選択された部分を切り出している。
まず、非同期処理で行われるため、メソッドの先頭にAsyncを追加する。次に、Rectangle(矩形)のWidthとHeightで初期化された、新しいWriteableBitmapのインスタンスmyWriteableBitmapオブジェクトを作成する。
イメージデータやファイルからデータを読み取る、FromStreamメソッドで、FileOpenPickerで指定したファイルのデータを読み取り、myCrop変数で参照しておく。
Cropメソッドでは、Rectangleで指定した領域を切り出し、WriteableBitmap型のメンバー変数mySelectedImageで参照しておく。Cropメソッド(WritebleBitmapExに含まれるメソッド)の書式は下記の通りだ。
WriteableBitmap.Crop(x As Integer,y As Integer,width As Integer,height As Integer)
切り出された画像を表示するresultImageのWidthにRectangleのWidthを指定し、HeightにはRectangleのHeightの値を指定。SourceプロパティにmySelectedImageオブジェクトを指定する。
Invalidateメソッドはビットマップ全体を再描画する。「保存」ボタンを表示状態にして、使用を可能にする。エラーが発生した場合は、ErrorShowメソッドを実行する。
「保存」ボタンがタップされた時の処理(saveButton_Clickメソッド処理)
Private Async Sub saveButton_Click(sender As Object, e As RoutedEventArgs) Handles saveButton.Click Dim myFolder As StorageFolder = Windows.Storage.KnownFolders.PicturesLibrary Dim SubFolder = Await myFolder.CreateFolderAsync("TrimingImage", CreationCollisionOption.OpenIfExists) Dim mySaveFile As StorageFile = Await SubFolder.CreateFileAsync(DateTime.Now.ToString("yyyyMMddHHmmss") & ".png") Dim myID As Guid = Windows.Graphics.Imaging.BitmapEncoder.PngEncoderId Await WriteableBitmapSaveExtensions.SaveToFile(mySelectedImage, mySaveFile, myID) Dim saveMessage As New MessageDialog("ピクチャフォルダー内のTrimingImageフォルダに保存しました。") Await saveMessage.ShowAsync GridView1.Items.Clear() saveButton.Visibility = Windows.UI.Xaml.Visibility.Collapsed Await AddPhoto() End Sub
この処理も非同期処理が行われるため、メソッドの先頭にAsyncを追加する。
ピクチャライブラリ―の「TrimingImage」フォルダーにアクセスするには、CreateFileAsyncメソッドでTrimingImageフォルダー内に「"yyyyMMddHHmmss"」形式のPNGファイルを作成。Windows.Graphics.Imaging.BitmapEncoder.PngEncoderIdで、PNG画像のグローバル一意識別子を取得して、変数myIDに格納しておく。
WinRTXamlToolkit.ImagingのWriteableBitmapSaveExtensions.SaveToFileメソッドで、切り出した画像(mySelectedImage)を「yyyyMMddHHmmss.png」に書き出す。WriteableBitmapSaveExtensions.SaveToFileメソッドの書式は下記だ。
WriteableBitmapSaveExtensions.SaveToFile(writeableBitmap as Windows.UI.Xaml.Media.Imageing.WriteableBitmap,output as Windows.Storages.StorageFile,encodeId as System.GUID)
保存した旨のメッセージボックスを表示。切り出し保存した画像の一覧を表示するGridView1をクリアする。「保存」ボタンを非表示にし、GridViewに切り出し保存した画像を追加するAddPhotoタスクを再実行する。
切り出され保存された画像の一覧を表示する処理(AddPhotoタスク処理)
Private Async Function AddPhoto() As Task Dim myFolder As StorageFolder = Windows.Storage.KnownFolders.PicturesLibrary Dim mySubFolder = Await myFolder.CreateFolderAsync("TrimingImage", CreationCollisionOption.OpenIfExists) myPictureFiles = Await mySubFolder.GetFilesAsync() If myPictureFiles.Count > 0 Then deleteButton.IsEnabled = True allDeleteButton.IsEnabled = True Else deleteButton.IsEnabled = False allDeleteButton.IsEnabled = False End If For Each myPhotoFile In myPictureFiles Dim bmp As New BitmapImage bmp.SetSource(Await myPhotoFile.OpenSequentialReadAsync) Dim myImage As New Image myImage.Stretch = Stretch.Uniform myImage.Width = 80 myImage.Height = 60 myImage.Source = bmp Dim myFileName As New TextBlock myFileName.Text = myPhotoFile.Name FileName = myPhotoFile.Path myFileName.FontSize = 10 myFileName.HorizontalAlignment = Windows.UI.Xaml.HorizontalAlignment.Center Dim myStackPanel As New StackPanel myStackPanel.Margin = New Thickness(3) myStackPanel.Children.Add(myImage) myStackPanel.Children.Add(myFileName) GridView1.Items.Add(myStackPanel) Next Index = myPictureFiles.Count If Index <= 0 Then Button1.IsEnabled = False Exit Function Else Dim message As New MessageDialog("一番新しいファイルが選択されます。") Await message.ShowAsync GridView1.Focus(Windows.UI.Xaml.FocusState.Keyboard) GridView1.SelectedIndex = Index - 1 GridView1.ScrollIntoView(GridView1.SelectedItem) End If End Function
この処理も非同期処理が行われるため、メソッドの先頭にAsyncを追加する。
ピクチャライブラリ―の「TrimingImage」フォルダーにアクセスするには、GetFilesAsyncメソッドでTrimingImageフォルダー内の画像を取得し、コレクションメンバー変数myPictureFilesに格納しておく。「TrimingImage」フォルダー内にファイルがある場合は、「削除」と「一括削除」ボタンの使用を可能にする。それ以外は使用不可とする。
コレクションメンバー変数myPictureFiles内のファイルを変数myPhotoFileに格納しながら、以下の処理を繰り返す。BitmapImageの新しいインスタンスbmpオブジェクトを作成し、SetSourceメソッドに、「Await myPhotoFile.OpenSequentialReadAsync」と指定して、順次読み取りアクセス用のストリームを開き、BitmapSourceのソースイメージに設定する。
新しいImageのインスタンスmyImageオブジェクトを作成し、WidthとHeightプロパティを設定する。Sourceプロパティにbmpオブジェクトを設定する。
TextBlockの新しいインスタンスmyFileNameオブジェクトを作成する。TextプロパティにTrimingImageフォルダー内のファイル名を指定。文字サイズには「10」を指定し、中央揃えとしておく。
StackPanelの新しいインスタンス、myStackPanelオブジェクトを作成。Marginに「3」を指定して余白を設ける。AddメソッドでmyStackPanelにmyImageとmyFileNameオブジェクトを追加し、そのmyStackPanelオブジェクトをGridView1に追加する。これで、切り出された画像とファイル名がGridView1に一覧で表示される。
「TrimingImage」フォルダー内に画像ファイルがない場合は、「切り出す」ボタンの使用を不可とし、処理を抜ける。「TrimingImage」フォルダー内に画像がある場合は、「一番新しい画像が選択されます。」のメッセージが表示される。
そして、GridView1にフォーカスを移し、一番新しく切り出された画像を選択状態にし、ScrollIntoViewメソッドで、その画像の位置までスクロールする。一番新しい画像が選択された状態になり、周囲に白い枠線が表示される。これで、キーボードの[←]や[→]キーで選択が可能になる。
※Windowsストアの審査では、こういった場合は、必ずキーボードでの選択ができないとリジェクトとなるので、注意が必要だ。
GridView1に表示されている画像が選択された時の処理(GridView1_SelectionChangedメソッド処理)
Private Async Sub GridView1_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) Handles GridView1.SelectionChanged flag = True Dim myIndex As Integer = GridView1.SelectedIndex If myIndex < 0 Then Exit Sub Else Dim myFolder As StorageFolder = Windows.Storage.KnownFolders.PicturesLibrary Dim mySubFolder = Await myFolder.CreateFolderAsync("TrimingImage", CreationCollisionOption.OpenIfExists) myPictureFiles = Await mySubFolder.GetFilesAsync() myFile = myPictureFiles(myIndex) Dim trimBmp = New BitmapImage trimBmp.SetSource(Await myPictureFiles(myIndex).OpenReadAsync) Image1.Source = trimBmp Rectangle1.Visibility = Windows.UI.Xaml.Visibility.Collapsed resultImage.Source = Nothing Button1.IsEnabled = False deleteButton.IsEnabled = True allDeleteButton.IsEnabled = True End If End Sub
この処理も非同期処理が行われるため、メソッドの先頭にAsyncを追加する。
次に、メンバー変数flagをTrueで初期化し、トリミングは不可としておく。GridView1から選択された画像のインデックスを変数myIndexに格納。GridView1から画像が選択された場合は、「TrimingImage」フォルダーにアクセスし、GetFilesAsyncメソッドでファイルを取得して、コレクションメンバー変数myPictureFilesで参照しておく。
myIndexに該当するファイルを取得しメンバー変数myFileに格納しておく。
新しいBitmapImageのインスタンスtrimBmpオブジェクトを作成。SetSourceメソッドに、「Await myPictureFiles(myIndex).OpenReadAsync」と指定して、指定した画像のランダムアクセス用のストリームを開き、BitmapSourceのソースイメージに設定する。
Image1のSourceプロパティにtrimBmpオブジェクトを指定。これで、GridView1から選択された画像がImage1に表示されるが、トリミングはできなくなる。
Rectangle1を非表示、切り出した画像を表示するresultImage領域をクリア、「切り出す」ボタンの使用を不可、「削除」と「一括削除」ボタンの使用を可能とする。
次回は、任意のフォルダ―から選択した画像をFacebookに投稿
今回は、ここまでだ。また次回の記事でお会いしよう。次回は任意のフォルダ―から選択した画像をFacebookに投稿する方法を紹介する。
関連リンク
本コンテストでは、2013年9月1日〜12月1日に新たにWindowsストアに新規公開されたアプリを募集します。入賞したアプリの製作者には、総額130万円の賞金が授与されますので、ふるってご応募ください。
著者プロフィール
PROJECT KySS 薬師寺 国安(やくしじ くにやす)
1950年生まれ。フリーVBプログラマ。高級婦人服メーカーの事務職に在職中、趣味でVBやActiveXに取り組み、記事を執筆。2003年よりフリー。.NETやRIAに関する執筆多数。Windowsストアアプリも多数公開中(約270本)。
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)。
PROJECT KySSは、1997年に薬師寺聖と結成したコラボレーション・ユニット
Copyright © ITmedia, Inc. All Rights Reserved.
関連記事
- 今でしょ! の終わりに安齋、家入らが評価したアプリとは〜「エイっと作ろう! Windowsストア アプリ選手権」授賞式レポート
謎のキャラ今出しょう子をマスコットに据えたコンテストを勝ち上がった10作品のプレゼン模様などをお届け。 - 初のアジャイル/リモート開発体制でも成功できた秘訣とは〜「Windowsタブレット向けアプリ開発」先駆けインタビュー
日本料理のレシピを海外に紹介するアプリ「Ippin」。初物づくしのアプリ開発を成功させた秘訣をディレクターに聞いた。コミュニケーションツールやドキュメントに盛り込んだ数々の工夫とは、どんなものだったのだろうか。 - Web開発者が手っ取り早くストアデビューする方法(1):Windowsストアにアプリを登録するための事前準備
Windowsストア初心者のために(主に、HTMLやJavaScriptを扱うWeb開発者向けに)、簡単なアプリを開発してWindowsストアに手っ取り早くデビューする手順を解説します。初回は、Microsoftアカウントの取得、Windowsストアアプリ開発者登録、開発環境準備について。 - 連載:Windowsストア・アプリ開発入門:第1回 Windowsストア・アプリってどんなもの?
ついにWindows 8.1の正式版がMSDNサブスクライバー向けに公開された。無償アップデートとなるため、今後は新しいWindows 8.1ストア・アプリが一般化するだろう。最新環境向けに新たにアプリ開発を始める人のための連載スタート。 - 特集:次期Windows 8.1&Visual Studio 2013 Preview概説(前編):大きく変わるWindowsストア・アプリ開発 〜 ビュー状態に関連する変更点
Windows 8.1(Preview版)の変更点や新機能を開発者視点で紹介。Windows 8用に作られたWindowsストア・アプリにはどんな影響があるのか? - UXClip(11):これからが本番、Windows 8アプリ開発
12月3日夜、Windows 8のハードウェアやアプリを開発者向けに紹介するイベントが行なわれた - Windows 8提供開始、対応アプリ登場は期待できるか?
マイクロソフトはWindows 8の提供を正式に開始した。Windowsストアもスタートし、いよいよWindows 8プラットフォームが市場投入となる。