我有一个对话框设计,其中相机预览应该在纵向模式下横向(参见图片)。我通过 getOptimalPreviewSize() 正确选择预览尺寸,当我不使用 setDisplayOrientation(90) 时,我得到以下结果:
当我使用 setDisplayOrientation(90) 时,我得到这个:
有人知道如何解决这个问题吗? 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/