Skip to content

Commit 37c98a0

Browse files
authored
[CameraView][iOS] Favor Photo Formats During Default Resolution Selection (#2941)
Fixed #2920
1 parent 32a0883 commit 37c98a0

File tree

2 files changed

+50
-13
lines changed

2 files changed

+50
-13
lines changed

src/CommunityToolkit.Maui.Camera/CameraManager.macios.cs

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -104,22 +104,21 @@ public async partial ValueTask UpdateCaptureResolution(Size resolution, Cancella
104104
cameraView.SelectedCamera = cameraProvider.AvailableCameras?.FirstOrDefault() ?? throw new CameraException("No camera available on device");
105105
}
106106

107-
var filteredFormatList = cameraView.SelectedCamera.SupportedFormats.Where(f =>
108-
{
109-
var d = ((CMVideoFormatDescription)f.FormatDescription).Dimensions;
110-
return d.Width <= resolution.Width && d.Height <= resolution.Height;
111-
}).ToList();
107+
var formatsMatchingResolution = cameraView.SelectedCamera.SupportedFormats
108+
.Where(format => MatchesResolution(format, resolution))
109+
.ToList();
112110

113-
filteredFormatList = [.. (filteredFormatList.Count is not 0 ? filteredFormatList : cameraView.SelectedCamera.SupportedFormats)
114-
.OrderByDescending(f =>
115-
{
116-
var d = ((CMVideoFormatDescription)f.FormatDescription).Dimensions;
117-
return d.Width * d.Height;
118-
})];
111+
var availableFormats = formatsMatchingResolution.Count is not 0
112+
? formatsMatchingResolution
113+
: GetPhotoCompatibleFormats(cameraView.SelectedCamera.SupportedFormats);
114+
115+
var selectedFormat = availableFormats
116+
.OrderByDescending(f => f.ResolutionArea)
117+
.FirstOrDefault();
119118

120-
if (filteredFormatList.Count is not 0)
119+
if (selectedFormat is not null)
121120
{
122-
captureDevice.ActiveFormat = filteredFormatList.First();
121+
captureDevice.ActiveFormat = selectedFormat;
123122
}
124123

125124
captureDevice.UnlockForConfiguration();
@@ -460,6 +459,24 @@ void UpdateVideoOrientation()
460459
previewView?.UpdatePreviewVideoOrientation(videoOrientation);
461460
}
462461

462+
IEnumerable<AVCaptureDeviceFormat> GetPhotoCompatibleFormats(IEnumerable<AVCaptureDeviceFormat> formats)
463+
{
464+
if (photoOutput is not null)
465+
{
466+
var photoPixelFormats = photoOutput.GetSupportedPhotoPixelFormatTypesForFileType(nameof(AVFileTypes.Jpeg));
467+
return formats.Where(format => photoPixelFormats.Contains((NSNumber)format.FormatDescription.MediaSubType));
468+
}
469+
470+
return formats;
471+
}
472+
473+
static bool MatchesResolution(AVCaptureDeviceFormat format, Size resolution)
474+
{
475+
var dimensions = ((CMVideoFormatDescription)format.FormatDescription).Dimensions;
476+
return dimensions.Width <= resolution.Width
477+
&& dimensions.Height <= resolution.Height;
478+
}
479+
463480
sealed class AVCapturePhotoCaptureDelegateWrapper : AVCapturePhotoCaptureDelegate
464481
{
465482
readonly TaskCompletionSource<CapturePhotoResult> taskCompletionSource = new();

src/CommunityToolkit.Maui.Camera/Extensions/CameraViewExtensions.macios.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using AVFoundation;
22
using CommunityToolkit.Maui.Core;
3+
using CoreMedia;
34

45
namespace CommunityToolkit.Maui.Extensions;
56

@@ -30,4 +31,23 @@ public static void UpdateAvailability(this ICameraView cameraView)
3031
{
3132
cameraView.IsAvailable = AVCaptureDevice.GetDefaultDevice(AVMediaTypes.Video) is not null;
3233
}
34+
35+
extension(AVCaptureDeviceFormat avCaptureDeviceFormat)
36+
{
37+
/// <summary>
38+
/// Gets the total resolution area in pixels (width × height) of the <see cref="AVCaptureDeviceFormat"/>.
39+
/// </summary>
40+
/// <value>
41+
/// The total number of pixels, calculated as width multiplied by height.
42+
/// </value>
43+
public int ResolutionArea
44+
{
45+
get
46+
{
47+
var dimensions = ((CMVideoFormatDescription)avCaptureDeviceFormat.FormatDescription).Dimensions;
48+
return dimensions.Width * dimensions.Height;
49+
}
50+
}
51+
52+
}
3353
}

0 commit comments

Comments
 (0)