Contrôles d’appareil photo manuel pour la capture photo et vidéo
Cet article vous montre comment utiliser les commandes manuelles de l’appareil pour activer des scénarios de capture de photos et de vidéos améliorés, notamment la stabilisation optique de l’image et le zoom fluide.
Les commandes dont il est question dans cet article sont toutes ajoutées à votre application en suivant le même modèle. Tout d’abord, vérifiez si la commande est prise en charge par l’appareil sur lequel s’exécute votre application. Si c’est le cas, définissez le mode souhaité pour la commande. En règle générale, si un contrôle particulier n’est pas pris en charge sur l’appareil actuel, vous devez désactiver ou masquer l’élément de l’interface utilisateur qui permet à l’utilisateur d’activer la fonctionnalité.
Le code de cet article a été adapté à partir de l’exemple Camera Manual Controls SDK. Vous pouvez télécharger l’exemple pour voir le code utilisé dans son contexte ou pour utiliser l’exemple comme point de départ pour votre propre application.
Remarque
Cet article repose sur les concepts et le code décrits dans Capture photo, vidéo et audio de base à l’aide de MediaCapture, qui décrit comment implémenter la capture photo et vidéo de base. Nous vous recommandons de vous familiariser avec le modèle de capture simple de contenu multimédia de cet article avant d’adopter des scénarios de capture plus avancés. Le code de cet article suppose que votre application a déjà une instance de MediaCapture qui a été correctement initialisée.
Toutes les API de contrôle d’appareil abordées dans cet article sont membres de l’espace de noms Windows.Media.Devices.
using Windows.Media.Devices;
Exposition
La commande ExposureControl vous permet de définir la vitesse d’obturation utilisée lors de la capture d’une photo ou d’une vidéo.
Cet exemple utilise un curseur pour ajuster la valeur d’exposition actuelle et une case à cocher pour activer l’ajustement automatique de l’exposition.
<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"/>
Vérifiez si l’appareil de capture actuel prend en charge l’ExposureControl en contrôlant la propriété Supported. Si le contrôle est pris en charge, vous pouvez afficher et activer l’interface utilisateur pour cette fonctionnalité. Définissez l’état de la case à cocher indiquant si l’ajustement automatique de l’exposition est actuellement actif sur la valeur de la propriété Auto.
La valeur d’exposition doit se situer dans la plage prise en charge par l’appareil et doit être un incrément de la taille de pas prise en charge. Obtenez les valeurs prises en charge pour l’appareil actuel en vérifiant les propriétés Min, Max et Step, qui sont utilisées pour définir les propriétés correspondantes de la commande du curseur.
Définissez la valeur du contrôle du curseur sur la valeur actuelle de l’ExposureControl après avoir désenregistré le gestionnaire d’événement ValueChanged afin que l’événement ne soit pas déclenché lors de la définition de la valeur.
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;
}
Dans le gestionnaire de l’événement ValueChanged, récupérez la valeur actuelle du contrôle et définissez la valeur d’exposition en appelant 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);
}
Dans le gestionnaire d’événement CheckedChanged de la case à cocher Exposition automatique, activez ou désactivez le réglage automatique de l’exposition en appelant SetAutoAsync et en transmettant une valeur booléenne.
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);
}
Important
Le mode d’exposition automatique n’est pris en charge que lorsque le flux de préversion est en cours d’exécution. Vérifiez que le flux de préversion est en cours d’exécution avant d’activer l’exposition automatique.
Compensation de l’exposition
La commande ExposureCompensationControl vous permet de définir la correction d’exposition utilisée lors de la capture d’une photo ou d’une vidéo.
Cet exemple utilise un curseur pour ajuster la valeur actuelle de la compensation d’exposition.
<Slider Name="EvSlider" ValueChanged="EvSlider_ValueChanged"/>
<TextBlock Text="{Binding ElementName=EvSlider,Path=Value}" Name="EvTextBlock"/>
Vérifiez que l’appareil de capture actuel prend en charge la commande ExposureCompensationControl en contrôlant la propriété Supported. Si le contrôle est pris en charge, vous pouvez afficher et activer l’interface utilisateur pour cette fonctionnalité.
La valeur de compensation de l’exposition doit se situer dans la plage prise en charge par l’appareil et doit être un incrément de la taille de pas prise en charge. Obtenez les valeurs prises en charge par l’appareil actuel en vérifiant les propriétés Min, Max et Step, qui sont utilisées pour définir les propriétés correspondantes de la commande de curseur.
Définissez la valeur du contrôle du curseur sur la valeur actuelle de l’ExposureCompensationControl après avoir désenregistré le gestionnaire de l’événement ValueChanged afin que l’événement ne soit pas déclenché lors de la définition de la valeur.
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;
}
Dans le gestionnaire de l’événement ValueChanged, récupérez la valeur actuelle du contrôle, puis définissez la valeur d’exposition en appelant 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);
}
Flash
Le contrôle Flash vous permet d’activer ou de désactiver le flash ou d’activer le flash automatique, c’est-à-dire que le système détermine dynamiquement s’il faut utiliser le flash. Cette commande vous permet également d’activer la réduction automatique des yeux rouges sur les appareils qui la prennent en charge. Ces paramètres s’appliquent tous à la prise de photos. La commande TorchControl est une commande distincte qui permet d’activer ou de désactiver la torche pour la capture vidéo.
Cet exemple utilise un ensemble de boutons radio pour permettre à l’utilisateur de basculer entre les paramètres d’activation, de désactivation et de flash automatique. Une case à cocher permet également de basculer entre la réduction des yeux rouges et la torche vidéo.
<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"/>
Vérifiez si l’appareil de capture actuel prend en charge le FlashControl en contrôlant la propriété Supported. Si le contrôle est pris en charge, vous pouvez afficher et activer l’interface utilisateur pour cette fonctionnalité. Si le FlashControl est pris en charge, l’atténuation automatique des yeux rouges peut ou non être prise en charge. Vérifiez donc la propriété RedEyeReductionSupported avant d’activer l’interface utilisateur. Le contrôle Torch étant distinct du contrôle Flash, vous devez également vérifier sa propriété Supported avant de l’utiliser.
Dans le gestionnaire d’événement Checked de chaque bouton radio flash, activez ou désactivez le paramètre flash correspondant. Notez que pour que le flash soit toujours utilisé, vous devez attribuer la valeur true à la propriété Enabled et la valeur false à la propriété Auto.
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;
}
Dans le gestionnaire de la case à cocher Réduction des yeux rouges, attribuez la valeur appropriée à la propriété RedEyeReduction.
private void RedEyeFlashCheckBox_CheckedChanged(object sender, RoutedEventArgs e)
{
_mediaCapture.VideoDeviceController.FlashControl.RedEyeReduction = (RedEyeFlashCheckBox.IsChecked == true);
}
Enfin, dans le gestionnaire de la case à cocher de la torche vidéo, attribuez la valeur appropriée à la propriété Enabled.
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.");
}
}
Remarque
Sur certains appareils, la torche n’émettra pas de lumière, même si TorchControl.Enabled est défini sur true, à moins que l’appareil ne dispose d’un flux de préversion en cours d’exécution et qu’il capture activement de la vidéo. L’ordre des opérations recommandé est d’activer la préversion vidéo, d’allumer la torche en réglant Enabled sur true, puis de lancer la capture vidéo. Sur certains appareils, la torche s’allume après le démarrage de la préversion. Sur d’autres appareils, la torche peut ne pas s’allumer tant que la capture vidéo n’est pas lancée.
Focus
L’objet FocusControl prend en charge trois méthodes différentes couramment utilisées pour régler la mise au point de l’appareil photo : la mise au point automatique continue, appuyer pour faire la mise au point et la mise au point manuelle. Une application de caméra peut prendre en charge ces trois méthodes, mais par souci de lisibilité, cet article aborde chaque technique séparément. Cette section explique également comment activer la lumière d’assistance à la mise au point.
Mise au point automatique continue
L’activation de l’autofocus continu permet à l’appareil photo d’ajuster la mise au point de manière dynamique pour tenter de conserver la mise au point sur le sujet de la photo ou de la vidéo. Cet exemple utilise un bouton radio pour activer ou désactiver l’autofocus continu.
<RadioButton Content="CAF" Name="CafFocusRadioButton" Checked="CafFocusRadioButton_Checked"/>
Vérifiez que l’appareil de capture actuel prend en charge le FocusControl en contrôlant la propriété Supported. Ensuite, déterminez si l’autofocus continu est pris en charge en vérifiant la liste SupportedFocusModes pour voir si elle contient la valeur FocusMode.Continuous, et si c’est le cas, affichez la case d’option autofocus continu.
var focusControl = _mediaCapture.VideoDeviceController.FocusControl;
if (focusControl.Supported)
{
CafFocusRadioButton.Visibility = focusControl.SupportedFocusModes.Contains(FocusMode.Continuous)
? Visibility.Visible : Visibility.Collapsed;
}
else
{
CafFocusRadioButton.Visibility = Visibility.Collapsed;
}
Dans le gestionnaire d’événement Checked pour la case d’option autofocus continu, utilisez la propriété VideoDeviceController.FocusControl pour obtenir une instance du contrôle. Appelez UnlockAsync pour déverrouiller le contrôle au cas où votre application aurait précédemment appelé LockAsync pour activer l’un des autres modes de mise au point.
Créez un nouvel objet FocusSettings et définissez la propriété Mode sur Continuous. Attribuez à la propriété AutoFocusRange une valeur adaptée au scénario de votre application ou sélectionnée par l’utilisateur à partir de votre interface utilisateur. Passez votre objet FocusSettings dans la méthode Configure, puis appelez FocusAsync pour lancer l’autofocus continu.
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();
}
Important
Le mode autofocus n’est pris en charge que lorsque le flux de préversion est en cours d’exécution. Vérifiez que le flux de préversion est en cours d’exécution avant d’activer l’autofocus continu.
Appuyer pour faire la mise au point
La technique « appuyer pour faire la mise au point » utilise les commandes FocusControl et RegionsOfInterestControl pour spécifier une sous-région de la trame de capture sur laquelle l’appareil de capture doit faire la mise au point. La région de mise au point est déterminée par l’utilisateur qui appuie sur l’écran affichant le flux de préversion.
Cet exemple utilise un bouton radio pour activer et désactiver le mode « appuyer pour mettre au point ».
<RadioButton Content="Tap" Name="TapFocusRadioButton" Checked="TapFocusRadioButton_Checked"/>
Vérifiez que l’appareil de capture actuel prend en charge le FocusControl en contrôlant la propriété Supported. Le contrôle RegionsOfInterest doit être pris en charge, et doit prendre en charge au moins une région, afin d’utiliser cette technique. Vérifiez les propriétés AutoFocusSupported et MaxRegions pour déterminer s’il faut afficher ou masquer le bouton radio pour appuyer sur la touche de mise au point.
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;
}
Dans le gestionnaire de l’événement Vérifié pour le bouton radio permettant d’appuyer pour faire la mise au point, utilisez la propriété VideoDeviceController.FocusControl pour obtenir une instance du contrôle. Appelez LockAsync pour verrouiller le contrôle au cas où votre application aurait précédemment appelé UnlockAsync pour activer la mise au point automatique continue, puis attendez que l’utilisateur appuie sur l’écran pour modifier la mise au point.
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
}
Cet exemple met l’accent sur une région lorsque l’utilisateur appuie sur l’écran, puis retire l’accent de cette région lorsque l’utilisateur appuie à nouveau sur l’écran, comme une bascule. Utilisez une variable booléenne pour suivre l’état actuel du basculement.
bool _isFocused = false;
L’étape suivante consiste à écouter l’événement lorsque l’utilisateur touche l’écran en gérant l’événement Tapped de l’élément CaptureElement qui affiche actuellement le flux de préversion de la capture. Si la caméra n’est pas en cours de préversion, ou si le mode « appuyer pour faire la mise au point » est désactivé, revenez du gestionnaire sans rien faire.
Si la variable de suivi _isFocused prend la valeur false et si la caméra n’est pas en cours de mise au point (déterminée par la propriété FocusState du FocusControl), commencez le processus de mise au point par tapotement. Obtenez la position de l’appui de l’utilisateur à partir des arguments de l’événement transmis au gestionnaire. Cet exemple profite également de l’occasion pour choisir la taille de la région sur laquelle la mise au point sera effectuée. Dans ce cas, la taille est égale à 1/4 de la plus petite dimension de l’élément de capture. Transmettez la position de l’appui et la taille de la région à la méthode d’aide TapToFocus définie dans la section suivante.
Si la bascule _isFocused est définie sur true, l’appui de l’utilisateur doit effacer le focus de la région précédente. C’est ce que fait la méthode d’aide TapUnfocus présentée ci-dessous.
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();
}
}
Dans la méthode d’aide TapToFocus, réglez d’abord la bascule _isFocused sur true afin que le prochain tapotement de l’écran libère le focus de la région appuyée.
La tâche suivante dans cette méthode d’aide consiste à déterminer le rectangle dans le flux de préversion qui sera assigné au contrôle de mise au point. Pour ce faire, deux étapes sont nécessaires. La première consiste à déterminer le rectangle que le flux de préversion occupe dans le contrôle CaptureElement. Cela dépend des dimensions du flux de préversion et de l’orientation de l’appareil. La méthode d’aide GetPreviewStreamRectInControl, présentée à la fin de cette section, exécute cette tâche et renvoie le rectangle contenant le flux de préversion.
La tâche suivante dans TapToFocus consiste à convertir l’emplacement de l’appui et la taille du rectangle de mise au point souhaitée, qui ont été déterminés dans le gestionnaire d’événement CaptureElement.Tapped, en coordonnées à l’intérieur du flux de capture. La méthode d’aide ConvertUiTapToPreviewRect, présentée plus loin dans cette section, effectue cette conversion et renvoie le rectangle, en coordonnées de flux de capture, où la mise au point sera demandée.
Maintenant que le rectangle cible a été obtenu, créez un nouvel objet RegionOfInterest, en définissant la propriété Bounds sur le rectangle cible obtenu dans les étapes précédentes.
Obtenez la commande FocusControl de l’appareil de capture. Créez un nouvel objet FocusSettings et définissez le Mode et l’AutoFocusRange aux valeurs souhaitées, après avoir vérifié qu’ils sont pris en charge par la FocusControl. Appelez Configure sur la FocusControl pour activer vos paramètres et signaler à l’appareil de commencer la mise au point sur la région spécifiée.
Ensuite, récupérez le RegionsOfInterestControl de l’appareil de capture et appelez SetRegionsAsync pour définir la région active. Plusieurs régions d’intérêt peuvent être définies sur les appareils qui le prennent en charge, mais cet exemple ne définit qu’une seule région.
Enfin, appelez FocusAsync sur le FocusControl pour lancer la mise au point.
Important
Lors de la mise en œuvre de l’action d’appuyer sur pour effectuer la mise au point, l’ordre des opérations est important. Vous devez appeler ces API dans l’ordre suivant :
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();
}
Dans la méthode d’aide TapUnfocus, obtenez le RegionsOfInterestControl et appelez ClearRegionsAsync pour effacer la région qui a été enregistrée avec le contrôle dans la méthode d’aide TapToFocus. Ensuite, obtenez le FocusControl et appelez FocusAsync pour que l’appareil refasse la mise au point sans région d’intérêt.
private async Task TapUnfocus()
{
_isFocused = false;
var roiControl = _mediaCapture.VideoDeviceController.RegionsOfInterestControl;
await roiControl.ClearRegionsAsync();
var focusControl = _mediaCapture.VideoDeviceController.FocusControl;
await focusControl.FocusAsync();
}
La méthode d’aide GetPreviewStreamRectInControl utilise la résolution du flux de prévisualisation et l’orientation de l’appareil pour déterminer le rectangle dans l’élément de prévisualisation qui contient le flux de prévisualisation, en éliminant tout remplissage letterboxed que le contrôle peut fournir pour maintenir le rapport hauteur/largeur du flux. Cette méthode utilise les variables membres de la classe définies dans l’exemple de code de capture de média de base qui se trouve dans Capture de base de photos, de vidéos et d’audio avec 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;
}
La méthode d’aide ConvertUiTapToPreviewRect prend comme arguments l’emplacement de l’événement d’appui, la taille souhaitée de la zone de mise au point et le rectangle contenant le flux de préversion obtenu à partir de la méthode d’aide GetPreviewStreamRectInControl. Cette méthode utilise ces valeurs et l’orientation actuelle de l’appareil pour calculer le rectangle dans le flux de préversion qui contient la région souhaitée. Une fois de plus, cette méthode utilise les variables membres de la classe définies dans l’exemple de code de capture de média de base que vous trouverez dans Capturez des photos et des vidéos avec 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);
}
Mise au point manuelle
La technique de mise au point manuelle utilise un curseur pour définir la profondeur de mise au point actuelle de l’appareil de capture. Un bouton radio permet d’activer ou de désactiver la mise au point manuelle.
<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"/>
Vérifiez que l’appareil de capture actuel prend en charge le FocusControl en contrôlant la propriété Supported. Si le contrôle est pris en charge, vous pouvez afficher et activer l’interface utilisateur pour cette fonctionnalité.
La valeur de mise au point doit se situer dans la plage prise en charge par l’appareil et doit être un incrément de la taille de pas prise en charge. Obtenez les valeurs prises en charge par l’appareil actuel en vérifiant les propriétés Min, Max et Step, qui sont utilisées pour définir les propriétés correspondantes du contrôle du curseur.
Définissez la valeur du contrôle du curseur sur la valeur actuelle du FocusControl après avoir désenregistré le gestionnaire d’événement ValueChanged afin que l’événement ne soit pas déclenché lorsque la valeur est définie.
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;
}
Dans le gestionnaire d’événement Checked pour le bouton radio de mise au point manuelle, récupérez l’objet FocusControl et appelez LockAsync au cas où votre application aurait précédemment déverrouillé la mise au point avec un appel à UnlockAsync.
private async void ManualFocusRadioButton_Checked(object sender, RoutedEventArgs e)
{
var focusControl = _mediaCapture.VideoDeviceController.FocusControl;
await focusControl.LockAsync();
}
Dans le gestionnaire d’événement ValueChanged du curseur à focalisation manuelle, récupérez la valeur actuelle du contrôle et définissez la valeur de focalisation en appelant 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);
}
Activez la lumière de mise au point
Sur les appareils qui le prennent en charge, vous pouvez activer une lumière de mise au point pour aider l’appareil à se mettre au point. Cet exemple utilise une case à cocher pour activer ou désactiver la lumière de mise au point.
<CheckBox Content="Assist Light" Name="FocusLightCheckBox" IsEnabled="{Binding ElementName=TapFocusRadioButton,Path=IsChecked}"
Checked="FocusLightCheckBox_CheckedChanged" Unchecked="FocusLightCheckBox_CheckedChanged"/>
Vérifiez que l’appareil de capture actuel prend en charge le FlashControl en contrôlant la propriété Supported. Vérifiez également la propriété AssistantLightSupported pour vous assurer que la lumière d’assistance est également prise en charge. Si ces deux éléments sont pris en charge, vous pouvez afficher et activer l’interface utilisateur pour cette fonctionnalité.
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;
}
Dans le gestionnaire de l’événement CheckedChanged, récupérez l’objet FlashControl des appareils de capture. Définissez la propriété AssistantLightEnabled pour activer ou désactiver la lumière de mise au point.
private void FocusLightCheckBox_CheckedChanged(object sender, RoutedEventArgs e)
{
var flashControl = _mediaCapture.VideoDeviceController.FlashControl;
flashControl.AssistantLightEnabled = (FocusLightCheckBox.IsChecked == true);
}
Vitesse ISO
Le contrôle IsoSpeedControl vous permet de définir la vitesse ISO utilisée lors de la capture d’une photo ou d’une vidéo.
Cet exemple utilise un curseur pour ajuster la valeur de compensation d’exposition actuelle et une case à cocher pour activer l’ajustement automatique de la vitesse 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"/>
Vérifiez que l’appareil de capture actuel prend en charge la commande IsoSpeedControl en contrôlant la propriété Supported. Si le contrôle est pris en charge, vous pouvez afficher et activer l’interface utilisateur pour cette fonctionnalité. Définissez l’état de la case à cocher indiquant si l’ajustement automatique de la vitesse ISO est actuellement actif sur la valeur de la propriété Auto.
La valeur de la vitesse ISO doit se situer dans la plage prise en charge par l’appareil et doit être un incrément de la taille de pas prise en charge. Obtenez les valeurs prises en charge pour l’appareil actuel en vérifiant les propriétés Min, Max et Step, qui sont utilisées pour définir les propriétés correspondantes du contrôle du curseur.
Définissez la valeur du contrôle du curseur à la valeur actuelle de l’IsoSpeedControl après avoir désenregistré le gestionnaire d’événement ValueChanged afin que l’événement ne soit pas déclenché lors de la définition de la valeur.
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;
}
}
Dans le gestionnaire d’événement ValueChanged, récupérez la valeur actuelle du contrôle et définissez la valeur de la vitesse ISO en appelant 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);
}
Dans le gestionnaire d’événement CheckedChanged de la case à cocher Vitesse ISO automatique, activez l’ajustement automatique de la vitesse ISO en appelant SetAutoAsync. Désactivez l’ajustement automatique de la vitesse ISO en appelant SetValueAsync et en transmettant la valeur actuelle du curseur.
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);
}
}
Stabilisation optique de l’image
La stabilisation optique de l’image (OIS) stabilise un flux vidéo capturé en manipulant mécaniquement l’appareil de capture matériel, ce qui peut donner un résultat supérieur à la stabilisation numérique. Sur les appareils qui ne prennent pas en charge OIS, vous pouvez utiliser VideoStabilizationEffect pour effectuer une stabilisation numérique sur votre vidéo capturée. Pour plus d’informations, voir Effets pour la capture vidéo.
Déterminez si l’OIS est pris en charge sur l’appareil actuel en vérifiant la propriété OpticalImageStabilizationControl.Supported.
Le contrôle OIS prend en charge trois modes : activé, désactivé et automatique, ce qui signifie que l’appareil détermine dynamiquement si l’OIS améliorerait la capture du média et, le cas échéant, active l’OIS. Pour déterminer si un mode particulier est pris en charge sur un appareil, vérifiez si la collection OpticalImageStabilizationControl.SupportedModes contient le mode souhaité.
Activez ou désactivez l’OIS en définissant OpticalImageStabilizationControl.Mode sur le mode souhaité.
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;
}
Fréquence des courants porteurs
Certains appareils photo prennent en charge le traitement anti-scintillement qui dépend de la connaissance de la fréquence CA des lignes électriques dans l’environnement actuel. Certains appareils prennent en charge la détermination automatique de la fréquence des lignes électriques, tandis que d’autres exigent que la fréquence soit définie manuellement. L’exemple de code suivant montre comment déterminer la prise en charge de la fréquence des lignes électriques sur l’appareil et, si nécessaire, comment définir la fréquence manuellement.
Commencez par appeler la méthode TryGetPowerlineFrequency du VideoDeviceController, en lui transmettant un paramètre de sortie de type PowerlineFrequency ; si cet appel échoue, cela signifie que le contrôle de la fréquence des courants porteurs n’est pas pris en charge sur l’appareil actuel. Si la fonctionnalité est prise en charge, vous pouvez déterminer si le mode automatique est disponible sur l’appareil en essayant de définir le mode automatique. Pour ce faire, appelez TrySetPowerlineFrequency et transmettez la valeur Auto. Si l’appel aboutit, cela signifie que votre fréquence CPL automatique est prise en charge. Si le contrôleur de fréquence CPL est pris en charge sur l’appareil mais que la détection automatique de la fréquence ne l’est pas, vous pouvez toujours définir manuellement la fréquence en utilisant TrySetPowerlineFrequency. Dans cet exemple, MyCustomFrequencyLookup est une méthode personnalisée que vous mettez en œuvre pour déterminer la fréquence correcte pour l’emplacement actuel de l’appareil.
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));
}
}
Balance des blancs
Le contrôle WhiteBalanceControl vous permet de définir la balance des blancs utilisée lors de la capture d’une photo ou d’une vidéo.
Cet exemple utilise un contrôle ComboBox pour sélectionner les préréglages de température de couleur intégrés et un contrôle Slider pour le réglage manuel de la balance des blancs.
<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"/>
Vérifiez si l’appareil de capture actuel prend en charge le WhiteBalanceControl en contrôlant la propriété Supported. Si le contrôle est pris en charge, vous pouvez afficher et activer l’interface utilisateur pour cette fonctionnalité. Définissez les éléments de la liste déroulante sur les valeurs de l’énumération ColorTemperaturePreset. Et définissez l’élément sélectionné sur la valeur actuelle de la propriété Preset.
Pour le contrôle manuel, la valeur de la balance des blancs doit se situer dans la plage prise en charge par l’appareil et correspondre à un incrément de la taille de pas prise en charge. Obtenez les valeurs prises en charge pour l’appareil actuel en vérifiant les propriétés Min, Max et Step, qui sont utilisées pour définir les propriétés correspondantes du contrôle par curseur. Avant d’activer le contrôle manuel, vérifiez que la plage entre les valeurs minimale et maximale prises en charge est supérieure à la taille du pas. Si ce n’est pas le cas, le contrôle manuel n’est pas pris en charge sur l’appareil actuel.
Définissez la valeur du contrôle du curseur sur la valeur actuelle du WhiteBalanceControl après avoir désenregistré le gestionnaire d’événements ValueChanged afin que l’événement ne soit pas déclenché lorsque la valeur est définie.
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;
}
Dans le gestionnaire d’événement SelectionChanged de la liste déroulante de préréglage de la température de couleur, récupérez le préréglage actuellement sélectionné et définissez la valeur du contrôle en appelant SetPresetAsync. Si la valeur de préréglage sélectionnée n’est pas Manuel, désactivez le curseur de balance des blancs manuelle.
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);
}
Dans le gestionnaire de l’événement ValueChanged, récupérez la valeur actuelle du contrôle et définissez la valeur de la balance des blancs en appelant 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);
}
Important
L’ajustement de la balance des blancs n’est possible que lorsque le flux de préversion est en cours d’exécution. Vérifiez que le flux de préversion est en cours d’exécution avant de définir la valeur ou le préréglage de la balance des blancs.
Important
La valeur de préréglage ColorTemperaturePreset.Auto indique au système d’ajuster automatiquement le niveau de la balance des blancs. Pour certains scénarios, tels que la capture d’une séquence de photos où les niveaux de balance des blancs doivent être les mêmes pour chaque trame, vous pouvez souhaiter verrouiller la commande sur la valeur automatique actuelle. Pour ce faire, appelez SetPresetAsync et spécifiez le préréglage Manuel et ne définissez pas de valeur sur la commande à l’aide de SetValueAsync. L’appareil bloquera alors la valeur actuelle. N’essayez pas de lire la valeur actuelle du contrôle et de passer la valeur retournée dans SetValueAsync parce que cette valeur n’est pas garantie d’être correcte.
Zoom
Le ZoomControl vous permet de définir le niveau de zoom utilisé lors de la capture d’une photo ou d’une vidéo.
Cet exemple utilise un contrôle de type curseur pour ajuster le niveau de zoom actuel. La section suivante montre comment ajuster le zoom en fonction d’un geste de pincement sur l’écran.
<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}"/>
Vérifiez que l’appareil de capture actuel prend en charge le ZoomControl en contrôlant la propriété Supported. Si le contrôle est pris en charge, vous pouvez afficher et activer l’interface utilisateur pour cette fonctionnalité.
La valeur du niveau de zoom doit se situer dans la plage prise en charge par l’appareil et doit être un incrément de la taille de pas prise en charge. Obtenez les valeurs prises en charge pour l’appareil actuel en vérifiant les propriétés Min, Max et Step, qui sont utilisées pour définir les propriétés correspondantes du contrôle de curseur.
Définissez la valeur du contrôle du curseur sur la valeur actuelle du ZoomControl après avoir désenregistré le gestionnaire d’événement ValueChanged afin que l’événement ne soit pas déclenché lors de la définition de la valeur.
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;
}
Dans le gestionnaire de l’événement ValueChanged, créez une nouvelle instance de la classe ZoomSettings, en fixant la propriété Value à la valeur actuelle du contrôle ZoomControl. Si la propriété SupportedModes du ZoomControl contient ZoomTransitionMode.Smooth, cela signifie que l’appareil prend en charge les transitions douces entre les niveaux de zoom. Comme ce mode offre une meilleure expérience à l’utilisateur, vous voudrez généralement utiliser cette valeur pour la propriété Mode de l’objet ZoomSettings.
Enfin, modifiez les paramètres de zoom actuels en passant votre objet ZoomSettings dans la méthode Configure de l’objet 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 progressif à l’aide d’un geste de pincement
Comme nous l’avons vu dans la section précédente, sur les appareils qui le prennent en charge, le mode zoom lisse permet à l’appareil de capture d’effectuer une transition fluide entre les niveaux de zoom numérique, ce qui permet à l’utilisateur d’ajuster dynamiquement le niveau de zoom au cours de l’opération de capture sans transitions discrètes et brutales. Cette section décrit comment ajuster le niveau de zoom en réponse à un geste de pincement.
Tout d’abord, déterminez si la commande de zoom numérique est prise en charge sur l’appareil actuel en vérifiant la propriété ZoomControl.Supported. Ensuite, déterminez si le mode de zoom lisse est disponible en vérifiant la propriété ZoomControl.SupportedModes pour voir si elle contient la valeur 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;
}
Sur un appareil doté de la technologie multi-touch, un scénario typique consiste à ajuster le facteur de zoom en fonction d’un geste de pincement à deux doigts. Définissez la propriété ManipulationMode du contrôle CaptureElement sur ManipulationModes.Scale pour activer le geste de pincement. Ensuite, enregistrez-vous pour l’événement ManipulationDelta qui est déclenché lorsque le geste de pincement change de taille.
private void RegisterPinchGestureHandler()
{
if (!IsSmoothZoomSupported())
{
return;
}
// Enable pinch/zoom gesture for the preview control
PreviewControl.ManipulationMode = ManipulationModes.Scale;
PreviewControl.ManipulationDelta += PreviewControl_ManipulationDelta;
}
Dans le gestionnaire de l’événement ManipulationDelta, mettez à jour le facteur de zoom en fonction de la modification du geste de pincement de l’utilisateur. La valeur ManipulationDelta.Scale représente le changement d’échelle du geste de pincement, de sorte qu’une petite augmentation de la taille du pincement correspond à un nombre légèrement supérieur à 1,0 et qu’une petite diminution de la taille du pincement correspond à un nombre légèrement inférieur à 1,0. Dans cet exemple, la valeur actuelle de la commande de zoom est multipliée par le delta d’échelle.
Avant de définir le facteur de zoom, vous devez vous assurer que la valeur n’est pas inférieure à la valeur minimale prise en charge par l’appareil, comme indiqué par la propriété ZoomControl.Min. Assurez-vous également que la valeur est inférieure ou égale à la valeur ZoomControl.Max. Enfin, vous devez vous assurer que le facteur de zoom est un multiple de la taille du pas de zoom pris en charge par l’appareil, comme indiqué par la propriété Step. Si votre facteur de zoom ne répond pas à ces exigences, une exception sera levée lorsque vous tenterez de définir le niveau de zoom sur l’appareil de capture.
Définissez le niveau de zoom sur l’appareil de capture en créant un nouvel objet ZoomSettings. Définissez la propriété Mode sur ZoomTransitionMode.Smooth, puis définissez la propriété Value sur le facteur de zoom souhaité. Enfin, appelez ZoomControl.Configure pour définir la nouvelle valeur de zoom sur l’appareil. L’appareil passera en douceur à la nouvelle valeur 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);
}