相机歪斜并旋转

时间:2016-10-29 18:37:52

标签: android android-camera surfaceview

我第一次使用表面视图和表面支架,对两者都有非常粗略的了解,在surfaceview中的实时图像预览是倾斜和旋转的,在搜索时我发现我需要设置CameraParameter但我能理解它有效,也有任何指导理解Camera2 api

public class CamActivity extends AppCompatActivity implements SurfaceHolder.Callback{

Camera mCamera;
SurfaceView surfaceView;
private SurfaceHolder mHolder;
FloatingActionButton cam;
private static final int pRequestCode = 5002;
private static final String[] mPermissions = {Manifest.permission.CAMERA, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_EXTERNAL_STORAGE};


@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.cam_layout);
    checkCameraHardware();
    checkPermissions();


    View decorView = getWindow().getDecorView();
    int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN;
    decorView.setSystemUiVisibility(uiOptions);

    surfaceView = (SurfaceView) findViewById(R.id.camera_preview);
    mHolder = surfaceView.getHolder();
    mHolder.addCallback(this);
    mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    cam = (FloatingActionButton) findViewById(R.id.fabCamera);
    cam.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    mCamera.takePicture(null, null, mPicture);
                }
            }
    );
}

private boolean checkCameraHardware() {
    if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
        // this device has a camera
        return true;
    } else {
        // no camera on this device
        return false;
    }
}

private void checkPermissions() {
    if (ContextCompat.checkSelfPermission(this, mPermissions[0]) != PackageManager.PERMISSION_GRANTED
            ||ContextCompat.checkSelfPermission(this, mPermissions[1]) != PackageManager.PERMISSION_GRANTED
            ||ContextCompat.checkSelfPermission(this, mPermissions[2]) != PackageManager.PERMISSION_GRANTED
            ||ContextCompat.checkSelfPermission(this, mPermissions[3]) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this, mPermissions, pRequestCode);
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    switch (requestCode) {
        case pRequestCode: {
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                Toast.makeText(this,"Camera Allowed",Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(this,"Camera Denied",Toast.LENGTH_SHORT).show();
            }
            if (grantResults.length > 0 && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
                Toast.makeText(this,"Location Allowed",Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(this,"Location Denied",Toast.LENGTH_SHORT).show();
            }
            if (grantResults.length > 0 && grantResults[2] == PackageManager.PERMISSION_GRANTED) {
                Toast.makeText(this,"Microphone Allowed",Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(this,"Microphone Denied",Toast.LENGTH_SHORT).show();
            }
            if (grantResults.length > 0 && grantResults[3] == PackageManager.PERMISSION_GRANTED) {
                Toast.makeText(this,"Storage Allowed",Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(this,"Storage Denied",Toast.LENGTH_SHORT).show();
            }
            return;
        }
    }
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
    try {
        mCamera = Camera.open();
    }
    catch (Exception e){
    }

    Camera.Parameters parameters = mCamera.getParameters();
    parameters.set("orientation", "portrait");
    mCamera.setParameters(parameters);

    try {
        mCamera.setPreviewDisplay(mHolder);
        mCamera.startPreview();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    if (mHolder.getSurface() == null){
        // preview surface does not exist
        return;
    }
    try {
        mCamera.stopPreview();
    } catch (Exception e){
    }

    try {
        mCamera.setPreviewDisplay(mHolder);
        mCamera.startPreview();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

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

private Camera.PictureCallback mPicture = new Camera.PictureCallback() {

    @Override
    public void onPictureTaken(byte[] data, Camera camera) {

        File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
        if (pictureFile == null){
            Log.d("", "Error creating media file, check storage permissions: " );
            return;
        }

        try {
            FileOutputStream fos = new FileOutputStream(pictureFile);
            fos.write(data);
            fos.close();
        } catch (FileNotFoundException e) {
            Log.d("", "File not found: " + e.getMessage());
        } catch (IOException e) {
            Log.d("", "Error accessing file: " + e.getMessage());
        }
    }
};

private static File getOutputMediaFile(int type){
    File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_PICTURES), "MyCameraApp");
    if (! mediaStorageDir.exists()){
        if (! mediaStorageDir.mkdirs()){
            Log.d("MyCameraApp", "failed to create directory");
            return null;
        }
    }
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    File mediaFile;
    if (type == MEDIA_TYPE_IMAGE){
        mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_"+ timeStamp + ".jpg");
    } else if(type == MEDIA_TYPE_VIDEO) {
        mediaFile = new File(mediaStorageDir.getPath() + File.separator + "VID_"+ timeStamp + ".mp4");
    } else {
        return null;
    }
    return mediaFile;
}

}

1 个答案:

答案 0 :(得分:0)

对于Camera2 API,您可以检查Android Studio或GitHub中的Android代码示例。

您可以像surfaceCreated()一样解决相机预览旋转和宽高比问题。请注意,您必须正确处理异常:

@Override
public void surfaceCreated(SurfaceHolder holder) {

    // You need to open the camera in a
    // different manner so you can obtain some info from it
    int numberOfCameras = Camera.getNumberOfCameras();
    Camera.CameraInfo info = new Camera.CameraInfo();
    mCamera = null;
    for (int i = 0; i < numberOfCameras; i++) {
        Camera.getCameraInfo(i, info);
        // Open a back camera
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
            try {
                mCamera = Camera.open(i);
                break;
            } catch (RuntimeException e) {
                // Could not open camera
            }
        }
    }
    if (mCamera == null) {
        // No camera found
    }

    Camera.Parameters parameters = mCamera.getParameters();

    // Rotate display
    // Code from here:
    // https://developer.android.com/reference/android/hardware/Camera.html#setDisplayOrientation(int)
    int rotation = activity.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;
    }
    mCamera.setDisplayOrientation(result);

    Camera.Size size = parameters.getPreviewSize();
    // You'll probably want to set the preview
    // width and height to match the preview size
    // aspect ratio that you can obtain by:
    // (double) size.width / (double) size.height
    //
    // Note that if the int result above modulo 180
    // equals 90, you'll have to exchange width for height
    // and vice versa.

    try {
        mCamera.setPreviewDisplay(mHolder);
        mCamera.startPreview();
    } catch (IOException e) {
        e.printStackTrace();
    }
}