简体   繁体   English

是否可以将 cameraX 或 Camera2 缩放到 Api 最大缩放限制之外

[英]Is it possible to zoom cameraX or Camera2 beyond the Api max zoom limit

So I'm trying to make a binoculars/Telescope kind of app but the problem is I want to zoom to the max.所以我正在尝试制作双筒望远镜/望远镜类的应用程序,但问题是我想放大到最大。 I have seen there are apps on the store that does that but not sure how.我已经看到商店中有应用程序可以做到这一点,但不确定如何。 I have tried cameraX linearZoom method but it only works in range between 0f - 1f Or is it possible to do this with Camera2 api?我已经尝试过 cameraX linearZoom 方法,但它只能在 0f - 1f 之间的范围内工作或者是否可以使用 Camera2 api 来做到这一点? Any help would be highly appreciate.任何帮助将不胜感激。 Please note I have only posted this queston after trying or researching different things for the whole day.请注意,我只是在尝试或研究了一整天不同的东西后才发布了这个问题。

Thanks谢谢

For the curiosity of this question I decided to throw myself and try, the solution I found will not be the most conventional but it currently works.出于对这个问题的好奇,我决定投身尝试,我发现的解决方案不是最传统的,但它目前有效。

After my first attempt I saw that it was not possible to increase the camera max_zoom so I thought of another way to enlarge what I was sending on the screen anyway.在我第一次尝试之后,我发现无法增加相机的max_zoom ,所以我想了另一种方法来放大我在屏幕上发送的内容。

My solution is based on the main layout in which you place the textureView in my case I decided to use a LinearLayout , that following some other guide i was able to zoom in by pinching it.我的解决方案基于您放置textureView的主要布局,在我的情况下,我决定使用LinearLayout ,按照其他一些指南,我可以通过捏它来放大。

    public class ZoomLinearLayout extends LinearLayout implements ScaleGestureDetector.OnScaleGestureListener {

        private enum Mode {
            NONE,
            DRAG,
            ZOOM
        }

        private static final float MIN_ZOOM = 1.0f;
        private static final float MAX_ZOOM = 10.0f;

        private Mode mode = Mode.NONE;
        private float scale = 1.0f;
        private float lastScaleFactor = 0f;

        private float startX = 0f;
        private float startY = 0f;

        private float dx = 0f;
        private float dy = 0f;
        private float prevDx = 0f;
        private float prevDy = 0f;

        public ZoomLinearLayout(Context context) {
            super(context);
            init(context);
        }

        public ZoomLinearLayout(Context context, AttributeSet attrs) {
            super(context, attrs);
            init(context);
        }

        public ZoomLinearLayout(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            init(context);
        }

        @SuppressLint("ClickableViewAccessibility")
        public void init(Context context) {
            final ScaleGestureDetector scaleDetector = new ScaleGestureDetector(context, this);
            this.setOnTouchListener(new OnTouchListener() {
                @Override
                public boolean onTouch(View view, MotionEvent motionEvent) {
                    switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) {
                        case MotionEvent.ACTION_DOWN:
                            if (scale > MIN_ZOOM) {
                                mode = Mode.DRAG;
                                startX = motionEvent.getX() - prevDx;
                                startY = motionEvent.getY() - prevDy;
                            }
                            break;
                        case MotionEvent.ACTION_MOVE:
                            if (mode == Mode.DRAG) {
                                dx = motionEvent.getX() - startX;
                                dy = motionEvent.getY() - startY;
                            }
                            break;
                        case MotionEvent.ACTION_POINTER_DOWN:
                            mode = Mode.ZOOM;
                            break;
                        case MotionEvent.ACTION_POINTER_UP:
                            mode = Mode.DRAG;
                            break;
                        case MotionEvent.ACTION_UP:
                            mode = Mode.NONE;
                            prevDx = dx;
                            prevDy = dy;
                            break;
                    }
                    scaleDetector.onTouchEvent(motionEvent);

                    if ((mode == Mode.DRAG && scale >= MIN_ZOOM) || mode == Mode.ZOOM) {
                        getParent().requestDisallowInterceptTouchEvent(true);
                        float maxDx = (child().getWidth() - (child().getWidth() / scale)) / 2 * scale;
                        float maxDy = (child().getHeight() - (child().getHeight() / scale)) / 2 * scale;
                        dx = Math.min(Math.max(dx, -maxDx), maxDx);
                        dy = Math.min(Math.max(dy, -maxDy), maxDy);
                        applyScaleAndTranslation();
                    }

                    return true;
                }
            });
        }

        @Override
        public boolean onScaleBegin(ScaleGestureDetector scaleDetector) {
            return true;
        }

        @Override
        public boolean onScale(ScaleGestureDetector scaleDetector) {
            float scaleFactor = scaleDetector.getScaleFactor();
            if (lastScaleFactor == 0 || (Math.signum(scaleFactor) == Math.signum(lastScaleFactor))) {
                scale *= scaleFactor;
                scale = Math.max(MIN_ZOOM, Math.min(scale, MAX_ZOOM));
                lastScaleFactor = scaleFactor;
            } else {
                lastScaleFactor = 0;
            }
            return true;
        }

        @Override
        public void onScaleEnd(ScaleGestureDetector scaleDetector) {
        }

        private void applyScaleAndTranslation() {
            child().setScaleX(scale);
            child().setScaleY(scale);
            child().setTranslationX(dx);
            child().setTranslationY(dy);
        }

        private View child() {
            return getChildAt(0);
        }

    }

What manages the maximum of our zoom is no longer the power of the camera but our variable MAX_ZOOM witch in our case is set to 10.0f (but you can actually change it).管理我们最大变焦的不再是相机的力量,而是我们的变量MAX_ZOOM女巫在我们的例子中设置为 10.0f(但您实际上可以更改它)。

The next step is to enclose the TextureView used in camera2 between the ZoomLinearLayout :下一步是将TextureView中使用的 TextureView 包含在ZoomLinearLayout之间:

    <com.giacomociardini.zoom.ZoomLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <FrameLayout
            android:id="@+id/container"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#000" />

    </com.giacomociardini.zoom.ZoomLinearLayout>

The FrameLayout is only a container for the fragment (the TextureView) that is in charge of all the hard work for the camera2, this is my final result: FrameLayout只是片段(TextureView)的容器,它负责 camera2 的所有艰苦工作,这是我的最终结果:

video视频

photo照片

Notice: the results are made by only zooming inside the view, if you combine it with the zoom of the camera you are gonna get a result way much smoother!注意:结果是通过仅在视图内部进行缩放得出的,如果将其与相机的缩放结合起来,您将获得更平滑的结果!

I believe what you are trying to do might not be very possible and is entirely dependent on the ability of the physical mobile camera unless the app's function is to automatically zoom in on an image taken by the onboard camera.我相信您尝试做的事情可能不太可能,并且完全取决于物理移动相机的能力,除非应用程序的 function 是自动放大车载相机拍摄的图像。 Read the api documentation and see if the api allows the ability to zoom in further than usual on an android camera.阅读 api 文档,看看 api 是否允许在 android 相机上比平时放大更多。 Good Luck!祝你好运!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM