Come utilizzare la fotocamera sul dispositivo con C# in un'applicazione UWP:parte 3, salvataggio di un'immagine

Come utilizzare la fotocamera sul dispositivo con C# in un'applicazione UWP:parte 3, salvataggio di un'immagine

In precedenza in questa serie, abbiamo esaminato come visualizzare in anteprima l'output della fotocamera del dispositivo e come utilizzare un pulsante fisico per mettere a fuoco la fotocamera.

Questa volta vorrei vedere come acquisire un'immagine e salvarla in una cartella del dispositivo locale.

Aggiunta della possibilità di salvare nella cartella delle immagini

Se desideri salvare le immagini in una delle tante cartelle standard di Windows, devi aggiungere questa funzionalità al manifest del pacchetto. Nel progetto VS2015 che abbiamo costruito nelle ultime due parti di questa serie, fai doppio clic sul file Package.appxmanifest. Nell'elenco delle funzionalità, spunta la casella con il testo "Libreria immagini".

La nostra applicazione è ora autorizzata a salvare nella libreria Immagini sul nostro dispositivo.

Acquisisci un'immagine utilizzando il pulsante del dispositivo

Nella parte 2, abbiamo configurato la nostra app per mettere a fuoco la fotocamera quando il pulsante è premuto a metà:dopo che è stato messo a fuoco, vorremmo premere completamente il pulsante per acquisire l'immagine attualmente visualizzata in anteprima. Per fare ciò, dobbiamo gestire l'evento CameraPressed nel nostro codice.

if (ApiInformation.IsTypePresent("Windows.Phone.UI.Input.HardwareButtons"))
{
    HardwareButtons.CameraHalfPressed += HardwareButtons_CameraHalfPressed;
    HardwareButtons.CameraPressed += HardwareButtons_CameraPressed;
}

Il passaggio successivo consiste nello scrivere il gestore dell'evento.

Scrivere in "Cartelle conosciute"

L'API UWP di Windows ha alcune funzioni già integrate che ci consentono di identificare cartelle speciali in Windows e salvare i file in queste cartelle.

Per ottenere queste cartelle speciali, utilizziamo la classe statica "KnownFolders". Per ciascuna di queste cartelle conosciute, sono disponibili metodi per creare file. Questi file creati implementano l'interfaccia IStorageFile e, fortunatamente, _mediaCapture ha un metodo chiamato CapturePhotoToStorageFileAsync, che ci consente di salvare un'immagine in un file che implementa questa interfaccia. Il codice seguente per il gestore di eventi mostra come è fatto.

private async void HardwareButtons_CameraPressed(object sender, CameraEventArgs e)
{
    // This is where we want to save to.
    var storageFolder = KnownFolders.SavedPictures;
 
    // Create the file that we're going to save the photo to.
    var file = await storageFolder.CreateFileAsync("sample.jpg", CreationCollisionOption.ReplaceExisting);
 
    // Update the file with the contents of the photograph.
    await _mediaCapture.CapturePhotoToStorageFileAsync(ImageEncodingProperties.CreateJpeg(), file);
}

Quindi ora abbiamo un'applicazione Windows di base, che funge da mirino, ci consente di mettere a fuoco se il dispositivo è in grado, quindi ci consente di salvare l'immagine attualmente visualizzata nella speciale cartella Windows SavedPictures. Questa è un'app piuttosto buona e l'abbiamo fatta in circa 100 righe di codice (mostrate di seguito). Non male!

using System;
using System.Linq;
using System.Threading.Tasks;
using Windows.Devices.Enumeration;
using Windows.Foundation.Metadata;
using Windows.Media.Capture;
using Windows.Media.Devices;
using Windows.Media.MediaProperties;
using Windows.Phone.UI.Input;
using Windows.Storage;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
 
namespace BasicCamera
{
    public sealed partial class MainPage : Page
    {
        // Provides functionality to capture the output from the camera
        private MediaCapture _mediaCapture;
 
        public MainPage()
        {
            InitializeComponent();
 
            Application.Current.Resuming += Application_Resuming;
 
            if (ApiInformation.IsTypePresent("Windows.Phone.UI.Input.HardwareButtons"))
            {
                HardwareButtons.CameraHalfPressed += HardwareButtons_CameraHalfPressed;
                HardwareButtons.CameraPressed += HardwareButtons_CameraPressed;
            }
        }
 
        private async void Application_Resuming(object sender, object o)
        {
            await InitializeCameraAsync();
        }
 
        protected override async void OnNavigatedTo(NavigationEventArgs e)
        {
            await InitializeCameraAsync();
        }
 
        private async Task InitializeCameraAsync()
        {
            if (_mediaCapture == null)
            {
                // Get the camera devices
                var cameraDevices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);
 
                // try to get the back facing device for a phone
                var backFacingDevice = cameraDevices
                    .FirstOrDefault(c => c.EnclosureLocation?.Panel == Windows.Devices.Enumeration.Panel.Back);
 
                // but if that doesn't exist, take the first camera device available
                var preferredDevice = backFacingDevice ?? cameraDevices.FirstOrDefault();
 
                // Create MediaCapture
                _mediaCapture = new MediaCapture();
 
                // Initialize MediaCapture and settings
                await _mediaCapture.InitializeAsync(
                    new MediaCaptureInitializationSettings
                    {
                        VideoDeviceId = preferredDevice.Id
                    });
 
                // Set the preview source for the CaptureElement
                PreviewControl.Source = _mediaCapture;
 
                // Start viewing through the CaptureElement 
                await _mediaCapture.StartPreviewAsync();
            }
        }
 
        private async void HardwareButtons_CameraHalfPressed(object sender, CameraEventArgs e)
        {
            // test if focus is supported
            if (_mediaCapture.VideoDeviceController.FocusControl.Supported)
            {
                // get the focus control from the _mediaCapture object
                var focusControl = _mediaCapture.VideoDeviceController.FocusControl;
 
                // try to get full range, but settle for the first supported one.
                var focusRange = focusControl.SupportedFocusRanges.Contains(AutoFocusRange.FullRange) ? AutoFocusRange.FullRange : focusControl.SupportedFocusRanges.FirstOrDefault();
 
                // try to get the focus mode for focussing just once, but settle for the first supported one.
                var focusMode = focusControl.SupportedFocusModes.Contains(FocusMode.Single) ? FocusMode.Single : focusControl.SupportedFocusModes.FirstOrDefault();
 
                // now configure the focus control with the range and mode as settings
                focusControl.Configure(
                    new FocusSettings
                    {
                        Mode = focusMode,
                        AutoFocusRange = focusRange
                    });
 
                // finally wait for the camera to focus
                await focusControl.FocusAsync();
            }
        }
 
        private async void HardwareButtons_CameraPressed(object sender, CameraEventArgs e)
        {
            // This is where we want to save to.
            var storageFolder = KnownFolders.SavedPictures;
 
            // Create the file that we're going to save the photo to.
            var file = await storageFolder.CreateFileAsync("sample.jpg", CreationCollisionOption.ReplaceExisting);
 
            // Update the file with the contents of the photograph.
            await _mediaCapture.CapturePhotoToStorageFileAsync(ImageEncodingProperties.CreateJpeg(), file);
        }
    }
}

Naturalmente, c'è ancora un po' di più da fare:questo codice non gestisce la pulizia delle risorse, né si occupa di ciò che accade quando l'applicazione viene sospesa o perde la messa a fuoco. Lo vedremo la prossima volta.