Com*_*are 15 android android-camera
我试图让相机预览在纵向模式下正常工作,其中活动本身可以正常改变方向(即,不被锁定到风景).
但是,使用setDisplayOrientation()严重打破了预览的行为.
这可以通过谷歌自己的ApiDemos来证明.第一个图像基于示例项目CameraPreview的android-17版本ApiDemos,其中我做的唯一更改是android:orientation="landscape"从清单中的此活动的条目中删除.下图是运行Android 4.2的Nexus 4显示屏上显示的内容的屏幕截图,相机指向一张8.5平方英寸的纸张:

该预览中不明显的是它旋转了90度.您在图像最右侧看到的袜子包裹的脚实际上位于正方形下方.
对此,至少对于横向模式,解决方案是使用setDisplayOrientation().但是,如果修改了Preview内部类的CameraPreview有mCamera.setDisplayOrientation(90);,你会得到这样的:

值得注意的是,广场不再是正方形.
它使用与SurfaceView以前相同的大小.我已经使用其他一些代码重现了这个场景ApiDemos,并且我TextureView在该代码中得到了相同的行为.
我简单地想到问题可能是getSupportedPreviewSizes()基于可能会返回不同的值setDisplayOrientation(),但快速测试表明情况并非如此.
任何人都知道如何setDisplayOrientation()在纵向模式下工作而不会破坏图像的宽高比推到预览中?
谢谢!
Com*_*are 15
好吧,我想我想出来了.众所周知的谜题有几个部分,我感谢@kcoppock帮助我解决其中一些问题的见解.
首先,在确定要选择的预览尺寸时,需要考虑方向.例如,getOptimalPreviewSize()from CameraPreviewof the ApiDemosis is is is not orientation,只是因为他们的应用版本的方向已锁定为横向.如果您希望方向浮动,则需要反转目标纵横比以匹配.那么,哪里getOptimalPreviewSize()有:
double targetRatio=(double)width / height;
Run Code Online (Sandbox Code Playgroud)
你还需要:
if (displayOrientation == 90 || displayOrientation == 270) {
targetRatio=(double)height / width;
}
Run Code Online (Sandbox Code Playgroud)
其中displayOrientation是一个从0到360的值,我从大约100行的一些严重丑陋的代码中确定,这就是为什么我将所有这些包装在一个可重用的组件中,我将很快发布.该代码是基于在setDisplayOrientation()JavaDoc中和这个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;
}
Run Code Online (Sandbox Code Playgroud)
这里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();
Run Code Online (Sandbox Code Playgroud)
那是错的.你真正需要的是:
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);
Run Code Online (Sandbox Code Playgroud)
如果没有这种变化,即使在风景中,我也会得到拉伸的纵横比.这不是一个问题CameraPreview的ApiDemos,因为他们不拍照,所以他们从来不叫setPictureSize().
但是,到目前为止,在Nexus 4上,我现在具有纵向和横向的纵横比,具有浮动方向(即,未锁定到横向).
如果我遇到其他设备所需的其他黑客,并且在发布时链接到我的CameraView/ CameraFragment组件,我会尽量记住修改这个问题.
更新#1
嗯,当然,它不可能通过近这么简单.:-)
解决setPictureSize()纵横比搞砸问题的问题......直到你拍照.此时,预览会切换到错误的宽高比.
一种可能性是将图片限制为与预览具有相同(或非常接近)宽高比的图片,因此不存在打嗝.我不喜欢这个答案,因为用户应该能够获得相机提供的任何图片尺寸.
您可以通过以下方式限制损坏的范围:
Camera.Parameters之前更新图片尺寸等Camera.Parameters拍摄照片后,在拍照时,这仍然呈现错误的宽高比.对于这个问题的长期解决方案 - 我认为 - 将在拍摄照片时暂时用静止图像(最后一个预览帧)替换相机预览.我最终会试试这个.
更新#2:我的CWAC-Camera库的 v0.0.1 现已可用,包含上述代码.
| 归档时间: |
|
| 查看次数: |
11614 次 |
| 最近记录: |