Особенности использования камеры и дополнительного функционала в iOS* и приложениях Windows* 8 Store

Загрузить статью

Загрузить статью Camera Usage and Features, from iOS* to Windows* 8 Store App [Eng., PDF 1.26MB]

Аннотация

Современные приложения, задействующие камеры, могут выполнять новые задачи и предоставляют пользователям более широкие возможности. В этой статье рассматриваются возможности использования камеры в приложениях для магазина Windows* 8 для съемки фотографий и процесса преобразования этих фотографий в кодировку base64, позволяющую передавать их как данные JSON по сети в серверную или локальную базу данных. Мы также обсудим отличия в использовании камеры между iOS* и Windows 8 и предложим несколько советов по портированию вашего кода.

Общая информация

Камера является одной из самых популярных функций в приложениях для мобильных устройств. Она позволяет снимать фотографии и записывать видео с различными параметрами. Все современные платформы операционных систем, такие как iOS и Windows 8, предоставляют API-интерфейсы и службы, упрощающие использование камеры как для пользователей, так и для программистов. В итоге элементы управления камерой в различных приложениях имеют единообразный и привычный вид. В некоторых приложениях в зависимости от решаемых задач могут применяться нестандартные модели использования камеры, но в большинстве случаев рекомендуется использовать модель по умолчанию.

В этой статье описан процесс портирования кода, использующего камеру, из приложений для iOS в приложения магазина Windows 8. Здесь рассматриваются такие вопросы, как вызов элемента управления, используемого по умолчанию для работы с камерой, обработка результата с помощью моделей асинхронного программирования и вывод изображения в пользовательском интерфейсе приложения Windows с помощью элемента управления Image.

Кроме того, здесь рассматривается кодирование изображений в строки формата base64 и декодирование; эта функция может использоваться в бизнес-приложениях для передачи изображений по сети в службы RESTful в виде данных JSON.

Элементы управления камеры и пользовательский интерфейс

Элементы управления, используемые по умолчанию для работы с камерой, имеют несколько стандартных настроек. Обычно они обрабатывают все действия пользователя с интерфейсом камеры, включая жесты касания, и возвращают результат (снятую фотографию или видео) в код, из которого они вызываются (через делегирование или асинхронные вызовы).

В зависимости от параметров API элементы управления камерой позволяют пользователям редактировать фотографии (например, обрезать) и вносить другие изменения. Если в стандартных элементах управления камерой недостаточно возможностей для редактирования и изменения, можно расширить их, разработав собственные элементы управления.

Эти элементы управления также могут предоставлять пользователям доступ к различным функциям камеры, включая вспышку, яркость и другие стандартные функции в зависимости от платформы.

Код, вызывающий эти элементы управления, обычно легко интегрируется, если вы придерживаетесь рекомендованных моделей использования API для соответствующей платформы.

Медицинское приложение из магазина Windows

Как мы уже делали в других статьях на сайте Intel Developer Zone, рассмотрим ситуацию на примере медицинского приложения из магазина Windows. Мы добавим в приложение функции съемки фотографии и обновления профиля пациента.

Приложение позволяет пользователю войти в систему, просмотреть список пациентов (рис. 1) и получить доступ к истории болезни пациентов, включая профили, записи врачей, результаты анализов, графики показателей жизнедеятельности и т. д:



Рис. 1. На странице Patients медицинского бизнес-приложения представлен список всех пациентов. При выборе пациента открывается его история болезни.

На рис. 1 во всех профилях используются стандартные изображения. Добавив функцию камеры, мы сможем при необходимости заменять эти изображения на последние фотографии из профиля каждого пациента.

Портирование кода, использующего камеру, с iOS на Windows 8

Платформа iOS предоставляет как стандартные элементы управления камерой, так и расширенное решение с более гибкими возможностями. API-интерфейс UIImagePickerController обеспечивает простой стандартный набор распространенных функций съемки фотографий с помощью камеры, тогда как объединенная платформа AV является полностью настраиваемым решением. Дополнительные сведения можно найти в следующем документе:

http://developer.apple.com/library/ios/documentation/AudioVideo/Conceptual/CameraAndPhotoLib_TopicsForIOS/Introduction/Introduction.html

Портирование функций камеры из iOS в приложения Windows 8 можно выполнять с помощью пользовательского интерфейса и элемента управления камерой по умолчанию CameraCaptureUI, входящего в пространство имен Windows.Media.Capture.

http://msdn.microsoft.com/EN-US/library/windows/apps/windows.media.capture.cameracaptureui.aspx

Использование пользовательского интерфейса камеры в Windows 8 и советы по делегированию кода

В этой статье приводится краткая ознакомительная информация о разработке приложений магазина Windows. В приложениях Windows 8, как и в других современных операционных системах (например, iOS), функции камеры необходимо декларировать в файле манифеста приложения. Дважды щелкните Package.appxmanifest в проекте Visual Studio* 2012, чтобы открыть редактор манифеста и изменить параметры. На рис. 2 показано, что в манифесте включена функция веб-камеры, что позволяет использовать данную функцию.



Рис. 2. Манифест приложения с функцией веб-камеры (снимок экрана получен в Visual Studio* 2012)

Теперь наш проект поддерживает доступ к функции камеры.

Когда приложение в первый раз получает доступ к камере, Windows 8 открывает диалоговое окно с запросом разрешения пользователя на доступ к камере. На рис. 3 показан пример.





Рис. 3. Диалоговое окно с запросом разрешения на доступ к камере (снимок экрана получен в Windows* 8)

Как указывалось ранее, приложения Магазина Windows в большинстве случаев могут использовать стандартный системный элемент управления камерой (класс CameraCaptureUI в пространстве имен Windows.Media.Capture). Преимуществом данного подхода является то, что пользователю уже знакомы элементы управления, жесты и принцип использования.

Обычно приложение вызывает элемент управления камерой в ответ на какое-либо действие пользователя, например нажатие кнопки или касание.

На рис. 4 показана панель приложения с кнопкой камеры, имеющей метку Photo.



Рис. 4. Кнопка и значок камеры (снимок экрана получен в Windows* 8)

Для кнопки камеры можно выбрать стандартный значок Windows (PhotoAppBarButtonStyle). На рис. 5 показан пример кода XAML для кнопки камеры, расположенной на панели приложения.

<Button x:Name="button_take_photo" Grid.Column="1" HorizontalAlignment="Left" Margin="0,0,0,0"
Style="{StaticResource PhotoAppBarButtonStyle}" Height="87" VerticalAlignment="Top" 
DataContext="{Binding Patient}" Command="{Binding PatientPicCmd}" RenderTransformOrigin="0.5,0.5" 
Visibility="Visible"/>

Рис. 5. Код XAML для кнопки камеры и стандартный значок на панели приложения ++

В Windows 8 события нажатия кнопки любого происхождения (касание, мышь и т. д.) автоматически направляются на один обработчик ввода, в данном случае — в свойство Command (привязка PatientPicCmd). Команда PatientPicCmd описана далее в этой статье.

При написании кода для приложений на основе XAML обычно рекомендуется реализовать шаблон MVVM. Дополнительные сведения о шаблоне MVVM см. в следующей статье:

http://msdn.microsoft.com/en-us/magazine/dd419663.aspx

Это позволит нам реализовать логику обработчика события кнопки внутри модели вида (View) пациента и использовать ту же модель вида и логику на всех страницах пользовательского интерфейса приложения путем простой привязки к свойствам. На рис. 6 показана другая страница пользовательского интерфейса с другой кнопкой камеры. Повторно реализовывать обработчик нажатия кнопки в коде XAML не нужно, так как мы просто выполняем привязку к тому же классу модели вида (ViewModel) пациента (в котором уже присутствует логика обработчика нажатия кнопки камеры).



Рис. 6. Другая страница пользовательского интерфейса с кнопкой камеры (снимок экрана получен в Windows* 8)

Вызов диалогового окна камеры в Windows 8 выполняется очень просто. Достаточно создать экземпляр класса CameraCaptureUI, определить его параметры и отобразить диалоговое окно пользовательского интерфейса камеры с помощью метода CaptureFileAsync этого экземпляра. Поскольку данный метод реализован в виде асинхронной модели, для его вызова необходимо использовать ключевое слово await.

Дополнительные сведения об асинхронном программировании в приложениях магазина Windows 8 см. в следующей статье.

http://msdn.microsoft.com/EN-US/library/vstudio/hh191443.aspx

На рис. 7 показан пример кода для вызова стандартного пользовательского интерфейса камеры в Windows 8.

private async void DoPatientPicCmd(object sender)
        {
            try
            {
                CameraCaptureUI dialog = new CameraCaptureUI();
               
                dialog.PhotoSettings.CroppedAspectRatio = new Size(4, 3);

                // fix the photo size to 300x300
                //dialog.PhotoSettings.CroppedSizeInPixels = new Size(300, 300);

                StorageFile photo = await dialog.CaptureFileAsync(CameraCaptureUIMode.Photo);
                if (photo == null) return;
              
                // custom process the photo
            }
            catch (Exception ex)
            {
// custom exception handling code

            }
        }

Рис. 7. Пример кода для вызова диалогового окна пользовательского интерфейса камеры ++

Класс CameraCaptureUI содержит два основных свойства: PhotoSettings и VideoSettings. Для вызова диалогового окна камеры в фоторежиме необходимо во время вызова указать параметр CameraCaptureUIMode.Photo.

PhotoSettings — это экземпляр класса CameraCaptureUIPhotoCaptureSettings, с помощью которого можно задавать различные параметры, например обрезку, соотношение сторон, максимальное разрешение и формат. Дополнительные сведения см. в следующей статье:

http://msdn.microsoft.com/EN-US/library/windows/apps/windows.media.capture.cameracaptureuiphotocapturesettings.aspx

В нашем примере кода выбрана обрезка с соотношением сторон 4 : 3. На рис. 8 показано диалоговое окно пользовательского интерфейса камеры по умолчанию. Функция видеозаписи в нем отключена, поскольку этот элемент управления вызван в фоторежиме. Доступны функции смены камеры (для переключения на заднюю, переднюю или другие камеры), изменения параметров камеры (например, разрешение) и таймера.



Рис. 8. Диалоговое окно пользовательского интерфейса камеры по умолчанию (снимок экрана получен в Windows* 8)

Для съемки фотографии пользователь может однократно коснуться или щелкнуть в любом месте экрана. В зависимости от конфигурации открывается еще одно диалоговое окно, позволяющее пользователю обрезать или отредактировать фотографию. Доступны только базовые функции редактирования, и их возможности ограничены. Для реализации расширенных возможностей редактирования рекомендуется использовать специализированный элемент управления пользовательского интерфейса камеры (либо можно добавить процесс редактирования позже).



Рис. 9. Пользовательский интерфейс камеры с базовыми функциями редактирования (снимок экрана получен в Windows* 8)

Если пользователь доволен снятой фотографией, он может либо нажать кнопку OK, либо переснять фотографию. После успешного выполнения действия (съемки фотографии и нажатия кнопки OK) диалоговое окно пользовательского интерфейса камеры возвращает фотографию, сохраненную как файл изображения (экземпляр класса StorageFile в пространстве имен Windows.Storage), и можно продолжить ее обработку или оставить как есть в модели данных.

Преобразование файла фотоизображения в буфер изображения

Чтобы передать фотоизображение в виде данных JSON в серверную базу данных (наиболее распространенная задача в приложениях для организаций), необходимо преобразовать его в строку с кодировкой base64. Для такого преобразования сначала необходимо преобразовать файл фотографии в буфер изображения, поскольку в функциях API, выполняющих кодирование и декодирование, должен использоваться буфер.

Настоятельно рекомендуется по возможности использовать асинхронную модель, так как вся эта обработка выполняется внутри обработчика нажатия кнопки фотографии.

Мы получаем доступ к файлу с использованием потока произвольного доступа и копируем его в буфер с помощью интерфейса DataReader. На рис. 10 показан пример кода.

                StorageFile photo = await dialog.CaptureFileAsync(CameraCaptureUIMode.Photo);
                if (photo == null) return;
              
                byte[] photoBuf = null;

                using (IRandomAccessStream photostream = await photo.OpenReadAsync())
                {
                    photoBuf = new byte[photostream.Size];
                    using (DataReader dr = new DataReader(await photo.OpenReadAsync()))
                    {
                        await dr.LoadAsync((uint)photostream.Size);
                        dr.ReadBytes(photoBuf);
                    }
                } 

Рис. 10. Пример кода, преобразующего файл фотографии в буфер ++

Кодирование буферов изображений в строки формата base64 и декодирование

Для кодирования и декодирования строк формата base64 можно использовать класс Convert в пространстве имен System. В предыдущем разделе рассматривалось преобразование фотоизображения в байтовый буфер, который можно использовать в функциях API, выполняющих преобразование в формат base64. Метод ToBase64String описан в следующем документе:

http://msdn.microsoft.com/EN-US/library/dhx0d524.aspx

Ниже приведен фрагмент кода, преобразующий буфер photoBuf, созданный в предыдущем разделе, в строку с кодировкой base64.

                Pic = Convert.ToBase64String(photoBuf, 0, photoBuf.Length);

Pic — это открытая (public) переменная-член класса модели вида пациента, который был описан ранее.

Обратное преобразование строки в буфер:

                var photoBuf = Convert.FromBase64String(pic);

Отображение изображения путем привязки элемента управления Image к объекту BitmapImage

Для отображения фотографии можно использовать элемент управления Image в XAML. Дополнительные сведения см. в следующем документе:

http://msdn.microsoft.com/EN-US/library/windows/apps/windows.ui.xaml.controls.image.aspx

Элемент управления Image имеет гибкие возможности и поддерживает различные форматы и параметры изображений. Например, можно отобразить фотографию путем привязки к модели вида пациента, как показано далее:

                <Image  Margin="0,40,20,0"            
                            DataContext="{Binding Patient}"
                            Source="{Binding Image}"></Image>

Свойство Source элемента управления Image позволяет автоматически преобразовать экземпляр BitmapImage или даже непосредственный путь к источнику в файл изображения. Для того, чтобы обновлять изображение динамически, можно для удобства привязать его к экземпляру BitmapImage. Дополнительные сведения об этом классе см. в следующей статье:

http://msdn.microsoft.com/EN-US/library/windows/apps/windows.ui.xaml.media.imaging.bitmapimage.aspx

При выполнении повторных действий настоятельно рекомендуется по возможности использовать асинхронные методы, так как эти свойства привязаны к элементам пользовательского интерфейса XAML.

Объект BitmapImage позволяет напрямую использовать идентификатор URI или настроить буфер фотографии в качестве входного потока с помощью метода SetSourceAsync. Мы используем метод SetSourceAsync для создания изображения профиля, если оно доступно, или для установки произвольно выбранного аватара (из ресурсов приложения) в зависимости от пола пациента. См. фрагмент кода на рис. 10 далее.

    public class PatientsViewModel : BindableBase
    {
        public PatientsViewModel() 
        {
            this.PatientPicCmd= new DelegateCommand(DoPatientPicCmd);
        }

        private string pic = string.Empty;
        public string Pic 
        { 
            get { return pic; } 
            set { 
                this.SetProperty(ref pic, value);                
            } 
        }

        private BitmapImage image = null;
        public BitmapImage Image
        {
            get
            {
                if (image == null) GetImageAsync();
                return image;
            }
        }

        public async Task GetImageAsync()
        {
            image = new BitmapImage();
            if (pic.Length > 1)
            {
                var photoBuf = Convert.FromBase64String(pic);
                using (InMemoryRandomAccessStream mrs = new InMemoryRandomAccessStream())
                {
                    using (DataWriter dw = new DataWriter(mrs.GetOutputStreamAt(0)))
                    {
                        dw.WriteBytes(photoBuf);
                        await dw.StoreAsync();
                    }
                    await image.SetSourceAsync(mrs);
                }
            }
            else
            {
                Random rand = new Random();
                String url = "ms-appx:///Assets/" + gender.ToLower() + rand.Next(1, 4).ToString() + ".png";
                StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(new Uri(url));                
                using (IRandomAccessStream fileStream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read))
                {
                    await image.SetSourceAsync(fileStream);
                }
            }
            OnPropertyChanged("Image");
        }
         …
         …

Рис. 10. Пример кода для отображения фотографии в элементе управления Image с помощью объекта BitmapImage и метода SetSourceAsync ++

В строковом свойстве Pic хранится строка с кодировкой base64, в которую мы преобразовали файл снятой фотографии. Это свойство можно передать в локальную или серверную базу данных. Свойство Image (с типом BitmapImage), привязанное к нашему элементу управления Image в XAML, просто возвращает экземпляр BitmapImage в зависимости от значения переменной Pic. Если переменная пуста, возвращается произвольно выбранный аватар; в противном случае строка base64 из переменной Pic преобразуется обратно в байтовый буфер, и возвращается содержащий его экземпляр BitmapImage.

На рис. 11 показан обновленный экран пациентов, который уже приводился на рис. 1.





Рисунок 11. Обновленная страница пользовательского интерфейса со списком пациентов (снимок экрана получен в Windows* 8)

Пользователь может щелкнуть любого пациента и обновить его изображение профиля, и благодаря привязке XAML все ссылки на него в элементах управления Image автоматически обновятся.

Выводы

Мы рассмотрели процесс портирования кода, использующего камеру, из приложений iOS в приложения Windows 8. В том числе мы рассмотрели вызов элемента управления, используемого по умолчанию для работы с камерой, обработка результата, использование моделей асинхронного программирования и вывод изображения в пользовательском интерфейсе приложения магазина Windows с помощью элемента управления Image. Кроме того, мы ознакомились с кодированием изображений в строки формата base64 и декодированием для удобства передачи изображений в службы RESTful в виде данных JSON.

Copyright © 2013 Intel Corporation. Все права защищены.

*Другие наименования и торговые марки могут быть собственностью третьих лиц.

++This sample source code is released under the Intel OBL Sample Source Code License (MS-LPL Compatible), Microsoft Limited Public License, and Visual Studio* 2012 License.

Pour de plus amples informations sur les optimisations de compilation, consultez notre Avertissement concernant les optimisations.