【问题标题】:How do I rotate a Camera preview to take landscape photos in portrait mode?如何旋转相机预览以在纵向模式下拍摄风景照片?
【发布时间】:2013-02-25 06:01:42
【问题描述】:

我从想要拍摄肖像照片的人那里看到很多建议,告诉他们将相机旋转 90 度。但是,无论我尝试什么,唯一真正“旋转”的是相机拍摄的图像,但是它保留了它的宽度和高度比例,所以发生的情况是,如果 SurfaceView 很窄,图片不会失真并且高的。

我想要实现的是拍摄一张在 3x4 布局中不变形的 4x3 照片。我知道它会相当窄,但目标是将预览视图旋转 -90 度,同时保持相机的正常纵横比。就目前而言,如果我想在我的纵向布局中定位照片,我所做的一切都会导致图像被挤压。

我开始怀疑我需要将一个矩阵应用于将其旋转 -90 度的预览,但我不确定如何去做,或者这是否真的是正确的方法。希望得到一些建议。

编辑:为了清楚起见,这里是 javadocs 的相关摘录: setPreviewSize() “如果显示方向设置为 0 或 180,则预览大小应设置为 480x320。如果显示方向设置为 90 或 270 ,预览尺寸应设置为 320x480。”

这完全无法解决您希望将设备保持在纵向模式但让相机预览出现在一个小的横向窗口中的情况(这是我想要实现的)。

TIA

【问题讨论】:

    标签: android camera


    【解决方案1】:

    如果您使用 SurfaceView 显示相机预览输出,并且您希望确保预览不失真,无论是在预览还是横向,您必须确保 SurfaceView 的纵横比与纵横比相匹配的相机预览大小。 SurfaceView 将简单地缩放预览以适应其自身,因此如果预览大小为 640x480 时它是 500x500,则预览看起来会垂直拉伸。

    概念上最简单的方法是简单地手动设置 SurfaceView 的宽度和高度,通过使用LayoutParamssetLayoutParams 将 SurfaceView 的布局更新为固定大小的布局。这种方法的问题在于它可能会因不同的屏幕尺寸而变得脆弱,因为您需要弄清楚您真正想要的像素尺寸是多少,并且对于 Android 上的直接跨设备布局,您真的想在 dp 中进行思考而不是像素。但是对于测试,您可以强制 SurfaceView 具有测试设备屏幕的宽度和由

    设置的高度
    surface height = preview height / preview width * surface width
    

    更好的方法是创建一个继承自 SurfaceView 的新类,该类在 View 的 onMeasure 方法中进行必要的纵横比调整。详细解释这一点很长,但请查看 Android 开发者网站上的custom components documentation 了解详细信息。但粗略地说,您需要设置的宽度/高度值始终与您配置的相机预览尺寸保持相同的纵横比。

    一旦你有了合适大小的surfaceView,你通常还需要用setDisplayOrientation旋转相机预览输出;计算方向数学可能会令人困惑,因此请使用上面文档链接中提供的代码示例来计算它。

    基本上,世界有一个坐标系,相机传感器有另一个(固定在设备上),UI 系统有第三个(固定在您当前的方向上),这三个坐标系可能会相对于彼此发生变化。虽然正确的预览方向不取决于设备相对于世界的位置,但相机拍摄的图片的方向却取决于(由setRotation 设置)。

    【讨论】:

    • 这是一个很好的解释,我终于可以拍出看起来不变形的照片,但是无论我尝试什么预览仍然是变形的。一个代码示例(如果有的话)实际上将预览旋转了 90º,以便设置为纵向的 Activity 可以显示正确的照片预览,我们将不胜感激...... 4 年来我一直在努力解决这个问题(打开和关闭) .
    • 假设预览仍然是指实时相机预览,而不是拍摄照片的缩略图 - 在简短的注释中对 Android 的布局系统进行概述是相当困难的。但是从调用 setDisplayOrientation 开始,上面链接的文档中有关于如何计算所需旋转量的示例代码。这至少能让你找到正确的方向。
    • 设置显示方向不会削减它。问题是预览是在定向之前测量的,因此它总是以相反的纵横比显示(这意味着如果图像变为 4:3,它会显示为 3:4(即使它仍然被收集为 4:3)所以它是扭曲的。
    • 正如我所说,它是必要的,但它本身还不够。在 onResume 或配置更改时,您知道 SurfaceView 在当前 UI 方向下需要哪个纵横比。所以你需要调整它的布局参数来匹配。这里有一个 FixedAspectSurfaceView 作为 camera2 API 的一个相机演示的一部分:github.com/googlesamples/android-HdrViewfinder/blob/master/… 它为非拉伸预览提供了一个基本类,仍然需要在方向更改时更改纵横比
    【解决方案2】:

    我的建议是,

    不要在 Android 的 Layout 上尝试更多,这东西很难。如果你想实现,你必须阅读 Android 的开源代码,并且应该自己改变。

    所以,我建议您使用 Canvas(导入图形包)并利用这些类。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-22
      • 1970-01-01
      • 2013-04-14
      • 1970-01-01
      • 2011-11-15
      • 1970-01-01
      • 2013-10-03
      • 2014-08-15
      相关资源
      最近更新 更多