skip to Main Content

I have been trying to achieve something like this using android camera2.

I want a rectangle to load on top of my camera preview and once i press a button to capture the image then the image should be cropped within the rectangle preview. I have tried numerous solutions i could find but most of them are using the deprecated android hardware.camera and not camera2. The ones i could find with camera2 and textureview does not have the code for cropping. In the above image, I have put an overlay on my texture view using an image I made in photoshop. So how should i crop it just within the rectangle bounds?

Thanks.

2

Answers


  1. To add the rectangle you can simply define an image in your xml layout file and position it in the centre of your preview.

    Cropping uses the SCALAR_CROP_REGION:

    Rect cropRect = new Rect(0, 0, 1755, 3120);
    captureRequestBuilder.set(CaptureRequest.SCALER_CROP_REGION, cropRect);

    Login or Signup to reply.
  2. Try this code, Its working for me

    MainActivity.java

        package com.example.myapplication;
        import android.app.Activity;
        import android.content.pm.ActivityInfo;
        import android.graphics.Bitmap;
        import android.graphics.BitmapFactory;
        import android.graphics.Matrix;
        import android.hardware.Camera;
        import android.hardware.Camera.PictureCallback;
        import android.os.Bundle;
        import android.util.Log;
        import android.view.GestureDetector;
        import android.view.MotionEvent;
        import android.view.View;
        import android.widget.Button;
        import android.widget.FrameLayout;
        import android.widget.ImageView;
        import android.widget.LinearLayout;
        import android.widget.RelativeLayout;
        import android.widget.Toast;
    
        public class MainActivity extends Activity {
    
        private ImageSurfaceView mImageSurfaceView;
        private Camera camera;
        RelativeLayout rl,cameraLayout;
        LinearLayout saveLayout;
        private FrameLayout cameraPreviewLayout;
        private ImageView capturedImageHolder,saveImage;
        int imageL,imageT,imageW,imageH,width,height,dpsize;
    
        Bitmap resizedBitmap;
        Camera mCamera = null;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    
            cameraPreviewLayout = (FrameLayout)findViewById(R.id.camera_preview);
            capturedImageHolder = (ImageView)findViewById(R.id.captured_image);
    
            rl = findViewById(R.id.rr2);
    
            cameraLayout = findViewById(R.id.cameraLayout);
            saveLayout = findViewById(R.id.saveLayout);
    
            saveImage = findViewById(R.id.saveImage);
    
            width= getWindowManager().getDefaultDisplay().getWidth();
            height= getWindowManager().getDefaultDisplay().getHeight();
    
            camera = checkDeviceCamera();
    
            mImageSurfaceView = new ImageSurfaceView(MainActivity.this, camera);
            cameraPreviewLayout.addView(mImageSurfaceView);
    
            dpsize = (int) (getResources().getDimension(R.dimen._150sdp));
            capturedImageHolder.setX((width-dpsize)/2);
            capturedImageHolder.setY((height -dpsize)/2);
    
            imageL= (int) capturedImageHolder.getX();
            imageT= (int) capturedImageHolder.getY();
            capturedImageHolder.setOnTouchListener(new MoveViewTouchListener(capturedImageHolder));
            Button captureButton = (Button)findViewById(R.id.button);
    
            captureButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    camera.takePicture(null, null, pictureCallback);
                }
            });
        }
    
        private Camera checkDeviceCamera(){
    
            try {
                mCamera = Camera.open();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return mCamera;
        }
        public void resetCamera()
        {
            if(mCamera!=null) {
                mCamera.release();
    
            }
        }
    
        PictureCallback pictureCallback = new PictureCallback() {
            @Override
            public void onPictureTaken(byte[] data, Camera camera) {
                Bitmap b = BitmapFactory.decodeByteArray(data, 0, data.length);
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inJustDecodeBounds = true;
                final int REQUIRED_SIZE = 512;
                int scale = 1;
                int wd= b.getWidth();
                while (wd >=( REQUIRED_SIZE)) {
                    wd= wd/2;
                    scale *= 2;
                }
                options.inSampleSize = scale;
                options.inJustDecodeBounds = false;
                Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length,options);
    
                if(bitmap==null){
                    Toast.makeText(MainActivity.this, "Captured image is empty", Toast.LENGTH_LONG).show();
                    return;
                }
                Matrix matrix = new Matrix();
                matrix.postRotate(90);
                bitmap= Bitmap.createBitmap(bitmap,0,0,bitmap.getWidth(),bitmap.getHeight(),matrix,false);
                int bh= bitmap.getHeight();
                int bw= bitmap.getWidth();
                width= rl.getWidth();
                height= rl.getHeight();
                int l = imageL*bw/width;
                int t = imageT*bh/height;
                int w = capturedImageHolder.getWidth()*bw/width;
                int h = capturedImageHolder.getHeight()*bh/height;
    
                cameraPreviewLayout.setVisibility(View.GONE);
                capturedImageHolder.setVisibility(View.VISIBLE);
                resizedBitmap= Bitmap.createBitmap(bitmap,l,t,w,h);
    
                if(resizedBitmap!=null) {
    
                    cameraLayout.setVisibility(View.GONE);
                    saveLayout.setVisibility(View.VISIBLE);
                    saveImage.setImageBitmap(resizedBitmap);
                }
            }
        };
    
        public class MoveViewTouchListener
                implements View.OnTouchListener
        {
            private GestureDetector mGestureDetector;
            private View mView;
    
    
            public MoveViewTouchListener(View view)
            {
                mGestureDetector = new GestureDetector(view.getContext(), mGestureListener);
                mView = view;
            }
    
            @Override
            public boolean onTouch(View v, MotionEvent event)
            {
                return mGestureDetector.onTouchEvent(event);
            }
    
            private GestureDetector.OnGestureListener mGestureListener = new GestureDetector.SimpleOnGestureListener()
            {
                private float mMotionDownX, mMotionDownY;
    
                @Override
                public boolean onDown(MotionEvent e)
                {
                    mMotionDownX = e.getRawX() - mView.getTranslationX();
                    mMotionDownY = e.getRawY() - mView.getTranslationY();
                    imageL= (int) mView.getX();
                    imageT= (int) mView.getY();
                    Log.d("imageview"," down");
                    return true;
                }
    
                @Override
                public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
                {
                    mView.setTranslationX(e2.getRawX() - mMotionDownX);
                    mView.setTranslationY(e2.getRawY() - mMotionDownY);
                    imageL= (int) mView.getX();
                    imageT= (int) mView.getY();
                    if((distanceX==0)&&(distanceY==0))
                    {
                        Log.d("imageview"," zoomed");
                    }
    
                    return true;
                }
                @Override
                public boolean onSingleTapUp(MotionEvent e) {
                    Log.d("imageview"," tapped");
                    return true;
                }
    
            };
        }
    }
    

    activiy_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/rl"
        >
    
        <RelativeLayout
            android:id="@+id/cameraLayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_alignParentStart="true"
            android:layout_alignParentTop="true"
            android:visibility="visible">
    
            <RelativeLayout
                android:id="@+id/rr2"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:elevation="5sp"
                android:gravity="center">
    
    
                <ImageView
                    android:id="@+id/captured_image"
                    android:layout_width="180sp"
                    android:layout_height="180sp"
                    android:elevation="8sp" />
    
                <FrameLayout
                    android:id="@+id/camera_preview"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_alignParentStart="true"
                    android:layout_alignParentTop="true" />
    
    
            </RelativeLayout>
    
    
            <Button
                android:gravity="center_horizontal"
                android:id="@+id/button"
                android:layout_width="50sp"
                android:layout_height="49dp"
                android:layout_alignParentBottom="true"
                android:layout_centerHorizontal="true"
                android:background="@drawable/squarecamera__camera_snap_selected"
                android:elevation="10dp" />
    
    
        </RelativeLayout>
    
        <LinearLayout
            android:visibility="gone"
            android:id="@+id/saveLayout"
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
                <LinearLayout
                    android:orientation="vertical"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent">
                    <ImageView
                        android:minHeight="200sp"
                        android:minWidth="200sp"
                        android:layout_gravity="center"
                        android:id="@+id/saveImage"
                        android:layout_width="200sp"
                        android:layout_height="200sp" />
    
                </LinearLayout>
        </LinearLayout>
    </RelativeLayout>
    

    ImageSurfaceView.java

        package com.example.myapplication;
    
        import android.content.Context;
        import android.hardware.Camera;
        import android.util.Log;
        import android.view.Display;
        import android.view.Surface;
        import android.view.SurfaceHolder;
        import android.view.SurfaceView;
        import android.view.WindowManager;
    
        import java.io.IOException;
    
        import static android.content.Context.WINDOW_SERVICE;
    
        public class ImageSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
    
        private Camera mCamera;
        private SurfaceHolder surfaceHolder;
        Context context;
        boolean isPreviewRunning = false;
    
        public ImageSurfaceView(Context context, Camera camera) {
            super(context);
            this.mCamera = camera;
            this.context = context;
            this.surfaceHolder = getHolder();
            this.surfaceHolder.addCallback(this);
        }
    
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            try {
                this.mCamera.setPreviewDisplay(holder);
                this.mCamera.startPreview();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            if (isPreviewRunning) {
                mCamera.stopPreview();
            }
    
            Display display = ((WindowManager)context.getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
    
            if(display.getRotation() == Surface.ROTATION_0) {
                mCamera.setDisplayOrientation(90);
            }
    
            if(display.getRotation() == Surface.ROTATION_90) {
            }
    
            if(display.getRotation() == Surface.ROTATION_180) {
            }
    
            if(display.getRotation() == Surface.ROTATION_270) {
    
                mCamera.setDisplayOrientation(180);
            }
    
            previewCamera();
        }
    
    
        public void previewCamera() {
            try {
                mCamera.setPreviewDisplay(surfaceHolder);
                mCamera.startPreview();
                isPreviewRunning = true;
            } catch(Exception e) {
                Log.d("hsfhj", "Cannot start preview", e);
            }
        }
        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            this.mCamera.stopPreview();
            this.mCamera.release();
        }
    }
    
    1. ImageSurfaceView is for camera functions.
    2. MoveViewTouchListener is the class for moving the square image over camera surface view.
    3. The cropping action works inside pictureCallback;
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search