You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Studio中如何修复CameraSource相机预览方向倾斜问题

解决CameraSource相机预览竖直显示问题

问题根因

你使用的CameraSource默认输出横屏帧数据,未适配设备竖屏姿态,直接将未做旋转处理的帧转换为Bitmap显示就会出现横向倾斜的情况。

1. 调整CameraSource初始化配置

你需要在初始化时设置适配竖屏的预览尺寸,避免预览拉伸,修改setupCameraSource方法如下:

private fun setupCameraSource() {
    val displayMetrics = activity!!.resources.displayMetrics
    val screenWidth = displayMetrics.widthPixels
    val screenHeight = displayMetrics.heightPixels

    cameraSource = CameraSource.Builder(activity, cameraSourceCustomDetector)
        .setAutoFocusEnabled(true)
        .setRequestedFps(10F)
        .setFacing(CameraSource.CAMERA_FACING_BACK)
        // 相机传感器默认横置,预览尺寸传值需宽高倒置适配竖屏
        .setRequestedPreviewSize(screenHeight, screenWidth)
        .build()
}

2. 帧数据转换时添加Bitmap旋转逻辑

你在CustomDetector.detect方法中拿到的原始帧是横屏格式,需要先按当前设备姿态旋转后再传入UI显示,步骤如下:

第一步:添加Bitmap旋转工具方法

在colorDetector类中添加旋转方法:

private fun rotateBitmap(bitmap: Bitmap, rotationDegree: Int): Bitmap {
    val matrix = Matrix()
    matrix.postRotate(rotationDegree.toFloat())
    val rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
    // 回收原始Bitmap避免内存泄漏
    bitmap.recycle()
    return rotatedBitmap
}

第二步:添加旋转角度计算方法

根据当前设备朝向和摄像头类型计算正确的旋转角度:

private fun getCorrectRotation(): Int {
    val display = activity?.windowManager?.defaultDisplay ?: return 90
    val baseDegree = when (display.rotation) {
        Surface.ROTATION_0 -> 90 // 正常竖屏
        Surface.ROTATION_90 -> 0 // 左侧横屏
        Surface.ROTATION_180 -> 270 // 反向竖屏
        Surface.ROTATION_270 -> 180 // 右侧横屏
        else -> 90
    }
    // 前置摄像头需要额外处理镜像翻转
    return if (cameraSource?.cameraFacing == CameraSource.CAMERA_FACING_FRONT) {
        (360 - baseDegree) % 360
    } else {
        baseDegree
    }
}

第三步:修改detect方法中的Bitmap处理逻辑

转换为Bitmap后先旋转再传入UI方法:

@RequiresApi(Build.VERSION_CODES.O)
override fun detect(frame: Frame?): SparseArray<Point>? {
    val byteBuffer: ByteBuffer = frame!!.grayscaleImageData
    val bytes: ByteArray = byteBuffer.array()
    val w = frame.metadata.width
    val h = frame.metadata.height
    val yuvimage = YuvImage(bytes, ImageFormat.NV21, w, h, null)
    val baos = ByteArrayOutputStream()
    yuvimage.compressToJpeg(
        Rect(0, 0, w, h),
        100,
        baos
    )

    val jpegArray = baos.toByteArray()
    var bitmap = BitmapFactory.decodeByteArray(jpegArray, 0, jpegArray.size)
    // 新增:旋转Bitmap到正确朝向
    val rotationDegree = getCorrectRotation()
    bitmap = rotateBitmap(bitmap, rotationDegree)

    val finalBitmap = bitmap
    activity?.runOnUiThread {
        getEditedImg(finalBitmap, finalBitmap.width, finalBitmap.height, cameraPreview!!, editCameraPreview!!, activity!!)
    }
    return null
}

额外优化建议

  • 若应用固定为竖屏展示,可以直接固定旋转角度为90度,无需动态计算,减少性能消耗
  • 官方CameraSource已随Google Play Services Vision库停止维护,后续迭代建议迁移到ML Kit的相机扫描组件,适配更简便

内容的提问来源于stack exchange,提问作者Chris Marec

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.15 12:15:04