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

Commit

Permalink
Fix preview size for camera view on Androud (#723) (#731)
Browse files Browse the repository at this point in the history
- 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 <eugen.richter@amcsgroup.com>
Co-authored-by: Gerald Versluis <gerald.versluis@microsoft.com>
  • Loading branch information
3 people authored Jan 7, 2021
1 parent 6e40ffd commit 2906094
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 10 deletions.
1 change: 1 addition & 0 deletions samples/XCT.Sample/Pages/Views/CameraViewPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
IsEnabled="False"
Maximum="10"
Minimum="1"
HorizontalOptions="FillAndExpand"
ValueChanged="ZoomSlider_ValueChanged"
Value="1" />
</StackLayout>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,19 @@
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using Camera = Android.Hardware.Camera;
using Math = System.Math;
using Rect = Android.Graphics.Rect;
using APoint = Android.Graphics.Point;

namespace Xamarin.CommunityToolkit.UI.Views
{
class CameraFragment : Fragment, TextureView.ISurfaceTextureListener
{
// Max preview width that is guaranteed by Camera2 API
const int MAX_PREVIEW_HEIGHT = 1080;
// Max preview height that is guaranteed by Camera2 API
const int MAX_PREVIEW_WIDTH = 1920;

CameraDevice device;
CaptureRequest.Builder sessionBuilder;
CameraCaptureSession session;
Expand Down Expand Up @@ -222,14 +229,42 @@ public async Task RetrieveCameraDevice(bool force = false)
}
Element.MaxZoom = maxDigitalZoom = (float)characteristics.Get(CameraCharacteristics.ScalerAvailableMaxDigitalZoom);
activeRect = (Rect)characteristics.Get(CameraCharacteristics.SensorInfoActiveArraySize);
sensorOrientation = (int)characteristics.Get(CameraCharacteristics.SensorOrientation);

var displaySize = new APoint();
Activity.WindowManager.DefaultDisplay.GetSize(displaySize);
var rotatedViewWidth = texture.Width;
var rotatedViewHeight = texture.Height;
var maxPreviewWidth = displaySize.X;
var maxPreviewHeight = displaySize.Y;

if (sensorOrientation == 90 || sensorOrientation == 270)
{
rotatedViewWidth = texture.Height;
rotatedViewHeight = texture.Width;
maxPreviewWidth = displaySize.Y;
maxPreviewHeight = displaySize.X;
}

if (maxPreviewHeight > MAX_PREVIEW_HEIGHT)
{
maxPreviewHeight = MAX_PREVIEW_HEIGHT;
}

if (maxPreviewWidth > MAX_PREVIEW_WIDTH)
{
maxPreviewWidth = MAX_PREVIEW_WIDTH;
}

photoSize = GetMaxSize(map.GetOutputSizes((int)ImageFormatType.Jpeg));
videoSize = GetMaxSize(map.GetOutputSizes(Class.FromType(typeof(MediaRecorder))));
previewSize = ChooseOptimalSize(
map.GetOutputSizes(Class.FromType(typeof(SurfaceTexture))),
texture.Width,
texture.Height,
rotatedViewWidth,
rotatedViewHeight,
maxPreviewWidth,
maxPreviewHeight,
cameraTemplate == CameraTemplate.Record ? videoSize : photoSize);
sensorOrientation = (int)characteristics.Get(CameraCharacteristics.SensorOrientation);
cameraType = (LensFacing)(int)characteristics.Get(CameraCharacteristics.LensFacing);

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

// chooses the smallest one whose width and height are at least as large as the respective requested values
ASize ChooseOptimalSize(ASize[] choices, int width, int height, ASize aspectRatio)
ASize ChooseOptimalSize(ASize[] choices, int width, int height, int maxWidth, int maxHeight, ASize aspectRatio)
{
var bigEnough = new List<ASize>();
var notBigEnough = new List<ASize>();
var w = aspectRatio.Width;
var h = aspectRatio.Height;
foreach (var option in choices)
{
if (option.Height == option.Width * h / w &&
option.Width >= width && option.Height >= height)
if (option.Width <= maxWidth && option.Height <= maxHeight &&
option.Height == option.Width * h / w)
{
bigEnough.Add(option);
if (option.Width >= width && option.Height >= height)
{
bigEnough.Add(option);
}
else
{
notBigEnough.Add(option);
}
}
}

Expand All @@ -943,11 +986,15 @@ ASize ChooseOptimalSize(ASize[] choices, int width, int height, ASize aspectRati
var minArea = bigEnough.Min(s => s.Width * s.Height);
return bigEnough.First(s => s.Width * s.Height == minArea);
}
else

if (notBigEnough.Count > 0)
{
LogError("Couldn't find any suitable preview size");
return choices[0];
var maxArea = notBigEnough.Max(s => s.Height * s.Width);
return notBigEnough.First(s => s.Height * s.Width == maxArea);
}

LogError("Couldn't find any suitable preview size");
return choices[0];
}
#endregion
}
Expand Down

0 comments on commit 2906094

Please sign in to comment.