[英]preview stretches in camera2 apis
以下答案假设您仅处于纵向模式。
你的问题是
如何在不拉伸的情况下全屏使用预览
让我们把它分解成两件事:
首先,你需要知道,这在逻辑上是不可能没有的作物,如果你的设备的视有任何可用的分辨率的相机提供了不同的纵横比。
所以我假设你接受裁剪预览。
StreamConfigurationMap map = mCameraCharacteristics.get(
CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
if (map == null) {
throw new IllegalStateException("Failed to get configuration map: " + mCameraId);
}
Size[] sizes = map.getOutputSizes(SurfaceTexture.class);
现在您将获得设备相机的可用分辨率(尺寸)列表。
这个想法是循环尺寸,看看哪一个最合适。 您可能需要编写自己的“最佳匹配”实现。
我不会在这里提供任何代码,因为我所拥有的与您的用例完全不同。 但理想情况下,它应该是这样的:
Size findBestSize (Size[] sizes) {
//Logic goes here
}
//...
textureView.setBufferSize(bestSize.getWidth(), bestSize.getHeight());
Surface surface = textureView.getSurface();
try {
mPreviewRequestBuilder = mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
mPreviewRequestBuilder.addTarget(surface);
mCamera.createCaptureSession(Arrays.asList(surface, mImageReader.getSurface()),
mSessionCallback, null);
} catch (final Exception e) {
//...
}
这与 Camera2 API 无关。 我们通过让SurfaceView
/ TextureView
延伸到设备视口之外来“裁剪”预览。
首先将SurfaceView
或TextureView
放在RelativeLayout
。
在从步骤 2 中获得纵横比后,使用下面的方法将其扩展到屏幕之外。
请注意,在这种情况下,您可能需要在启动相机之前就知道此纵横比。
//Suppose this value is obtained from Step 2.
//I simply test here by hardcoding a 3:4 aspect ratio, where my phone has a thinner aspect ratio.
float cameraAspectRatio = (float) 0.75;
//Preparation
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int screenWidth = metrics.widthPixels;
int screenHeight = metrics.heightPixels;
int finalWidth = screenWidth;
int finalHeight = screenHeight;
int widthDifference = 0;
int heightDifference = 0;
float screenAspectRatio = (float) screenWidth / screenHeight;
//Determines whether we crop width or crop height
if (screenAspectRatio > cameraAspectRatio) { //Keep width crop height
finalHeight = (int) (screenWidth / cameraAspectRatio);
heightDifference = finalHeight - screenHeight;
} else { //Keep height crop width
finalWidth = (int) (screenHeight * cameraAspectRatio);
widthDifference = finalWidth - screenWidth;
}
//Apply the result to the Preview
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) cameraView.getLayoutParams();
lp.width = finalWidth;
lp.height = finalHeight;
//Below 2 lines are to center the preview, since cropping default occurs at the right and bottom
lp.leftMargin = - (widthDifference / 2);
lp.topMargin = - (heightDifference / 2);
cameraView.setLayoutParams(lp);
如果您不关心第 2 步的结果,您实际上可以忽略第 1 步到第 3 步,只需使用那里的库,只要您可以配置其纵横比即可。 (貌似这个是最好的,不过我还没试过)
我已经使用我的分叉库进行了测试。 在不修改我的库的任何代码的情况下,我仅使用步骤 4 就设法使预览全屏:
而且刚拍照后的预览也不会失真,因为预览也超出了您的屏幕。
但是输出图像将包含您在预览中看不到的区域,这很有意义。
Step 1 到 Step 3 的代码一般参考谷歌的 CameraView 。
这是某些设备上的常见问题。 我注意到它主要是在三星上。 您可以使用在TextureView
上设置转换的TextureView
,使其像ImageView
行为一样 centerCrop
我也遇到过类似的情况,但是这一行解决了我的问题
view_finder.preferredImplementationMode = PreviewView.ImplementationMode.TEXTURE_VIEW
在您的 xml 中:
<androidx.camera.view.PreviewView
android:id="@+id/view_finder"
android:layout_width="match_parent"
android:layout_height="match_parent" />
对于使用cameraX的相机实现,您可以参考https://github.com/android/camera-samples/tree/master/CameraXBasic
我想出你的问题是什么。 你可能正在尝试这样的事情:
textureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int j) {
cam.startPreview(surfaceTexture, i, j);
cam.takePicture();
}
public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) { }
public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) { return false; }
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) { }
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.