好的,我想我想通了。众所周知的难题有几个部分,我感谢@kcoppock 的洞察力帮助我解决了其中的一些问题。
首先,在确定要选择的预览尺寸时,您需要考虑方向。例如,getOptimalPreviewSize()
from the CameraPreview
ofApiDemos
忽略方向,仅仅是因为他们的应用程序版本将方向锁定为横向。如果您希望让方向浮动,则需要反转目标纵横比以匹配。那么,哪里getOptimalPreviewSize()
有:
double targetRatio=(double)width / height;
你还需要:
if (displayOrientation == 90 || displayOrientation == 270) {
targetRatio=(double)height / width;
}
哪里displayOrientation
是一个从 0 到 360 的值,我从大约 100 行一些非常丑陋的代码中确定,这就是为什么我将所有这些都包装在一个我将很快发布的可重用组件中。该setDisplayOrientation()
代码基于JavaDocs和这个 StackOverflow 答案。
(顺便说一句,如果您在 2013 年 7 月 1 日之后阅读此内容,并且在此答案中看不到该组件的链接,请发表评论以提醒我,因为我忘记了)
其次,在控制您使用的SurfaceView
/的纵横比时,您需要考虑显示方向。TextureView
来自的CameraPreview
活动ApiDemos
有自己Preview
ViewGroup
的处理纵横比,并且您需要反转纵横比以用于纵向:
if (displayOrientation == 90
|| displayOrientation == 270) {
previewWidth=mPreviewSize.height;
previewHeight=mPreviewSize.width;
}
else {
previewWidth=mPreviewSize.width;
previewHeight=mPreviewSize.height;
}
displayOrientation
相同的值在哪里(90
分别270
是纵向和反向纵向,请注意,我没有尝试让反向纵向或反向横向工作,因此可能需要更多调整)。
第三——也是我觉得很气愤的一个——你必须在setPictureSize()
调用Camera.Parameters
. 否则,就好像图片的纵横比应用于预览帧,搞砸了。
所以我曾经有类似以下的代码:
Camera.Parameters parameters=camera.getParameters();
Camera.Size pictureSize=getHost().getPictureSize(parameters);
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
parameters.setPictureSize(pictureSize.width, pictureSize.height);
parameters.setPictureFormat(ImageFormat.JPEG);
camera.setParameters(parameters);
camera.startPreview();
这是错误的。你真正需要的是:
Camera.Parameters parameters=camera.getParameters();
Camera.Size pictureSize=getHost().getPictureSize(parameters);
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
camera.setParameters(parameters);
camera.startPreview();
parameters=camera.getParameters();
parameters.setPictureSize(pictureSize.width, pictureSize.height);
parameters.setPictureFormat(ImageFormat.JPEG);
camera.setParameters(parameters);
如果没有这种变化,即使在横向上,我也会得到一个拉伸的纵横比。这对CameraPreview
的来说不是问题ApiDemos
,因为他们没有拍照,所以他们从来没有打电话给setPictureSize()
。
但是,到目前为止,在 Nexus 4 上,我现在有纵向和横向的方形纵横比,具有浮动方向(即,未锁定为横向)。
如果我遇到其他设备所需的其他黑客攻击,我会尽量记住修改这个问题,并在它们发布时链接到我的CameraView
/组件。CameraFragment
更新#1
嗯,当然,不可能这么简单。:-)
解决了setPictureSize()
搞砸纵横比的问题……直到你拍照为止。此时,预览切换到错误的纵横比。
一种可能性是将图片限制为与预览具有相同(或非常接近)纵横比的图片,因此不存在打嗝。我不喜欢这个答案,因为用户应该能够获得相机提供的任何图片尺寸。
您可以通过以下方式限制损坏范围:
Camera.Parameters
仅在拍照前更新图片大小等
- 拍照
Camera.Parameters
后恢复到拍照前
在拍摄照片的瞬间,这仍然会显示错误的纵横比。对此的长期解决方案 - 我认为 - 将在拍摄照片时暂时用静止图像(最后一个预览帧)替换相机预览。我最终会试试这个。
更新#2:我的 CWAC-Camera 库的 v0.0.1 现在可用,包含上述代码。