gpt4 book ai didi

android - 纵向模式下的相机 setDisplayOrientation() 会破坏纵横比

转载 作者:可可西里 更新时间:2023-11-01 18:46:31 32 4
gpt4 key购买 nike

我试图让相机预览在纵向模式下正常工作,其中允许 Activity 本身正常更改方向(即不锁定为横向)。

使用setDisplayOrientation()但是,严重破坏了预览的行为。

这可以通过 Google 自己的 ApiDemos 来演示。第一张图片基于CameraPreview来自 android-17 ApiDemos 的版本示例项目,我所做的唯一更改是删除 android:orientation="landscape"来自 list 中此 Activity 的条目。下图是运行 Android 4.2 的 Nexus 4 显示屏上显示的屏幕截图,摄像头指向 8.5 英寸方形纸:

Nexus 4 ApiDemos Preview, Portrait Mode

从该预览中不明显的是它旋转了 90 度。您在图像最右侧看到的穿着 socks 的脚实际上在正方形的下方。

至少对于横向模式,解决方案是使用 setDisplayOrientation() .但是,如果您修改 Preview CameraPreview 的内部类拥有mCamera.setDisplayOrientation(90); ,你得到这个:

Nexus 4 ApiDemos Preview, Portrait Mode, with setDisplayOrientation(90)

值得注意的是,正方形不再是正方形。

这使用相同的 SurfaceView大小和以前一样。我已经用 ApiDemos 之外的一些其他代码重现了这种情况。 ,我得到与 TextureView 相同的行为在那个代码中。

我简要地认为问题可能是getSupportedPreviewSizes()可能会根据 setDisplayOrientation() 返回不同的值,但快速测试表明情况并非如此。

任何人都知道如何获得setDisplayOrientation()在纵向模式下工作而不破坏推送到预览的图像的纵横比?

谢谢!

最佳答案

好的,我想我想通了。众所周知的难题有几个部分,我感谢@kcoppock 的洞察力帮助我解决了其中的一些问题。

首先,在确定要选择的预览尺寸时,您需要考虑方向。例如,getOptimalPreviewSize()来自 CameraPreviewApiDemos忽略方向,仅仅是因为他们的那个应用程序版本的方向锁定为横向。如果您希望让方向 float ,则需要反转目标纵横比以匹配。那么,getOptimalPreviewSize()有:

double targetRatio=(double)width / height;

你还需要:
if (displayOrientation == 90 || displayOrientation == 270) {
targetRatio=(double)height / width;
}

在哪里 displayOrientation是一个从 0 到 360 的值,我从大约 100 行一些严重丑陋的代码中确定,这就是为什么我将所有这些都包装在一个可重用的组件中,我将很快发布。该代码基于 the setDisplayOrientation() JavaDocsthis StackOverflow answer .

(顺便说一句,如果您在 2013 年 7 月 1 日之后阅读此内容,并且在此答案中看不到该组件的链接,请发表评论以提醒我,因为我忘记了)

其次,在控制 SurfaceView 的纵横比时需要考虑显示方向。/ TextureView你正在使用的。 CameraPreview来自 ApiDemos 的 Activity 有自己的 Preview ViewGroup处理纵横比,您需要反转纵横比以用于纵向:
    if (displayOrientation == 90
|| displayOrientation == 270) {
previewWidth=mPreviewSize.height;
previewHeight=mPreviewSize.width;
}
else {
previewWidth=mPreviewSize.width;
previewHeight=mPreviewSize.height;
}

在哪里 displayOrientation是相同的值( 90270 分别是纵向和反向纵向,请注意,我没有尝试让反向纵向或反向横向工作,因此可能需要更多调整)。

第三个——也是我觉得很气愤的一个——你必须在调用 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);

如果没有这种变化,即使在横向上,我也会得到一个拉伸(stretch)的纵横比。这对 CameraPreview 来说不是问题的 ApiDemos ,因为他们没有拍照,所以他们从来没有打过 setPictureSize() .

但是,到目前为止,在 Nexus 4 上,我现在有纵向和横向的方形纵横比,具有 float 方向(即未锁定为横向)。

如果我遇到其他设备所需的其他黑客攻击,我会尽量记住修改这个问题,并链接到我的 CameraView/ CameraFragment组件发布时。

更新 #1

嗯,当然,不可能这么简单。 :-)

修复 setPictureSize() 的问题搞砸了纵横比的工作......直到你拍照。此时,预览切换到错误的纵横比。

一种可能性是将图片限制为与预览具有相同(或非常接近)纵横比的图片,因此不存在打嗝。我不喜欢这个答案,因为用户应该能够获得相机提供的任何图片尺寸。

您可以通过以下方式限制损坏范围:
  • 只更新Camera.Parameters的图片大小等就在拍照前
  • 恢复到拍照前Camera.Parameters拍照后

  • 在拍摄照片的瞬间,这仍然会显示错误的纵横比。对此的长期解决方案 - 我认为 - 将在拍摄照片时暂时用静止图像(最后一个预览帧)替换相机预览。我最终会试试这个。

    更新 #2 : v0.0.1 of my CWAC-Camera library现在可用,包含上述代码。

    关于android - 纵向模式下的相机 setDisplayOrientation() 会破坏纵横比,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17126633/

    32 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com