如何让CameraController捕获的图片填充CameraPreview整个视口?
return cameraView
}
#### startCamera方法(在onCreate中调用) ```kotlin private fun startCamera() { cameraController = LifecycleCameraController(requireContext()) cameraController.bindToLifecycle(this) }
拍照回调实现
cameraController.takePicture(ContextCompat.getMainExecutor(requireContext()), object : ImageCapture.OnImageCapturedCallback() { override fun onCaptureSuccess(image: ImageProxy) { Log.d("ImageCapture", "Success") val buffer = image.planes[0].buffer val bytes = ByteArray(buffer.capacity()) buffer[bytes] val bitmapImage = BitmapFactory.decodeByteArray(bytes, 0, bytes.size) imagePreview.rotation = image.imageInfo.rotationDegrees.toFloat() imagePreview.setImageBitmap(bitmapImage) imagePreview.isVisible = true } override fun onError(exception: ImageCaptureException) { Log.e("ImageCapture", "Failed to capture image: $exception") super.onError(exception) } })
补充说明
尝试过以下裁剪方式也无效:
val croppedBitmap = Bitmap.createBitmap( bitmapImage, image.cropRect.left, image.cropRect.top, image.cropRect.width(), image.cropRect.height() )
怀疑问题出在ImageView的布局适配,而非相机逻辑本身。
解决方案
1. 修改ImageView的缩放模式
当前adjustViewBounds="true"会保持图片比例但不填满容器,改成以下配置:
<ImageView android:id="@+id/image_preview" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="centerCrop" android:adjustViewBounds="false" />
centerCrop会让图片按比例缩放至填满整个ImageView,超出部分自动裁剪,完全符合“填满屏幕”的需求。
2. 匹配PreviewView的宽高比裁剪图片
直接用ImageProxy的cropRect裁剪不生效,是因为它基于传感器原始分辨率,未考虑显示方向和Preview的缩放比例。需要手动计算裁剪区域:
override fun onCaptureSuccess(image: ImageProxy) { Log.d("ImageCapture", "Success") // 获取适配显示方向的Bitmap val originalBitmap = image.toBitmap() // 计算PreviewView和图片的宽高比 val previewRatio = viewFinder.width.toFloat() / viewFinder.height.toFloat() val imageRatio = originalBitmap.width.toFloat() / originalBitmap.height.toFloat() val scaledBitmap: Bitmap = if (previewRatio > imageRatio) { // Preview更宽,裁剪图片左右两侧 val targetWidth = (originalBitmap.height * previewRatio).toInt() val cropX = (originalBitmap.width - targetWidth) / 2 Bitmap.createBitmap(originalBitmap, cropX, 0, targetWidth, originalBitmap.height) } else { // Preview更高,裁剪图片上下两侧 val targetHeight = (originalBitmap.width / previewRatio).toInt() val cropY = (originalBitmap.height - targetHeight) / 2 Bitmap.createBitmap(originalBitmap, 0, cropY, originalBitmap.width, targetHeight) } // 设置旋转并显示图片 imagePreview.rotation = image.imageInfo.rotationDegrees.toFloat() imagePreview.setImageBitmap(scaledBitmap) imagePreview.isVisible = true // 务必关闭ImageProxy释放资源 image.close() }
3. 提前配置CameraController的ImageCapture参数
在startCamera中设置ImageCapture的宽高比与PreviewView一致,确保拍摄的图片比例更贴近预览:
private fun startCamera() { cameraController = LifecycleCameraController(requireContext()) // 等待View布局完成后获取正确宽高比,避免onCreate中宽高为0 viewFinder.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener { override fun onGlobalLayout() { viewFinder.viewTreeObserver.removeOnGlobalLayoutListener(this) val previewRatio = Rational(viewFinder.width, viewFinder.height) cameraController.setImageCaptureCropAspectRatio(previewRatio) } }) cameraController.bindToLifecycle(this) }
内容的提问来源于stack exchange,提问作者Muellllkreis
相关产品推荐
相关产品推荐

