Android custom camera and preview deformation after customization

Keywords: SurfaceView Mobile

Today, I found that the preview interface will be deformed when I customize the camera on the handheld terminal

First look for the problem:

When I adjust the direction of the preview interface, I find that 90 ° rotation can change this problem, but the preview interface as a whole will also cross over. It will be difficult for page customization development, and it is not the final solution, just around it

solve the problem:

Then I found a lot of relevant information from the Internet, and the final result is that the preview angle and camera width and height of the device are not compatible with the device, resulting in

So I started from this aspect, and finally I succeeded, not much code

resolvent:

First of all, I want to initialize SurfaceView

 //Initialize SurfaceView
    public void initSurfaceView() {
//There are some attributes that can change the direction of the camera, but I don't want to fix the problem here
//        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        mSurfaceHolder = mSurfaceView.getHolder();
        mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//Surface view does not maintain its own buffer, waiting for the screen rendering engine to push the content to the user
        mSurfaceHolder.addCallback(this);
    }

Listening events are also relatively simple without complicated logic

//After creation
@Override
public void surfaceCreated(SurfaceHolder holder) {
    //Open Camera 
    mPresenter.openCamera(mContext);
}

//After the change
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    mSurfaceHolder = holder;
}

//After destruction
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    //Free memory
    mPresenter.releaseCamera();
}

Notice that this is the point

//Open Camera 
    @Override
    public void openCamera(Context context, SurfaceHolder mSurfaceHolder, SurfaceView mSurfaceView) {
        mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
        try {
            mCamera.setPreviewDisplay(mSurfaceHolder);
        } catch (IOException e) {
            e.printStackTrace();
        }
//        In order to adapt to the problem of setparams failure of some mobile phones, if it fails, it will not be set
        try {
            Camera.Parameters parameters = mCamera.getParameters();
            Point bestPreviewSizeValue1 = findBestPreviewSizeValue(parameters.getSupportedPreviewSizes());
            parameters.setPreviewSize(bestPreviewSizeValue1.x, bestPreviewSizeValue1.y);
            mCamera.setParameters(parameters);
        } catch (Exception e) {
            Log.d("wangc", "set parameters fail");
        }

        //Make horizontal and vertical screen judgment and then correct the image
        //If it's a vertical screen
        if (context.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {
            mCamera.setDisplayOrientation(90);
        } else {//If it's a horizontal screen
            mCamera.setDisplayOrientation(0);
        }
        //Open Preview
        mCamera.startPreview();
        //If you want to achieve continuous autofocus, you must add
        mCamera.cancelAutoFocus();
    }

Get the corresponding size

/**
 * The size closest to the aspect ratio can be obtained by comparison (if there is the same size, it is preferred)
 * @return Get the size closest to the original width to height ratio
 */
private static Point findBestPreviewSizeValue(List<Camera.Size> sizeList){
    int bestX = 0;
    int bestY = 0;
    int size = 0;
    for (Camera.Size nowSize : sizeList){
        int newX = nowSize.width;
        int newY = nowSize.height;
        int newSize = Math.abs(newX * newX) + Math.abs(newY * newY);
        float ratio = (float) (newY * 1.0 / newX);
        if(newSize >= size && ratio != 0.75){//Make sure the picture is 16:9
            bestX  = newX;
            bestY = newY;
            size = newSize;
        }else if(newSize < size){
            continue;
        }
    }
    if(bestX > 0 && bestY > 0){
        return new Point(bestX,bestY);
    }
    return null;

}

Next, let's have a pleasant development

//Photograph
@Override
public void takePic() {
    mCamera.takePicture(null, null, new Camera.PictureCallback() {
        @Override
        public void onPictureTaken(byte[] data, Camera camera) {

        }
    });
}

 

Posted by mindspin311 on Mon, 06 Jan 2020 02:36:35 -0800