简体   繁体   English

如何旋转相机预览以纵向模式拍摄风景照片?

[英]How do I rotate a Camera preview to take landscape photos in portrait mode?

I see a lot of advice from people wanting to take portrait photos that tell them to rotate the camera by 90 degrees. 我收到了很多想拍摄人像照片的建议,告诉他们将相机旋转90度。 However, no matter what I try the only thing that actually "rotates" is the image being taken by the camera, however it retains it's width and height proportions, so what happens is that the picture is only not distorted if the SurfaceView is narrow and tall. 但是,无论我尝试什么,唯一能真正“旋转”的是相机拍摄的图像,但它会保留其宽度和高度比例,因此发生的情况是,只有在SurfaceView狭窄且高。

What I'm trying to achieve is to take a 4x3 photo that is NOT warped in a 3x4 layout. 我要实现的是拍摄一张4x3的照片,该照片在3x4布局中没有变形。 It will be fairly narrow, I know, but the object is to rotate the Preview view -90degrees and yet preserve the normal aspect ratio of the Camera. 我知道它会很窄,但目的是将“预览”视图旋转-90度,同时保持相机的正常纵横比。 As it stands, everything I've tried has resulted in the image being squished if I want to orient the photo across my portrait layout. 就目前而言,如果我想将照片定向在我的肖像布局上,我尝试过的一切都会导致图像被压缩。

I'm starting to suspect that I'll need to apply a matrix to the Preview that will rotate it -90 degrees, but I'm not sure how to go about doing that, or if that's actually the right approach. 我开始怀疑是否需要将一个矩阵应用于Preview并将其旋转-90度,但是我不确定该怎么做,或者这是否是正确的方法。 Would love some advice. 会喜欢一些建议。

Edit: Just to be clear here's the relevant excerpt from the javadocs: setPreviewSize() "If the display orientation is set to 0 or 180, preview size should be set to 480x320. If the display orientation is set to 90 or 270, preview size should be set to 320x480." 编辑:为了清楚起见,这是来自javadocs的相关摘录:setPreviewSize()“如果显示方向设置为0或180,则预览大小应设置为480x320。如果显示方向设置为90或270,则预览大小应该设置为320x480。”

That totally fails to address the situation where you want to hold the device in portrait mode but have the camera preview appear in a small landscape window (which is what I'm trying to achieve). 这完全无法解决您想要将设备保持在纵向模式但将相机预览显示在一个小的横向窗口中的情况(这是我要实现的目标)。

TIA TIA

If you're using a SurfaceView to display camera preview output, and you want to make sure your preview is not distorted, either in preview or in landscape, you have to make sure the aspect ratio of your SurfaceView matches the aspect ratio of the camera preview size. 如果您使用SurfaceView来显示相机预览输出,并且想要确保预览不失真(在预览或横向模式下),则必须确保SurfaceView的纵横比与相机的纵横比匹配预览尺寸。 The SurfaceView will simply scale the preview to fit inside itself, so if it's 500x500 while your preview size is 640x480, preview will look stretched vertically. SurfaceView会简单地缩放预览以使其适合自身,因此,如果预览尺寸为640x480,缩放比例为500x500,则预览看起来会垂直拉伸。

The conceptually simplest approach is to simply manually set the SurfaceView's width and height, by updating the SurfaceView's layout to a fixed-size one with LayoutParams and setLayoutParams . 从概念上讲,最简单的方法是通过使用LayoutParamssetLayoutParams将SurfaceView的布局更新为固定大小的布局,从而简单地手动设置SurfaceView的宽度和高度。 The problem with this approach is that it can be brittle with different screen sizes, since you need to figure out what the sizes in pixels you want really are, and for straightforward across-device layout on Android, you really want to be thinking in dp instead of pixels. 这种方法的问题是,在不同的屏幕尺寸下,它可能会很脆弱,因为您需要确定您真正想要的像素大小,并且对于Android上的直接跨设备布局,您真的想在dp中进行思考而不是像素。 But for testing, you can just force your SurfaceView to have the width of the test device's screen, and height set by 但是对于测试,您可以强制SurfaceView设置测试设备屏幕的宽度,并通过以下方式设置高度:

surface height = preview height / preview width * surface width

A better approach would be to create a new class inherited from SurfaceView, which does the necessary aspect-ratio adjustments in the View's onMeasure method. 更好的方法是创建一个从SurfaceView继承的新类,该类在View的onMeasure方法中进行必要的宽高比调整。 Explaining that in detail is lengthy, but look over the custom components documentation on the Android developer's site for details. 详细解释很长,但是请查看Android开发人员网站上的自定义组件文档以了解详细信息。 But roughly speaking, you need to set width/height values that always result in the same aspect ratio as the camera preview size you've configured. 但粗略地说,您需要设置宽度/高度值,以始终获得与您配置的摄像机预览尺寸相同的宽高比。

Once you have the right-sized surfaceView, you do usually also need to rotate the camera preview output with setDisplayOrientation ; 拥有合适尺寸的surfaceView之后,通常还需要使用setDisplayOrientation旋转相机预览输出; working out the orientation math can be confusing, so use the code sample provided at the documentation link above to work it out. 计算方向数学可能会造成混淆,因此请使用上面的文档链接中提供的代码示例进行计算。

Basically, the world has one coordinate system, the camera sensor has another (fixed to the device), and the UI system has a third (fixed to your current orientation), and all three may change relative to each other. 基本上,世界有一个坐标系,摄像头传感器有另一个坐标系(固定在设备上),UI系统有第三个坐标系(固定在您当前的方向上),所有这三个坐标可能会相对变化。 While the correct preview orientation does not depend on the position of the device relative to the world, the orientation of the pictures taken by the camera does (which is set by setRotation ). 尽管正确的预览方向不取决于设备相对于世界的位置,但相机拍摄的图片的方向却取决于(由setRotation设置)。

My Suggestion is, 我的建议是

Don't try more on Layout in Android, it is very difficult to that stuff And iff you want to acheive, you must read the opensource code of Android and should change in that itself. 不要在Android的Layout上尝试更多,很难做到这一点。如果您想实现这一点,则必须阅读Android的开源代码,并且必须对其进行更改。

So, i suggest you to use Canvas(Import Graphics package) and make use of those classes. 因此,我建议您使用Canvas(导入图形包)并使用这些类。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM