这与google vision API有关。 CameraPreview适用于全屏。但是在框中预览相机时图像会失真。
这是我用过的代码。我的问题是预览填满了框,但预览被拉伸,我无法调整cameraPreview的大小。变量CameraPreview是SurfaceView类型。我使用CameraSource来开始预览。有没有办法改变CameraPreview(SurfaceView)的大小并使预览裁剪适合一个盒子?
cameraPreview.getHolder().addCallback(new SurfaceHolder.Callback() {
protected List<Camera.Size> mPreviewSizeList;
protected List<Camera.Size> mPictureSizeList;
protected Camera.Size mPreviewSize;
protected Camera.Size mPictureSize;
protected boolean mSurfaceChanged = false;
private int mSurfaceChangedCallDepth = 0;
private int mCenterPosX = -1;
private int mCenterPosY = 0;
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(ClientIdScannerActivity.this,
new String[]{Manifest.permission.CAMERA}, RequestCameraPermissionId);
Toast.makeText(ClientIdScannerActivity.this, "The App requires this permission", Toast.LENGTH_SHORT).show();
return;
}
try {
cameraSource.start(cameraPreview.getHolder());
} catch (Exception ex) {
ex.printStackTrace();
}
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
mSurfaceChangedCallDepth++;
/* cameraSource.stop();
Camera.Parameters cameraParams = mCamera.getParameters();
if (!mSurfaceChanged) {
Camera.Size previewSize = determinePreviewSize(cameraWidth, cameraHight);
Camera.Size pictureSize = determinePictureSize(previewSize);
mPreviewSize = previewSize;
mPictureSize = pictureSize;
mSurfaceChanged = adjustSurfaceLayoutSize(previewSize,i1, i2);
if (mSurfaceChanged && (mSurfaceChangedCallDepth <= 1)) {
return;
}
}
cameraParams.setRotation(270);
if (UtilFunctions.isTablet()) {
} else {
mCamera.setDisplayOrientation(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ? 270 : 90);
}*/
// cameraParams.setRotation(270);
// mCamera.setDisplayOrientation(UtilFunctions.isTablet() ? 90 : 270);
/* cameraParams.set("orientation", "portrait");
// cameraParams.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
cameraParams.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
cameraParams.setPictureSize(mPictureSize.width, mPictureSize.height);
if (cameraParams.getSupportedFocusModes().contains(
Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
cameraParams.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
}*/
mSurfaceChanged = false;
try {
if (ActivityCompat.checkSelfPermission(ClientIdScannerActivity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
Toast.makeText(ClientIdScannerActivity.this, "App requires Camera permission to scan ID", Toast.LENGTH_SHORT).show();
return;
}
cameraSource.start(cameraPreview.getHolder());
} catch (Exception e) {
// Remove failed size
// Reconfigure
if (mPreviewSizeList.size() > 0) { // prevent infinite loop
surfaceChanged(null, 0, i1, i2);
} else {
// Utils.showToast(CameraNewActivity.this, "Can't start preview", Toast.LENGTH_LONG);
}
}
mSurfaceChangedCallDepth--;
}
protected Camera.Size determinePreviewSize(int reqWidth, int reqHeight) {
int reqPreviewWidth = 640;//reqHeight; // requested width in terms of camera hardware
int reqPreviewHeight = 480;// reqWidth; // requested height in terms of camera hardware
Camera.Size retSize = null;
for (Camera.Size size : mPreviewSizeList) {
if (size.width == reqPreviewWidth && size.height == reqPreviewHeight) {
retSize = size;
}
}
// retSize = mPreviewSizeList.get(mPreviewSizeList.size()-1);
return retSize;
}
protected Camera.Size determinePictureSize(Camera.Size previewSize) {
Camera.Size retSize = null;
for (Camera.Size size : mPictureSizeList) {
if (size.equals(previewSize)) {
return size;
}
}
// if the preview size is not supported as a picture size
float reqRatio = ((float) previewSize.width) / previewSize.height;
float curRatio, deltaRatio;
float deltaRatioMin = Float.MAX_VALUE;
for (Camera.Size size : mPictureSizeList) {
curRatio = ((float) size.width) / size.height;
deltaRatio = Math.abs(reqRatio - curRatio);
if (deltaRatio < deltaRatioMin) {
deltaRatioMin = deltaRatio;
retSize = size;
}
}
return retSize;
}
protected boolean adjustSurfaceLayoutSize(Camera.Size previewSize,
int availableWidth, int availableHeight) {
float tmpLayoutHeight = previewSize.width;
float tmpLayoutWidth = previewSize.height;
float factH, factW, fact;
factH = availableHeight / tmpLayoutHeight;
factW = availableWidth / tmpLayoutWidth;
// if (factH < factW) {
// fact = factH;
// } else {
fact = factW;
// }
FrameLayout.LayoutParams layoutParams =(FrameLayout.LayoutParams) cameraPreview.getLayoutParams();
int layoutHeight = (int) (tmpLayoutHeight * fact);
int layoutWidth = (int) (tmpLayoutWidth * fact);
boolean layoutChanged;
if ((layoutWidth != cameraPreview.getWidth()) || (layoutHeight != cameraPreview.getHeight())) {
layoutParams.height = layoutHeight;
layoutParams.width = layoutWidth;
if (mCenterPosX >= 0) {
layoutParams.topMargin = mCenterPosY - (layoutHeight / 2);
layoutParams.leftMargin = mCenterPosX - (layoutWidth / 2);
}
cameraPreview.setLayoutParams(layoutParams); // this will trigger another surfaceChanged invocation.
layoutChanged = true;
} else {
layoutChanged = false;
}
return layoutChanged;
}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
cameraSource.stop();
}
});
答案 0 :(得分:0)
请注意,'全屏'相机预览存在同样的问题。无法保证所选预览大小的宽高比足够接近屏幕的宽高比。请在此处查看更多详细信息: Camera Preview Stretched on Few Android Devices 。
您自然必须选择适合视图的最佳宽度和高度,但这还不够。您必须将预览表面的“悬挂”部分隐藏在某些非透明视图后面。例如,请参阅make a circular preview。
另一个重要的事情是始终保持预览和图片尺寸同步。这并不意味着它们必须相同,但宽高比应该是。当宽高比变化以捕捉照片时,某些设备会产生奇怪的效果。