Android Camera preview zoom using double finger touch

后端 未结 3 1979
醉梦人生
醉梦人生 2021-02-06 08:29

I am trying to do zoom using double finger touch gesture in the camera preview mode. But i unable to do that. I have done that Zoom control on the ImageView and it\'s working fi

相关标签:
3条回答
  • 2021-02-06 08:44

    I got the solution of my problem, Following is the solution.

     case MotionEvent.ACTION_MOVE:
    
    
                  if (mode == ZOOM) {
                    float newDist = spacing(event);
    
                    double zoomDist = newDist-oldDist;
    
                    if(zoomDist > 0){
                        if(zoomDist > 50 && zoomDist <= 200){
    
                            if (curZoomLevel < mZoomMax && gestureZoom == 0) {
                                gestureZoom ++;
                                GestureZoomIn();
                            }
    
                        }else if(zoomDist > 200 && zoomDist <= 300){
    
    
                            if (curZoomLevel < mZoomMax && gestureZoom == 1) {
    
                                gestureZoom ++;
                                GestureZoomIn();
                            }
                        }else if(zoomDist > 300 && zoomDist <= 400){
    
                            if (curZoomLevel < mZoomMax && gestureZoom == 2) {
    
                                gestureZoom++;
                                GestureZoomIn();
                            }
    

    //

     private void GestureZoomIn(){
           if (mParameters.isZoomSupported()){
                mZoomMax = mParameters.getMaxZoom();
                if (zoom_text_value<mZoomMax) {
                    zoom_text_value++;
                    curZoomLevel++;
                    zoom_float=zoom_float+0.5;
                    onZoomValueChanged(curZoomLevel);
    

    //

    private void GestureZoomOut(){
           if (mParameters.isZoomSupported()){
    
                if (0<zoom_text_value) {
                    zoom_text_value--;
                    curZoomLevel--;
                    zoom_float=zoom_float-0.5;
                    onZoomValueChanged(curZoomLevel);
    

    The above code i used to implement the multi zoom in camera review.

    0 讨论(0)
  • 2021-02-06 08:51

    Here is a solution I found on github: https://github.com/Betulaphobe/ChatCapsule/blob/8d4f00a7d4c9166aa7ce974670fdf3033a6064f4/chc_application/src/chc/helpers/CameraPreview.java

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // Get the pointer ID
        Camera.Parameters params = mCamera.getParameters();
        int action = event.getAction();
    
    
        if (event.getPointerCount() > 1) {
            // handle multi-touch events
            if (action == MotionEvent.ACTION_POINTER_DOWN) {
                mDist = getFingerSpacing(event);
            } else if (action == MotionEvent.ACTION_MOVE && params.isZoomSupported()) {
                mCamera.cancelAutoFocus();
                handleZoom(event, params);
            }
        } else {
            // handle single touch events
            if (action == MotionEvent.ACTION_UP) {
                handleFocus(event, params);
            }
        }
        return true;
    }
    
    private void handleZoom(MotionEvent event, Camera.Parameters params) {
        int maxZoom = params.getMaxZoom();
        int zoom = params.getZoom();
        float newDist = getFingerSpacing(event);
        if (newDist > mDist) {
            //zoom in
            if (zoom < maxZoom)
                zoom++;
        } else if (newDist < mDist) {
            //zoom out
            if (zoom > 0)
                zoom--;
        }
        mDist = newDist;
        params.setZoom(zoom);
        mCamera.setParameters(params);
    }
    
    public void handleFocus(MotionEvent event, Camera.Parameters params) {
        int pointerId = event.getPointerId(0);
        int pointerIndex = event.findPointerIndex(pointerId);
        // Get the pointer's current position
        float x = event.getX(pointerIndex);
        float y = event.getY(pointerIndex);
    
        List<String> supportedFocusModes = params.getSupportedFocusModes();
        if (supportedFocusModes != null && supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
            mCamera.autoFocus(new Camera.AutoFocusCallback() {
                @Override
                public void onAutoFocus(boolean b, Camera camera) {
                    // currently set to auto-focus on single touch
                }
            });
        }
    }
    
    /** Determine the space between the first two fingers */
    private float getFingerSpacing(MotionEvent event) {
        // ...
        float x = event.getX(0) - event.getX(1);
        float y = event.getY(0) - event.getY(1);
        return FloatMath.sqrt(x * x + y * y);
    }
    
    0 讨论(0)
  • 2021-02-06 09:01

    Take a look at my implementation. Support for both Camera APIs: camera and camera2. You can zoom by using double finger touch.

    This is how I use the code on my Activities.

    For camera API just:

    private void setupZoomHandler(final Camera.Parameters parameters) {
        if ( parameters.isZoomSupported() ) {
            SimpleZoomHandlerBuilder.forView( mCameraPreview )
                    .setMaxZoom( parameters.getMaxZoom() )
                    .setZoomListener( new SimpleZoomHandler.IZoomHandlerListener() {
                        @Override
                        public void onZoomChanged(int newZoom) {
                            Camera.Parameters params = mCamera.getParameters();
                            params.setZoom( newZoom );
                            mCamera.setParameters( params );
                        }
                    } )
                    .build();
        }
    }
    

    And for camera2 API just:

    private void setupZoomHandler(CameraCharacteristics cameraCharacteristics) {
        ActiveArrayZoomHandlerBuilder.forView( mTextureView )
                .setActiveArraySize( cameraCharacteristics.get( CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE ) )
                .setMaxZoom( cameraCharacteristics.get( CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM ) * 10 )
                .setZoomListener( new ActiveArrayZoomHandler.IZoomHandlerListener() {
                    @Override
                    public void onZoomChanged(Rect zoom) {
                        mCaptureRequestBuilder.set( CaptureRequest.SCALER_CROP_REGION, zoom );
                        updatePreview();
                    }
                } )
                .build();
    }
    

    Here are the classes you need to zoom handling:

    public abstract class AbstractZoomHandler implements View.OnTouchListener {
    
    private static final int FINGER_SPACING_DELTA_FOR_ZOOM = 25;
    private static final int FINGER_SPACING_ZOOM_INCREMENT = 5;
    
    private static final float DEFAULT_ZOOM_HARDNESS = 0.4f;
    
    private float lastFingerSpacingTime;
    private float fingerSpacingBuffer;
    
    protected int zoomLevel;
    protected float zoomIncrement;
    protected float maxZoom;
    
    public AbstractZoomHandler(View touchableView) {
        touchableView.setOnTouchListener( this );
        this.lastFingerSpacingTime = 0;
        this.fingerSpacingBuffer = 0;
        this.zoomLevel = 1;
        setZoomHardness( DEFAULT_ZOOM_HARDNESS );
    }
    
    public void setMaxZoom(float maxZoom) {
        this.maxZoom = maxZoom;
    }
    
    public void setZoomHardness(float zoomHardness) {
        this.zoomIncrement = Math.round( zoomHardness * FINGER_SPACING_ZOOM_INCREMENT );
    }
    
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if ( !isPrepared() ) {
            return true;
        }
        if ( event.getAction() == MotionEvent.ACTION_UP ) {
            fingerSpacingBuffer = 0;
            return true;
        }
        if ( isTwoFingersTouchEvent( event ) ) {
            int newZoomLevel = performTwoFingersZoom( event );
            recalculateZoom( newZoomLevel );
        }
        return true;
    }
    
    private boolean isTwoFingersTouchEvent(MotionEvent event) {
        return event.getPointerCount() == 2;
    }
    
    private int performTwoFingersZoom(MotionEvent event) {
        int newZoomLevel = zoomLevel;
        float currentFingerSpacingTime = getFingerSpacing( event );
        fingerSpacingBuffer += currentFingerSpacingTime - lastFingerSpacingTime;
        if ( fingerSpacingBuffer >= FINGER_SPACING_DELTA_FOR_ZOOM && maxZoom > zoomLevel ) {
            newZoomLevel += zoomIncrement;
            fingerSpacingBuffer = 0;
        } else if ( fingerSpacingBuffer <= -FINGER_SPACING_DELTA_FOR_ZOOM && zoomLevel > 1 ) {
            newZoomLevel -= zoomIncrement;
            ;
            fingerSpacingBuffer = 0;
        }
        lastFingerSpacingTime = currentFingerSpacingTime;
        return newZoomLevel;
    }
    
    private void recalculateZoom(int newZoomLevel) {
        if ( newZoomLevel == zoomLevel ||
                newZoomLevel < 0 ||
                newZoomLevel > maxZoom) {
            return;
        }
        zoomLevel = newZoomLevel;
        notifyZoomChanged( zoomLevel );
    }
    
    private float getFingerSpacing(MotionEvent event) {
        float x = event.getX( 0 ) - event.getX( 1 );
        float y = event.getY( 0 ) - event.getY( 1 );
        return (float) Math.sqrt( x * x + y * y );
    }
    
    public abstract void notifyZoomChanged(int zoom);
    
    public abstract boolean isPrepared();
    
    }
    

    For Camera:

    public class SimpleZoomHandler extends AbstractZoomHandler {
    
    private IZoomHandlerListener zoomHandlerListener;
    
    SimpleZoomHandler(View touchableView) {
        super( touchableView );
    }
    
    public void setZoomHandlerListener(IZoomHandlerListener zoomHandlerListener) {
        this.zoomHandlerListener = zoomHandlerListener;
    }
    
    @Override
    public void notifyZoomChanged(int zoom) {
        zoomHandlerListener.onZoomChanged( zoom );
    }
    
    @Override
    public boolean isPrepared() {
        return zoomHandlerListener != null;
    }
    
    public interface IZoomHandlerListener {
    
        void onZoomChanged(int newZoom);
    
    }
    }
    

    And for Camera2:

    public class ActiveArrayZoomHandler extends AbstractZoomHandler {
    
    private IZoomHandlerListener zoomHandlerListener;
    private Rect activeArraySize;
    
    ActiveArrayZoomHandler(View touchableView) {
        super( touchableView );
    }
    
    public void setZoomHandlerListener(IZoomHandlerListener zoomHandlerListener) {
        this.zoomHandlerListener = zoomHandlerListener;
    }
    
    public void setActiveArraySize(Rect activeArraySize) {
        this.activeArraySize = activeArraySize;
    }
    
    
    @Override
    public void notifyZoomChanged(int zoom) {
        int minW = (int) (activeArraySize.width() / maxZoom);
        int minH = (int) (activeArraySize.height() / maxZoom);
        int difW = activeArraySize.width() - minW;
        int difH = activeArraySize.height() - minH;
        int cropW = difW / 100 * zoomLevel;
        int cropH = difH / 100 * zoomLevel;
        cropW -= cropW & 3;
        cropH -= cropH & 3;
        Rect zoomRect = new Rect( cropW, cropH, activeArraySize.width() - cropW, activeArraySize.height() - cropH );
        zoomHandlerListener.onZoomChanged( zoomRect );
    }
    
    @Override
    public boolean isPrepared() {
        return zoomHandlerListener != null && activeArraySize != null;
    }
    
    public interface IZoomHandlerListener {
    
        void onZoomChanged(Rect zoom);
    
    }
    }
    

    And their respective Builder to make it fluent interface. For camera API:

    public class SimpleZoomHandlerBuilder {
    
    private SimpleZoomHandler simpleZoomHandler;
    
    public static SimpleZoomHandlerBuilder forView(View touchableView) {
        return new SimpleZoomHandlerBuilder( touchableView );
    }
    
    private SimpleZoomHandlerBuilder(View touchableView) {
        simpleZoomHandler = new SimpleZoomHandler( touchableView );
    }
    
    public SimpleZoomHandlerBuilder setZoomListener(SimpleZoomHandler.IZoomHandlerListener listener) {
        simpleZoomHandler.setZoomHandlerListener( listener );
        return this;
    }
    
    public SimpleZoomHandlerBuilder setMaxZoom(float maxZoom) {
        simpleZoomHandler.setMaxZoom( maxZoom );
        return this;
    }
    
    public SimpleZoomHandler build() {
        return simpleZoomHandler;
    }
    
    }
    

    And for camera2 API:

    public class ActiveArrayZoomHandlerBuilder {
    
    private ActiveArrayZoomHandler activeArrayZoomHandler;
    
    public static ActiveArrayZoomHandlerBuilder forView(View touchableView) {
        return new ActiveArrayZoomHandlerBuilder( touchableView );
    }
    
    private ActiveArrayZoomHandlerBuilder(View touchableView) {
        activeArrayZoomHandler = new ActiveArrayZoomHandler( touchableView );
    }
    
    public ActiveArrayZoomHandlerBuilder setZoomListener(ActiveArrayZoomHandler.IZoomHandlerListener listener) {
        activeArrayZoomHandler.setZoomHandlerListener( listener );
        return this;
    }
    
    public ActiveArrayZoomHandlerBuilder setMaxZoom(float maxZoom) {
        activeArrayZoomHandler.setMaxZoom( maxZoom );
        return this;
    }
    
    public ActiveArrayZoomHandlerBuilder setActiveArraySize(Rect activeArraySize) {
        activeArrayZoomHandler.setActiveArraySize( activeArraySize );
        return this;
    }
    
    public ActiveArrayZoomHandler build() {
        return activeArrayZoomHandler;
    }
    
    }
    
    0 讨论(0)
提交回复
热议问题