Skip to content
This repository was archived by the owner on May 1, 2024. It is now read-only.

Commit 2906094

Browse files
WebDucerEugen Richterjfversluis
authored
Fix preview size for camera view on Androud (#723) (#731)
- Fix based on sample implementation for Camera2 API from Google - https://github.com/android/camera-samples/blob/4aac9c7763c285d387194a558416a4458f29e275/CameraXTfLite/utils/src/main/java/com/example/android/camera/utils/CameraSizes.kt#L50-L78 Co-authored-by: Eugen Richter <[email protected]> Co-authored-by: Gerald Versluis <[email protected]>
1 parent 6e40ffd commit 2906094

File tree

2 files changed

+58
-10
lines changed

2 files changed

+58
-10
lines changed

samples/XCT.Sample/Pages/Views/CameraViewPage.xaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
IsEnabled="False"
2525
Maximum="10"
2626
Minimum="1"
27+
HorizontalOptions="FillAndExpand"
2728
ValueChanged="ZoomSlider_ValueChanged"
2829
Value="1" />
2930
</StackLayout>

src/CommunityToolkit/Xamarin.CommunityToolkit/Views/CameraView/Android/CameraFragment.android.cs

Lines changed: 57 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,19 @@
3636
using Xamarin.Forms;
3737
using Xamarin.Forms.Platform.Android;
3838
using Camera = Android.Hardware.Camera;
39+
using Math = System.Math;
3940
using Rect = Android.Graphics.Rect;
41+
using APoint = Android.Graphics.Point;
4042

4143
namespace Xamarin.CommunityToolkit.UI.Views
4244
{
4345
class CameraFragment : Fragment, TextureView.ISurfaceTextureListener
4446
{
47+
// Max preview width that is guaranteed by Camera2 API
48+
const int MAX_PREVIEW_HEIGHT = 1080;
49+
// Max preview height that is guaranteed by Camera2 API
50+
const int MAX_PREVIEW_WIDTH = 1920;
51+
4552
CameraDevice device;
4653
CaptureRequest.Builder sessionBuilder;
4754
CameraCaptureSession session;
@@ -222,14 +229,42 @@ public async Task RetrieveCameraDevice(bool force = false)
222229
}
223230
Element.MaxZoom = maxDigitalZoom = (float)characteristics.Get(CameraCharacteristics.ScalerAvailableMaxDigitalZoom);
224231
activeRect = (Rect)characteristics.Get(CameraCharacteristics.SensorInfoActiveArraySize);
232+
sensorOrientation = (int)characteristics.Get(CameraCharacteristics.SensorOrientation);
233+
234+
var displaySize = new APoint();
235+
Activity.WindowManager.DefaultDisplay.GetSize(displaySize);
236+
var rotatedViewWidth = texture.Width;
237+
var rotatedViewHeight = texture.Height;
238+
var maxPreviewWidth = displaySize.X;
239+
var maxPreviewHeight = displaySize.Y;
240+
241+
if (sensorOrientation == 90 || sensorOrientation == 270)
242+
{
243+
rotatedViewWidth = texture.Height;
244+
rotatedViewHeight = texture.Width;
245+
maxPreviewWidth = displaySize.Y;
246+
maxPreviewHeight = displaySize.X;
247+
}
248+
249+
if (maxPreviewHeight > MAX_PREVIEW_HEIGHT)
250+
{
251+
maxPreviewHeight = MAX_PREVIEW_HEIGHT;
252+
}
253+
254+
if (maxPreviewWidth > MAX_PREVIEW_WIDTH)
255+
{
256+
maxPreviewWidth = MAX_PREVIEW_WIDTH;
257+
}
258+
225259
photoSize = GetMaxSize(map.GetOutputSizes((int)ImageFormatType.Jpeg));
226260
videoSize = GetMaxSize(map.GetOutputSizes(Class.FromType(typeof(MediaRecorder))));
227261
previewSize = ChooseOptimalSize(
228262
map.GetOutputSizes(Class.FromType(typeof(SurfaceTexture))),
229-
texture.Width,
230-
texture.Height,
263+
rotatedViewWidth,
264+
rotatedViewHeight,
265+
maxPreviewWidth,
266+
maxPreviewHeight,
231267
cameraTemplate == CameraTemplate.Record ? videoSize : photoSize);
232-
sensorOrientation = (int)characteristics.Get(CameraCharacteristics.SensorOrientation);
233268
cameraType = (LensFacing)(int)characteristics.Get(CameraCharacteristics.LensFacing);
234269

235270
if (Resources.Configuration.Orientation == AOrientation.Landscape)
@@ -923,17 +958,25 @@ ASize GetMaxSize(ASize[] imageSizes)
923958
}
924959

925960
// chooses the smallest one whose width and height are at least as large as the respective requested values
926-
ASize ChooseOptimalSize(ASize[] choices, int width, int height, ASize aspectRatio)
961+
ASize ChooseOptimalSize(ASize[] choices, int width, int height, int maxWidth, int maxHeight, ASize aspectRatio)
927962
{
928963
var bigEnough = new List<ASize>();
964+
var notBigEnough = new List<ASize>();
929965
var w = aspectRatio.Width;
930966
var h = aspectRatio.Height;
931967
foreach (var option in choices)
932968
{
933-
if (option.Height == option.Width * h / w &&
934-
option.Width >= width && option.Height >= height)
969+
if (option.Width <= maxWidth && option.Height <= maxHeight &&
970+
option.Height == option.Width * h / w)
935971
{
936-
bigEnough.Add(option);
972+
if (option.Width >= width && option.Height >= height)
973+
{
974+
bigEnough.Add(option);
975+
}
976+
else
977+
{
978+
notBigEnough.Add(option);
979+
}
937980
}
938981
}
939982

@@ -943,11 +986,15 @@ ASize ChooseOptimalSize(ASize[] choices, int width, int height, ASize aspectRati
943986
var minArea = bigEnough.Min(s => s.Width * s.Height);
944987
return bigEnough.First(s => s.Width * s.Height == minArea);
945988
}
946-
else
989+
990+
if (notBigEnough.Count > 0)
947991
{
948-
LogError("Couldn't find any suitable preview size");
949-
return choices[0];
992+
var maxArea = notBigEnough.Max(s => s.Height * s.Width);
993+
return notBigEnough.First(s => s.Height * s.Width == maxArea);
950994
}
995+
996+
LogError("Couldn't find any suitable preview size");
997+
return choices[0];
951998
}
952999
#endregion
9531000
}

0 commit comments

Comments
 (0)