내보내기(0) 인쇄
모두 확장

방법: Windows Phone용 기본 카메라 응용프로그램 만들기

2012-02-09

Windows Phone OS 7.1 을 사용하면 단말기 카메라에 프로그래밍 방식으로 액세스할 수 있습니다. 이 항목은 사진 촬영용 카메라 API로 시연하는 카메라 응용프로그램을 만드는 방법을 설명하는 시리즈의 첫 번째 과정입니다. 이 항목에서는 카메라 뷰파인더를 표시하고, 프로그래밍 방식으로 셔터를 트리거하고, 촬영한 이미지를 미디어 라이브러리 및 격리된 저장소에 저장하는 방법에 대해 설명합니다.

이 항목에서는 다음 단계를 다룹니다.

  1. 카메라 UI 만들기

  2. 뷰파인더 및 카메라 기반 이벤트 구현

  3. 미디어 라이브러리 및 격리된 저장소에 저장

팁팁:

이 항목은 기본 카메라 샘플에 해당합니다. 전체 프로젝트를 다운로드하려면 Windows Phone용 코드 샘플을 참조하십시오.

이 기본 카메라 응용프로그램을 완성한 후 그 다음 항목에는 플래시 및 초점 구현, 촬영 해상도 변경 및 휴대폰 하드웨어 셔터 버튼 사용 등의 기능이 포함됩니다. 계속 진행하려면 먼저 이 항목에 나오는 기본 카메라 응용프로그램을 완성해야 합니다. 그 다음 항목은 이 응용프로그램을 기반으로 구성되며 이 항목에서 구현된 특성에 기능을 추가합니다.

이러한 모든 항목을 완료하고 나면 완성된 솔루션이 다음 이미지와 같이 표시됩니다.

AP_Con_CameraAnatomy

이 항목에서 SH 버튼만 응용프로그램에 추가됩니다. 플래시, 자동 초점, 해상도 버튼은 이 시리즈의 다른 항목에서 추가됩니다.

참고참고:

Windows Phone OS 7.1 의 기능을 사용하기 위해 Windows Phone OS 7.0 응용프로그램을 업그레이드하는 경우 카메라 기능 ID_CAP_ISV_CAMERA는 응용프로그램 매니페스트 파일 WMAppManifest.xml에 자동으로 추가되지 않습니다. ID_CAP_ISV_CAMERA가 없으면 카메라 API를 사용하는 응용프로그램이 작동하지 않습니다. 새 Windows Phone OS 7.1 프로젝트에서는 이 기능이 응용프로그램 매니페스트 파일에 포함되어 있습니다.

Windows Phone SDK 의 이번 릴리스의 경우 이 항목은 Windows Phone 단말기에서만 완료될 수 있고 Windows Phone 에뮬레이터에서는 완료될 수 없습니다.

이 항목은 C# 개발을 기준으로 하지만 Visual Basic 코드도 제공됩니다. 

이 섹션에서는 촬영된 프레임을 표시할 뷰파인더 영역과 이미지를 촬영할 셔터 버튼으로 구성된 카메라 UI를 만듭니다.

카메라 UI를 만들려면

  1. Windows Phone용 Visual Studio 2010 Express 에서 파일 | 새 프로젝트 메뉴 명령을 선택하여 새 프로젝트를 만듭니다.

  2. 새 프로젝트 창이 표시됩니다. Visual C# 템플릿을 확장하고 Windows Phone용 Silverlight 템플릿을 선택합니다.

  3. Windows Phone 응용프로그램 템플릿을 선택합니다. 이름 상자에 선택한 이름을 입력합니다.

  4. 확인을 클릭합니다. 새 Windows Phone 응용프로그램 창이 표시됩니다.

  5. 대상 Windows Phone 버전 메뉴에서 Windows Phone 7.1 이 선택되었는지 확인합니다.

  6. 확인을 클릭합니다. 새 프로젝트가 생성되고 MainPage.xaml이 Visual Studio 디자이너 창에서 열립니다.

  7. 프로젝트 메뉴에서 참조 추가를 선택합니다. .NET 탭에서 Microsoft.XNA.Framework를 선택하고 확인을 클릭합니다.

  8. MainPage.xaml에서 다음 코드에 나오는 대로 phone:PhoneApplicationPage 요소를 업데이트합니다.

        SupportedOrientations="Landscape" Orientation="LandscapeLeft"
        shell:SystemTray.IsVisible="False"
    
    

    이렇게 하면 가로 방향의 페이지가 구성되고 시스템 트레이가 숨겨집니다.

  9. MainPage.xaml에서 LayoutRoot라는 Grid를 다음 코드로 바꿉니다.

        <!--LayoutRoot is the root grid where all page content is placed-->
        <Grid x:Name="LayoutRoot" Background="Transparent">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="640" />
                <ColumnDefinition Width="160" />
            </Grid.ColumnDefinitions>
            
            <Canvas x:Name="viewfinderCanvas" Width="640" Height="480" 
                       HorizontalAlignment="Left" >
                
                <!--Camera viewfinder -->
                <Canvas.Background>
                    <VideoBrush x:Name="viewfinderBrush" />
                </Canvas.Background>
             </Canvas>
            
            <!--Button StackPanel to the right of viewfinder>-->
            <StackPanel Grid.Column="1" >
                <Button x:Name="ShutterButton" Content="SH" Click="ShutterButton_Click" FontSize="26" FontWeight="ExtraBold" Height="75" />
            </StackPanel>
    
            <!--Used for debugging >-->
            <TextBlock Height="40" HorizontalAlignment="Left" Margin="8,428,0,0" Name="txtDebug" VerticalAlignment="Top" Width="626" FontSize="24" FontWeight="ExtraBold" />
        </Grid>
    
    

    이 코드는 셔터 버튼 SH를 포함하는 StackPanel 컨트롤을 사용하여 640 x 480 뷰파인더 영역을 만듭니다. 다음 섹션에서 ShutterButton_Click 이벤트를 구현합니다.

    참고참고:

    이 연습에서 소프트웨어 셔터 버튼은 단지 PhotoCamera API에 대한 프로그래밍 방식의 액세스를 보여 주기 위한 것입니다. 최종 사용자의 환경을 최적화하려면 응용프로그램이 카메라의 하드웨어 셔터 버튼을 사용하는 것이 좋습니다. 하드웨어 셔터 버튼을 구현하는 방법에 대한 내용은 방법: Windows Phone에서 하드웨어 카메라 셔터 버튼 액세스를 참조하십시오.

  10. 기본 페이지에 대한 코드 숨김 파일인 MainPage.xaml.cs를 열고 페이지의 맨 위에 다음 지시문을 추가합니다.

    // Directives
    using Microsoft.Devices;
    using System.IO;
    using System.IO.IsolatedStorage;
    using Microsoft.Xna.Framework.Media;
    
    
  11. MainPage.xaml.csMainPage 클래스에서 MainPage 클래스 생성자 위에 다음 변수 선언을 추가합니다.

        // Variables
        private int savedCounter = 0;
        PhotoCamera cam;
        MediaLibrary library = new MediaLibrary();
    
    
  12. 카메라 응용프로그램을 만들려면 응용프로그램 매니페스트 파일에서 카메라 기능을 선언해야 합니다. 그렇지 않으면 응용프로그램이 작동하지 않습니다. WMAppManifest.xml을 열고 다음 기능 요소가 있는지 확인합니다.

    <Capability Name="ID_CAP_ISV_CAMERA"/>
    
  13. (선택 사항) 응용프로그램에 전면을 향하는 카메라가 필요하게 하려는 경우 응용프로그램 매니페스트 파일의 Capabilities 요소에 전면을 향하는 카메라 기능을 더 추가합니다.

    <Capability Name="ID_HW_FRONTCAMERA"/>
    

    이 기능은 새 프로젝트에 자동으로 추가되지 않으므로 수동으로 추가해야 합니다. 전면을 향하는 카메라가 없는 사용자에게는 단말기가 응용프로그램의 요구 사항을 충족하지 않는다는 알림이 표시되지만 사용자가 기능을 다운로드하도록 선택할 수 있습니다. 이 응용프로그램은 카메라를 사용하도록 설계되었지만 이 기능이 응용프로그램에 필요한 것은 아닙니다. 자세한 내용은 Windows Phone의 카메라 및 사진 개요기능 단원을 참조하십시오.

뷰파인더를 구현하려면 viewfinderBrush 소스를 Windows Phone 카메라에 설정합니다. 또한 카메라 초기화, 촬영 완료, 이미지 가용성 등, 여러 카메라 기반 이벤트를 구현합니다.

뷰파인더 및 카메라 기반 이벤트를 구현하려면

  1. MainPage.xaml.cs에서 다음 코드를 MainPage 클래스에 추가합니다.

    참고참고:

    이 과정의 다음 단계를 완료할 때까지 Visual Studio에 현재 컨텍스트에 없는 메서드에 대한 오류가 표시될 수 있습니다. 이러한 메서드는 다음 단계에서 추가됩니다.

            //Code for initialization, capture completed, image availability events; also setting the source for the viewfinder.
            protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
            {
    
                // Check to see if the camera is available on the device.
                if ((PhotoCamera.IsCameraTypeSupported(CameraType.Primary) == true) ||
                     (PhotoCamera.IsCameraTypeSupported(CameraType.FrontFacing) == true))
                {
                    // Initialize the camera, when available.
                    if (PhotoCamera.IsCameraTypeSupported(CameraType.FrontFacing))
                    {
                        // Use front-facing camera if available.
                        cam = new Microsoft.Devices.PhotoCamera(CameraType.FrontFacing);
                    }
                    else
                    {
                        // Otherwise, use standard camera on back of device.
                        cam = new Microsoft.Devices.PhotoCamera(CameraType.Primary);
                    }
    
                    // Event is fired when the PhotoCamera object has been initialized.
                    cam.Initialized += new EventHandler<Microsoft.Devices.CameraOperationCompletedEventArgs>(cam_Initialized);
    
                    // Event is fired when the capture sequence is complete.
                    cam.CaptureCompleted += new EventHandler<CameraOperationCompletedEventArgs>(cam_CaptureCompleted);
    
                    // Event is fired when the capture sequence is complete and an image is available.
                    cam.CaptureImageAvailable += new EventHandler<Microsoft.Devices.ContentReadyEventArgs>(cam_CaptureImageAvailable);
    
                    // Event is fired when the capture sequence is complete and a thumbnail image is available.
                    cam.CaptureThumbnailAvailable += new EventHandler<ContentReadyEventArgs>(cam_CaptureThumbnailAvailable);
    
                    //Set the VideoBrush source to the camera.
                    viewfinderBrush.SetSource(cam);
                }
                else
                {
                    // The camera is not supported on the device.
                    this.Dispatcher.BeginInvoke(delegate()
                    {
                        // Write message.
                        txtDebug.Text = "A Camera is not available on this device.";
                    });
    
                    // Disable UI.
                    ShutterButton.IsEnabled = false;
                }
            }
            protected override void OnNavigatingFrom(System.Windows.Navigation.NavigatingCancelEventArgs e)
            {
                if (cam != null)
                {
                    // Dispose camera to minimize power consumption and to expedite shutdown.
                    cam.Dispose();
    
                    // Release memory, ensure garbage collection.
                    cam.Initialized -= cam_Initialized;
                    cam.CaptureCompleted -= cam_CaptureCompleted;
                    cam.CaptureImageAvailable -= cam_CaptureImageAvailable;
                    cam.CaptureThumbnailAvailable -= cam_CaptureThumbnailAvailable;
                }
            }
    
    

    이 코드는 OnNavigatedTo(NavigationEventArgs) 메서드를 사용하여 cam이라는 PhotoCamera 개체를 만들고 여러 이벤트를 구성합니다. 이 코드는 또한 VideoBrush 소스를 휴대폰 카메라 개체 cam으로 설정합니다.

    단말기에 기본 카메라 외에 셀프 카메라가 있는 경우 응용프로그램은 셀프 카메라를 사용합니다. 모든 단말기에 셀프 카메라가 있는 것은 아니므로 PhotoCamera 개체를 만들기 전에 사용 가능 여부를 확인하기 위해 IsCameraTypeSupported(CameraType) 메서드가 사용됩니다. 단말기에 어떤 유형의 카메라도 없는 경우도 있습니다. 이 경우 UI를 사용할 수 없게 되고 메시지가 표시됩니다.

    Windows Phone 실행 모델을 설명하기 위해, PhotoCamera 개체는 OnNavigatedTo(NavigationEventArgs) 메서드에서 초기화되고 OnNavigatingFrom(NavigatingCancelEventArgs) 메서드가 실행되는 동안 명시적으로 삭제됩니다. PhotoCamera 이벤트의 이벤트 처리기는 OnNavigatedTo(NavigationEventArgs)에서 추가되고 메모리 확보를 위해 OnNavigatingFrom(NavigatingCancelEventArgs)에서 제거됩니다.

    참고참고:

    카메라 미리 보기 버퍼에서 개별 프레임을 분석하고 처리하는 방법에 대한 내용은 방법: Windows Phone용 카메라 응용프로그램에서 회색조 작업을 참조하십시오.

  2. MainPage.xaml.cs에서 다음 코드를 MainPage 클래스에 추가합니다.

        // Update the UI if initialization succeeds.
        void cam_Initialized(object sender, Microsoft.Devices.CameraOperationCompletedEventArgs e)
        {
            if (e.Succeeded)
            {
                this.Dispatcher.BeginInvoke(delegate()
                {
                    // Write message.
                    txtDebug.Text = "Camera initialized.";
                });
            }
        }
    
    

    이 코드는 카메라 Initialized 이벤트를 사용하여 txtDebug라는 TextBlock을 업데이트합니다. BeginInvoke 메서드는 응용프로그램 UI가 다른 스레드에서 실행되므로 상태를 업데이트하는 데 필요합니다.

  3. MainPage.xaml.cs에서 다음 코드를 MainPage 클래스에 추가합니다.

            // Ensure that the viewfinder is upright in LandscapeRight.
            protected override void OnOrientationChanged(OrientationChangedEventArgs e)
            {
                if (cam != null)
                {
                    // LandscapeRight rotation when camera is on back of device.
                    int landscapeRightRotation = 180;
    
                    // Change LandscapeRight rotation for front-facing camera.
                    if (cam.CameraType == CameraType.FrontFacing) landscapeRightRotation = -180;
    
                    // Rotate video brush from camera.
                    if (e.Orientation == PageOrientation.LandscapeRight)
                    {
                        // Rotate for LandscapeRight orientation.
                        viewfinderBrush.RelativeTransform =
                            new CompositeTransform() { CenterX = 0.5, CenterY = 0.5, Rotation = landscapeRightRotation };
                    }
                    else
                    {
                        // Rotate for standard landscape orientation.
                        viewfinderBrush.RelativeTransform =
                            new CompositeTransform() { CenterX = 0.5, CenterY = 0.5, Rotation = 0 };
                    }
                }
    
                base.OnOrientationChanged(e);
            }
    
    

    이 코드는 카메라가 거꾸로(LandscapeRight 방향) 되어 있을 때 viewfinderBrush가 똑바로 있게 합니다. 카메라가 사용자를 향해 있으면 단말기 뒤쪽에 있을 때와는 반대 방향으로 해당 브러시가 회전해야 합니다.

    참고참고:

    비디오 브러시를 180도 회전하면 방향에 상관없이 결과가 동일하지만, 이 코드는 카메라 유형에 따라 UI 방향을 맞추는 방법을 보여 주는 예제를 제공합니다.

  4. MainPage.xaml.cs에서 다음 코드를 MainPage 클래스에 추가합니다.

            private void ShutterButton_Click(object sender, RoutedEventArgs e)
            {
                if (cam != null)
                {
                    try
                    {
                        // Start image capture.
                        cam.CaptureImage();
                    }
                    catch (Exception ex)
                    {
                        this.Dispatcher.BeginInvoke(delegate()
                        {
                            // Cannot capture an image until the previous capture has completed.
                            txtDebug.Text = ex.Message;
                        });
                    }
                }
            }
    
        void cam_CaptureCompleted(object sender, CameraOperationCompletedEventArgs e)
        {
            // Increments the savedCounter variable used for generating JPEG file names.
            savedCounter++;
        }
    
    

    이 코드는 셔터 버튼 및 촬영 완료 이벤트를 구현합니다. 셔터 버튼은 XAML 코드로 만든 소프트웨어 버튼으로, 정지 이미지를 촬영합니다. CaptureCompleted 이벤트는 이 프로젝트에서 savedCounter 변수를 증가시키기 위해 사용되며, 다음 섹션에서는 JPEG 명명을 위해 사용됩니다.

Windows Phone OS 7.1 을 대상으로 하는 카메라 응용프로그램의 경우 사진을 찍으면 두 개의 이미지가 캡처됩니다. 하나는 최대 해상도 이미지이고, 다른 하나는 갤러리 뷰에서 최대 해상도 사진을 불러오는 데 사용되는 축소판 이미지입니다. 이 섹션에서는 최대 해상도 이미지를 단말기 미디어 라이브러리에 넣는 방법에 대해 설명합니다. 또한 최대 해상도 이미지와 축소판 이미지를 격리된 저장소에 저장하는 방법에 대해서도 설명합니다.

이미지를 미디어 라이브러리 및 격리된 저장소에 저장하려면

  1. MainPage.xaml.cs에서 다음 코드를 MainPage 클래스에 추가합니다.

        // Informs when full resolution picture has been taken, saves to local media library and isolated storage.
        void cam_CaptureImageAvailable(object sender, Microsoft.Devices.ContentReadyEventArgs e)
        {
            string fileName = savedCounter + ".jpg";
    
            try
            {   // Write message to the UI thread.
                Deployment.Current.Dispatcher.BeginInvoke(delegate()
                {
                    txtDebug.Text = "Captured image available, saving picture.";
                });
    
                // Save picture to the library camera roll.
                library.SavePictureToCameraRoll(fileName, e.ImageStream);
    
                // Write message to the UI thread.
                Deployment.Current.Dispatcher.BeginInvoke(delegate()
                {
                    txtDebug.Text = "Picture has been saved to camera roll.";
    
                });
    
                // Set the position of the stream back to start
                e.ImageStream.Seek(0, SeekOrigin.Begin);
    
                // Save picture as JPEG to isolated storage.
                using (IsolatedStorageFile isStore = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    using (IsolatedStorageFileStream targetStream = isStore.OpenFile(fileName, FileMode.Create, FileAccess.Write))
                    {
                        // Initialize the buffer for 4KB disk pages.
                        byte[] readBuffer = new byte[4096];
                        int bytesRead = -1;
    
                        // Copy the image to isolated storage. 
                        while ((bytesRead = e.ImageStream.Read(readBuffer, 0, readBuffer.Length)) > 0)
                        {
                            targetStream.Write(readBuffer, 0, bytesRead);
                        }
                    }
                }
    
                // Write message to the UI thread.
                Deployment.Current.Dispatcher.BeginInvoke(delegate()
                {
                    txtDebug.Text = "Picture has been saved to isolated storage.";
    
                });
            }
            finally
            {
                // Close image stream
                e.ImageStream.Close();
            }
    
        }
    
        // Informs when thumbnail picture has been taken, saves to isolated storage
        // User will select this image in the pictures application to bring up the full-resolution picture. 
        public void cam_CaptureThumbnailAvailable(object sender, ContentReadyEventArgs e)
        {
            string fileName = savedCounter + "_th.jpg";
    
            try
            {
                // Write message to UI thread.
                Deployment.Current.Dispatcher.BeginInvoke(delegate()
                {
                    txtDebug.Text = "Captured image available, saving thumbnail.";
                });
    
                // Save thumbnail as JPEG to isolated storage.
                using (IsolatedStorageFile isStore = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    using (IsolatedStorageFileStream targetStream = isStore.OpenFile(fileName, FileMode.Create, FileAccess.Write))
                    {
                        // Initialize the buffer for 4KB disk pages.
                        byte[] readBuffer = new byte[4096];
                        int bytesRead = -1;
    
                        // Copy the thumbnail to isolated storage. 
                        while ((bytesRead = e.ImageStream.Read(readBuffer, 0, readBuffer.Length)) > 0)
                        {
                            targetStream.Write(readBuffer, 0, bytesRead);
                        }
                    }
                }
    
                // Write message to UI thread.
                Deployment.Current.Dispatcher.BeginInvoke(delegate()
                {
                    txtDebug.Text = "Thumbnail has been saved to isolated storage.";
    
                });
            }
            finally
            {
            // Close image stream
            e.ImageStream.Close();
            }
        }
    
    

    이 코드는 CaptureImageAvailableCaptureThumbnailAvailable 이벤트를 구현합니다. 첫 번째 메서드는 최대 해상도 이미지를 단말기 미디어 라이브러리와 격리된 저장소에 저장하고, 두 번째 메서드는 축소판 이미지를 격리된 저장소에 저장하는 방법을 나타냅니다.

    참고참고:

    사진 허브의 저장된 사진 앨범에 사진을 저장하려면 SavePicture 메서드를 사용합니다. 이 예제에 사용된 SavePictureToCameraRoll 메서드는 카메라 앨범에 이미지를 저장합니다.

  2. 단말기에서 디버그 | 디버깅 시작 메뉴 명령을 선택하여 응용프로그램을 실행합니다. SH 버튼을 눌러 응용프로그램을 테스트합니다. txtDebug TextBlock은 격리된 저장소에 대한 저장 작업의 상태를 나타냅니다. 응용프로그램을 종료한 후 사진 허브의 카메라 앨범 폴더에서 응용프로그램으로 찍은 사진을 찾을 수 있습니다.

    다음 예제는 이 시점에서 UI를 표시하는 방법에 대해 설명합니다.

    AP_Con_CameraWireFrame

    이 예제에서 소프트웨어 셔터 버튼 SH는 UI의 오른쪽 상단에 표시되고, 망고 사진은 viewfinderCanvas라는 Canvas 컨트롤에 표시됩니다.

  3. 이제 기본 카메라 응용프로그램이 완성되었습니다. 이 응용프로그램을 사용하여 다음 항목으로 진행할 수 있습니다.

Microsoft는 MSDN 웹 사이트에 대한 귀하의 의견을 이해하기 위해 온라인 설문 조사를 진행하고 있습니다. 참여하도록 선택하시면 MSDN 웹 사이트에서 나가실 때 온라인 설문 조사가 표시됩니다.

참여하시겠습니까?
표시:
© 2014 Microsoft