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

2012年6月22日(金)
PROJECT KySS

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

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

リスト4 (MainPage.xaml.vb)

Option Strict On
Imports Microsoft.Devices
Imports System.Windows.Media.Imaging
Imports System.Windows.Threading

Partial Public Class MainPage
  Inherits PhoneApplicationPage
 
  ' コンストラクター
  Public Sub New()
    InitializeComponent()
  End Sub

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

  Dim myCamera As PhotoCamera

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

  Dim wb As WriteableBitmap

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

Dim 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オブジェクトを指定します。カメラが付いていない場合は、別スレッドからメッセージを表示します。

  Protected Overrides Sub OnNavigatedTo(e As System.Windows.Navigation.NavigationEventArgs)
    Dim myParam As IDictionary(Of String, String) = NavigationContext.QueryString
    If myParam.ContainsKey("zoom") = True Then
      myZoom.ScaleX = CDbl(myParam("zoom"))
      myZoom.ScaleY = CDbl(myParam("zoom"))
 
      Select Case CDbl(myParam("zoom"))
        Case 0
          toubaiRadioButton.IsChecked = True
        Case 3
          sanbaiRadioButton.IsChecked = True
      End Select
    End If
 
    If (PhotoCamera.IsCameraTypeSupported(CameraType.Primary) = True Or PhotoCamera.IsCameraTypeSupported(CameraType.FrontFacing) = True) Then
      myCamera = New PhotoCamera
      AddHandler myCamera.Initialized, AddressOf myCamera_Initialized
      myVideoBrush.SetSource(myCamera)
    Else
      Me.Dispatcher.BeginInvoke(Sub()
                    MessageBox.Show("カメラの使用ができません。")
                    Exit Sub
                          End Sub)
    End If
    MyBase.OnNavigatedTo(e)
  End Sub

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

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

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

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

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

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

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

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

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

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

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

  Private Sub myCamera_Initialized(ByVal sender As Object, ByVal e As Microsoft.Devices.CameraOperationCompletedEventArgs)
    If e.Succeeded Then
      Deployment.Current.Dispatcher.BeginInvoke(Sub()
        mainImage.Visibility = Visibility.Visible
        wb = New WriteableBitmap(CInt(myCamera.PreviewResolution.Width), CInt(myCamera.PreviewResolution.Height))
          Me.mainImage.Source = wb
          myCamera.FlashMode = FlashMode.Auto
          myTimer.Interval = TimeSpan.FromSeconds(0.1)
 
          AddHandler myTimer.Tick, Sub(mySender As Object, myArgs As EventArgs)
          Try
              Dim ARGBPx(CInt(myCamera.PreviewResolution.Width) * CInt(myCamera.PreviewResolution.Height) - 1) As Integer
              myCamera.GetPreviewBufferArgb32(ARGBPx)
              Deployment.Current.Dispatcher.BeginInvoke(Sub()
                  ARGBPx.CopyTo(wb.Pixels, 0)
                  wb.Invalidate()
                                                End Sub)
          Catch
            Exit Sub
          End Try
                    End Sub
          myTimer.Start()
        End Sub)
    End If
  End Sub

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

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

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

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

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

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

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

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

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

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

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

  Private Sub sanbaiRadioButton_Checked(sender As Object, e As System.Windows.RoutedEventArgs) Handles sanbaiRadioButton.Checked
    myTimer.Stop()
    NavigationService.Navigate(New Uri(String.Format("/MainPage.xaml?zoom={0}", 3), UriKind.Relative))
  End Sub
End 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メルマガ会員のサービス内容を見る

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