
在Android应用开发中,尤其涉及相机功能时,设备屏幕方向(如横屏或竖屏)与相机传感器本身的物理方向之间常常存在差异。CameraX库在很大程度上简化了这一复杂性,但开发者仍需理解其工作原理,尤其是在特定分辨率和方向需求下。
AndroidManifest.xml文件中的android:screenOrientation属性用于锁定Activity的屏幕方向。例如:
这个设置直接影响了设备界面的呈现,但相机传感器捕获原始图像的方式可能与此独立。
在使用CameraX的ImageAnalysis.Builder或ImageCapture.Builder时,setTargetResolution(new Size(width, height))方法用于指定期望的输出图像分辨率。需要注意的是,CameraX会尝试选择一个最接近指定分辨率且相机支持的分辨率。
一个常见的误解是,当设备从横屏切换到竖屏时,如果将setTargetResolution从Size(1280, 720)改为Size(720, 1280),系统会直接提供一个宽度为720、高度为1280的图像,并且其方向也与设备屏幕方向完全匹配。实际上,Size(720, 1280)确实指定了期望的输出尺寸,即宽度为720像素,高度为1280像素。然而,相机传感器捕获的原始数据可能仍然是基于其原生方向(通常是横向)。CameraX会负责旋转这些数据以适应目标分辨率,但最终传递给ImageAnalyzer或ImageCapture回调的图像,其“逻辑”方向可能需要进一步处理。
当您需要将一个原本只在横屏模式下工作的CameraX应用迁移到只在竖屏模式下工作时,需要进行以下关键调整:
首先,将AndroidManifest.xml中Activity的screenOrientation属性从landscape改为portrait:
<activity
android:name=".MainActivity"
android:exported="true"
android:screenOrientation="portrait"
tools:ignore="LockedOrientationActivity">
</activity>接下来,在您的相机辅助类(如CameraHelper.java)中,根据新的屏幕方向调整ImageAnalysis和ImageCapture的目标分辨率。如果您之前在横屏模式下使用Size(1280, 720),那么在竖屏模式下,您应该使用Size(720, 1280)。
示例代码修改:
private void bindCamera(@NonNull ProcessCameraProvider cameraProvider) {
Log.d(TAG, "Binding camera");
CameraSelector cameraSelector = new CameraSelector.Builder()
.requireLensFacing(CameraSelector.LENS_FACING_BACK)
.build();
// Image analysis settings
ImageAnalysis.Builder imageAnalysisBuilder = new ImageAnalysis.Builder();
ImageAnalysis imageAnalysis = imageAnalysisBuilder
.setImageQueueDepth(1)
.setTargetResolution(new Size(720, 1280)) // 调整为竖屏模式的宽度和高度
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.build();
imageAnalysis.setAnalyzer(analyzerExecutor, imageAnalyzer);
var captureBuilder = new ImageCapture.Builder();
captureBuilder.setTargetRotation(Surface.ROTATION_0). // 对于竖屏,通常设置为Surface.ROTATION_0或由系统自动决定
setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY).
setTargetResolution(new Size(3024, 4032)). // 调整为竖屏模式的宽度和高度 (例如,从4032x3024变为3024x4032)
setJpegQuality(Constants.JPEG_QUALITY).
setFlashMode(ImageCapture.FLASH_MODE_OFF);
// ... 其他 ImageCapture 配置 ...
imageCapture = captureBuilder.build();
try {
cameraProvider.unbindAll();
if (lifecycleOwner.getLifecycle().getCurrentState() != DESTROYED) {
this.camera = cameraProvider.bindToLifecycle(lifecycleOwner,
cameraSelector,
imageCapture,
imageAnalysis);
}
} catch (Exception e) {
Log.e(TAG, "Camera binding failed", e);
MainActivity.instance.snackbar.showError("Camera binding failed", e);
}
}注意: setTargetRotation参数在CameraX中非常重要。它告诉CameraX输出图像相对于设备的自然方向需要旋转多少度。当screenOrientation设置为portrait时,通常Surface.ROTATION_0或Surface.ROTATION_90(取决于设备传感器的原生方向和CameraX的内部处理)是合适的。CameraX会尽力优化以减少处理开销。在某些情况下,CameraX会自动处理大部分旋转,但了解其作用有助于调试。
即使您正确设置了setTargetResolution为Size(720, 1280),CameraX提供的ImageProxy(在ImageAnalysis中)或捕获的图像数据(在ImageCapture中)可能仍然需要进一步的旋转才能正确显示。这是因为相机传感器通常以其原生方向(例如,横向)捕获图像,而CameraX会提供一个rotationDegrees值,指示如何旋转图像以匹配设备当前的显示方向。
对于ImageAnalysis中的ImageProxy:
ImageProxy对象包含一个imageInfo.rotationDegrees属性,它表示图像需要旋转多少度才能正确显示。您需要在处理图像数据时应用这个旋转。
public class MyImageAnalyzer implements ImageAnalysis.Analyzer {
@Override
public void analyze(@NonNull ImageProxy imageProxy) {
// 获取需要应用的旋转角度
int rotationDegrees = imageProxy.getImageInfo().getRotationDegrees();
// 获取图像数据 (例如,YUV_420_888 格式)
// Image image = imageProxy.getImage();
// 在这里处理图像数据,并应用 rotationDegrees
// 例如,将YUV数据转换为Bitmap并旋转:
// Bitmap bitmap = yuvToBitmap(image); // 假设有这个转换方法
// Matrix matrix = new Matrix();
// matrix.postRotate(rotationDegrees);
// Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
// 处理 rotatedBitmap...
imageProxy.close(); // 非常重要:处理完后关闭ImageProxy
}
// 示例:YUV_420_888 转 Bitmap 并旋转的简化逻辑
// 实际生产环境需要更健壮的YUV转RGB/Bitmap实现
private Bitmap yuvToBitmap(Image image, int rotationDegrees) {
// ... (复杂的YUV转RGB逻辑,此处省略) ...
// 假设我们已经得到了一个原始的Bitmap
Bitmap originalBitmap = ...;
if (rotationDegrees != 0) {
Matrix matrix = new Matrix();
matrix.postRotate(rotationDegrees);
return Bitmap.createBitmap(originalBitmap, 0, 0, originalBitmap.getWidth(), originalBitmap.getHeight(), matrix, true);
} else {
return originalBitmap;
}
}
}对于ImageCapture捕获的图像:
当通过ImageCapture.takePicture()捕获图像时,您会收到一个ImageProxy或一个文件。如果接收到ImageProxy,处理方式与ImageAnalysis类似。如果直接保存到文件,CameraX通常会根据setTargetRotation和设备方向自动写入正确的EXIF方向标签,但某些情况下您可能仍需要在加载图像后检查并应用旋转。
在Android CameraX应用中处理设备方向与相机传感器方向不匹配的问题,关键在于理解setTargetResolution的实际作用以及对图像数据的后处理。通过在AndroidManifest.xml中设置正确的屏幕方向,并在ImageAnalysis和ImageCapture中指定与设备方向匹配的目标分辨率,同时利用ImageProxy.getImageInfo().getRotationDegrees()对捕获到的图像数据进行必要的旋转,可以确保应用在不同屏幕方向下都能正确地显示和处理相机图像,避免分辨率混淆和图像方向错误。
以上就是Android CameraX:设备方向切换中的图像分辨率与方向处理实践的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号