【问题标题】:Camera Preview Stretched on Front Facing Camera在前置摄像头上拉伸的摄像头预览
【发布时间】:2016-07-21 09:37:41
【问题描述】:

您好,我正在开发一个 android 自定义相机应用程序,并面临相机预览在其前置摄像头上的以下设备上拉伸的问题:

  1. 华为荣耀 4c(仅限前置摄像头)
  2. HTC One M7(仅限前置摄像头)
  3. 还有一些其他设备...因为我只有以下设备要测试,所以其他设备也可能存在问题。

问题是摄像头预览与后置摄像头配合得非常好,但只有当我将我的应用程序与前置摄像头一起使用时它才会延伸!


代码

这是我用于相机预览类的代码:

 import android.content.Context;
 import android.graphics.Rect;
 import android.hardware.Camera;
 import android.util.Log;
 import android.view.Gravity;
 import android.view.MotionEvent;
 import android.view.SurfaceHolder;
 import android.view.SurfaceView;
 import android.widget.FrameLayout;
 import android.widget.Toast;
 import java.util.ArrayList;
 import java.util.List;

 public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {

//Variables de' Preview
private SurfaceHolder mHolder;
private List<Camera.Size> mSupportedPreviewSizes;
private Camera.Size mPreviewSize;
private int FOCUS_AREA_SIZE=300;
public static Camera previewCamera;
////////////////////////

//protected LOGGER keys
protected final String EXCEPTION_KEY="xception";
//////////////////////////

public CameraPreview(Context context, Camera camera) {
    super(context);

    //get the camera
    previewCamera = camera;

    // supported preview sizes
    mSupportedPreviewSizes = previewCamera.getParameters().getSupportedPreviewSizes();

    // Install a SurfaceHolder.Callback so we get notified when the
    // underlying surface is created and destroyed.
    mHolder = getHolder();
    mHolder.addCallback(this);
    // deprecated setting, but required on Android versions prior to 3.0
    mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    mHolder.setKeepScreenOn(true);

}


@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
    try{
        //when the surface is created, we can set the camera to draw images in this surfaceholder
        previewCamera.setPreviewDisplay(surfaceHolder);
        previewCamera.startPreview();
    } catch(Exception exp){
        Log.i(EXCEPTION_KEY,"FROM surfaceCreated: "+exp.toString());
    }
}

@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i2, int i3) {
    //before changing the application orientation, you need to stop the preview, rotate and then start it again

    if(mHolder.getSurface() == null)//check if the surface is ready to receive camera data
        return;

    try{
        previewCamera.stopPreview();
    } catch (Exception e){
        //this will happen when you are trying the camera if it's not running
    }

    //now, recreate the camera preview
    try{
        //set the camera preview on every preview change
        setPreview();
        previewCamera.setPreviewDisplay(mHolder);
        previewCamera.startPreview();
    } catch(Exception exp){
        Log.i(EXCEPTION_KEY,"FROM surfaceChanged: "+exp.toString());
    }
}


public void setPreview(){
    try{
        //set the focusable true
        this.setFocusable(true);
        //set the touch able true
        this.setFocusableInTouchMode(true);
        //set the camera display orientation lock
        previewCamera.setDisplayOrientation(90);

        //get the camera parameters
        Camera.Parameters parameters = previewCamera.getParameters();
        //set the preview size
        parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
        //set the parameter
        previewCamera.setParameters(parameters);
    }catch(Exception exp){
        Log.i(EXCEPTION_KEY,"FROM setPreview: "+exp.toString());
    }
}


@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
    //our app has only one screen, so we'll destroy the camera in the surface
    //if you are using with more screens, please move this code your activity
    try{
        //handle in Activity onResume and onPause
    }catch(Exception exp){
        Log.i(EXCEPTION_KEY,"FROM surfaceDestroyed: "+exp.toString());
    }
}

//Override Methods here
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    try{
        final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
        final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
        setMeasuredDimension(width, height);

        if (mSupportedPreviewSizes != null) {
            mPreviewSize = PreviewSizeParameters.getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
        }
    }catch(Exception exp){
        Log.i(EXCEPTION_KEY,"FROM onMeasure: "+exp.toString());
    }
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////

private void stopPreviewAndFreeCamera() {

    if (previewCamera != null) {
        // Call stopPreview() to stop updating the preview surface.
        previewCamera.stopPreview();

        // Important: Call release() to release the camera for use by other
        // applications. Applications should release the camera immediately
        // during onPause() and re-open() it during onResume()).
        previewCamera.release();

        previewCamera = null;
    }
}

//end of class here

  }

谁能告诉我我的代码中缺少什么,因为它只影响使用前置摄像头的某些设备。


谢谢

【问题讨论】:

    标签: android camera surfaceview front-camera


    【解决方案1】:

    以下代码在我的环境中运行。
    surfaceChanged 中调用getOptimalPreviewSize,使用SurfaceView 和高度。

    public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
    
        ...
    
        @Override
        public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int w, int h) {
            //before changing the application orientation, you need to stop the preview, rotate and then start it again
    
            if(mHolder.getSurface() == null)//check if the surface is ready to receive camera data
                return;
    
            try{
                previewCamera.stopPreview();
            } catch (Exception e){
                //this will happen when you are trying the camera if it's not running
            }
    
            //now, recreate the camera preview
            try{
                //set the focusable true
                this.setFocusable(true);
                //set the touch able true
                this.setFocusableInTouchMode(true);
                //set the camera display orientation lock
                previewCamera.setDisplayOrientation(90);
    
                Camera.Parameters params = previewCamera.getParameters();
                List<Camera.Size> sizes = params.getSupportedPreviewSizes();
                Camera.Size optimalSize = getOptimalPreviewSize(sizes,w,h);
                params.setPreviewSize(optimalSize.width,optimalSize.height);
                previewCamera.setParameters(params);
    
                previewCamera.setPreviewDisplay(mHolder);
                previewCamera.startPreview();
            } catch(Exception exp){
                Log.i(EXCEPTION_KEY,"FROM surfaceChanged: "+exp.toString());
            }
        }
    
        ...
    
        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;
        }
    //end of class here
    
    }
    

    【讨论】:

    • 您是否使用我的代码在其上提供拉伸相机预览的某些设备进行了检查?我的意思是您是否在我的问题中提到的设备上测试过您的代码?
    • 我没有华为荣耀 4c 或 HTC One M7。所以我测试了Nexus5(Android6)。首先,我检查了你的代码并且预览被拉伸了。而且通过我修改的代码,预览没有被拉伸。
    • Oki 那我早上试试
    • 你知道为什么它只对有棒棒糖的设备进行拉伸吗?
    • 哦,对不起..我不知道。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多