如何使用Camera类旋转捕获的图像

时间:2018-06-05 11:09:41

标签: android android-camera

我正在尝试使用Camera类和SurfaceView来实现自定义相机。但相机拍摄的图像会旋转。 SurfaceView中的预览也在旋转,但在代码中我使用 setCameraDisplayOrientation()方法修复了它。下面是在屏幕和图像中生成的图像。我拍了截图。

surfaceView:Surfaceview-preview of camera ImageView:imageview- after capture

我正在使用的代码是:

public class CustomCameraActivity extends AppCompatActivity implements PictureCallback, SurfaceHolder.Callback
{

    private Camera mCamera;
    private ImageView mCameraImage;
    private SurfaceView mCameraPreview;
    private Button mCaptureImageButton;
    private byte[] mCameraData;
    private boolean mIsCapturing;

    private OnClickListener mCaptureImageButtonClickListener = new OnClickListener() {
    @Override
    public void onClick(View v) {
        App.getInstance().setCapturedPhotoData(null);
        captureImage();
    }
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_custom_camera);


    mImgViewCover = (ImageView) findViewById(R.id.imgVw_customCameraCover);

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


    mCameraPreview = (SurfaceView) findViewById(R.id.preview_view);
    final SurfaceHolder surfaceHolder = mCameraPreview.getHolder();
    surfaceHolder.addCallback(this);

    if(Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB)
        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

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

    mIsCapturing = true;
    }

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

    if (mCamera == null) {
        try {
        mCamera = Camera.open();
        mCamera.setPreviewDisplay(mCameraPreview.getHolder());
        if (mIsCapturing) {
            mCamera.startPreview();
        }
        } catch (Exception e) {
        Toast.makeText(CustomCameraActivity.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 (holder.getSurface() == null)
        return;

    try {  mCamera.stopPreview();
    } catch (Exception e) {   }

    if (mCamera != null) {
        try {
        Camera.Parameters parameters = mCamera.getParameters();

        List<Size> sizes = parameters.getSupportedPreviewSizes();
         Size optimalSize = getOptimalPreviewSize(sizes, width, height);



        parameters.setPreviewSize(optimalSize.width, optimalSize.height);

        mCamera.setParameters(parameters);

        setCameraDisplayOrientation(this, Camera.CameraInfo.CAMERA_FACING_BACK, mCamera ); 

        if (mIsCapturing) {
            mCamera.startPreview();
        }
        } catch (Exception e) {
        Toast.makeText(CustomCameraActivity.this, "Unable to start camera preview.", Toast.LENGTH_LONG).show();
        }
    }
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder)
    {
    try {
        mCamera = Camera.open();
        mCamera.setPreviewDisplay(holder);
    } catch (IOException exception) {
        mCamera.release();
        mCamera = null;
    }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
    if (mCamera != null)
    {  mCamera.stopPreview();
        mCamera.release();
        mCamera = null;}
    }

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


    }

    private void setupImageCapture() {
    mCameraImage.setVisibility(View.INVISIBLE);
    mCameraPreview.setVisibility(View.VISIBLE);
    mCamera.startPreview();
    mCaptureImageButton.setText("capture image");
    mCaptureImageButton.setOnClickListener(mCaptureImageButtonClickListener);
    }

    private void setupImageDisplay() {
    Bitmap bitmap = BitmapFactory.decodeByteArray(mCameraData, 0, mCameraData.length);
         mCameraImage.setImageBitmap(bitmap);


    mCamera.stopPreview();
    mCameraPreview.setVisibility(View.INVISIBLE);
    mCameraImage.setVisibility(View.VISIBLE);

    if (mCameraData != null) {
        Intent intent = new Intent();
        intent.putExtra(EXTRA_CAMERA_DATA, mCameraData);
        setResult(RESULT_OK, intent);

         } else {
        setResult(RESULT_CANCELED);
    }

    }


     private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
    final double ASPECT_TOLERANCE = 0.5;
    double targetRatio = (double) w / h;
    if (sizes == null) return null;
    Size optimalSize = null;
    double minDiff = Double.MAX_VALUE;
    int targetHeight = h;
    // Try to find an size match aspect ratio and size
    for (Size size : sizes) {
        double ratio = (double) size.width / size.height;
        if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
        if (Math.abs(size.height - targetHeight) < minDiff) {
        optimalSize = size;
        minDiff = Math.abs(size.height - targetHeight);
        }
    }
    // Cannot find the one match the aspect ratio, ignore the requirement
    if (optimalSize == null) {
        minDiff = Double.MAX_VALUE;
        for (Size size : sizes) {
        if (Math.abs(size.height - targetHeight) < minDiff) {
            optimalSize = size;
            minDiff = Math.abs(size.height - targetHeight);
        }
        }
    }
    return optimalSize;
    }


    public static void setCameraDisplayOrientation(Context context,
                           int cameraId, android.hardware.Camera camera) {

    android.hardware.Camera.CameraInfo info =
        new android.hardware.Camera.CameraInfo();

    android.hardware.Camera.getCameraInfo(cameraId, info);

    int rotation =  ((Activity)context).getWindowManager().getDefaultDisplay().getRotation();
    int degrees = 0;

    switch (rotation) {
        case Surface.ROTATION_0: degrees = 0; break;
        case Surface.ROTATION_90: degrees = 90; break;
        case Surface.ROTATION_180: degrees = 180; break;
        case Surface.ROTATION_270: degrees = 270; break;
    }

    int result;
    if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
        result = (info.orientation + degrees) % 360;
        result = (360 - result) % 360;  // compensate the mirror
    } else {  // back-facing
        result = (info.orientation - degrees + 360) % 360;
    }
    camera.setDisplayOrientation(result);
    // camera.getParameters().setRotation(result);

    }

}

我可以在使用代码显示之前将位图旋转到90,然后使用代码:

 public static Bitmap rotateImage(Bitmap img, int degree) {
    Matrix matrix = new Matrix();
    matrix.postRotate(degree);
    Bitmap rotatedImg = Bitmap.createBitmap(img, 0, 0, img.getWidth(), img.getHeight(), matrix, true);
    img.recycle();
    return rotatedImg;
}

但它不应该是解决问题的正确方法。那么,我该如何修复它并在imageView中显示非旋转图像?

2 个答案:

答案 0 :(得分:1)

使用这种方式使用表面视图Java代码

打开相机
public class CameraOverlayActivity extends AppCompatActivity implements SurfaceHolder.Callback {
    Camera camera;
    SurfaceView surfaceView;
    SurfaceHolder surfaceHolder;
    boolean previewing = false;
    LayoutInflater controlInflater = null;

    private File videoPath;
    private ImageView imgCapture;
    int camBackId;
    String strVideoFolderPath;
    private ProgressDialog progressDialog;
    Camera.Parameters parameters;
    public boolean hasFlash;
    public boolean camRotation = false;
    private RelativeLayout relativeLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_camera_overlay);

        relativeLayout = findViewById(R.id.control);

        camBackId = Camera.CameraInfo.CAMERA_FACING_BACK;
        hasFlash = this.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
        surfaceView = findViewById(R.id.surface);
        progressDialog = new ProgressDialog(this);
        progressDialog.setTitle(null);
        progressDialog.setCancelable(false);
        surfaceHolder = surfaceView.getHolder();
        surfaceHolder.addCallback(this);
        strVideoFolderPath = Environment.getExternalStorageDirectory().getAbsolutePath();
        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        controlInflater = LayoutInflater.from(getBaseContext());
        videoPath = new File(Environment.getExternalStorageDirectory() + "/sw/raw");
        if (videoPath.exists()) {
            if (videoPath.isDirectory()) {
                if (videoPath.listFiles().length != 0) {
                    String[] children = videoPath.list();
                    for (int i = 0; i < children.length; i++) {
                        new File(videoPath, children[i]).delete();
                    }
                }
            }
        }
        if (!videoPath.exists()) {
            videoPath.mkdirs();
        }

        imgCapture = findViewById(R.id.img_capture);
        imgCapture.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (camera != null) {
                    if (previewing) {
                        System.gc();
                        try {
                            capturePhoto();
                        } catch (Exception e) {
                            Log.v("ERRORR", e.getMessage());
                            e.printStackTrace();
                        }
                    }
                }
            }
        });

    }

    public void capturePhoto() throws Exception {
        camera.takePicture(null, null, myPictureCallback_JPG);

    }

    @Override
    protected void onResume() {
        super.onResume();
        Display display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
    }

    Camera.PictureCallback myPictureCallback_JPG = new Camera.PictureCallback() {

        @Override
        public void onPictureTaken(byte[] arg0, Camera arg1) {
            // TODO Auto-generated method stub
            FileOutputStream outStream = null;
            //camera.startPreview();
            try {
                Date date = new Date();
                String filename = "/rec" + date.toString().replace(" ", "_").replace(":", "_") + ".jpg";
                filename = filename.replace("+", "");
                File file = new File(Environment.getExternalStorageDirectory() + "/Switch It");
                if (!file.exists())
                    file.mkdirs();
                outStream = new FileOutputStream(file + filename);
                outStream.write(arg0);
                outStream.close();
                Log.v("File_Path", file.getAbsolutePath());
                Intent returnIntent = new Intent();
                returnIntent.putExtra("img_capture", file.getAbsolutePath() + filename);
                setResult(Activity.RESULT_OK, returnIntent);
                finish();
            } catch (FileNotFoundException e) {
                Log.e("ERROR 1", e.getMessage());
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
                Log.e("ERROR 2", e.getMessage());
            } finally {
            }
        }
    };


    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
                               int height) {
        // TODO Auto-generated method stub
        if (previewing) {
            camera.stopPreview();
            previewing = false;
        }

        if (camera != null) {
            try {
                camera.setPreviewDisplay(surfaceHolder);
                parameters = camera.getParameters();
                if (getPackageManager().hasSystemFeature("android.hardware.camera.autofocus")) {
                    parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
                }

                camera.startPreview();
                if (hasFlash) {
                    parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
                }
                camera.setParameters(parameters);
                previewing = true;

            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        camera = Camera.open();
        if (android.os.Build.VERSION.SDK_INT > 7) {
            Display display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
            if (display.getRotation() == Surface.ROTATION_0) {
                camera.setDisplayOrientation(90);
                camRotation = true;
            }
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        if (camera != null) {
            camera.stopPreview();
            camera.release();
            camera = null;
            previewing = false;
        }
    }

}

答案 1 :(得分:0)

根据您的要求旋转图像时,只需旋转imageview角度您可以旋转ImageView使用此

mImageView.setRotation(yourRequiredAngle)

希望它有所帮助。