虫眼鏡でズームするサンプルとその応用

2012年6月22日(金)
PROJECT KySS

次に、MainPage.xamlを展開して表示されるMainPage.xaml.vbをダブルクリックして、リスト4のコードを記述します。

ロジックコードを記述する

リスト4 (MainPage.xaml.vb)

01Option Strict On
02Imports Microsoft.Devices
03Imports System.Windows.Media.Imaging
04Imports System.Windows.Threading
05 
06Partial Public Class MainPage
07  Inherits PhoneApplicationPage
08  
09  ' コンストラクター
10  Public Sub New()
11    InitializeComponent()
12  End Sub

myCameraを、PhotoCameraクラスのメンバ変数として宣言します。このクラスは、カメラアプリケーションの基本カメラ機能を提供し、イメージ・キャプチャ、フォーカス、解像度、フラッシュ・モードなどの機能を有効にして構成するためのメンバが含まれています。

1Dim myCamera As PhotoCamera

WriteableBitmap型のメンバ変数wbを宣言します。このクラスは、書き込み更新することのできるBitmapSourceを提供するクラスです。

1Dim wb As WriteableBitmap

新しいDispatcherTimerクラスのインスタンスmyTimerを、メンバ変数として宣言します。このクラスは、指定した時間の間隔で処理されるタイマーを表します。

1Dim myTimer As New DispatcherTimer

ページがアクティブになった時呼び出されるメソッド

RadioButtonにチェックが入り、MainPage.xamlが呼び出された時、MainPage.xamlから渡された文字データを受け取ります。文字データは、NavigationContextのQueryStringに、Dictionaryとして提供されます。

ContainsKeyメソッドで、指定したキーワード(この場合zoom)が Dictionary に格納されているかどうかを判断します。格納されている場合は、送信時のキーワード(zoom)をもとに渡された文字列情報の値(param(“zoom”))を取得し、ScaleTransformのScaleXとScaleYプロパティに指定します。

Zoomの値が0の場合はtoubaiRadioButtonにチェックが入り、3の場合は、sanbaiRadioButtonにチェックが入ります。

PhotoCamera.IsCameraTypeSupportedメソッドで、指定された種類のカメラがデバイスでサポートされているかどうかを判断します。

カメラが背面、または前面に配置されている場合は、新しいPhotoCameraのインスタンスmyCameraを作成します。AddHandlerステートメントで、カメラ オブジェクトが初期化された時に発生するInitializedイベントに、イベントハンドラを追加します。

VideoBrushのSetSourceメソッドでmyCameraオブジェクトを指定します。カメラが付いていない場合は、別スレッドからメッセージを表示します。

01Protected Overrides Sub OnNavigatedTo(e As System.Windows.Navigation.NavigationEventArgs)
02  Dim myParam As IDictionary(Of String, String) = NavigationContext.QueryString
03  If myParam.ContainsKey("zoom") = True Then
04    myZoom.ScaleX = CDbl(myParam("zoom"))
05    myZoom.ScaleY = CDbl(myParam("zoom"))
06 
07    Select Case CDbl(myParam("zoom"))
08      Case 0
09        toubaiRadioButton.IsChecked = True
10      Case 3
11        sanbaiRadioButton.IsChecked = True
12    End Select
13  End If
14 
15  If (PhotoCamera.IsCameraTypeSupported(CameraType.Primary) = True Or PhotoCamera.IsCameraTypeSupported(CameraType.FrontFacing) = True) Then
16    myCamera = New PhotoCamera
17    AddHandler myCamera.Initialized, AddressOf myCamera_Initialized
18    myVideoBrush.SetSource(myCamera)
19  Else
20    Me.Dispatcher.BeginInvoke(Sub()
21                  MessageBox.Show("カメラの使用ができません。")
22                  Exit Sub
23                        End Sub)
24  End If
25  MyBase.OnNavigatedTo(e)
26End Sub

ページがアクティブでなくなった時に呼び出されるメソッド

myCameraオブジェクトに関連付けが無い場合は、RemoveHandlerメソッドでInitializedイベントを削除します。

1Protected Overrides Sub OnNavigatingFrom(e As System.Windows.Navigation.NavigatingCancelEventArgs)
2  If myCamera IsNot Nothing Then
3    RemoveHandler myCamera.Initialized, AddressOf myCamera_Initialized
4  End If
5End Sub

カメラ オブジェクトが初期化された時に発生する処理

カメラ操作が成功した場合の処理です。別スレッドから以下の処理を行います。

mainImageを表示します。イメージの、現在での解像度の幅と高さで初期化されたWriteableBitmapの新しいインスタンス、wbを作成します。mainImageのSourceプロパティにはwbオブジェクトを指定し、カメラのフラッシュモードは自動に設定します。

タイマーのIntervalプロパティに0.1ミリセコンドを指定します。タイマーをスタートします。タイマー間隔が経過すると発生するTickイベントに、イベントハンドラを指定します。イベントハンドラ内では、以下の処理を行います。

イメージの、現在の解像度での幅と高さを乗算した配列を持つ、配列変数ARGBPxを宣言します。

GetPreviewBufferArgb32メソッドで、現在のファインダーARGBフレームをバッファにコピーします。

別スレッドより、CopyToメソッドを使って、バッファをWriteableBitmapへコピーします。

WriteableBitmap.Invalidateメソッドで、ビットマップ全体を再描画します。

01Private Sub myCamera_Initialized(ByVal sender As Object, ByVal e As Microsoft.Devices.CameraOperationCompletedEventArgs)
02  If e.Succeeded Then
03    Deployment.Current.Dispatcher.BeginInvoke(Sub()
04      mainImage.Visibility = Visibility.Visible
05      wb = New WriteableBitmap(CInt(myCamera.PreviewResolution.Width), CInt(myCamera.PreviewResolution.Height))
06        Me.mainImage.Source = wb
07        myCamera.FlashMode = FlashMode.Auto
08        myTimer.Interval = TimeSpan.FromSeconds(0.1)
09 
10        AddHandler myTimer.Tick, Sub(mySender As Object, myArgs As EventArgs)
11        Try
12            Dim ARGBPx(CInt(myCamera.PreviewResolution.Width) * CInt(myCamera.PreviewResolution.Height) - 1) As Integer
13            myCamera.GetPreviewBufferArgb32(ARGBPx)
14            Deployment.Current.Dispatcher.BeginInvoke(Sub()
15                ARGBPx.CopyTo(wb.Pixels, 0)
16                wb.Invalidate()
17                                              End Sub)
18        Catch
19          Exit Sub
20        End Try
21                  End Sub
22        myTimer.Start()
23      End Sub)
24  End If
25End Sub

mainImageがタップされた時の処理

カメラのフォーカスを合わせます。フォーカスが完了した時に発生するmyCamera_AutoFocusCompletedイベントハンドラを実行します。

1Private Sub mainImage_Tap(sender As Object, e As System.Windows.Input.GestureEventArgs) Handles mainImage.Tap
2  myCamera.Focus()
3  AddHandler myCamera.AutoFocusCompleted, AddressOf myCamera_AutoFocusCompleted
4End Sub

カメラのフォーカスが合った時に発生する処理

RemoveHandlerステートメントで、myCamera_AutoFocusCompletedイベントハンドラを削除します。

1Private Sub myCamera_AutoFocusCompleted(sender As Object, e As CameraOperationCompletedEventArgs)
2  RemoveHandler myCamera.AutoFocusCompleted, AddressOf myCamera_AutoFocusCompleted
3End Sub

toubaiRadioButtonがチェックされた時の処理

タイマーを中止し、引数zoomに0の値を持たせて、MainPage.xamlに遷移します。

1Private Sub toubaiRadioButton_Checked(sender As Object, e As System.Windows.RoutedEventArgs) Handles toubaiRadioButton.Checked
2  myTimer.Stop()
3  NavigationService.Navigate(New Uri(String.Format("/MainPage.xaml?zoom={0}", 0), UriKind.Relative))
4End Sub

sanbaiRadioButtonがチェックされた時の処理

タイマーを中止し、引数zoomに3の値を持たせて、MainPage.xamlに遷移します。

1  Private Sub sanbaiRadioButton_Checked(sender As Object, e As System.Windows.RoutedEventArgs) Handles sanbaiRadioButton.Checked
2    myTimer.Stop()
3    NavigationService.Navigate(New Uri(String.Format("/MainPage.xaml?zoom={0}", 3), UriKind.Relative))
4  End Sub
5End Class

今回のサンプルは以上で終了です。

【参照リンク】

PROJECT KySSでは現在、16個のWindows PhoneアプリをMarketplaceに公開しています。試用版もありますので、興味のある方はお試しください。
→参照:Windows Phone App Information(PROJECT KySS)

  • 画像の一部を拡大するサンプル

  • カメラで拡大表示するサンプル

四国のSOHO。薬師寺国安(VBプログラマ)と、薬師寺聖(デザイナ、エンジニア)によるコラボレーション・ユニット。1997年6月、Dynamic HTMLとDirectAnimationの普及を目的として結成。共同開発やユニット名義での執筆活動を行う。XMLおよび.NETに関する著書や連載多数。最新刊は「Silverlight実践プログラミング」両名とも、Microsoft MVP for Development Platforms - Client App Dev (Oct 2003-Sep 2012)。http://www.PROJECTKySS.NET/

連載バックナンバー

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています