android - 相机预览出现拉伸
问题描述
我试图将相机 2 与谷歌示例中的 AutoFitTextureView 一起使用。
我是这样设置的
private void setUpCameraOutputs() {
CameraManager manager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);
try {
if (manager != null) {
for (String cameraId : manager.getCameraIdList()) {
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
// We don't use a front facing camera in this sample.
//noinspection ConstantConditions
if (characteristics.get(LENS_FACING) == LENS_FACING_FRONT) continue;
StreamConfigurationMap map = characteristics.get(SCALER_STREAM_CONFIGURATION_MAP);
if(map != null) {
// For still image captures, we use the largest available size.
List<Size> outputSizes = Arrays.asList(map.getOutputSizes(sImageFormat));
Size largest = Collections.max(outputSizes, new CompareSizesByArea());
mImageReader = ImageReader.newInstance(640, 480, sImageFormat, 8);
mImageReader.setOnImageAvailableListener(mOnImageAvailableListener, mBackgroundHandler);
// Danger, W.R.! Attempting to use too large a preview size could exceed the camera
// bus' bandwidth limitation, resulting in gorgeous previews but the storage of
// garbage capture data.
mPreviewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class), largest.getWidth(), largest.getHeight(), largest);
//mPreviewSize = new Size(largest.getWidth(), largest.getHeight());
setAspectRatio2(mPreviewSize);
Logging.e(TAG, "WIDTH: " + mPreviewSize.getWidth() + " HEIGHT: " + mPreviewSize.getHeight());
mCameraId = cameraId;
}
//return;
}
}else{
Logging.e(TAG,"No Manager");
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void setAspectRatio(){
int orientation = mContext.getResources().getConfiguration().orientation;
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
mTextureView.setAspectRatio(mPreviewSize.getWidth(),mPreviewSize.getHeight());
} else {
mTextureView.setAspectRatio(mPreviewSize.getHeight(),mPreviewSize.getWidth());
}
}
private void setAspectRatio2(Size largest){
float cameraAspectRatio = (float) largest.getHeight() / largest.getWidth();
//Preparation
DisplayMetrics metrics = new DisplayMetrics();
WindowManager wm = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE));
wm.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
LayoutParams lp = (FrameLayout.LayoutParams) mTextureView.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);
mTextureView.setLayoutParams(lp);
}
private static Size chooseOptimalSize(Size[] choices, int width, int height, Size aspectRatio) {
// Collect the supported resolutions that are at least as big as the preview Surface
List<Size> bigEnough = new ArrayList<>();
int w = aspectRatio.getWidth();
int h = aspectRatio.getHeight();
double ratio = (double) h / w;
for (Size option : choices) {
double optionRatio = (double) option.getHeight() / option.getWidth();
if (ratio == optionRatio) {
bigEnough.add(option);
}
}
// Pick the smallest of those, assuming we found any
if (bigEnough.size() > 0) {
return Collections.min(bigEnough, new CompareSizesByArea());
} else {
Logging.e(TAG, "Couldn't find any suitable preview size");
return choices[1];
}
}
我尝试使用 2 种不同的方法设置纵横比,但它们似乎都不能满足我的需要。预览像我想要的那样占据所有屏幕,但相机预览总是显得僵硬,东西看起来更薄。我已经从stackoverflow尝试了一些建议,但仍然没有得到完美的结果。
解决方案
推荐阅读
- php - 仅在我的站点上更改服务器上的 PHP 版本
- angular - Primeng选择动态p-tabPanel
- c# - Parallel.ForEach 有条件
- python - What is the proper way of passing on variables to classes in python/pyqt?
- smartcard - PKCS#11 - 在已配置的智能卡上写入新证书时,如何保护智能卡所有者免受恶意智能卡提供商的侵害
- kubernetes - 为什么我在 Minikube 上得到“未绑定的即时 PersistentVolumeClaims”?
- android - 使用 React Native + Expo + FCM 创建的双重推送通知
- css - 图像超出屏幕并在底部创建滚动条
- node.js - 使用 mongoose 更新 MongoDB 文档的问题
- jms - Apama JMS Correlator Adapter 动态流控制