Cropping a full screen camera image bitmap into a Surface view height and width

做~自己de王妃 提交于 2021-01-28 05:15:08

问题


I am trying to click only a rectangular portion of the screen from camera using this code:

Java code: package com.example.cameraapplication;

import androidx.appcompat.app.AppCompatActivity;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.hardware.Camera;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

import java.io.IOException;

public class CameraActivity extends Activity implements Camera.PictureCallback, SurfaceHolder.Callback {

    public static final String EXTRA_CAMERA_DATA = "camera_data";

    private static final String KEY_IS_CAPTURING = "is_capturing";

    private Camera mCamera, dummyCamera;
    private ImageView mCameraImage;
    private SurfaceView mCameraPreview,s1;
    private Button mCaptureImageButton;
    private byte[] mCameraData;
    private boolean mIsCapturing;
    private View v1;

    private View.OnClickListener mCaptureImageButtonClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            try {
//                mCamera.release();
//                mCamera = Camera.open();
//                mCamera.setPreviewDisplay(mCameraPreview.getHolder());
//                mCamera.startPreview();
//                final SurfaceHolder surfaceHolder = mCameraPreview.getHolder();
//                surfaceHolder.addCallback(CameraActivity.this);
//                surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
                captureImage();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    };

    private View.OnClickListener mRecaptureImageButtonClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            setupImageCapture();
        }
    };

    private View.OnClickListener mDoneButtonClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (mCameraData != null) {
                Intent intent = new Intent();
                intent.putExtra(EXTRA_CAMERA_DATA, mCameraData);
                setResult(RESULT_OK, intent);
            } else {
                setResult(RESULT_CANCELED);
            }
            finish();
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_camera);

        mCameraImage = (ImageView) findViewById(R.id.camera_image_view);
        mCameraImage.setVisibility(View.INVISIBLE);
        v1 = findViewById(R.id.v1);

        mCameraPreview = (SurfaceView) findViewById(R.id.preview_view);
        s1 = (SurfaceView) findViewById(R.id.preview_view_1);
//        final SurfaceHolder surfaceHolder = mCameraPreview.getHolder();
//        surfaceHolder.addCallback(this);
//        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

        final SurfaceHolder surfaceHolder2 = s1.getHolder();
        surfaceHolder2.addCallback(this);
        surfaceHolder2.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

        mCaptureImageButton = (Button) findViewById(R.id.capture_image_button);
        mCaptureImageButton.setOnClickListener(mCaptureImageButtonClickListener);

        final Button doneButton = (Button) findViewById(R.id.done_button);
        doneButton.setOnClickListener(mDoneButtonClickListener);

        mIsCapturing = true;
    }

    @Override
    protected void onSaveInstanceState(Bundle savedInstanceState) {
        super.onSaveInstanceState(savedInstanceState);

        savedInstanceState.putBoolean(KEY_IS_CAPTURING, mIsCapturing);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);

        mIsCapturing = savedInstanceState.getBoolean(KEY_IS_CAPTURING, mCameraData == null);
        if (mCameraData != null) {
            setupImageDisplay();
        } else {
            setupImageCapture();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();

        if (mCamera == null) {
            try {
                mCamera = Camera.open();
//                dummyCamera = mCamera;
                mCamera.setPreviewDisplay(s1.getHolder());
//                dummyCamera.setPreviewDisplay(s1.getHolder());
                if (mIsCapturing) {
//                    dummyCamera.startPreview();
                    mCamera.startPreview();
                }
            } catch (Exception e) {
                e.printStackTrace();
                Toast.makeText(CameraActivity.this, "Unable to open camera.", Toast.LENGTH_LONG)
                        .show();
            }
        }
    }

    @Override
    protected void onPause() {
        super.onPause();

        if (mCamera != null) {
            mCamera.release();
            mCamera = null;
        }
    }

    @Override
    public void onPictureTaken(byte[] data, Camera camera) {
        mCameraData = data;
        setupImageDisplay();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        if (mCamera != null) {
            try {
//                mCamera.stopPreview();
                mCamera.setPreviewDisplay(holder);
//                dummyCamera.setPreviewDisplay(s1.getHolder());
                if (mIsCapturing) {
                    mCamera.startPreview();
//                    dummyCamera.startPreview();
                }
            } catch (IOException e) {
                e.printStackTrace();
                Toast.makeText(CameraActivity.this, "Unable to start camera preview.", Toast.LENGTH_LONG).show();
            }
        }
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
    }

    private void captureImage() {
        mCamera.takePicture(null, null, this);
    }

    private void setupImageCapture() {
        try {
            mCameraImage.setVisibility(View.INVISIBLE);
            mCameraPreview.setVisibility(View.VISIBLE);
            s1.setVisibility(View.VISIBLE);
            v1.setVisibility(View.VISIBLE);
            mCamera.setPreviewDisplay(s1.getHolder());
            mCamera.startPreview();
            mCaptureImageButton.setText(R.string.capture_image);
            mCaptureImageButton.setOnClickListener(mCaptureImageButtonClickListener);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    private void setupImageDisplay() {
        Bitmap bitmap = BitmapFactory.decodeByteArray(mCameraData, 0, mCameraData.length);
        Bitmap resizedbitmap1=Bitmap.createBitmap(bitmap, 0,0,mCameraPreview.getWidth(), mCameraPreview.getHeight());

        mCameraImage.setImageBitmap(resizedbitmap1);
        mCamera.stopPreview();
        mCameraPreview.setVisibility(View.INVISIBLE);
        s1.setVisibility(View.INVISIBLE);
        v1.setVisibility(View.INVISIBLE);
        mCameraImage.setVisibility(View.VISIBLE);
        mCaptureImageButton.setText(R.string.recapture_image);
        mCaptureImageButton.setOnClickListener(mRecaptureImageButtonClickListener);
    }
}

Layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/transparent"
    android:orientation="vertical">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/capturing_image" />

    <FrameLayout
        android:id="@+id/camera_frame"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">

        <ImageView
            android:id="@+id/camera_image_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

        <SurfaceView
            android:id="@+id/preview_view_1"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

        <View
            android:id="@+id/v1"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#CCFFFFFF"/>

        <SurfaceView
            android:id="@+id/preview_view"
            android:layout_margin="80dp"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

<!--        <LinearLayout-->
<!--            android:layout_width="match_parent"-->
<!--            android:background="@android:color/transparent"-->
<!--            android:layout_height="match_parent">-->
<!--            -->
<!--        </LinearLayout>-->


    </FrameLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:gravity="center"
        android:orientation="horizontal">

        <Button
            android:id="@+id/capture_image_button"
            android:layout_width="150dp"
            android:layout_height="wrap_content"
            android:text="@string/capture_image" />

        <Button
            android:id="@+id/done_button"
            android:layout_width="150dp"
            android:layout_height="wrap_content"
            android:text="@string/done" />
    </LinearLayout>

</LinearLayout>

Here seems to be 2 workarounds:

  1. Either i dynamically set the surface view "camera_image_view" at the time user try to capture screen. But i tried that in onClick and it is not working. Please suggest me some changes if you found any bug in that.

  2. Clicking a full screen image and then cropping it to whatever fits inside the length and width of "camera_image_view". I tried this also but i think there is some flaw in this line:

    Bitmap resizedbitmap1=Bitmap.createBitmap(bitmap, 0,0,mCameraPreview.getWidth(), mCameraPreview.getHeight());

as it is generating some broken colors instead of the cropped image.

So please help me with any of the two ways as both will work for me.

来源:https://stackoverflow.com/questions/61731115/cropping-a-full-screen-camera-image-bitmap-into-a-surface-view-height-and-width

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!