Можно ли увеличить cameraX или Camera2 за пределы максимального увеличения Api - PullRequest
5 голосов
/ 18 апреля 2020

Итак, я пытаюсь сделать приложение типа бинокля / телескопа, но проблема в том, что я хочу увеличить до максимума. Я видел, что в магазине есть приложения, которые делают это, но не уверены, как это сделать. Я пробовал метод cameraX linearZoom, но он работает только в диапазоне от 0f до 1f. Или это возможно сделать с помощью Camera2 api? Любая помощь будет высоко ценится. Обратите внимание, что я отправил этот квест только после того, как попробовал или исследовал разные вещи в течение всего дня.

Спасибо

Ответы [ 2 ]

3 голосов
/ 06 мая 2020

Для любопытства по этому вопросу я решил броситься и попробовать, решение, которое я нашел, не будет самым обычным, но в настоящее время оно работает.

После моей первой попытки я увидел, что это было невозможно увеличить камеру max_zoom, поэтому я подумал о другом способе увеличения того, что я отправлял на экран, в любом случае.

Мое решение основано на основном макете, в котором вы помещаете 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);
        }

    }

То, что управляет максимумом нашего увеличения, больше не сила камеры, а наша переменная MAX_ZOOM witch в нашем случае установлено на 10.0f (но вы можете изменить его).

Следующий шаг - заключить TextureView, используемый в camera2, между 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>

FrameLayout является только контейнером для фрагмента (TextureView), который отвечает за всю тяжелую работу для камеры2, это мой окончательный результат:

результат

0 голосов
/ 29 апреля 2020

Я полагаю, что то, что вы пытаетесь сделать, может быть не очень возможным и полностью зависит от возможностей физической мобильной камеры, если функция приложения не заключается в автоматическом увеличении изображения, полученного встроенной камерой. Прочитайте документацию по API и посмотрите, позволяет ли API увеличить изображение, как обычно, на камере android. Удачи!

...