選択した画像をトリミングして保存させるには2カ月で160本作った還暦開発者が送る10のアプリ開発ノウハウ(9)(4/4 ページ)

» 2013年12月10日 18時00分 公開
[薬師寺国安,PROJECT KySS]
前のページへ 1|2|3|4       

「切り出す」ボタンがタップされたときの処理(Button1_Clickメソッド処理)

 このアプリの肝となる処理だ。WriteableBitmapExのCropメソッドを使用して、矩形で選択された部分を切り出す。

  1. Private Async Sub Button1_Click(sender As Object, e As RoutedEventArgs) Handles Button1.Click
  2. Try
  3. Dim myWriteableBitmap = New WriteableBitmap(CInt(Rectangle1.Width), CInt(Rectangle1.Height))
  4.          ‘ このプログラムの肝。矩形で選択された部分を切り出す処理だ。
  5. Dim myCrop = Await myWriteableBitmap.FromStream(Await myFile.OpenReadAsync)
  6. mySelectedImage = myCrop.Crop(CInt(Rectangle1.Margin.Left), CInt(Rectangle1.Margin.Top), CInt(Rectangle1.Width), CInt(Rectangle1.Height))
  7. resultImage.Width = Rectangle1.Width
  8. resultImage.Height = Rectangle1.Height
  9. resultImage.Source = mySelectedImage
  10. mySelectedImage.Invalidate()
  11. saveButton.Visibility = Windows.UI.Xaml.Visibility.Visible
  12. saveButton.IsEnabled = True
  13. Catch
  14. ErrorShow()
  15. End Try
  16. End Sub

 以降、上記コードの中身を詳細に見ていこう。

 まず、非同期処理で行われるためメソッドの先頭に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メソッド処理)

  1. Private Async Sub saveButton_Click(sender As Object, e As RoutedEventArgs) Handles saveButton.Click
  2. Dim myFolder As StorageFolder = Windows.Storage.KnownFolders.PicturesLibrary
  3. Dim SubFolder = Await myFolder.CreateFolderAsync("TrimingImage", CreationCollisionOption.OpenIfExists)
  4. Dim mySaveFile As StorageFile = Await SubFolder.CreateFileAsync(DateTime.Now.ToString("yyyyMMddHHmmss") & ".png")
  5. Dim myID As Guid = Windows.Graphics.Imaging.BitmapEncoder.PngEncoderId
  6. Await WriteableBitmapSaveExtensions.SaveToFile(mySelectedImage, mySaveFile, myID)
  7. Dim saveMessage As New MessageDialog("ピクチャフォルダー内のTrimingImageフォルダに保存しました。")
  8. Await saveMessage.ShowAsync
  9. GridView1.Items.Clear()
  10. saveButton.Visibility = Windows.UI.Xaml.Visibility.Collapsed
  11. Await AddPhoto()
  12. 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タスク処理)

  1. Private Async Function AddPhoto() As Task
  2. Dim myFolder As StorageFolder = Windows.Storage.KnownFolders.PicturesLibrary
  3. Dim mySubFolder = Await myFolder.CreateFolderAsync("TrimingImage", CreationCollisionOption.OpenIfExists)
  4. myPictureFiles = Await mySubFolder.GetFilesAsync()
  5. If myPictureFiles.Count > 0 Then
  6. deleteButton.IsEnabled = True
  7. allDeleteButton.IsEnabled = True
  8. Else
  9. deleteButton.IsEnabled = False
  10. allDeleteButton.IsEnabled = False
  11. End If
  12. For Each myPhotoFile In myPictureFiles
  13. Dim bmp As New BitmapImage
  14. bmp.SetSource(Await myPhotoFile.OpenSequentialReadAsync)
  15. Dim myImage As New Image
  16. myImage.Stretch = Stretch.Uniform
  17. myImage.Width = 80
  18. myImage.Height = 60
  19. myImage.Source = bmp
  20. Dim myFileName As New TextBlock
  21. myFileName.Text = myPhotoFile.Name
  22. FileName = myPhotoFile.Path
  23. myFileName.FontSize = 10
  24. myFileName.HorizontalAlignment = Windows.UI.Xaml.HorizontalAlignment.Center
  25. Dim myStackPanel As New StackPanel
  26. myStackPanel.Margin = New Thickness(3)
  27. myStackPanel.Children.Add(myImage)
  28. myStackPanel.Children.Add(myFileName)
  29. GridView1.Items.Add(myStackPanel)
  30. Next
  31. Index = myPictureFiles.Count
  32. If Index <= 0 Then
  33.          Button1.IsEnabled = False
  34. Exit Function
  35. Else
  36. Dim message As New MessageDialog("一番新しいファイルが選択されます。")
  37. Await message.ShowAsync
  38. GridView1.Focus(Windows.UI.Xaml.FocusState.Keyboard)
  39. GridView1.SelectedIndex = Index - 1
  40. GridView1.ScrollIntoView(GridView1.SelectedItem)
  41. End If
  42. 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メソッド処理)

  1. Private Async Sub GridView1_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) Handles GridView1.SelectionChanged
  2. flag = True
  3. Dim myIndex As Integer = GridView1.SelectedIndex
  4. If myIndex < 0 Then
  5. Exit Sub
  6. Else
  7. Dim myFolder As StorageFolder = Windows.Storage.KnownFolders.PicturesLibrary
  8. Dim mySubFolder = Await myFolder.CreateFolderAsync("TrimingImage", CreationCollisionOption.OpenIfExists)
  9. myPictureFiles = Await mySubFolder.GetFilesAsync()
  10. myFile = myPictureFiles(myIndex)
  11. Dim trimBmp = New BitmapImage
  12. trimBmp.SetSource(Await myPictureFiles(myIndex).OpenReadAsync)
  13. Image1.Source = trimBmp
  14. Rectangle1.Visibility = Windows.UI.Xaml.Visibility.Collapsed
  15. resultImage.Source = Nothing
  16. Button1.IsEnabled = False
  17. deleteButton.IsEnabled = True
  18.          allDeleteButton.IsEnabled = True
  19. End If
  20. 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領域をクリア、「切り出す」ボタンの使用を不可、「削除」と「一括削除」ボタンの使用を可能とする。

最終回は、画像をY軸を中心に回転させる

 今回は、ここまでだ。また次回の記事でお会いしよう。次回は、いよいよ最終回。画像をY軸を中心に回転させる方法を紹介する。

著者プロフィール

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年に薬師寺聖と結成したコラボレーション・ユニット

前のページへ 1|2|3|4       

Copyright © ITmedia, Inc. All Rights Reserved.

スポンサーからのお知らせPR

Smart & Social 鬯ョ�ォ�ス�ェ髯区サゑスソ�ス�ス�ス�ス�コ髣包スオ隴∵コキ�ク�キ�ス�ケ隴趣ス「�ス�ス�ス�ウ鬩幢ス「�ス�ァ�ス�ス�ス�ュ鬩幢ス「隴趣ス「�ス�ス�ス�ウ鬩幢ス「�ス�ァ�ス�ス�ス�ー

鬮ォ�エ陝キ�「�ス�ス�ス�ャ鬮ォ�エ鬲�シ夲スス�ス�ス�・鬮ォ�エ陝カ�キ�ス�」�ス�ッ髣厄スォ�ス�」

注目のテーマ

4AI by @IT - AIを作り、動かし、守り、生かす
Microsoft & Windows最前線2025
AI for エンジニアリング
ローコード/ノーコード セントラル by @IT - ITエンジニアがビジネスの中心で活躍する組織へ
Cloud Native Central by @IT - スケーラブルな能力を組織に
システム開発ノウハウ 【発注ナビ】PR
あなたにおすすめの記事PR

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。