SurfaceView可以拉伸相机预览

时间:2014-12-26 05:35:20

标签: android android-camera surfaceview android-orientation aspect-ratio

我添加了FrameLayout,其中显示了相机预览,但预览正在拉伸。

我尝试过https://stackoverflow.com/a/19592492/1597844中提供的解决方案,但这也无济于事。

你能帮我知道我的代码有什么问题吗?

我得到的输出是Upper Image gets skewed horizontally (portrait mode) and the below one gets stretched vertically (Landscape mode) 上部图像水平倾斜(纵向模式),下部图像垂直拉伸(横向模式) 我正在使用的代码是

mCamera = Camera.open(findBackFacingCamera());
        Camera.Parameters parameters = mCamera.getParameters();
        parameters.set("jpeg-quality", 100);
        parameters.setPictureFormat(PixelFormat.JPEG);
        List<Size> sizes = parameters.getSupportedPreviewSizes();
        Size optimalSize = getOptimalPreviewSize(sizes, getResources().getDisplayMetrics().widthPixels, getResources().getDisplayMetrics().heightPixels);
        parameters.setPreviewSize(optimalSize.width, optimalSize.height);
        mCamera.setParameters(parameters);

        mPicture = getPictureCallback();
        mPreview = new CameraPreview(myContext, mCamera);
        backCameraPreview.removeAllViews();
        backCameraPreview.addView(mPreview);

获得最佳预览尺寸的方法

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

    if (sizes == null) return null;
    Size optimalSize = null;
    double minDiff = Double.MAX_VALUE;
    int targetHeight = h;
    for (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 (Size size : sizes) {
            if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }
    }
    return optimalSize;
}

我的xml看起来像这样

 <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:weightSum="2">

    <FrameLayout
        android:id="@+id/dual_camera_capture_activity_ll_back_view"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:background="@android:color/white"
        android:orientation="horizontal"
        android:padding="10dp" />

    <FrameLayout
        android:id="@+id/dual_camera_capture_activity_fl_front_view"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_weight="1"
        android:background="@android:color/white"
        android:orientation="horizontal"
        android:padding="10dp" />
</LinearLayout>

这是我的SurfaceView的CameraPreview类

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private final Context mContext;
private SurfaceHolder mHolder;
private Camera mCamera;
private static String TAG = "Dual Camera";
private float mDist;


public CameraPreview(Context context, Camera camera) {
    super(context);
    mContext = context;
    mCamera = camera;
    mHolder = getHolder();
    mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    mHolder.addCallback(this);
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
    Log.d(TAG, "surface created");
    // The Surface has been created, now tell the camera where to draw the
    // preview.
    try {
        mCamera.setPreviewDisplay(holder);
        mCamera.setDisplayOrientation(90);
        mCamera.startPreview();
    } catch (IOException e) {
        Log.d(TAG, "Error setting camera preview: " + e.getMessage());
    }
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    Log.d(TAG, "surface destroyed");
    this.getHolder().removeCallback(this);
}

public void refreshCamera(Camera camera) {
    setCamera(camera);
    if (mCamera != null) {
        Display display = ((Activity) mContext).getWindowManager().getDefaultDisplay();
        if (mHolder.getSurface() == null) {
            return;
        }
        try {
            mCamera.stopPreview();
        } catch (Exception e) {
            e.printStackTrace();
        }
        Camera.Parameters parameters = mCamera.getParameters();
        if (display.getRotation() == Surface.ROTATION_0) {
            mCamera.setDisplayOrientation(90);
        }
        if (display.getRotation() == Surface.ROTATION_90) {
        }
        if (display.getRotation() == Surface.ROTATION_180) {
        }

        if (display.getRotation() == Surface.ROTATION_270) {
        }
        mCamera.setParameters(parameters);
        try {
            mCamera.setPreviewDisplay(mHolder);
            mCamera.startPreview();
        } catch (Exception e) {
            Log.d(VIEW_LOG_TAG, "Error starting camera preview: " + e.getMessage());
        }
    }
}

public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    refreshCamera(mCamera);
}

public void setCamera(Camera camera) {
    mCamera = camera;
}

}

你能告诉我我做错了吗?

1 个答案:

答案 0 :(得分:-1)

这是因为预览尺寸的分辨率较低

设置预览尺寸硬编码参数.setPreviewSize(1920,720);