Доступ к камере в Windows Phone 8

В любом устройстве на Windows Phone есть камера. Еще с первых версий WP7 SDK был возможен программный доступ к камере и осущствлялся при помощи стандартных диалогов. Это позволяло запустить стандартное приложение для получения фотографий, получить изображение и передать его в приложение. Все это отлично работало в сценариях получения одной статической фотографии и дальнейшей её обработки. Однако, при таком подходе становятся невозможными многие сценарии, например возможность создания приложения дополненной реальности. Поэтому Windows Phone 8 SDK содержит механизмы прямого доступа к камере, минуя стандартный диалог операционной системы.

Чтобы воспользоваться возможностями доступа к камере в манифесте приложения необходимо установить возможность ID_CAP_ISV_CAMERA.

За доступ к камере отвечает объект PhotoCamera. Прежде чем проинициализировать камеру, следует проверить её доступность. Для этого следует вызвать статический метод IsCameraSupported() В Windows Phone 8 можно работать с задней и основной камерой. При использовании камеры следует указать какую именно из них мы хотим использовать.

if (PhotoCamera.IsCameraTypeSupported(CameraType.Primary) == true)
{
  // ...
}

Чтобы отобразить картинку с камеры, необходимо добавить на страницу элемент VideoBrush. Для этого создадим визуальный объект, например Rectangle, и в качестве заливки установим VideoBrush:

<Rectangle Height="400" Width="400">
  <Rectangle.Fill>
    <VideoBrush x:Name="video"></VideoBrush>
  </Rectangle.Fill>
</Rectangle>

Для простого доступа к VideoBrush я задал имя. Понятно, что этого можно не делать и найти VideoBrush через свойство Fill основного элемента.

Теперь можно проинициализировать камеру. Для этого создадим объект PhotoCamera и укажем куда именно нужно отображать видеопоток:

if (PhotoCamera.IsCameraTypeSupported(CameraType.Primary) == true)
{
  _camera = new PhotoCamera(CameraType.Primary);
  video.SetSource(_camera);
}

Теперь, если мы запустим наше приложение, то на странице появится видео, которое передается с камеры. Операционная система передает перевернутое изображение. Чтобы корректно отображать картинку, повернем изображение на 90 градусов. Для этого воспользуемся стандартными трансформациями элементов управления в XAML:

<Rectangle Height="400" Width="400">
  <Rectangle.RenderTransform>
    <RotateTransform Angle="90" CenterX="200" CenterY="200"></RotateTransform>
  </Rectangle.RenderTransform>
  <Rectangle.Fill>
    <VideoBrush x:Name="video"></VideoBrush>
  </Rectangle.Fill>
</Rectangle>

Запустим приложение и увидим изображение с камеры:

Для корректной работы приложения следует также позаботиться о том, чтобы удалять объект PhotoCamera, когда он становится ненужным. Поэтому я добавлю на страницу следующий код:

protected override void OnNavigatedFrom(NavigationEventArgs e)
{
  if (_camera != null)
    _camera.Dispose();

  base.OnNavigatedFrom(e);
}

Он уничтожает объект PhotoCamera как только мы уходим со страницы.

Скорее всего вам захочется не только отображать изображение на странице, но и захватывать его для дальнейшей обработки или сохранения. Для того, чтобы получить изображение с камеры необходимо вызвать метод CaptureImage:

private void CaptureClick(object sender, RoutedEventArgs e)
{
  _camera.CaptureImage();
}

Этот вызов сообщит камере о том, что приложение хочет получить полноразмерную картинку. Когда камера будет готова отдать изображение будет сгенерировано событие CaptureImageAvailable. Поэтому все, что нам необходимо сделать – подписаться на событие и обработать данные с камеры в обработчике:

protected override void OnNavigatedTo(NavigationEventArgs e)
{
  if (PhotoCamera.IsCameraTypeSupported(CameraType.Primary) == true)
  {
    _camera = new PhotoCamera(CameraType.Primary);
    _camera.CaptureImageAvailable += _cam_CaptureImageAvailable;
    video.SetSource(_camera);
  }

  base.OnNavigatedTo(e);
}

void _cam_CaptureImageAvailable(object sender, ContentReadyEventArgs e)
{
  // e.ImageStream 
}