Make Camera preview better for all the phones

心不动则不痛 提交于 2020-01-25 20:33:26

问题


I have an camera app which calculates the screen size and display the preview. My Preview class works fine for phone which as 720*1080 and 1080*1920 screen resolution when app starts initially. If I go to next activity and come back to camera activity. Preview works only for 720*1080 screen, but not for 1080*1920. It fails in SurfaceChanged method in setting the parameters.

// My CameraPreview Class

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {

    protected List<Camera.Size> mSupportedPreviewSizes;
    private Camera.Size mPreviewSize;
    private Camera mCamera;

    public CameraPreview(Activity activity, Camera camera) {
        super(activity);
        mCamera = camera;
        SurfaceHolder mHolder = getHolder();
        mHolder.addCallback(this);
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        mHolder.setKeepScreenOn(true);
        setCamera(mCamera);
        }

    public void setCamera(Camera camera) {
        mCamera = camera;
        if (mCamera != null) {
            mCamera.setDisplayOrientation(getDisplayOrientation());
            mSupportedPreviewSizes =  mCamera.getParameters().getSupportedPreviewSizes();
            requestLayout();

            Camera.Parameters parameters = mCamera.getParameters();

            List<String> focusModes =   parameters.getSupportedFocusModes();
                       if(focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)){
                parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
                mCamera.setParameters(parameters);
                }

Setting the exposure Compensation in a unique way.

parameters.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_AUTO);
            int exposureCompensation = parameters.getMinExposureCompensation();
            int exposureCompensation2 = parameters.getMaxExposureCompensation();
            int exposureCompensationFinal = (exposureCompensation + exposureCompensation2)/2;

            parameters.setExposureCompensation(exposureCompensationFinal);

            mCamera.setParameters(parameters);
               }

            }


    public int getDisplayOrientation(){
        Camera.CameraInfo info = new Camera.CameraInfo();
        Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_FRONT, info);
        WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
        Display display = wm.getDefaultDisplay();

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

        int result;
        if(info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT){
            result = (info.orientation + degree) % 360;
            result = (360 - result) % 360;
        }else{
            result = (info.orientation - degree + 360) % 360;
        }
        return result;
    }


    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        try {
            if (mCamera != null) {
                   mCamera.setPreviewDisplay(holder);

                          }

        } catch (IOException e) {
            Log.d("DG_DEBUG", "Error setting camera preview in surfaceCreated: " + e.getMessage());
        }
    }


    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);

         final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
        setMeasuredDimension(width, height);

        if (mSupportedPreviewSizes != null) {
            mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);

        }
    }

    private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int width, int height) {

        Camera.Size optimalSize = null;
        final double ASPECT_TOLERANCE = 0.1;
        double targetRatio = (double) height / width;

        double minDiff = Double.MAX_VALUE;

        for (Camera.Size size : sizes) {
            double ratio = (double) size.width / size.height;
            if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
            if (Math.abs(size.height - height) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - height);
                }
        }
        if (optimalSize == null) {
            minDiff = Double.MAX_VALUE;
            for (Camera.Size size : sizes) {
                if (Math.abs(size.height - height) < minDiff) {
                    optimalSize = size;
                    minDiff = Math.abs(size.height - height);
                }
            }
        }
        if (optimalSize == null) {
            Log.d("getOptimalPreviewSize", "Optimal size not found");
        } else {
            Log.d("getOptimalPreviewSize",
                    String.format(
                            "getOptimalPreviewSize result: width = %d, height = %d for input width = %d, height = %d",
                            optimalSize.width, optimalSize.height, width,
                            height));
        }

        return optimalSize;
    }

    private Camera.Size getOptimalPictureSize() {
        if (mCamera == null) {
            return null;
        }

        List<Camera.Size> cameraSizes = mCamera.getParameters().getSupportedPictureSizes();
        Camera.Size optimalSize = mCamera.new Size(0, 0);
         double previewRatio = (double) mPreviewSize.width / mPreviewSize.height;

        for (Camera.Size size : cameraSizes) {
            double ratio = (double) size.width / size.height;
            if (Math.abs(ratio - previewRatio) > 0.01f)
                continue;
            if (size.height > optimalSize.height) {
                 optimalSize = size;
            }
        }

        if (optimalSize.height == 0) {
           for (Camera.Size size : cameraSizes) {
                if (size.height > optimalSize.height) {
                    optimalSize = size;
                }
            }
        }
        return optimalSize;
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        if (mCamera != null) {

            Camera.Size optimalSize = getOptimalPictureSize();
            mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();

            requestLayout();

            Camera.Parameters parameters = mCamera.getParameters();

            parameters.setPictureSize(mPreviewSize.width, mPreviewSize.height);

            parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
            requestLayout();

            parameters.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_AUTO);

// It fails at this step. It says Failed to set the parameters.I get this error if i'm using the Nexus 5 for testing app. But it works perfectly for 720*1080 resolution.

             mCamera.setParameters(parameters);
                       mCamera.startPreview();
                   }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        try {
            if (mCamera != null) {
                mCamera.stopPreview();
                mCamera.release();
            }
        } catch (Exception e) {
            Log.d("SurfaceDestroyed", " Error handling surface destroy method");
        }

    }
}

Log Details

02-03 19:20:09.328  18839-18839/ com.android.example E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.android.example, PID: 18839
    java.lang.RuntimeException: setParameters failed
            at android.hardware.Camera.native_setParameters(Native Method)
            at android.hardware.Camera.setParameters(Camera.java:1876)
            at com.android.example.CameraPreview.surfaceChanged(CameraPreview.java:267)
            at android.view.SurfaceView.updateWindow(SurfaceView.java:590)
            at android.view.SurfaceView.onWindowVisibilityChanged(SurfaceView.java:238)
            at android.view.View.dispatchWindowVisibilityChanged(View.java:8697)
            at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1269)
            at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1269)
            at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1269)
            at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1269)
            at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1269)
            at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1311)
            at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1054)
            at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5779)
            at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
            at android.view.Choreographer.doCallbacks(Choreographer.java:580)
            at android.view.Choreographer.doFrame(Choreographer.java:550)
            at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
            at android.os.Handler.handleCallback(Handler.java:739)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5221)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)

来源:https://stackoverflow.com/questions/28305367/make-camera-preview-better-for-all-the-phones

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