照相方向

2021-11-15

Android 照相方向说明

前置摄像头的坐标系相对于竖屏手机坐标系逆时针旋转了270度,拍摄的image展示时先逆时针旋转了270度,因此需要再旋转90度与设备相同

后置摄像头的坐标系相对于竖屏手机坐标系顺时针旋转了90度,拍摄的image展示时逆时针旋转设备旋转的角度,因此如果设备顺时针旋转90度,那么image就不用做调整了(这个设备旋转角度是按照人面对后置摄像头,顺时针旋转)

前置摄像头:front_portrait后置摄像头:front_portrait

​ 前置摄像头预览是承镜像关系的。

​ 因为摄像头坐标系与设备是固定关系的,当旋转设备时,相应的摄像头坐标系也相应旋转。例如:

使用后置摄像头,设备逆时针旋转90度,即设备横屏拍摄,则摄像头坐标系也逆时针旋转90度,随后拍照图片坐标系会旋转270度,再逆时针旋转90度后调整正常

front_portraitCamera sensor in landscape orientation with image upright.Camera sensor rotated to portait orientation with image sideways,             top right.Camera sensor rotated to landscape orientation with image             upright.

对于后置摄像头,imageBuffer是逆时针旋转设备已旋转的角度,前置摄像头则是顺时针设备已旋转的角度(设备旋转顺时针为正)。

private fun showImage(reader: ImageReader){
        val image = reader.acquireNextImage()
        val buffer = image.planes[0].buffer
        val bytes = ByteArray(buffer.remaining())
        buffer.get(bytes)
        val characteristics = cameraManager!!.getCameraCharacteristics(cameraId!!)
        val displayRotation: Int = windowManager.defaultDisplay.rotation
        val degree = getJpegOrientation(characteristics,currentDeviceOrientation)
        val matrix = Matrix()
            .apply {
            postRotate(degree.toFloat())
        }
        var bitmap = BitmapFactory.decodeByteArray(bytes,0,bytes.size)
        bitmap = Bitmap.createBitmap(bitmap,0,0, bitmap.width ,bitmap.height,matrix,false)
        if (null != bitmap){
            binding.imageview.setImageBitmap(bitmap)
        }
        image.close()//需要关闭image,否则多次拍照会有问题
    }

 /**
     * 根据设备旋转方向计算bitmap应该旋转的角度 为90的倍数
     *
     * @param c
     * @param deviceOrientation 设备实时的旋转角度
     * @return
     */
private fun getJpegOrientation(c: CameraCharacteristics, deviceOrientation: Int): Int {
        var orientation = deviceOrientation
        if (orientation == OrientationEventListener.ORIENTATION_UNKNOWN) return 0
        val sensorOrientation = c.get(CameraCharacteristics.SENSOR_ORIENTATION)!!

        // Round device orientation to a multiple of 90
        orientation = (orientation + 45) / 90 * 90

        // Reverse device orientation for front-facing cameras
        val facingFront =
            c.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT
        if (facingFront) orientation = -orientation

        // Calculate desired JPEG orientation relative to camera orientation to make
        // the image upright relative to the device orientation
        return (sensorOrientation + orientation + 360) % 360
    }