在几台Android设备上延伸的相机预览

San*_*rma 27 camera android

我正在为Android应用程序制作自定义相机,如"SnapChat",但相机预览在诸如(Moto g第二代,一个+一个)但很少(三星s3,三星s4)等少数设备上延伸.我使用以下参考 全屏相机显示/预览不保持纵横比 - 图像歪斜,拉伸以适应屏幕.但这对我100%没有帮助.我在分享屏幕.

三星摩托G第二代的拉伸图像是. 在此输入图像描述 在此输入图像描述

没有拉伸的三星S3图像是Above

private void setPreviewLayout() {
    if (null == mCamera) {
        return;
    }
    Camera.Parameters parameters = null;
    Camera.Size size = null;
    try {
        int screenWidth = (int) getResources().getDisplayMetrics().widthPixels;
        int screenHeight = (int) getResources().getDisplayMetrics().heightPixels;
        parameters = mCamera.getParameters();
        size = getOptimalPreviewSize(mCamera.getParameters().getSupportedPreviewSizes(), screenWidth, screenHeight);
        if (size != null) {

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

        }

        parameters.setPictureSize(screenHeight, screenWidth);
        ;
        mCamera.setParameters(parameters);
        if (on && currentCameraId == Camera.CameraInfo.CAMERA_FACING_BACK) {
            parameters.setFlashMode(Camera.Parameters.FLASH_MODE_ON);
        } else {
            parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
        }
        parameters.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_AUTO);
        parameters.setExposureCompensation(0);
        parameters.setPictureFormat(ImageFormat.JPEG);
        parameters.setJpegQuality(100);
        List<String> focusModes = parameters.getSupportedFocusModes();
        if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
            parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
        } else if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
            parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
        }
        mCamera.setParameters(parameters);
        /*
         * camera.setPreviewDisplay(surfaceHolder); camera.startPreview();
         */

    } catch (Exception e) {
        e.printStackTrace();
    }

}
private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
    final double ASPECT_TOLERANCE = 0.1;
    double targetRatio = (double) h / w;

    if (sizes == null)
        return null;

    Camera.Size optimalSize = null;
    double minDiff = Double.MAX_VALUE;

    int targetHeight = h;

    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 - targetHeight) < minDiff) {
            optimalSize = size;
            minDiff = Math.abs(size.height - targetHeight);
        }
    }

    if (optimalSize == null) {
        minDiff = Double.MAX_VALUE;
        for (Camera.Size size : sizes) {
            if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }
    }
    return optimalSize;
}
Run Code Online (Sandbox Code Playgroud)

Ale*_*ohn 19

使用getOptimalPreviewSize()很重要,但它并不能解决所有布局中所有设备的所有拉伸问题.您必须准备好稍微裁剪预览,以便预览填充屏幕而不会失真.

有不同的技术来强制表面的大小不同于实际的屏幕尺寸,但这个我觉得最容易:

我添加CameraView到我的布局:

public class CameraView extends SurfaceView implements SurfaceHolder.Callback {

public CameraView(Context context, AttributeSet attr) {
    super(context, attr);

    // install a SurfaceHolder.Callback so we get notified when the
    // underlying surface is created and destroyed.
    getHolder().addCallback(this);
}

@Override public void surfaceCreated(SurfaceHolder holder) {
    openCamera();
    bCameraInitialized = false;
}

@Override public void surfaceDestroyed(SurfaceHolder holder) {
    camera.release();
}

@Override public void surfaceChanged(SurfaceHolder holder,
        int format, int w, int h) {
        if (bCameraInitialized) {
            // we will get here after we have resized the surface, see below 
            return;
        }
        cameraSetup(w, h);
        bCameraInitialized = true;
}

private void cameraSetup(int w, int h) {
    // set the camera parameters, including the preview size

    FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
    double cameraAspectRatio = ((double)optimalSize.width)/optimalSize.height;

    if (((double)h)/w > cameraAspectRatio) {
        lp.width = (int)(h/cameraAspectRatio+0.5);
        lp.height = h;
    }
    else {
        lp.height = (int)(w*cameraAspectRatio + 0.5);
        lp.width = w;
        lp.topMargin = (h - lp.height)/2;
    }
    lp.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP;

    setLayoutParams(lp);
    requestLayout();
}
Run Code Online (Sandbox Code Playgroud)

为了强调主要思想,我没有包含错误处理,我没有在这里展示如何使用辅助Looper实际启动摄像头.