繁体   English   中英

使用android camera2在相机预览中显示矩形并在其中裁剪图像

[英]Show rectangle in camera preview and crop image within it using android camera2

我一直在努力实现的东西像这样采用了android camera2。

我希望在我的相机预览上加载一个矩形,然后按一个按钮捕获图像,然后在矩形预览中裁剪图像。 我已经尝试了很多我能找到的解决方案,但大多数都使用了弃用的android hardware.camera而不是camera2。 我可以用camera2和textureview找到的那些没有裁剪的代码。 在上图中,我使用在photoshop中制作的图像在我的纹理视图上放置了一个叠加层。 那么我应该如何在矩形范围内裁剪它呢?

谢谢。

要添加矩形,您只需在xml布局文件中定义图像并将其放置在预览的中心。

裁剪使用SCALAR_CROP_REGION:

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

试试这个代码,它适合我

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用于相机功能。
  2. MoveViewTouchListener是用于在相机表面视图上移动方形图像的类。
  3. 裁剪动作在pictureCallback内部起作用;

暂无
暂无

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

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