Compartilhar via


Controles manuais da câmera para a captura de fotos e vídeos

Este artigo mostra como usar controles manuais de dispositivo para habilitar cenários aprimorados de captura de fotos e vídeos, incluindo estabilização óptica de imagem e zoom suave.

Os controles discutidos neste artigo são todos adicionados ao seu aplicativo usando o mesmo padrão. Primeiro, verifique se o controle é compatível com o dispositivo atual no qual seu aplicativo está sendo executado. Se o controle for suportado, defina o modo desejado para o controle. Normalmente, se um controle específico não tiver suporte no dispositivo atual, você deverá desabilitar ou ocultar o elemento da interface do usuário que permite ao usuário habilitar o recurso.

O código neste artigo foi adaptado do exemplo do SDK de controles manuais da câmera. Você pode baixar o exemplo para ver o código usado no contexto ou para usar o exemplo como ponto de partida para seu próprio aplicativo.

Observação

Este artigo se baseia em conceitos e códigos discutidos em Captura básica de fotos, áudio e vídeo com o MediaCapture, que descreve as etapas para implementar uma captura básica de fotos e vídeos. Recomendamos que você se familiarize com o padrão de captura de mídia básica neste artigo antes de passar para cenários de captura mais avançados. O código neste artigo presume que seu aplicativo já tenha uma instância de MediaCapture inicializada corretamente.

Todas as APIs de controle de dispositivo abordadas neste artigo são membros do namespace Windows.Media.Devices.

using Windows.Media.Devices;

Exposure

O ExposureControl permite que você defina a velocidade do obturador usada durante a captura de fotos ou vídeos.

Este exemplo usa um controle Slider para ajustar o valor de exposição atual e uma caixa de seleção para alternar o ajuste automático de exposição.

<Slider Name="ExposureSlider" ValueChanged="ExposureSlider_ValueChanged"/>
<TextBlock Name="ExposureTextBlock" Text="{Binding ElementName=ExposureSlider,Path=Value}"/>
<CheckBox Name="ExposureAutoCheckBox" Content="Auto" Checked="ExposureCheckBox_CheckedChanged" Unchecked="ExposureCheckBox_CheckedChanged"/>

Verifique se o dispositivo de captura atual oferece suporte ao ExposureControl verificando a propriedade Supported. Se o controle for suportado, você poderá mostrar e habilitar a interface do usuário para esse recurso. Defina o estado marcado da caixa de seleção para indicar se o ajuste automático de exposição está ativo no momento para o valor da propriedade Auto.

O valor de exposição deve estar dentro do intervalo suportado pelo dispositivo e deve ser um incremento do tamanho da etapa suportada. Saiba quais são os valores suportados para o dispositivo atual conferindo as propriedades Min, Max e Step, que são usadas para definir as propriedades correspondentes do controle deslizante.

Defina o valor do controle deslizante para o valor atual de ExposureControl após cancelar o manipulador de evento ValueChanged para que o evento não seja acionado quando o valor for definido.

var exposureControl = _mediaCapture.VideoDeviceController.ExposureControl;

if (exposureControl.Supported)
{
    ExposureAutoCheckBox.Visibility = Visibility.Visible;
    ExposureSlider.Visibility = Visibility.Visible;

    ExposureAutoCheckBox.IsChecked = exposureControl.Auto;

    ExposureSlider.Minimum = exposureControl.Min.Ticks;
    ExposureSlider.Maximum = exposureControl.Max.Ticks;
    ExposureSlider.StepFrequency = exposureControl.Step.Ticks;

    ExposureSlider.ValueChanged -= ExposureSlider_ValueChanged;
    var value = exposureControl.Value;
    ExposureSlider.Value = value.Ticks;
    ExposureSlider.ValueChanged += ExposureSlider_ValueChanged;
}
else
{
    ExposureAutoCheckBox.Visibility = Visibility.Collapsed;
    ExposureSlider.Visibility = Visibility.Collapsed;
}

No manipulador de evento ValueChanged, obtenha o valor atual do controle e defina o valor de exposição chamando SetValueAsync.

private async void ExposureSlider_ValueChanged(object sender, Windows.UI.Xaml.Controls.Primitives.RangeBaseValueChangedEventArgs e)
{
    var value = TimeSpan.FromTicks((long)(sender as Slider).Value);
    await _mediaCapture.VideoDeviceController.ExposureControl.SetValueAsync(value);
}

No manipulador de evento CheckedChanged da caixa de verificação da exposição automática, ative ou desative o ajuste automático de exposição chamando SetAutoAsync e passando um valor booleano.

private async void ExposureCheckBox_CheckedChanged(object sender, RoutedEventArgs e)
{
    if(! _isPreviewing)
    {
        // Auto exposure only supported while preview stream is running.
        return;
    }

    var autoExposure = ((sender as CheckBox).IsChecked == true);
    await _mediaCapture.VideoDeviceController.ExposureControl.SetAutoAsync(autoExposure);
}

Importante

O modo de exposição automática só é suportado enquanto o fluxo de visualização estiver em execução. Verifique se o fluxo de visualização está em execução antes de ativar a exposição automática.

Compensação da exposição

O ExposureCompensationControl permite que você defina a compensação de exposição usada durante a captura de fotos ou vídeos.

Este exemplo usa um controle deslizante para ajustar o valor de compensação de exposição atual.

<Slider Name="EvSlider" ValueChanged="EvSlider_ValueChanged"/>
<TextBlock Text="{Binding ElementName=EvSlider,Path=Value}" Name="EvTextBlock"/>

Confira se o dispositivo de captura atual é compatível com ExposureControl verificando a propriedade Supported. Se o controle for suportado, você poderá mostrar e habilitar a interface do usuário para esse recurso.

O valor da compensação de exposição deve estar dentro do intervalo suportado pelo dispositivo e deve ser um incremento do tamanho da etapa suportada. Saiba quais são os valores suportados para o dispositivo atual conferindo as propriedades Min, Max e Step, que são usadas para definir as propriedades correspondentes do controle deslizante.

Defina o valor do controle deslizante como o valor atual do ExposureCompensationControl depois de cancelar o registro do manipulador de evento ValueChanged para que o evento não seja acionado quando o valor for definido.

var exposureCompensationControl = _mediaCapture.VideoDeviceController.ExposureCompensationControl;

if (exposureCompensationControl.Supported)
{
    EvSlider.Visibility = Visibility.Visible;
    EvSlider.Minimum = exposureCompensationControl.Min;
    EvSlider.Maximum = exposureCompensationControl.Max;
    EvSlider.StepFrequency = exposureCompensationControl.Step;

    EvSlider.ValueChanged -= EvSlider_ValueChanged;
    EvSlider.Value = exposureCompensationControl.Value;
    EvSlider.ValueChanged += EvSlider_ValueChanged;
}
else
{
    EvSlider.Visibility = Visibility.Collapsed;
}

No manipulador de evento ValueChanged, obtenha o valor atual do controle e defina o valor de exposição chamando SetValueAsync.

private async void EvSlider_ValueChanged(object sender, Windows.UI.Xaml.Controls.Primitives.RangeBaseValueChangedEventArgs e)
{
    var value = (sender as Slider).Value;
    await _mediaCapture.VideoDeviceController.ExposureCompensationControl.SetValueAsync((float)value);
}

Piscando

O FlashControl permite que você habilite ou desative o flash ou ative o flash automático, onde o sistema determina dinamicamente se deseja usar o flash. Esse controle também permite que você habilite a redução automática de olhos vermelhos em dispositivos compatíveis com esse recurso. Todas essas configurações se aplicam à captura de fotos. O TorchControl é um controle separado para ligar ou desligar a tocha para captura de vídeo.

Este exemplo usa um conjunto de botões de opção para permitir que o usuário alterne entre as configurações de ativação, desativação e flash automático. Uma caixa de seleção também é fornecida para permitir a alternância da redução de olhos vermelhos e da tocha de vídeo.

<RadioButton Name="FlashOnRadioButton" Content="On" Checked="FlashOnRadioButton_Checked"/>
<RadioButton Name="FlashAutoRadioButton" Content="Auto" Checked="FlashAutoRadioButton_Checked"/>
<RadioButton Name="FlashOffRadioButton" Content="Off" Checked="FlashOffRadioButton_Checked"/>
<CheckBox Name="RedEyeFlashCheckBox" Content="Red Eye" Visibility="Collapsed" Checked="RedEyeFlashCheckBox_CheckedChanged" Unchecked="RedEyeFlashCheckBox_CheckedChanged"/>
<CheckBox Name="TorchCheckBox" Content="Video Light" Visibility="Collapsed" Checked="TorchCheckBox_CheckedChanged" Unchecked="TorchCheckBox_CheckedChanged"/>

Verifique se o dispositivo de captura atual oferece suporte ao FlashControl verificando a propriedade Supported. Se o controle for suportado, você poderá mostrar e habilitar a interface do usuário para esse recurso. Se o FlashControl for suportado, a redução automática de olhos vermelhos pode ou não ser suportada, portanto, verifique a propriedade RedEyeReductionSupported antes de ativar a interface do usuário. Como o TorchControl é separado do controle flash, você também deve verificar sua propriedade Supported antes de usá-lo.

No manipulador de eventos Checked para cada um dos botões de opção do flash, habilite ou desabilite a configuração de flash correspondente apropriada. Para definir o flash para ser usado sempre, você deve definir a propriedade Enabled como true e a propriedade Auto como false.

var flashControl = _mediaCapture.VideoDeviceController.FlashControl;

if (flashControl.Supported)
{
    FlashAutoRadioButton.Visibility = Visibility.Visible;
    FlashOnRadioButton.Visibility = Visibility.Visible;
    FlashOffRadioButton.Visibility = Visibility.Visible;

    FlashAutoRadioButton.IsChecked = true;

    if (flashControl.RedEyeReductionSupported)
    {
        RedEyeFlashCheckBox.Visibility = Visibility.Visible;
    }

    // Video light is not strictly part of flash, but users might expect to find it there
    if (_mediaCapture.VideoDeviceController.TorchControl.Supported)
    {
        TorchCheckBox.Visibility = Visibility.Visible;
    }
}
else
{
    FlashAutoRadioButton.Visibility = Visibility.Collapsed;
    FlashOnRadioButton.Visibility = Visibility.Collapsed;
    FlashOffRadioButton.Visibility = Visibility.Collapsed;
}
private void FlashOnRadioButton_Checked(object sender, RoutedEventArgs e)
{
    _mediaCapture.VideoDeviceController.FlashControl.Enabled = true;
    _mediaCapture.VideoDeviceController.FlashControl.Auto = false;
}

private void FlashAutoRadioButton_Checked(object sender, RoutedEventArgs e)
{
    _mediaCapture.VideoDeviceController.FlashControl.Enabled = true;
    _mediaCapture.VideoDeviceController.FlashControl.Auto = true;
}

private void FlashOffRadioButton_Checked(object sender, RoutedEventArgs e)
{
    _mediaCapture.VideoDeviceController.FlashControl.Enabled = false;
}

No manipulador da caixa de seleção de redução de olhos vermelhos, defina a propriedade RedEyeReduction com o valor apropriado.

private void RedEyeFlashCheckBox_CheckedChanged(object sender, RoutedEventArgs e)
{
    _mediaCapture.VideoDeviceController.FlashControl.RedEyeReduction = (RedEyeFlashCheckBox.IsChecked == true);
}

Finalmente, na caixa de seleção do manipulador da tocha de vídeo, defina a propriedade Enabled como o valor apropriado.

private void TorchCheckBox_CheckedChanged(object sender, RoutedEventArgs e)
{
    _mediaCapture.VideoDeviceController.TorchControl.Enabled = (TorchCheckBox.IsChecked == true);

    if(! (_isPreviewing && _isRecording))
    {
        System.Diagnostics.Debug.WriteLine("Torch may not emit light if preview and video capture are not running.");
    }
}

Observação

Em alguns dispositivos, a tocha não emitirá luz, mesmo se TorchControl.Enabled estiver definido como true, a menos que o dispositivo tenha um fluxo de visualização em execução e esteja capturando vídeo ativamente. A ordem recomendada de operações é ativar a visualização de vídeo, ligar a tocha definindo Enabled como true e, em seguida, iniciar a captura de vídeo. Em alguns dispositivos, a tocha acenderá após o início da visualização. Em outros dispositivos, a tocha pode não acender até que a captura de vídeo seja iniciada.

Foco

Três métodos diferentes comumente usados para ajustar o foco da câmera são compatíveis com o objeto FocusControl: foco automático contínuo, toque para focar e foco manual. Um aplicativo de câmera pode oferecer suporte a todos esses três métodos, mas para facilitar a leitura, este artigo discute cada técnica separadamente. Esta seção também discute como ativar a luz de assistência de foco.

Foco automático contínuo

Ativar o foco automático contínuo instrui a câmera a ajustar o foco dinamicamente para tentar manter o assunto da foto ou vídeo em foco. Este exemplo usa um botão de opção para ativar e desativar o foco automático contínuo.

<RadioButton Content="CAF" Name="CafFocusRadioButton" Checked="CafFocusRadioButton_Checked"/>

Verifique se o dispositivo de captura atual oferece suporte ao FocusControl verificando a propriedade Supported. Em seguida, determine se o foco automático contínuo é suportado verificando a lista SupportedFocusModes para ver se ela contém o valor FocusMode.Continuous e, em caso afirmativo, mostre o botão de opção de foco automático contínuo.

var focusControl = _mediaCapture.VideoDeviceController.FocusControl;

if (focusControl.Supported)
{
    CafFocusRadioButton.Visibility = focusControl.SupportedFocusModes.Contains(FocusMode.Continuous) 
        ? Visibility.Visible : Visibility.Collapsed;
}
else
{
    CafFocusRadioButton.Visibility = Visibility.Collapsed;
}

No manipulador de evento Checked para o botão de opção de foco automático contínuo, use a propriedade VideoDeviceController.FocusControl para obter uma instância do controle. Chame UnlockAsync para desbloquear o controle caso seu aplicativo tenha chamado LockAsync para habilitar um dos outros modos de foco.

Crie um objeto FocusSettings e defina a propriedade Mode como Continuous. Defina a propriedade AutoFocusRange como um valor apropriado para o cenário do aplicativo ou selecionado pelo usuário na interface do usuário. Passe o objeto FocusSettings para o método Configure e chame FocusAsync para iniciar o foco automático contínuo.

private async void CafFocusRadioButton_Checked(object sender, RoutedEventArgs e)
{
    if(! _isPreviewing)
    {
        // Autofocus only supported while preview stream is running.
        return;
    }

    var focusControl = _mediaCapture.VideoDeviceController.FocusControl;
    await focusControl.UnlockAsync();
    var settings = new FocusSettings { Mode = FocusMode.Continuous, AutoFocusRange = AutoFocusRange.FullRange };
    focusControl.Configure(settings);
    await focusControl.FocusAsync();
}

Importante

O modo de foco automático só é suportado enquanto o fluxo de visualização está em execução. Verifique se o fluxo de visualização está em execução antes de ativar o foco automático contínuo.

Toque para focar

A técnica de tocar para focar usa o FocusControl e o RegionsOfInterestControl para especificar uma sub-região do quadro de captura onde o dispositivo de captura deve se concentrar. A região de foco é determinada pelo toque do usuário na tela que exibe o fluxo de visualização.

Este exemplo usa um botão de opção para habilitar e desabilitar o modo de toque para focar.

<RadioButton Content="Tap" Name="TapFocusRadioButton" Checked="TapFocusRadioButton_Checked"/>

Verifique se o dispositivo de captura atual oferece suporte ao FocusControl verificando a propriedade Supported. O RegionsOfInterestControl deve ser suportado, e deve suportar pelo menos uma região, a fim de usar esta técnica. Verifique as propriedades AutoFocusSupported e MaxRegions para determinar se o botão de opção deve ser exibido ou ocultado para tocar para focar.

var focusControl = _mediaCapture.VideoDeviceController.FocusControl;

if (focusControl.Supported)
{
    TapFocusRadioButton.Visibility = (_mediaCapture.VideoDeviceController.RegionsOfInterestControl.AutoFocusSupported &&
                                      _mediaCapture.VideoDeviceController.RegionsOfInterestControl.MaxRegions > 0) 
                                      ? Visibility.Visible : Visibility.Collapsed;
}
else
{
    TapFocusRadioButton.Visibility = Visibility.Collapsed;
}

No manipulador de evento Checked para o botão de rádio de tocar para focar, use a propriedade VideoDeviceController.FocusControl para obter uma instância do controle. Chame LockAsync para bloquear o controle caso seu aplicativo tenha chamado UnlockAsync para habilitar o foco automático contínuo e, em seguida, aguarde até que o usuário toque na tela para alterar o foco.

private async void TapFocusRadioButton_Checked(object sender, RoutedEventArgs e)
{
    // Lock focus in case Continuous Autofocus was active when switching to Tap-to-focus
    var focusControl = _mediaCapture.VideoDeviceController.FocusControl;
    await focusControl.LockAsync();
    // Wait for user tap
}

Este exemplo se concentra em uma região quando o usuário toca na tela e, em seguida, remove o foco dessa região quando o usuário toca novamente, como uma alternância. Use uma variável booleana para controlar o estado alternado atual.

bool _isFocused = false;

A próxima etapa é escutar o evento quando o usuário toca na tela manipulando o evento Tapped do CaptureElement que está exibindo o fluxo de visualização da captura no momento. Se a câmera não estiver visualizando no momento ou se o modo de toque para focar estiver desativado, retorne do manipulador sem fazer nada.

Se a variável de rastreamento _isFocused for alternada para false, e se a câmera não estiver atualmente no processo de foco (determinado pela propriedade FocusState do FocusControl), inicie o processo de tocar para focar. Obtenha a posição do toque do usuário a partir dos args de eventos passados para o manipulador. Este exemplo também usa essa oportunidade para escolher o tamanho da região que será focada. Nesse caso, o tamanho é 1/4 da menor dimensão do elemento de captura. Passe a posição de toque e o tamanho da região para o método auxiliar TapToFocus definido na próxima seção.

Se a alternância _isFocused estiver definida como true, o toque do usuário deverá limpar o foco da região anterior. Isso é feito no método auxiliar TapUnfocus mostrado abaixo.

private async void PreviewControl_Tapped(object sender, TappedRoutedEventArgs e)
{
    if (!_isPreviewing || (TapFocusRadioButton.IsChecked != true)) return;

    if (!_isFocused && _mediaCapture.VideoDeviceController.FocusControl.FocusState != MediaCaptureFocusState.Searching)
    {
        var smallEdge = Math.Min(Window.Current.Bounds.Width, Window.Current.Bounds.Height);

        // Choose to make the focus rectangle 1/4th the length of the shortest edge of the window
        var size = new Size(smallEdge / 4, smallEdge / 4);
        var position = e.GetPosition(sender as UIElement);

        // Note that at this point, a rect at "position" with size "size" could extend beyond the preview area. The following method will reposition the rect if that is the case
        await TapToFocus(position, size);
    }
    else
    {
        await TapUnfocus();
    }
}

No método auxiliar TapToFocus, primeiro defina a alternância _isFocused como true para que o próximo toque na tela libere o foco da região tocada.

A próxima tarefa neste método auxiliar é determinar o retângulo dentro do fluxo de visualização que será atribuído ao controle de foco. Isso requer duas etapas. A primeira etapa é determinar o retângulo que o fluxo de visualização ocupa dentro do controle CaptureElement. Isso depende das dimensões do fluxo de visualização e da orientação do dispositivo. O método auxiliar GetPreviewStreamRectInControl, mostrado no fim desta seção, executa essa tarefa e retorna o retângulo que contém o fluxo de visualização.

A próxima tarefa no TapToFocus é converter o local de toque e o tamanho do retângulo de foco desejado, que foram determinados no manipulador de eventos CaptureElement.Tapped em coordenadas dentro do fluxo de captura. O método auxiliar ConvertUiTapToPreviewRect, mostrado posteriormente nesta seção, executa essa conversão e retorna o retângulo, em coordenadas de fluxo de captura, onde o foco será solicitado.

Agora que o retângulo de destino foi obtido, crie um objeto RegionOfInterest definindo a propriedade Bounds para o retângulo de destino obtido nas etapas anteriores.

Obtenha o FocusControl do dispositivo de captura. Crie um objeto FocusSettings e defina o Mode e o AutoFocusRange para os valores desejados depois de verificar se eles são suportados pelo FocusControl. Chame Configure no FocusControl para ativar suas configurações e sinalizar o dispositivo para começar a se concentrar na região especificada.

Em seguida, obtenha o RegionsOfInterestControl do dispositivo de captura e chame SetRegionsAsync para definir a região ativa. Várias regiões de interesse podem ser definidas em dispositivos que oferecem suporte a ele, mas este exemplo define apenas uma única região.

Finalmente, chame FocusAsync no FocusControl para iniciar o foco.

Importante

Ao implementar o toque para focar, a ordem das operações é importante. Você deve chamar essas APIs na seguinte ordem:

  1. FocusControl.Configure
  2. RegionsOfInterestControl.SetRegionsAsync
  3. FocusControl.FocusAsync
public async Task TapToFocus(Point position, Size size)
{
    _isFocused = true;

    var previewRect = GetPreviewStreamRectInControl();
    var focusPreview = ConvertUiTapToPreviewRect(position, size, previewRect);

    // Note that this Region Of Interest could be configured to also calculate exposure 
    // and white balance within the region
    var regionOfInterest = new RegionOfInterest
    {
        AutoFocusEnabled = true,
        BoundsNormalized = true,
        Bounds = focusPreview,
        Type = RegionOfInterestType.Unknown,
        Weight = 100,
    };


    var focusControl = _mediaCapture.VideoDeviceController.FocusControl;
    var focusRange = focusControl.SupportedFocusRanges.Contains(AutoFocusRange.FullRange) ? AutoFocusRange.FullRange : focusControl.SupportedFocusRanges.FirstOrDefault();
    var focusMode = focusControl.SupportedFocusModes.Contains(FocusMode.Single) ? FocusMode.Single : focusControl.SupportedFocusModes.FirstOrDefault();
    var settings = new FocusSettings { Mode = focusMode, AutoFocusRange = focusRange };
    focusControl.Configure(settings);

    var roiControl = _mediaCapture.VideoDeviceController.RegionsOfInterestControl;
    await roiControl.SetRegionsAsync(new[] { regionOfInterest }, true);

    await focusControl.FocusAsync();
}

No método auxiliar TapUnfocus, obtenha o RegionsOfInterestControl e chame ClearRegionsAsync para limpar a região que foi registrada com o controle dentro do método auxiliar TapToFocus. Em seguida, obtenha o FocusControl e chame FocusAsync para fazer com que o dispositivo refoque sem uma região de interesse.

private async Task TapUnfocus()
{
    _isFocused = false;

    var roiControl = _mediaCapture.VideoDeviceController.RegionsOfInterestControl;
    await roiControl.ClearRegionsAsync();

    var focusControl = _mediaCapture.VideoDeviceController.FocusControl;
    await focusControl.FocusAsync();
}

O método auxiliar GetPreviewStreamRectInControl usa a resolução do fluxo de visualização e a orientação do dispositivo para determinar o retângulo dentro do elemento de visualização que contém o fluxo de visualização, cortando qualquer preenchimento letterbox que o controle possa fornecer para manter a proporção do fluxo. Esse método usa variáveis de membro de classe definidas no código de exemplo de captura de mídia básico encontrado em Captura básica de foto, vídeo e áudio com MediaCapture.

public Rect GetPreviewStreamRectInControl()
{
    var result = new Rect();

    var previewResolution = _mediaCapture.VideoDeviceController.GetMediaStreamProperties(MediaStreamType.VideoPreview) as VideoEncodingProperties;

    // In case this function is called before everything is initialized correctly, return an empty result
    if (PreviewControl == null || PreviewControl.ActualHeight < 1 || PreviewControl.ActualWidth < 1 ||
        previewResolution == null || previewResolution.Height == 0 || previewResolution.Width == 0)
    {
        return result;
    }

    var streamWidth = previewResolution.Width;
    var streamHeight = previewResolution.Height;

    // For portrait orientations, the width and height need to be swapped
    if (_displayOrientation == DisplayOrientations.Portrait || _displayOrientation == DisplayOrientations.PortraitFlipped)
    {
        streamWidth = previewResolution.Height;
        streamHeight = previewResolution.Width;
    }

    // Start by assuming the preview display area in the control spans the entire width and height both (this is corrected in the next if for the necessary dimension)
    result.Width = PreviewControl.ActualWidth;
    result.Height = PreviewControl.ActualHeight;

    // If UI is "wider" than preview, letterboxing will be on the sides
    if ((PreviewControl.ActualWidth / PreviewControl.ActualHeight > streamWidth / (double)streamHeight))
    {
        var scale = PreviewControl.ActualHeight / streamHeight;
        var scaledWidth = streamWidth * scale;

        result.X = (PreviewControl.ActualWidth - scaledWidth) / 2.0;
        result.Width = scaledWidth;
    }
    else // Preview stream is "wider" than UI, so letterboxing will be on the top+bottom
    {
        var scale = PreviewControl.ActualWidth / streamWidth;
        var scaledHeight = streamHeight * scale;

        result.Y = (PreviewControl.ActualHeight - scaledHeight) / 2.0;
        result.Height = scaledHeight;
    }

    return result;
}

O método auxiliar ConvertUiTapToPreviewRect usa como argumentos o local do evento tap, o tamanho desejado da região de foco e o retângulo que contém o fluxo de visualização obtido do método auxiliar GetPreviewStreamRectInControl. Esse método usa esses valores e a orientação atual do dispositivo para calcular o retângulo dentro do fluxo de visualização que contém a região desejada. Novamente, esse método usa variáveis de membro de classe definidas no código de exemplo de captura de mídia básico encontrado em Capturar fotos e vídeos com MediaCapture.

private Rect ConvertUiTapToPreviewRect(Point tap, Size size, Rect previewRect)
{
    // Adjust for the resulting focus rectangle to be centered around the position
    double left = tap.X - size.Width / 2, top = tap.Y - size.Height / 2;

    // Get the information about the active preview area within the CaptureElement (in case it's letterboxed)
    double previewWidth = previewRect.Width, previewHeight = previewRect.Height;
    double previewLeft = previewRect.Left, previewTop = previewRect.Top;

    // Transform the left and top of the tap to account for rotation
    switch (_displayOrientation)
    {
        case DisplayOrientations.Portrait:
            var tempLeft = left;

            left = top;
            top = previewRect.Width - tempLeft;
            break;
        case DisplayOrientations.LandscapeFlipped:
            left = previewRect.Width - left;
            top = previewRect.Height - top;
            break;
        case DisplayOrientations.PortraitFlipped:
            var tempTop = top;

            top = left;
            left = previewRect.Width - tempTop;
            break;
    }

    // For portrait orientations, the information about the active preview area needs to be rotated
    if (_displayOrientation == DisplayOrientations.Portrait || _displayOrientation == DisplayOrientations.PortraitFlipped)
    {
        previewWidth = previewRect.Height;
        previewHeight = previewRect.Width;
        previewLeft = previewRect.Top;
        previewTop = previewRect.Left;
    }

    // Normalize width and height of the focus rectangle
    var width = size.Width / previewWidth;
    var height = size.Height / previewHeight;

    // Shift rect left and top to be relative to just the active preview area
    left -= previewLeft;
    top -= previewTop;

    // Normalize left and top
    left /= previewWidth;
    top /= previewHeight;

    // Ensure rectangle is fully contained within the active preview area horizontally
    left = Math.Max(left, 0);
    left = Math.Min(1 - width, left);

    // Ensure rectangle is fully contained within the active preview area vertically
    top = Math.Max(top, 0);
    top = Math.Min(1 - height, top);

    // Create and return resulting rectangle
    return new Rect(left, top, width, height);
}

Foco manual

A técnica de foco manual usa um controle deslizante para definir a profundidade de foco atual do dispositivo de captura. Um botão de opção é usado para ativar e desativar o foco manual.

<Slider Name="FocusSlider" IsEnabled="{Binding ElementName=ManualFocusRadioButton,Path=IsChecked}" ValueChanged="FocusSlider_ValueChanged"/>
<TextBlock Text="{Binding ElementName=FocusSlider,Path=Value,FallbackValue='0'}"/>
<RadioButton Content="Manual" Name="ManualFocusRadioButton" Checked="ManualFocusRadioButton_Checked" IsChecked="False"/>

Verifique se o dispositivo de captura atual oferece suporte ao FocusControl verificando a propriedade Supported. Se o controle for suportado, você poderá mostrar e habilitar a interface do usuário para esse recurso.

O foco deve estar dentro do intervalo suportado pelo dispositivo e deve ser um incremento do tamanho da etapa suportada. Saiba quais são os valores suportados para o dispositivo atual conferindo as propriedades Min, Max e Step, que são usadas para definir as propriedades correspondentes do controle deslizante.

Defina o valor do controle deslizante como o valor atual do FocusControl depois de cancelar o registro do manipulador de evento ValueChanged para que o evento não seja acionado quando o valor for definido.

var focusControl = _mediaCapture.VideoDeviceController.FocusControl;

if (focusControl.Supported)
{
    FocusSlider.Visibility = Visibility.Visible;
    ManualFocusRadioButton.Visibility = Visibility.Visible;

    FocusSlider.Minimum = focusControl.Min;
    FocusSlider.Maximum = focusControl.Max;
    FocusSlider.StepFrequency = focusControl.Step;
    

    FocusSlider.ValueChanged -= FocusSlider_ValueChanged;
    FocusSlider.Value = focusControl.Value;
    FocusSlider.ValueChanged += FocusSlider_ValueChanged;
}
else
{
    FocusSlider.Visibility = Visibility.Collapsed;
    ManualFocusRadioButton.Visibility = Visibility.Collapsed;
}

No manipulador de eventos Checked para o botão de opção de foco manual, obtenha o objeto FocusControl e chame LockAsync caso seu aplicativo tenha desbloqueado o foco anteriormente com uma chamada para UnlockAsync.

private async void ManualFocusRadioButton_Checked(object sender, RoutedEventArgs e)
{
    var focusControl = _mediaCapture.VideoDeviceController.FocusControl;
    await focusControl.LockAsync();
}

No manipulador de eventos ValueChanged do controle deslizante de foco manual, obtenha o valor atual do controle e defina o valor de foco chamando SetValueAsync.

private async void FocusSlider_ValueChanged(object sender, Windows.UI.Xaml.Controls.Primitives.RangeBaseValueChangedEventArgs e)
{
    var value = (sender as Slider).Value;
    await _mediaCapture.VideoDeviceController.FocusControl.SetValueAsync((uint)value);
}

Ativar a luz de foco

Em dispositivos que o suportem, você pode ativar uma luz de assistência de foco para ajudar o dispositivo a focar. Este exemplo usa uma caixa de seleção para habilitar ou desabilitar a luz de assistência de foco.

<CheckBox Content="Assist Light" Name="FocusLightCheckBox" IsEnabled="{Binding ElementName=TapFocusRadioButton,Path=IsChecked}"
                  Checked="FocusLightCheckBox_CheckedChanged" Unchecked="FocusLightCheckBox_CheckedChanged"/>

Verifique se o dispositivo de captura atual oferece suporte ao FlashControl verificando a propriedade Supported. Verifique também o AssistantLightSupported para se certificar de que a luz de assistência também é suportada. Se ambos forem compatíveis, você poderá mostrar e habilitar a interface do usuário para esse recurso.

var focusControl = _mediaCapture.VideoDeviceController.FocusControl;

if (focusControl.Supported)
{

    FocusLightCheckBox.Visibility = (_mediaCapture.VideoDeviceController.FlashControl.Supported &&
                                     _mediaCapture.VideoDeviceController.FlashControl.AssistantLightSupported) ? Visibility.Visible : Visibility.Collapsed;
}
else
{
    FocusLightCheckBox.Visibility = Visibility.Collapsed;
}

No manipulador de eventos CheckedChanged, obtenha o objeto FlashControl dos dispositivos de captura. Defina a propriedade AssistantLightEnabled para habilitar ou desabilitar a luz de foco.

private void FocusLightCheckBox_CheckedChanged(object sender, RoutedEventArgs e)
{
    var flashControl = _mediaCapture.VideoDeviceController.FlashControl;

    flashControl.AssistantLightEnabled = (FocusLightCheckBox.IsChecked == true);
}

Velocidade da ISO

O IsoSpeedControl permite que você defina a velocidade ISO usada durante a captura de fotos ou vídeos.

Este exemplo usa um controle deslizante para ajustar o valor da compensação da exposição atual e uma caixa de seleção para alternar o ajuste automático do ISO.

<Slider Name="IsoSlider" ValueChanged="IsoSlider_ValueChanged"/>
<TextBlock Text="{Binding ElementName=IsoSlider,Path=Value}" Visibility="{Binding ElementName=IsoSlider,Path=Visibility}"/>
<CheckBox Name="IsoAutoCheckBox" Content="Auto" Checked="IsoAutoCheckBox_CheckedChanged" Unchecked="IsoAutoCheckBox_CheckedChanged"/>

Verifique se o dispositivo de captura atual é compatível com IsoSpeedControl verificando a propriedade Supported. Se o controle for suportado, você poderá mostrar e habilitar a interface do usuário para esse recurso. Defina o estado marcado da caixa de seleção para indicar se o ajuste automático do ISO está ativo no momento para o valor da propriedade Auto.

O valor da velocidade do ISO deve estar dentro do intervalo suportado pelo dispositivo e deve ser um incremento do tamanho da etapa suportada. Saiba quais são os valores suportados para o dispositivo atual conferindo as propriedades Min, Max e Step, que são usadas para definir as propriedades correspondentes do controle deslizante.

Defina o valor do controle deslizante como o valor atual do IsoSpeedControl depois de cancelar o registro do manipulador de evento ValueChanged para que o evento não seja acionado quando o valor for definido.

private void UpdateIsoControlCapabilities()
{
    var isoSpeedControl = _mediaCapture.VideoDeviceController.IsoSpeedControl;

    if (isoSpeedControl.Supported)
    {
        IsoAutoCheckBox.Visibility = Visibility.Visible;
        IsoSlider.Visibility = Visibility.Visible;

        IsoAutoCheckBox.IsChecked = isoSpeedControl.Auto;
        
        IsoSlider.Minimum = isoSpeedControl.Min;
        IsoSlider.Maximum = isoSpeedControl.Max;
        IsoSlider.StepFrequency = isoSpeedControl.Step;

        IsoSlider.ValueChanged -= IsoSlider_ValueChanged;
        IsoSlider.Value = isoSpeedControl.Value;
        IsoSlider.ValueChanged += IsoSlider_ValueChanged;
    }
    else
    {
        IsoAutoCheckBox.Visibility = Visibility.Collapsed;
        IsoSlider.Visibility = Visibility.Collapsed;
    }
}

No manipulador de evento ValueChanged, obtenha o valor atual do controle e defina o valor da velocidade do ISO chamando SetValueAsync.

private async void IsoSlider_ValueChanged(object sender, Windows.UI.Xaml.Controls.Primitives.RangeBaseValueChangedEventArgs e)
{
    var value = (sender as Slider).Value;
    await _mediaCapture.VideoDeviceController.IsoSpeedControl.SetValueAsync((uint)value);
}

Na caixa de seleção do manipulador de eventos CheckedChanged da velocidade do ISO automático, ative o ajuste automático de velocidade ISO chamando SetAutoAsync. Desative o ajuste automático de velocidade ISO chamando SetValueAsync e passando o valor atual do controle deslizante.

private async void IsoAutoCheckBox_CheckedChanged(object sender, RoutedEventArgs e)
{
    var autoIso = (sender as CheckBox).IsChecked == true;

    if (autoIso)
    {
        await _mediaCapture.VideoDeviceController.IsoSpeedControl.SetAutoAsync();
    }
    else
    {
        await _mediaCapture.VideoDeviceController.IsoSpeedControl.SetValueAsync((uint)IsoSlider.Value);
    }
}

Estabilização óptica de imagem

A estabilização óptica de imagem (OIS) estabiliza um fluxo de vídeo capturado manipulando mecanicamente o dispositivo de captura de hardware, o que pode fornecer um resultado superior à estabilização digital. Em dispositivos que não dão suporte ao OIS, você pode usar o VideoStabilizationEffect para executar a estabilização digital no vídeo capturado. Para mais informações, consulte Efeitos para captura de vídeo.

Determine se o OIS é suportado no dispositivo atual verificando a propriedade OpticalImageStabilizationControl.Supported.

O controle OIS é compatível com três modos: ativado, desativado e automático, o que significa que o dispositivo determina dinamicamente se o OIS melhoraria a captura de mídia e, em caso afirmativo, habilita o OIS. Para determinar se um modo específico é suportado em um dispositivo, verifique se a coleção OpticalImageStabilizationControl.SupportedModes contém o modo desejado.

Habilite ou desabilite o OIS definindo o OpticalImageStabilizationControl.Mode para o modo desejado.

private void SetOpticalImageStabilizationMode(OpticalImageStabilizationMode mode)
{
    if (!_mediaCapture.VideoDeviceController.OpticalImageStabilizationControl.Supported)
    {
        ShowMessageToUser("Optical image stabilization not available");
        return;
    }

    var stabilizationModes = _mediaCapture.VideoDeviceController.OpticalImageStabilizationControl.SupportedModes;

    if (!stabilizationModes.Contains(mode))
    {
        ShowMessageToUser("Optical image stabilization setting not supported");
        return;
    }

    _mediaCapture.VideoDeviceController.OpticalImageStabilizationControl.Mode = mode;
}

Frequência Powerline

Alguns dispositivos de câmera suportam processamento anticintilação, que depende de saber a frequência CA das linhas de energia no ambiente atual. Alguns dispositivos suportam a determinação automática da frequência da linha elétrica, enquanto outros exigem que a frequência seja ajustada manualmente. O exemplo de código a seguir mostra como determinar o suporte à frequência da linha elétrica no dispositivo e, se necessário, como definir a frequência manualmente.

Primeiro, chame o método VideoDeviceController TryGetPowerlineFrequency, passando um parâmetro de saída do tipo PowerlineFrequency. Se essa chamada falhar, o controle de frequência da linha elétrica não será suportado no dispositivo atual. Se o recurso for suportado, você poderá determinar se o modo automático está disponível no dispositivo tentando definir o modo automático. Faça isso chamando TrySetPowerlineFrequency e passando o valor Auto. Se a chamada for bem-sucedida, isso significa que a frequência da linha elétrica automática é suportada. Se o controlador de frequência da linha elétrica for suportado no dispositivo, mas a detecção automática de frequência não for, você ainda poderá definir manualmente a frequência usando TrySetPowerlineFrequency. Neste exemplo, MyCustomFrequencyLookup é um método personalizado que você implementa para determinar a frequência correta para o local atual do dispositivo.

 PowerlineFrequency getFrequency;

 if (! _mediaCapture.VideoDeviceController.TryGetPowerlineFrequency(out getFrequency))
 {
     // Powerline frequency is not supported on this device.
     return;
 }

 if (! _mediaCapture.VideoDeviceController.TrySetPowerlineFrequency(PowerlineFrequency.Auto))
 {
     // Set the frequency manually
     PowerlineFrequency setFrequency = MyCustomFrequencyLookup();
     if (_mediaCapture.VideoDeviceController.TrySetPowerlineFrequency(setFrequency))
     {
         System.Diagnostics.Debug.WriteLine(String.Format("Powerline frequency manually set to {0}.", setFrequency));
     }
 }

Balanço de branco

O WhiteBalanceControl permite que você defina o balanço de branco usado durante a captura de foto ou vídeo.

Este exemplo usa um controle ComboBox para selecionar entre predefinições internas de temperatura de cor e um controle Slider para ajuste manual de balanço de branco.

<Slider Name="WbSlider" ValueChanged="WbSlider_ValueChanged"/>
<TextBlock Name="WbTextBox" Text="{Binding ElementName=WbSlider,Path=Value}" Visibility="{Binding ElementName=WbSlider,Path=Visibility}"/>
<ComboBox Name="WbComboBox" SelectionChanged="WbComboBox_SelectionChanged"/>

Verifique se o dispositivo de captura atual é compatível com WhiteBalanceControl verificando a propriedade Supported. Se o controle for suportado, você poderá mostrar e habilitar a interface do usuário para esse recurso. Defina os itens da caixa de combinação para os valores da enumeração ColorTemperaturePreset. Defina o item selecionado como o valor atual da propriedade Preset.

Para controle manual, o valor do balanço de branco deve estar dentro do intervalo suportado pelo dispositivo e deve ser um incremento do tamanho da etapa suportada. Saiba quais são os valores suportados para o dispositivo atual conferindo as propriedades Min, Max e Step, que são usadas para definir as propriedades correspondentes do controle deslizante. Antes de ativar o controle manual, verifique se o intervalo entre os valores mínimo e máximo suportados é maior do que o tamanho da etapa. Se não for, o controle manual não será suportado no dispositivo atual.

Defina o valor do controle deslizante como o valor atual do WhiteBalanceControl depois de cancelar o registro do manipulador de evento ValueChanged para que o evento não seja acionado quando o valor for definido.

           var whiteBalanceControl = _mediaCapture.VideoDeviceController.WhiteBalanceControl;

           if (whiteBalanceControl.Supported)
           {
               WbSlider.Visibility = Visibility.Visible;
               WbComboBox.Visibility = Visibility.Visible;

               if (WbComboBox.ItemsSource == null)
               {
                   WbComboBox.ItemsSource = Enum.GetValues(typeof(ColorTemperaturePreset)).Cast<ColorTemperaturePreset>();
               }

               WbComboBox.SelectedItem = whiteBalanceControl.Preset;

               if (whiteBalanceControl.Max - whiteBalanceControl.Min > whiteBalanceControl.Step)
               {

                   WbSlider.Minimum = whiteBalanceControl.Min;
                   WbSlider.Maximum = whiteBalanceControl.Max;
                   WbSlider.StepFrequency = whiteBalanceControl.Step;

                   WbSlider.ValueChanged -= WbSlider_ValueChanged;
                   WbSlider.Value = whiteBalanceControl.Value;
                   WbSlider.ValueChanged += WbSlider_ValueChanged;
               }
               else
               {
                   WbSlider.Visibility = Visibility.Collapsed;
               }
           }
           else
           {
               WbSlider.Visibility = Visibility.Collapsed;
               WbComboBox.Visibility = Visibility.Collapsed;
           }

No manipulador de eventos SelectionChanged da caixa de combinação predefinição de temperatura de cor, obtenha a predefinição selecionada atualmente e defina o valor do controle chamando SetPresetAsync. Se o valor predefinido selecionado não for Manual, desative o controle deslizante do balanço de branco manual.

private async void WbComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if(!_isPreviewing)
    {
        // Do not set white balance values unless the preview stream is running.
        return;
    }

    var selected = (ColorTemperaturePreset)WbComboBox.SelectedItem;
    WbSlider.IsEnabled = (selected == ColorTemperaturePreset.Manual);
    await _mediaCapture.VideoDeviceController.WhiteBalanceControl.SetPresetAsync(selected);

}

No manipulador de evento ValueChanged, obtenha o valor atual do controle e defina o valor do balanço de branco chamando SetValueAsync.

private async void WbSlider_ValueChanged(object sender, Windows.UI.Xaml.Controls.Primitives.RangeBaseValueChangedEventArgs e)
{
    if (!_isPreviewing)
    {
        // Do not set white balance values unless the preview stream is running.
        return;
    }

    var value = (sender as Slider).Value;
    await _mediaCapture.VideoDeviceController.WhiteBalanceControl.SetValueAsync((uint)value);
}

Importante

O ajuste do balanço de branco só é suportado enquanto o fluxo de visualização estiver em execução. Verifique se o fluxo de visualização está em execução antes de definir o valor de balanço de branco ou a predefinição.

Importante

O valor predefinido ColorTemperaturePreset.Auto instrui o sistema a ajustar automaticamente o nível de balanço de branco. Para alguns cenários, como capturar uma sequência de fotos em que os níveis de balanço de branco devem ser os mesmos para cada foto, convém bloquear o controle para o valor automático atual. Para fazer isso, chame SetPresetAsync, especifique a predefinição Manual e não defina um valor no controle usando SetValueAsync. Isso fará com que o dispositivo bloqueie o valor atual. Não tente ler o valor de controle atual e logo depois passar o valor retornado para SetValueAsync porque não há garantia de que esse valor estará correto.

Zoom

O ZoomControl permite que você defina o nível de zoom usado durante a captura de foto ou vídeo.

Este exemplo usa um controle deslizante para ajustar o nível de zoom atual. A seção a seguir mostra como ajustar o zoom com base em um gesto de pinça na tela.

<Slider Name="ZoomSlider" Grid.Row="0" Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Stretch" ValueChanged="ZoomSlider_ValueChanged"/>
<TextBlock Grid.Row="1" HorizontalAlignment="Center" Text="{Binding ElementName=ZoomSlider,Path=Value}"/>

Confira se o dispositivo de captura atual é compatível com ZoomControl verificando a propriedade Supported. Se o controle for suportado, você poderá mostrar e habilitar a interface do usuário para esse recurso.

O valor do nível de zoom deve estar dentro do intervalo suportado pelo dispositivo e deve ser um incremento do tamanho da etapa suportada. Saiba quais são os valores suportados para o dispositivo atual conferindo as propriedades Min, Max e Step, que são usadas para definir as propriedades correspondentes do controle deslizante.

Defina o valor do controle deslizante como o valor atual do ZoomControl depois de cancelar o registro do manipulador de evento ValueChanged para que o evento não seja acionado quando o valor for definido.

var zoomControl = _mediaCapture.VideoDeviceController.ZoomControl;

if (zoomControl.Supported)
{
    ZoomSlider.Visibility = Visibility.Visible;

    ZoomSlider.Minimum = zoomControl.Min;
    ZoomSlider.Maximum = zoomControl.Max;
    ZoomSlider.StepFrequency = zoomControl.Step;
    
    ZoomSlider.ValueChanged -= ZoomSlider_ValueChanged;
    ZoomSlider.Value = zoomControl.Value;
    ZoomSlider.ValueChanged += ZoomSlider_ValueChanged;
}
else
{
    ZoomSlider.Visibility = Visibility.Collapsed;
}

No manipulador de eventos ValueChanged, crie uma instância da classe ZoomSettings, definindo a propriedade Value como o valor atual do controle deslizante de zoom. Se a propriedade SupportedModes do ZoomControl contiver ZoomTransitionMode.Smooth, significa que o dispositivo oferece suporte a transições suaves entre níveis de zoom. Como esse modo fornece uma melhor experiência do usuário, você normalmente vai querer usar esse valor para a propriedade Mode no objeto ZoomSettings.

Altere as configurações de zoom atuais passando o objeto ZoomSettings para o método Configure do objeto ZoomControl.

private void ZoomSlider_ValueChanged(object sender, Windows.UI.Xaml.Controls.Primitives.RangeBaseValueChangedEventArgs e)
{
    var level = (float)ZoomSlider.Value;
    var settings = new ZoomSettings { Value = level };

    var zoomControl = _mediaCapture.VideoDeviceController.ZoomControl;
    if (zoomControl.SupportedModes.Contains(ZoomTransitionMode.Smooth))
    {
        settings.Mode = ZoomTransitionMode.Smooth;
    }
    else
    {
        settings.Mode = zoomControl.SupportedModes.First();
    }

    zoomControl.Configure(settings);
}

Zoom suave usando o gesto de pinça

Como discutido na seção anterior, em dispositivos compatíveis, o modo de zoom suave permite que o dispositivo de captura faça uma transição suave entre os níveis de zoom digital, permitindo que o usuário ajuste dinamicamente o nível de zoom durante a operação de captura sem transições discretas e ruidosas. Esta seção descreve como ajustar o nível de zoom em resposta a um gesto de pinça.

Primeiro, determine se o controle de zoom digital é suportado no dispositivo atual verificando a propriedade ZoomControl.Supported. Em seguida, determine se o modo de zoom suave está disponível verificando o ZoomControl.SupportedModes para ver se ele contém o valor ZoomTransitionMode.Smooth.

private bool IsSmoothZoomSupported()
{
    if (!_mediaCapture.VideoDeviceController.ZoomControl.Supported)
    {
        ShowMessageToUser("Digital zoom is not supported on this device.");
        return false;
    }

    var zoomModes = _mediaCapture.VideoDeviceController.ZoomControl.SupportedModes;

    if (!zoomModes.Contains(ZoomTransitionMode.Smooth))
    {
        ShowMessageToUser("Smooth zoom not supported");
        return false;
    }

    return true;
}

Em um dispositivo habilitado para multitoque, um cenário comum é ajustar o fator de zoom com base em um gesto de pinça com dois dedos. Defina a propriedade ManipulationMode do controle CaptureElement como ManipulationModes.Scale para habilitar o gesto de pinçar. Em seguida, registre para o evento ManipulationDelta, que é gerado quando o gesto de pinça muda de tamanho.

private void RegisterPinchGestureHandler()
{
    if (!IsSmoothZoomSupported())
    {
        return;
    }

    // Enable pinch/zoom gesture for the preview control
    PreviewControl.ManipulationMode = ManipulationModes.Scale;
    PreviewControl.ManipulationDelta += PreviewControl_ManipulationDelta;
}

No manipulador do evento ManipulationDelta, atualize o fator de zoom com base na alteração no gesto de pinça do usuário. O valor ManipulationDelta.Scale representa a mudança na escala do gesto de pinça de tal forma que um pequeno aumento no tamanho da pinça é um número ligeiramente maior que 1,0 e uma pequena diminuição no tamanho da pinça é um número ligeiramente menor que 1.0. Neste exemplo, o valor atual do controle de zoom é multiplicado pelo delta da escala.

Antes de definir o fator de zoom, certifique-se de que o valor não é menor do que o valor mínimo suportado pelo dispositivo, conforme indicado pela propriedade ZoomControl.Min. Além disso, verifique se o valor é menor ou igual ao valor ZoomControl.Max. Finalmente, você deve se certificar de que o fator de zoom é um múltiplo do tamanho da etapa de zoom suportado pelo dispositivo, conforme indicado pela propriedade Step. Se o fator de zoom não atender a esses requisitos, uma exceção será lançada quando você tentar definir o nível de zoom no dispositivo de captura.

Defina o nível de zoom no dispositivo de captura criando um objeto ZoomSettings. Defina a propriedade Mode como ZoomTransitionMode.Smooth e, em seguida, defina a propriedade Value como o fator de zoom desejado. Chame ZoomControl.Configure para definir o novo valor de zoom no dispositivo. O dispositivo fará uma transição suave para o novo valor de zoom.

private void PreviewControl_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
    var zoomControl = _mediaCapture.VideoDeviceController.ZoomControl;

    // Example zoom factor calculation based on size of scale gesture
    var zoomFactor = zoomControl.Value * e.Delta.Scale;

    if (zoomFactor < zoomControl.Min) zoomFactor = zoomControl.Min;
    if (zoomFactor > zoomControl.Max) zoomFactor = zoomControl.Max;
    zoomFactor = zoomFactor - (zoomFactor % zoomControl.Step);

    var settings = new ZoomSettings();
    settings.Mode = ZoomTransitionMode.Smooth;
    settings.Value = zoomFactor;

    _mediaCapture.VideoDeviceController.ZoomControl.Configure(settings);

}