#xamarin.android #zooming #pinchzoom
Вопрос:
теперь я применяю масштабирование и уменьшение масштаба, когда перед съемкой он не работает должным образом, но он не работает должным образом? Есть ли какой-нибудь пример? Я вызываю эту функцию, когда устройство распознает жест щипка. Заранее спасибо.
public override bool OnTouchEvent(MotionEvent e)
{
global::Android.Hardware.Camera.Parameters parameters = camera.GetParameters();
maximumZoomLevel = (float)cameraCharacteristics?.Get(CameraCharacteristics.ScalerAvailableMaxDigitalZoom);
Android.Graphics.Rect rect = (Android.Graphics.Rect)cameraCharacteristics?.Get(CameraCharacteristics.SensorInfoActiveArraySize);
if (rect == null) return false;
float currentFingerSpacing;
if (e.PointerCount == 2)
{
currentFingerSpacing = getFingerSpacing(e);
float delta = 0.05f;
if (fingerSpacing != 0)
{
if (currentFingerSpacing > fingerSpacing)
{ //Don't over zoom-in
if ((maximumZoomLevel - zoomLevel) <= delta)
{
delta = maximumZoomLevel - zoomLevel;
}
zoomLevel = zoomLevel delta;
}
else if (currentFingerSpacing < fingerSpacing)
{ //Don't over zoom-out
if ((zoomLevel - delta) < 1f)
{
delta = zoomLevel - 1f;
}
zoomLevel = zoomLevel - delta;
}
float ratio = (float)1 / zoomLevel;
int croppedWidth = (int)(rect.Width() - Math.Round((float)rect.Width() * ratio));
int croppedHeight = (int)(rect.Height() - Math.Round((float)rect.Height() * ratio));
//Finally, zoom represents the zoomed visible area
zoom = new Android.Graphics.Rect(croppedWidth / 2, croppedHeight / 2,
rect.Width() - croppedWidth / 2, rect.Height() - croppedHeight / 2);
previewRequestBuilder.Set(CaptureRequest.ScalerCropRegion, zoom);
}
fingerSpacing = currentFingerSpacing;
captureSession.SetRepeatingRequest(previewRequestBuilder.Build(), CaptureCallBack, null);
}
return true;
}
Комментарии:
1. Характеристика камеры возвращает значение null, я не знаю, почему это происходит
2. частное статическое пространство с плавающей точкой getFingerSpacing(событие движения e) { float x = e.getX(0) — e.getX(1); float y = e.getY(0) — e.getY(1); возврат (float)Math.Sqrt(x * x y * y); } он всегда возвращает исключение индекса указателя
Ответ №1:
Вот соответствующий код функции, пожалуйста, проверьте его.
var manager = Android.App.Application.Context.GetSystemService(Context.CameraService) as CameraManager;
var id_list = manager.GetCameraIdList();
var characteristics = manager.GetCameraCharacteristics(id_list[0]);
float maxZoom;
Rect mSensorSize = (Rect)characteristics.Get(CameraCharacteristics.SensorInfoActiveArraySize);
if (mSensorSize == null)
{
maxZoom = 1.0f;
return;
}
Rect mCropRegion = new Rect();
float zoom = 1.5f;
var newZoom = MathUtils.Clamp(zoom, 1.0f, 6.0f);
int centerX = mSensorSize.Width() / 2;
int centerY = mSensorSize.Height() / 2;
int deltaX = (int)((0.5f * mSensorSize.Width()) / newZoom);
int deltaY = (int)((0.5f * mSensorSize.Height()) / newZoom);
mCropRegion.Set(centerX - deltaX,
centerY - deltaY,
centerX deltaX,
centerY deltaY);
mPreviewRequestBuilder.Set(CaptureRequest.ScalerCropRegion, mCropRegion);
mCaptureSession.SetRepeatingRequest(mPreviewRequestBuilder.Build(), null, null);//you could define the callback and handler
Обратитесь: https://docs.microsoft.com/en-us/answers/questions/343552/zoom-in-camera2basic-xamarin.html
Обновить:
Если вы используете его в форме xamarin, вы можете обратиться к следующему коду:
[assembly: ExportRenderer(typeof(CameraPage), typeof(CameraPageRenderer))]
namespace App10.Droid
{
class CameraPageRenderer : PageRenderer, TextureView.ISurfaceTextureListener
{
global::Android.Hardware.Camera camera;
global::Android.Widget.Button takePhotoButton;
global::Android.Widget.Button toggleFlashButton;
global::Android.Widget.Button switchCameraButton;
global::Android.Views.View view;
Activity activity;
CameraFacing cameraType;
TextureView textureView;
SurfaceTexture surfaceTexture;
bool flashOn;
public CameraPageRenderer(Context context) : base(context)
{
}
float oldDist = 1f;
public override bool OnTouchEvent(MotionEvent e)
{
switch (e.Action amp; MotionEventActions.Mask)
{
case MotionEventActions.Down:
oldDist = getFingerSpacing(e);
break;
case MotionEventActions.Move:
float newDist = getFingerSpacing(e);
if (newDist > oldDist)
{
//mCamera is your Camera which used to take picture, it should already exit in your custom Camera
handleZoom(true, camera);
}
else if (newDist < oldDist)
{
handleZoom(false, camera);
}
oldDist = newDist;
break;
}
return true;
}
private static float getFingerSpacing(MotionEvent e)
{
if (e.PointerCount == 2)
{
float x = e.GetX(0) - e.GetX(1);
float y = e.GetY(0) - e.GetY(1);
return (float)Math.Sqrt(x*x y*y);
}
return 0;
}
private void handleZoom(bool isZoomIn, global::Android.Hardware.Camera camera)
{
global::Android.Hardware.Camera.Parameters parameters = camera.GetParameters();
if (parameters.IsZoomSupported)
{
int maxZoom = parameters.MaxZoom;
int zoom = parameters.Zoom;
if (isZoomIn amp;amp; zoom < maxZoom)
{
zoom ;
}
else if (zoom > 0)
{
zoom--;
}
parameters.Zoom = zoom;
camera.SetParameters(parameters);
camera.SetPreviewTexture(surfaceTexture);
PrepareAndStartCamera();
}
else
{
Android.Util.Log.Error("lv", "zoom not supported");
}
}
protected override void OnElementChanged(ElementChangedEventArgs<Page> e)
{
base.OnElementChanged(e);
if (e.OldElement != null || Element == null)
{
return;
}
try
{
SetupUserInterface();
//SetupEventHandlers();
AddView(view);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(@" ERROR: ", ex.Message);
}
}
void SetupUserInterface()
{
activity = this.Context as Activity;
view = activity.LayoutInflater.Inflate(Resource.Layout.CameraLayout, this, false);
cameraType = CameraFacing.Back;
textureView = view.FindViewById<TextureView>(Resource.Id.textureView);
textureView.SurfaceTextureListener = this;
}
protected override void OnLayout(bool changed, int l, int t, int r, int b)
{
base.OnLayout(changed, l, t, r, b);
var msw = MeasureSpec.MakeMeasureSpec(r - l, MeasureSpecMode.Exactly);
var msh = MeasureSpec.MakeMeasureSpec(b - t, MeasureSpecMode.Exactly);
view.Measure(msw, msh);
view.Layout(0, 0, r - l, b - t);
}
public void OnSurfaceTextureAvailable(SurfaceTexture surface, int width, int height)
{
camera = global::Android.Hardware.Camera.Open((int)cameraType);
textureView.LayoutParameters = new FrameLayout.LayoutParams(width, height);
surfaceTexture = surface;
camera.SetPreviewTexture(surface);
PrepareAndStartCamera();
}
public bool OnSurfaceTextureDestroyed(SurfaceTexture surface)
{
camera.StopPreview();
camera.Release();
return true;
}
public void OnSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height)
{
PrepareAndStartCamera();
}
public void OnSurfaceTextureUpdated(SurfaceTexture surface)
{
}
void PrepareAndStartCamera()
{
camera.StopPreview();
var display = activity.WindowManager.DefaultDisplay;
if (display.Rotation == SurfaceOrientation.Rotation0)
{
camera.SetDisplayOrientation(90);
}
if (display.Rotation == SurfaceOrientation.Rotation270)
{
camera.SetDisplayOrientation(180);
}
camera.StartPreview();
}
}
}
Комментарии:
1. как установить mPreviewRequestBuilder и mCaptureSession, потому что это вызывает исключение nullreference
2. я не знаю, почему это происходит, он всегда выдает нулевые значения в mPreviewRequestBuilder, mCaptureSession все, что я пропустил, пожалуйста, дайте мне знать, если я что-то пропустил
3. над скриншотом добавлено
4. пожалуйста, ответьте на эти вопросы. Спасибо
5. как добиться отображения процентного значения масштабирования в визуализаторе (например: значение масштабирования после отображения zoomin 1.0 в пользовательском интерфейсе)