Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Wenn Ihre App ein Foto oder Video für die Verwendung außerhalb der App erfasst, z. B. speichern in einer Datei oder Freigabe, müssen Sie das Bild mit den richtigen Ausrichtungsmetadaten codieren, damit der Inhalt in anderen Apps und Geräten ordnungsgemäß angezeigt wird. In diesem Artikel wird gezeigt, wie Sie eine Hilfsklasse zum Verwalten der Kameraausrichtung in einer WinUI 3-Desktop-App verwenden.
Prerequisites
Bevor Sie beginnen, stellen Sie sicher, dass Sie folgendes haben:
- Ein WinUI 3-Desktopprojekt (verpackt oder entpackt).
- Eine kompatible Kamera, die mit Ihrem Gerät verbunden ist.
- Für Ihre App deklarierter Kamerazugriff:
Verpackte Apps: Hinzufügen der
webcamGerätefunktion zuPackage.appxmanifest:<Capabilities> <DeviceCapability Name="webcam" /> </Capabilities>Entpackte Apps: Es gibt keine Manifestfunktion zum Deklarieren. Der Kamerazugriff wird stattdessen durch die Einstellung Desktop-Apps den Zugriff auf Ihre Kamera erlauben unter Einstellungen>Datenschutz & Sicherheit>Kamera auf dem Gerät des Benutzers gesteuert.
Der Benutzer kann den Kamerazugriff auf Betriebssystemebene in beiden Fällen weiterhin verweigern. Überprüfen Sie den Zugriff, bevor Sie die Kamera initialisieren und den verweigerten Fall ordnungsgemäß behandeln, wie in der Datenschutzeinstellung für die Windows Kamera beschrieben.
Orientierungskonzepte
Desktop-Apps werden in der Regel auf Geräten mit festen Bildschirmen ausgeführt, sodass Sie keine kontinuierliche Drehung wie eine mobile App durchführen müssen. Sie müssen jedoch weiterhin Folgendes berücksichtigen:
- Ausrichtung des Kamerasensors – Der physische Montagewinkel des Kamerasensors, der je nach Gerät variiert.
- Externe Kameradrehung – Externe Webcams können vom Benutzer gedreht werden.
Die wichtigste Idee besteht darin, beim Codieren eines aufgenommenen Fotos oder Videos eine Drehungskorrektur anzuwenden, sodass die Ausgabe dem Entspricht, was der Benutzer in der Vorschau sieht.
Erstellen einer CameraRotationHelper-Klasse
Die folgende Hilfsklasse verwaltet Rotationswerte anhand der Ausrichtung des Kamerasensors und der Ausrichtungssensoren des Geräts:
using Windows.Devices.Enumeration;
using Windows.Devices.Sensors;
using Windows.Media.Capture;
using Windows.Storage.FileProperties;
public class CameraRotationHelper
{
private readonly EnclosureLocation _cameraEnclosureLocation;
private readonly SimpleOrientationSensor _orientationSensor;
private SimpleOrientation _deviceOrientation =
SimpleOrientation.NotRotated;
public event EventHandler<bool> OrientationChanged;
public CameraRotationHelper(
EnclosureLocation cameraEnclosureLocation)
{
_cameraEnclosureLocation = cameraEnclosureLocation;
_orientationSensor =
SimpleOrientationSensor.GetDefault();
if (_orientationSensor != null)
{
_orientationSensor.OrientationChanged +=
OrientationSensor_OrientationChanged;
}
}
private void OrientationSensor_OrientationChanged(
SimpleOrientationSensor sender,
SimpleOrientationSensorOrientationChangedEventArgs args)
{
if (args.Orientation != SimpleOrientation.Faceup &&
args.Orientation != SimpleOrientation.Facedown)
{
_deviceOrientation = args.Orientation;
OrientationChanged?.Invoke(this, true);
}
}
public static bool IsEnclosureLocationExternal(
EnclosureLocation enclosureLocation)
{
return enclosureLocation == null ||
enclosureLocation.Panel == Windows.Devices.Enumeration.Panel.Unknown;
}
private bool IsCameraMirrored()
{
// Front panel cameras are mirrored by convention
return _cameraEnclosureLocation?.Panel == Windows.Devices.Enumeration.Panel.Front;
}
private SimpleOrientation GetCameraOrientation()
{
if (IsEnclosureLocationExternal(_cameraEnclosureLocation))
{
return SimpleOrientation.NotRotated;
}
// Get the sensor orientation from the device
return _deviceOrientation;
}
/// <summary>
/// Gets the rotation to apply to the camera preview stream.
/// </summary>
public VideoRotation GetCameraPreviewOrientation()
{
if (IsEnclosureLocationExternal(_cameraEnclosureLocation))
{
return VideoRotation.None;
}
return ConvertSimpleOrientationToVideoRotation(
GetCameraOrientation());
}
/// <summary>
/// Gets the rotation to apply when encoding a photo.
/// </summary>
public PhotoOrientation GetCapturePhotoOrientation()
{
if (IsEnclosureLocationExternal(_cameraEnclosureLocation))
{
return PhotoOrientation.Normal;
}
int encodingRotation = ConvertDeviceOrientationToDegrees(
GetCameraOrientation());
if (IsCameraMirrored())
{
encodingRotation = (360 - encodingRotation) % 360;
}
return ConvertDegreesToPhotoOrientation(encodingRotation);
}
/// <summary>
/// Gets the clockwise rotation to apply when encoding a video.
/// </summary>
public int GetCaptureVideoOrientation()
{
if (IsEnclosureLocationExternal(_cameraEnclosureLocation))
{
return 0;
}
int rotation = ConvertDeviceOrientationToDegrees(
GetCameraOrientation());
if (IsCameraMirrored())
{
rotation = (360 - rotation) % 360;
}
return rotation;
}
public void Dispose()
{
if (_orientationSensor != null)
{
_orientationSensor.OrientationChanged -=
OrientationSensor_OrientationChanged;
}
}
private static int ConvertDeviceOrientationToDegrees(
SimpleOrientation orientation)
{
// TODO: This mapping from counterclockwise SimpleOrientation values
// to clockwise degree values (for example, mapping
// Rotated90DegreesCounterclockwise to 90) was carried over from the
// original UWP sample this article is based on. Verify this mapping
// against physical devices before relying on it in production; do
// not change these values without hardware verification.
return orientation switch
{
SimpleOrientation.Rotated90DegreesCounterclockwise => 90,
SimpleOrientation.Rotated180DegreesCounterclockwise => 180,
SimpleOrientation.Rotated270DegreesCounterclockwise => 270,
_ => 0,
};
}
private static VideoRotation ConvertSimpleOrientationToVideoRotation(
SimpleOrientation orientation)
{
// TODO: See the verification note on ConvertDeviceOrientationToDegrees
// above — this CCW-to-CW mapping needs the same device verification
// before the values are changed.
return orientation switch
{
SimpleOrientation.Rotated90DegreesCounterclockwise =>
VideoRotation.Clockwise90Degrees,
SimpleOrientation.Rotated180DegreesCounterclockwise =>
VideoRotation.Clockwise180Degrees,
SimpleOrientation.Rotated270DegreesCounterclockwise =>
VideoRotation.Clockwise270Degrees,
_ => VideoRotation.None,
};
}
private static PhotoOrientation ConvertDegreesToPhotoOrientation(
int degrees)
{
return degrees switch
{
90 => PhotoOrientation.Rotate90,
180 => PhotoOrientation.Rotate180,
270 => PhotoOrientation.Rotate270,
_ => PhotoOrientation.Normal,
};
}
}
Verwenden Sie die Hilfsklasse
Initialisieren Sie das Hilfsprogramm, nachdem Sie Ihre MediaCapture Instanz erstellt haben, und kennen Sie die Gehäuseposition der Kamera:
private CameraRotationHelper _rotationHelper;
private MediaCapture _mediaCapture;
private async Task InitializeCameraAsync()
{
_mediaCapture = new MediaCapture();
await _mediaCapture.InitializeAsync();
var cameraDevice = _mediaCapture.MediaCaptureSettings;
// Find the camera device info to get enclosure location
var devices = await DeviceInformation.FindAllAsync(
DeviceClass.VideoCapture);
var deviceInfo = devices.FirstOrDefault(
d => d.Id == cameraDevice.VideoDeviceId);
_rotationHelper = new CameraRotationHelper(
deviceInfo?.EnclosureLocation);
_rotationHelper.OrientationChanged += (s, e) =>
{
// Update preview rotation when device orientation changes
DispatcherQueue.TryEnqueue(UpdatePreviewRotation);
};
}
Drehung auf die Vorschau anwenden
Legen Sie die Vorschaudrehung für Ihre MediaCapture Instanz fest, wenn sich die Ausrichtung ändert:
private void UpdatePreviewRotation()
{
var rotation = _rotationHelper.GetCameraPreviewOrientation();
_mediaCapture.SetPreviewRotation(rotation);
}
Anwenden der Drehung beim Aufnehmen eines Fotos
Legen Sie die Ausrichtungsmetadaten fest, wenn Sie ein aufgenommenes Foto speichern:
using System.Collections.Generic;
using Windows.Storage;
using Windows.Storage.FileProperties;
private async Task CapturePhotoWithOrientationAsync()
{
var file = await ApplicationData.Current.LocalFolder
.CreateFileAsync("photo.jpg",
CreationCollisionOption.GenerateUniqueName);
await _mediaCapture.CapturePhotoToStorageFileAsync(
ImageEncodingProperties.CreateJpeg(), file);
// Set the orientation metadata. ImageProperties.Orientation is
// read-only, so save the EXIF orientation value directly through
// the file's property store instead.
var photoOrientation =
_rotationHelper.GetCapturePhotoOrientation();
var propertiesToSave = new List<KeyValuePair<string, object>>
{
new KeyValuePair<string, object>(
"System.Photo.Orientation", photoOrientation)
};
await file.Properties.SavePropertiesAsync(propertiesToSave);
}
Important
ApplicationData.Current.LocalFolder erfordert Paketidentität (MSIX). Nicht paketierte Apps können ApplicationData nicht ohne Paketidentität verwenden. Verwenden Sie stattdessen für nicht paketierte Apps Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) oder einen anderen Win32-Dateipfad.
Note
SimpleOrientationSensor ist auf allen Desktopgeräten nicht verfügbar. Prüfen Sie, ob SimpleOrientationSensor.GetDefault() den Wert null zurückgibt, und behandeln Sie den Fall, dass kein Ausrichtungssensor vorhanden ist. Bei externen Kameras ist die Drehung in der Regel NotRotated.
Verwandte Inhalte
Windows developer