我的相机预览被拉伸和压扁。我怎么解决这个问题?
My camera preview is stretched and squashed. How can I solve this problem?
(我已经看过其他类似问题的答案,但对我没有帮助)。
我是 Android Camera 2 API 的新手,我正在尝试创建自定义相机。
一切正常,但当 phone 处于纵向模式时预览会被拉伸,而当 phone 处于横向模式时预览会被压扁。
那么,我该如何解决我的问题?
这里是可能包含错误的代码。
private void setUpCameraOutputs(int width, int height) {
try {
CameraCharacteristics characteristics = this.cameraManager.getCameraCharacteristics(this.cameraId);
StreamConfigurationMap map = characteristics.get(
CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
if (map != null) {
this.imageReader = ImageReader.newInstance(width, height, ImageFormat.JPEG, 2);
this.imageReader.setOnImageAvailableListener(
this.imageReaderListener,
this.backgroundHandler);
Point displaySize = new Point();
this.getWindowManager().getDefaultDisplay().getSize(displaySize);
int maxPreviewWidth = displaySize.x;
int maxPreviewHeight = displaySize.y;
if (MAX_PREVIEW_WIDTH < maxPreviewWidth) {
maxPreviewWidth = MAX_PREVIEW_WIDTH;
}
if (MAX_PREVIEW_HEIGHT < maxPreviewHeight) {
maxPreviewHeight = MAX_PREVIEW_HEIGHT;
}
//Viene selezionata la risoluzione ideale per l'anteprima
this.previewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class),
width, height, maxPreviewWidth, maxPreviewHeight);
}
} catch (CameraAccessException e) {
e.printStackTrace();
} catch (NullPointerException e) {
//L'eccezione è lanciata quando le Camera2API sono usate,
//ma non sono supportate dal dispositivo
this.showToast("Camera2 API not supported on this device");
}
}
在这个方法中我找到了预览的最佳分辨率
private static Size chooseOptimalSize(Size[] choices, int
textureViewWidth, int textureViewHeight,
int maxWidth, int maxHeight) {
//Raccoglie tutte le risoluzioni grandi almeno quanto la superficie di anteprima
List<Size> bigEnough = new ArrayList<>();
//Raccoglie tutte le risoluzioni più piccole della superficie di anteprima
List<Size> notBigEnough = new ArrayList<>();
//int w = aspectRatio.getWidth();
int w = maxWidth;
//int h = aspectRatio.getHeight();
int h = maxHeight;
for (Size option : choices) {
if (option.getWidth() <= maxWidth && option.getHeight() <= maxHeight)
if (option.getHeight() == option.getWidth() * h / w) {
if (option.getWidth() >= textureViewWidth && option.getHeight() >= textureViewHeight) {
bigEnough.add(option);
} else {
notBigEnough.add(option);
}
}
}
//Pick the smallest of those big enoughPrende la risoluzione minima tra quelle grandi abbastanza.
//Se non ce ne sono di grandi abbastanza prende quella più grande tra quelle non
//abbastanza grandi
if (bigEnough.size() > 0) {
return Collections.min(bigEnough, new CompareSizesByArea());
} else if (notBigEnough.size() > 0) {
return Collections.max(notBigEnough, new CompareSizesByArea());
} else {
Log.e("Camera2", "Couldn't find any suitable preview size");
return choices[0];
}
}
预览大小应与您用来显示它的表面的纵横比匹配。 Camera2 示例使用 AutoFitTextureView 包装器 class 帮助重塑视图以适合预览大小,但将其复制到您的项目中可能很容易出错,因为它取决于充气机的细微差别。
为简单起见,将 TextureView 的大小设置为 1600px x 900px,this.previewSize
设置为 1920 x 1080。
你应该看看来自 Google 的官方 Android Camera2 示例:https://github.com/googlesamples/android-Camera2Basic
具体来说,您要实现的目标主要由 Camera2BasicFragment 文件中的 AutoFitTextureView class and the chooseOptimalSize method 完成,这里是一个片段:
private static Size chooseOptimalSize(Size[] choices, int textureViewWidth,
int textureViewHeight, int maxWidth, int maxHeight, Size aspectRatio) {
// Collect the supported resolutions that are at least as big as the preview Surface
List<Size> bigEnough = new ArrayList<>();
// Collect the supported resolutions that are smaller than the preview Surface
List<Size> notBigEnough = new ArrayList<>();
int w = aspectRatio.getWidth();
int h = aspectRatio.getHeight();
for (Size option : choices) {
if (option.getWidth() <= maxWidth && option.getHeight() <= maxHeight &&
option.getHeight() == option.getWidth() * h / w) {
if (option.getWidth() >= textureViewWidth &&
option.getHeight() >= textureViewHeight) {
bigEnough.add(option);
} else {
notBigEnough.add(option);
}
}
}
// Pick the smallest of those big enough. If there is no one big enough, pick the
// largest of those not big enough.
if (bigEnough.size() > 0) {
return Collections.min(bigEnough, new CompareSizesByArea());
} else if (notBigEnough.size() > 0) {
return Collections.max(notBigEnough, new CompareSizesByArea());
} else {
Log.e(TAG, "Couldn't find any suitable preview size");
return choices[0];
}
}
开始使用 Android Camera2 API 可能会让人望而生畏。除了 official documentation 和上述官方示例之外,还有一些(希望如此)有用的博客文章,例如:
(我已经看过其他类似问题的答案,但对我没有帮助)。 我是 Android Camera 2 API 的新手,我正在尝试创建自定义相机。 一切正常,但当 phone 处于纵向模式时预览会被拉伸,而当 phone 处于横向模式时预览会被压扁。 那么,我该如何解决我的问题?
这里是可能包含错误的代码。
private void setUpCameraOutputs(int width, int height) {
try {
CameraCharacteristics characteristics = this.cameraManager.getCameraCharacteristics(this.cameraId);
StreamConfigurationMap map = characteristics.get(
CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
if (map != null) {
this.imageReader = ImageReader.newInstance(width, height, ImageFormat.JPEG, 2);
this.imageReader.setOnImageAvailableListener(
this.imageReaderListener,
this.backgroundHandler);
Point displaySize = new Point();
this.getWindowManager().getDefaultDisplay().getSize(displaySize);
int maxPreviewWidth = displaySize.x;
int maxPreviewHeight = displaySize.y;
if (MAX_PREVIEW_WIDTH < maxPreviewWidth) {
maxPreviewWidth = MAX_PREVIEW_WIDTH;
}
if (MAX_PREVIEW_HEIGHT < maxPreviewHeight) {
maxPreviewHeight = MAX_PREVIEW_HEIGHT;
}
//Viene selezionata la risoluzione ideale per l'anteprima
this.previewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class),
width, height, maxPreviewWidth, maxPreviewHeight);
}
} catch (CameraAccessException e) {
e.printStackTrace();
} catch (NullPointerException e) {
//L'eccezione è lanciata quando le Camera2API sono usate,
//ma non sono supportate dal dispositivo
this.showToast("Camera2 API not supported on this device");
}
}
在这个方法中我找到了预览的最佳分辨率
private static Size chooseOptimalSize(Size[] choices, int
textureViewWidth, int textureViewHeight,
int maxWidth, int maxHeight) {
//Raccoglie tutte le risoluzioni grandi almeno quanto la superficie di anteprima
List<Size> bigEnough = new ArrayList<>();
//Raccoglie tutte le risoluzioni più piccole della superficie di anteprima
List<Size> notBigEnough = new ArrayList<>();
//int w = aspectRatio.getWidth();
int w = maxWidth;
//int h = aspectRatio.getHeight();
int h = maxHeight;
for (Size option : choices) {
if (option.getWidth() <= maxWidth && option.getHeight() <= maxHeight)
if (option.getHeight() == option.getWidth() * h / w) {
if (option.getWidth() >= textureViewWidth && option.getHeight() >= textureViewHeight) {
bigEnough.add(option);
} else {
notBigEnough.add(option);
}
}
}
//Pick the smallest of those big enoughPrende la risoluzione minima tra quelle grandi abbastanza.
//Se non ce ne sono di grandi abbastanza prende quella più grande tra quelle non
//abbastanza grandi
if (bigEnough.size() > 0) {
return Collections.min(bigEnough, new CompareSizesByArea());
} else if (notBigEnough.size() > 0) {
return Collections.max(notBigEnough, new CompareSizesByArea());
} else {
Log.e("Camera2", "Couldn't find any suitable preview size");
return choices[0];
}
}
预览大小应与您用来显示它的表面的纵横比匹配。 Camera2 示例使用 AutoFitTextureView 包装器 class 帮助重塑视图以适合预览大小,但将其复制到您的项目中可能很容易出错,因为它取决于充气机的细微差别。
为简单起见,将 TextureView 的大小设置为 1600px x 900px,this.previewSize
设置为 1920 x 1080。
你应该看看来自 Google 的官方 Android Camera2 示例:https://github.com/googlesamples/android-Camera2Basic
具体来说,您要实现的目标主要由 Camera2BasicFragment 文件中的 AutoFitTextureView class and the chooseOptimalSize method 完成,这里是一个片段:
private static Size chooseOptimalSize(Size[] choices, int textureViewWidth,
int textureViewHeight, int maxWidth, int maxHeight, Size aspectRatio) {
// Collect the supported resolutions that are at least as big as the preview Surface
List<Size> bigEnough = new ArrayList<>();
// Collect the supported resolutions that are smaller than the preview Surface
List<Size> notBigEnough = new ArrayList<>();
int w = aspectRatio.getWidth();
int h = aspectRatio.getHeight();
for (Size option : choices) {
if (option.getWidth() <= maxWidth && option.getHeight() <= maxHeight &&
option.getHeight() == option.getWidth() * h / w) {
if (option.getWidth() >= textureViewWidth &&
option.getHeight() >= textureViewHeight) {
bigEnough.add(option);
} else {
notBigEnough.add(option);
}
}
}
// Pick the smallest of those big enough. If there is no one big enough, pick the
// largest of those not big enough.
if (bigEnough.size() > 0) {
return Collections.min(bigEnough, new CompareSizesByArea());
} else if (notBigEnough.size() > 0) {
return Collections.max(notBigEnough, new CompareSizesByArea());
} else {
Log.e(TAG, "Couldn't find any suitable preview size");
return choices[0];
}
}
开始使用 Android Camera2 API 可能会让人望而生畏。除了 official documentation 和上述官方示例之外,还有一些(希望如此)有用的博客文章,例如: