You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

安卓Lollipop版本后SurfaceView与BitmapFactory相机图像质量过低问题咨询

解决SurfaceView相机捕获图像分辨率低/仅显示1/4画面的问题

嘿,我看你遇到了SurfaceView相机捕获图像的棘手问题——在部分设备(尤其是Android 5.0+系统)上,图像分辨率偏低,甚至只能拿到1/4的画幅。结合你给出的代码片段,我来帮你拆解核心原因并给出针对性的修复方案:

1. 先改掉最明显的代码坑:inSampleSize=2的误用

你代码里设置了options.inSampleSize = 2,这个参数的作用是把图像的宽和高都缩小为原来的1/2,直接导致最终生成的Bitmap分辨率是原始捕获图像的1/4,这大概率是你看到"仅捕获1/4图像"的直接原因!
如果你的需求是保留原始捕获图像的完整分辨率,要么直接移除这个参数,要么把它设为1:

BitmapFactory.Options options = new BitmapFactory.Options();
// 移除options.inSampleSize = 2,或者显式设置为1(不进行采样缩小)
options.inSampleSize = 1; 
Bitmap myImage = BitmapFactory.decodeByteArray(imageData, 0, imageData.length, options);

2. 相机预览尺寸与捕获尺寸不匹配(Android 5.0+高频问题)

Android 5.0之后,相机API对预览和捕获尺寸的一致性要求更严格。如果SurfaceView的预览尺寸和相机设置的捕获尺寸比例、大小不匹配,就会导致捕获的图像被裁剪、拉伸,表现为分辨率异常:

  • 你需要先获取相机支持的预览尺寸列表捕获尺寸列表,找到两者共同支持的最大尺寸,同时要保证这个尺寸的比例和SurfaceView的宽高比一致:
// 获取相机参数
Camera.Parameters params = camera.getParameters();
// 获取相机支持的捕获尺寸列表
List<Camera.Size> pictureSizes = params.getSupportedPictureSizes();
// 获取相机支持的预览尺寸列表
List<Camera.Size> previewSizes = params.getSupportedPreviewSizes();
// 自定义方法:找到同时适配预览、捕获和SurfaceView比例的最优尺寸
Camera.Size optimalSize = findOptimalSize(pictureSizes, previewSizes, surfaceWidth, surfaceHeight);
// 给相机设置统一的捕获和预览尺寸
params.setPictureSize(optimalSize.width, optimalSize.height);
params.setPreviewSize(optimalSize.width, optimalSize.height);
camera.setParameters(params);
  • 实现findOptimalSize时,记得优先匹配SurfaceView的宽高比例,避免图像被拉伸或裁剪。

3. 图像数据格式处理错误

相机捕获的原始数据通常是NV21格式的字节流,而BitmapFactory.decodeByteArray默认只认JPEG格式。如果你的相机设置的是setPictureFormat(ImageFormat.NV21),直接用decodeByteArray解析会导致错误,表现为分辨率异常甚至图像损坏:

  • 正确的做法是先把NV21格式转换成JPEG,再解析成Bitmap:
// 先获取相机设置的捕获图像宽高
int picWidth = camera.getParameters().getPictureSize().width;
int picHeight = camera.getParameters().getPictureSize().height;
// 将NV21字节流转换为YuvImage
YuvImage yuvImage = new YuvImage(imageData, ImageFormat.NV21, picWidth, picHeight, null);
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
// 压缩成JPEG格式
yuvImage.compressToJpeg(new Rect(0, 0, picWidth, picHeight), quality, outStream);
byte[] jpegBytes = outStream.toByteArray();
// 再用BitmapFactory解析JPEG数据
Bitmap myImage = BitmapFactory.decodeByteArray(jpegBytes, 0, jpegBytes.length);

4. Android 5.0+的权限兼容性问题

Android 5.0之后,动态权限(尤其是CAMERA权限)的要求更严格,如果没有正确获取权限,相机可能会自动 fallback 到低分辨率模式:

  • 确保在运行时申请CAMERA权限,并且在权限授予成功后再初始化相机;
  • 对于Android 6.0+设备,一定要检查Manifest.permission.CAMERA是否被授予。

总结

优先检查inSampleSize参数的设置——这是最容易踩的坑;其次确保相机预览和捕获尺寸一致,处理好NV21到JPEG的格式转换;最后验证相机权限是否正确获取。按这个顺序排查,大概率能解决你的问题。

内容的提问来源于stack exchange,提问作者Ankit Jayaprakash

火山引擎 最新活动