android - 肖像模式下的相机风景预览

标签 android android-camera surfaceview landscape-portrait

我有一个对话框设计,其中相机预览应该在纵向模式下横向(参见图片)。我通过 getOptimalPreviewSize() 正确选择预览尺寸,当我不使用 setDisplayOrientation(90) 时,我得到以下结果:

enter image description here

当我使用 setDisplayOrientation(90) 时,我得到这个:

enter image description here

有人知道如何解决这个问题吗? android 可以做这样的事情吗?

答案(感谢艾迪·塔瓦拉):
由于当 xml 中的凸轮 View 为水平方向时,您无法纵向处理整个凸轮图片,因此您应该进行裁剪。我决定水平放置并裁剪底部的所有内容:

|           |
| _________ |   _____
||         ||  |     |
||         ||  | ^-^ |
||  ______ ||  | \_/ |
|| | ^-^  |||  |  |  |    
|| |_\_/_ |||  |__|__|
||   image ||   sensor
||         ||
||         ||
||_________||
||  < O [] ||
|___________|
    device

您应该使用TextureView来指定适合和裁剪的矩阵。类似的东西(kotlin):

fun camInit() {
    val camParam = camera.parameters
    val optimalSize = getOptimalPortraitPreviewSize(camParam.supportedPreviewSizes, width, height)

    camParam.setPreviewSize(optimalSize.width, optimalSize.height)
    camera.parameters = camParam

    camera.setPreviewTexture(surface)

    val scaleDelta = optimalSize.height - preview.width // for portrait
    val scaleY: Float = (optimalSize.width.toFloat() - scaleDelta) / preview.height // for portrait

    val matrix = Matrix()
    matrix.setScale(1f, scaleY)    // 1f cause we fit horizontally

    preview.setTransform(matrix)

    camera.startPreview()
}

请注意,对于纵向模式,您应该使用特定的 getOptimalProtraitPreviewSize(),因为每个人都使用标准函数来获取相机预览最佳尺寸(使用 ASPECT_TOLERANCE 和其他内容)可以返回小分辨率的尺寸。尝试这样的事情:

fun getOptimalPortraitPreviewSize(sizes: List<Camera.Size>, previewWidth: Int) {

    var selectedSize: Camera.Size = sizes[0]

    for (size in sizes) {
        // use size's height cause of portrait
        val currentSizeWidthDelta = abs(size.height - previewWidth)
        val selectedSizeWidthDelta = abs(selectedSize.height - previewWidth)
        if (currentSizeWidthDelta < selectedSizeWidthDelta) selectedSize = size
    }

    return selectedSize
}

最佳答案

图像传感器的长边与设备的长边对齐。

(bad ascii art):
____________
|           |
| _________ |   _____
||         ||  |     |
||         ||  |     |
||         ||  |     |
||         ||  |     |
||         ||  |_____|
||         ||   sensor
||         ||   physical 
||         ||   orientation
||_________||
||  < O [] ||
|___________|
    device

鉴于此,您无法像这样绘制图像:

_____________
|           |
| _________ |   _____
||         ||  |     |
||         ||  |     |
||  ______ ||  |     |
|| |      |||  |     |
|| |______|||  |_____|
||   image ||   sensor
||         ||
||         ||
||_________||
||  < O [] ||
|___________|
    device

除非您旋转图像(在这种情况下,向上不是向上):

_____________
|           |
| _________ |   _____
||         ||  |     |
||         ||  | ^-^ |
||  ______ ||  | \_/ |
|| | <-\__|||  |  |  |    
|| |_<-/__|||  |__|__|
||   image ||   sensor
||         ||
||         ||
||_________||
||  < O [] ||
|___________|
    device

或者水平拉伸(stretch)图像,这看起来很糟糕:

_____________
|           |
| _________ |   _____
||         ||  |     |
||         ||  | ^-^ |
||  ______ ||  | \_/ |
|| | ^___^|||  |  |  |    
|| |___|__|||  |__|__|
||   image ||   sensor
||         ||
||         ||
||_________||
||  < O [] ||
|___________|
    device

或者您裁剪图像的切片,这会大大减少 FOV:

_____________
|           |
| _________ |   _____
||         ||  |     |
||         ||  | ^-^ |
||  ______ ||  | \_/ |
|| | ^-^  |||  |  |  |    
|| |_\_/__|||  |__|__|
||   image ||   sensor
||         ||
||         ||
||_________||
||  < O [] ||
|___________|
    device

由于当手机处于横向状态时,图像传感器处于横向状态,因此如果不发生这三件事之一,就无法在纵向 UI 中放置横向预览。您要么需要在纵向 UI 中进行纵向预览,要么需要裁剪图像。这不是 Android 的限制,而只是几何形状的限制。

如果您想要裁剪,您可能需要将相机数据发送到 SurfaceTexture,并在 OpenGL 中进行裁剪(如果您想要实时预览)。

关于android - 肖像模式下的相机风景预览,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48157420/

相关文章:

Android GUI 覆盖

android - SurfaceFlinger、SurfaceView、Surface、SurfaceHolder 和 Bitmap 是 Android

java - 无法解析方法 getFilter() 方法

android - 如何处理小部件按钮

android - 从相机预览中获取触摸像素的颜色

安卓相机X |颜色检测

android - 位图 - 内存不足异常

Android 如何支持不同的手机版本和屏幕尺寸?

android - 通过 adb 获取蓝牙 MAC 地址

android - 如何在小窗口打开 "zxing Barcode"扫描画面?